Esempio n. 1
0
        public void setSps(ref SequenceParameterSet sps)
        {
            separateColourPlaneFlag = sps.separateColourPlaneFlag;
            frameIndexBits          = sps.frameIndexBits;

            timingFormat = new TimingFormat(ref sps);

            Logger.logInfo("VideoSampleReader.setSps: separateColourPlaneFlag = {0}, frameIndexBits = {1}",
                           separateColourPlaneFlag, frameIndexBits);
        }
Esempio n. 2
0
        public TimingFormat(ref SequenceParameterSet sps)
        {
            cpbDpbDelaysPresent = sps.vui.CpbDpbDelaysPresent;
            if (cpbDpbDelaysPresent)
            {
                cpbRemovalDelayLength = sps.vui.hrd.CpbRemovalDelayLength;
                dpbOutputDelayLength  = sps.vui.hrd.DpbOutputDelayLength;
            }
            else
            {
                cpbRemovalDelayLength = dpbOutputDelayLength = 0;
            }

            timeOffsetLength = sps.vui.hrd.TimeOffsetLength;
            timeScale        = sps.vui.timeScale;
            numUnitsInTick   = sps.vui.numUnitsInTick;

            picStructPresent = sps.vui.flags.HasFlag(eVuiFlags.PicStruct);
        }
Esempio n. 3
0
        internal VideoParams264(TrackEntry videoTrack)
        {
            // File.WriteAllBytes( @"C:\Temp\2remove\mkv\videoPrivateData.bin", videoTrack.codecPrivate );
            ReadOnlySpan <byte> codecPrivate = videoTrack.codecPrivate.AsSpan();
            int          cbHeader            = Marshal.SizeOf <NativeStruct>();
            NativeStruct ns = codecPrivate.Slice(0, cbHeader).cast <NativeStruct>()[0];

            profile = ns.profileCode;
            profileCompatibility = ns.profileCompatibility;
            levelCode            = ns.levelCode;

            int offset = cbHeader;

            sps = ContainerUtils.copyBlobs(ns.numOfSequenceParameterSets, codecPrivate, ref offset);

            // File.WriteAllBytes( @"C:\Temp\2remove\mkv\sps.bin", sps[ 0 ] );

            int ppsCount = codecPrivate[offset++];

            pps = ContainerUtils.copyBlobs(ppsCount, codecPrivate, ref offset);

            ReadOnlySpan <byte> spsBlob = sps[0].AsSpan();

            if (MiscUtils.getNaluType(spsBlob[0]) != eNaluType.SPS)
            {
                throw new ApplicationException("The SPS is invalid, wrong NALU type");
            }
            spsBlob = spsBlob.Slice(1);

            BitReader spsReader = new BitReader(spsBlob);

            parsedSps = new SequenceParameterSet(ref spsReader);

            chromaFormat   = parsedSps.chromaFormat;
            bitDepthLuma   = parsedSps.bitDepthLuma;
            bitDepthChroma = parsedSps.bitDepthChroma;
            m_decodedSize  = new sDecodedVideoSize(parsedSps.decodedSize, parsedSps.cropRectangle, chromaFormat);
        }
        /// <summary>
        /// Process the short term reference picture sets.
        /// </summary>
        /// <remarks>
        /// Reference:
        ///  7.3.7 Short-term reference picture set syntax
        ///  7.4.8 Short-term reference picture set semantics
        /// </remarks>
        private ShortTermRefPicSet ProcessShortTermRefPicSets(NalUnitBitstreamNavigator nav, SequenceParameterSet sps, uint stRpsIdx)
        {
            var result = new ShortTermRefPicSet();

            if (stRpsIdx != 0)
            {
                result.inter_ref_pic_set_prediction_flag = nav.ReadBit(); //inter_ref_pic_set_prediction_flag u(1)
            }

            if (result.inter_ref_pic_set_prediction_flag)
            {
                if (stRpsIdx == sps.num_short_term_ref_pic_sets)
                {
                    result.delta_idx_minus1 = nav.ReadNonNegativeExponentialGolombAsUInt32(); //delta_idx_minus1 ue(v)
                }

                result.delta_rps_sign       = nav.ReadBit() ? (byte)1 : (byte)0;              //delta_rps_sign u(1)
                result.abs_delta_rps_minus1 = nav.ReadNonNegativeExponentialGolombAsUInt32(); //abs_delta_rps_minus1 ue(v)
                // long deltaRps = (1 - 2 * delta_rps_sign) * (abs_delta_rps_minus1 + 1);

                uint numDeltaPocs = CalculateNumDeltaPictureOrderCounts(sps.ShortTermRefPicSets, stRpsIdx, result);
                for (int j = 0; j <= numDeltaPocs; j++)
                {
                    result.used_by_curr_pic_flag.Add(nav.ReadBit()); //used_by_curr_pic_flag[ j ] u(1)
                    if (!result.used_by_curr_pic_flag[j])
                    {
                        result.use_delta_flag.Add(nav.ReadBit());    //use_delta_flag[ j ] u(1)
                    }
                }
            }
            else
            {
                result.num_negative_pics = nav.ReadNonNegativeExponentialGolombAsUInt32(); //num_negative_pics ue(v)
                result.num_positive_pics = nav.ReadNonNegativeExponentialGolombAsUInt32(); //num_positive_pics ue(v)

                if (result.num_negative_pics > sps.sps_max_dec_pic_buffering_minus1[sps.sps_max_sub_layers_minus1])
                {
                    System.Console.WriteLine("ShortTermRefPicSet.num_negative_pics > sps_max_dec_pic_buffering_minus1");
                    return(result);
                }

                if (result.num_positive_pics > sps.sps_max_dec_pic_buffering_minus1[sps.sps_max_sub_layers_minus1])
                {
                    System.Console.WriteLine("ShortTermRefPicSet.num_positive_pics > sps_max_dec_pic_buffering_minus1");
                    return(result);
                }

                for (int i = 0; i < result.num_negative_pics; i++)
                {
                    result.delta_poc_s0_minus1.Add(nav.ReadNonNegativeExponentialGolombAsUInt32()); //delta_poc_s0_minus1[ i ] ue(v)
                    result.used_by_curr_pic_s0_flag.Add(nav.ReadBit());                             //used_by_curr_pic_s0_flag[ i ] u(1)
                }

                for (int i = 0; i < result.num_positive_pics; i++)
                {
                    result.delta_poc_s1_minus1.Add(nav.ReadNonNegativeExponentialGolombAsUInt32()); //delta_poc_s1_minus1[ i ] ue(v)
                    result.used_by_curr_pic_s1_flag.Add(nav.ReadBit());                             //used_by_curr_pic_s1_flag[ i ] u(1)
                }
            }

            return(result);
        }
        /// <summary>
        /// Process a Sequence Parameter Set NAL Unit.
        /// </summary>
        /// <remarks>
        /// Reference 7.3.2.2 Sequence parameter set RBSP syntax - seq_parameter_set_rbsp()
        /// </remarks>
        private byte[] ProcessSequenceParameterSetNalUnit(byte[] nalUnitBytes)
        {
            var sps = new SequenceParameterSet();

            var nav = new NalUnitBitstreamNavigator(nalUnitBytes);

            nav.SkipBits(16);                                                        // Skip the 2 byte Nal Unit header

            nav.SkipBits(4);                                                         // sps_video_parameter_set_id u(4)

            sps.sps_max_sub_layers_minus1 = nav.ReadBitsAsByte(3);                   // sps_max_sub_layers_minus1 u(3)

            nav.SkipBit();                                                           // sps_temporal_id_nesting_flag u(1)

            ProcessProfileTierLevel(nav, true, sps.sps_max_sub_layers_minus1);       //profile_tier_level( 1, sps_max_sub_layers_minus1 )

            nav.ReadNonNegativeExponentialGolombAsUInt32();                          //sps_seq_parameter_set_id ue(v)

            uint chroma_format_idc = nav.ReadNonNegativeExponentialGolombAsUInt32(); //chroma_format_idc ue(v)

            if (chroma_format_idc == 3)
            {
                nav.SkipBit();     // separate_colour_plane_flag u(1)
            }

            nav.ReadNonNegativeExponentialGolombAsUInt32(); //pic_width_in_luma_samples ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //pic_height_in_luma_samples ue(v)

            bool conformance_window_flag = nav.ReadBit();   //conformance_window_flag u(1)

            if (conformance_window_flag)
            {
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //conf_win_left_offset ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //conf_win_right_offset ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //conf_win_top_offset ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //conf_win_bottom_offset ue(v)
            }

            nav.ReadNonNegativeExponentialGolombAsUInt32(); //bit_depth_luma_minus8 ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //bit_depth_chroma_minus8 ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_max_pic_order_cnt_lsb_minus4 ue(v)

            sps.sps_max_dec_pic_buffering_minus1 = new uint[sps.sps_max_sub_layers_minus1 + 1];
            bool sps_sub_layer_ordering_info_present_flag = nav.ReadBit(); //sps_sub_layer_ordering_info_present_flag u(1)

            for (int i = (sps_sub_layer_ordering_info_present_flag ? 0 : sps.sps_max_sub_layers_minus1); i <= sps.sps_max_sub_layers_minus1; i++)
            {
                sps.sps_max_dec_pic_buffering_minus1[i] = nav.ReadNonNegativeExponentialGolombAsUInt32(); //sps_max_dec_pic_buffering_minus1[i] ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32();                                           //sps_max_num_reorder_pics[i] ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32();                                           //sps_max_latency_increase_plus1[i] ue(v)
            }

            nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_min_luma_coding_block_size_minus3 ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_diff_max_min_luma_coding_block_size ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_min_luma_transform_block_size_minus2 ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_diff_max_min_luma_transform_block_size ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //max_transform_hierarchy_depth_inter ue(v)
            nav.ReadNonNegativeExponentialGolombAsUInt32(); //max_transform_hierarchy_depth_intra ue(v)

            bool scaling_list_enabled_flag = nav.ReadBit(); //scaling_list_enabled_flag u(1)

            if (scaling_list_enabled_flag)
            {
                bool sps_scaling_list_data_present_flag = nav.ReadBit(); //sps_scaling_list_data_present_flag u(1)
                if (sps_scaling_list_data_present_flag)
                {
                    ProcessScalingListData(nav); //scaling_list_data()
                }
            }

            nav.SkipBit();                         //amp_enabled_flag u(1)
            nav.SkipBit();                         //sample_adaptive_offset_enabled_flag u(1)

            bool pcm_enabled_flag = nav.ReadBit(); //pcm_enabled_flag u(1)

            if (pcm_enabled_flag)
            {
                nav.SkipBits(4);                                //pcm_sample_bit_depth_luma_minus1 u(4)
                nav.SkipBits(4);                                //pcm_sample_bit_depth_chroma_minus1 u(4)
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_min_pcm_luma_coding_block_size_minus3 ue(v)
                nav.ReadNonNegativeExponentialGolombAsUInt32(); //log2_diff_max_min_pcm_luma_coding_block_size ue(v)
                nav.SkipBit();                                  //pcm_loop_filter_disabled_flag u(1)
            }

            sps.num_short_term_ref_pic_sets = nav.ReadNonNegativeExponentialGolombAsUInt32(); //num_short_term_ref_pic_sets ue(v)
            for (uint i = 0; i < sps.num_short_term_ref_pic_sets; i++)
            {
                sps.ShortTermRefPicSets.Add(ProcessShortTermRefPicSets(nav, sps, i)); //st_ref_pic_set( i )
            }

            bool long_term_ref_pics_present_flag = nav.ReadBit(); //long_term_ref_pics_present_flag u(1)

            if (long_term_ref_pics_present_flag)
            {
                uint num_long_term_ref_pics_sps = nav.ReadNonNegativeExponentialGolombAsUInt32(); //num_long_term_ref_pics_sps ue(v)
                for (int i = 0; i < num_long_term_ref_pics_sps; i++)
                {
                    nav.ReadNonNegativeExponentialGolombAsUInt32(); //lt_ref_pic_poc_lsb_sps[i] u(v)
                    nav.SkipBit();                                  //used_by_curr_pic_lt_sps_flag[i] u(1)
                }
            }

            nav.SkipBit();                                    //sps_temporal_mvp_enabled_flag u(1)
            nav.SkipBit();                                    //strong_intra_smoothing_enabled_flag u(1)

            bool vui_parameters_present_flag = nav.ReadBit(); //vui_parameters_present_flag u(1)

            if (vui_parameters_present_flag)
            {
                ProcessVideoUsabilityInformationParameters(nav); //vui_parameters()
            }

            // **********************************************
            // NOTE: Parsing has only implemented up to here... There are still more extensions...
            // **********************************************

            //sps_extension_present_flag u(1)
            //if( sps_extension_present_flag ) {
            //    sps_range_extension_flag u(1)
            //    sps_multilayer_extension_flag u(1)
            //    sps_3d_extension_flag u(1)
            //    sps_scc_extension_flag u(1)
            //    sps_extension_4bits u(4)
            //}

            //if ( sps_range_extension_flag )
            //    sps_range_extension( )

            //if( sps_multilayer_extension_flag )
            //    sps_multilayer_extension( ) /* specified in Annex F *

            //if (sps_3d_extension_flag)
            //    sps_3d_extension() /* specified in Annex I *

            //if (sps_scc_extension_flag)
            //    sps_scc_extension()

            //if (sps_extension_4bits)
            //    while (more_rbsp_data())
            //        sps_extension_data_flag u(1)

            return(nalUnitBytes);
        }
Esempio n. 6
0
        /// <summary>
        /// Look into a slice just to get width, height, and aspect ratio.
        /// NOTE: This is no longer used.
        /// </summary>
        private void GetScreenDimensions(IVideoTrack video)
        {
            if ((video.PayloadType == VideoPayloadType.unknown) || (video.PayloadType == VideoPayloadType.jpeg) || (video.PayloadType == VideoPayloadType.mjpeg))
            {
                return;
            }

            // this will only work for H.264 video source

            IMediaTrackSliceEnumerator slices = (IMediaTrackSliceEnumerator)video.GetEnumerator();

            slices.MoveNext();
            Slice slice       = slices.Current;;
            int   countToZero = slice.SliceSize;
            ulong totalSize   = 0UL;

            BinaryReader reader = new BinaryReader(new MemoryStream(slice.SliceBytes));

            while (countToZero > 4)
            {
                ulong naluLen = BE32(reader.ReadUInt32());
                long  nextPos = reader.BaseStream.Position + (long)naluLen;
                uint  typ     = reader.ReadByte();
                if ((naluLen > (ulong)countToZero) || (naluLen < 2))
                {
                    throw new Exception("Invalid video payload");
                }

                // access unit delimiter (aud) always comes first and its size is not added to total size because
                // it is be added back to the payload.
                if ((typ & 0x1Fu) == 9u)
                {
                    if (naluLen != 2)
                    {
                        throw new Exception("Wrong nalu delimiter length");
                    }
                    reader.ReadByte(); // discard (we don't need it here)
                }

                // if nalu type is Sequence Param Set, pick up width and height
                // also, build private codec data from this SPS
                // NOTE: it matters which video track this qbox belongs!
                if ((typ & 0x1Fu) == 7u)
                {
                    byte[] buf = new byte[naluLen];
                    reader.Read(buf, 1, (int)naluLen - 1);
                    totalSize += (4 + naluLen);
                    // parse the SPS bit stream, just to get the correct width and height of video.
                    BitReader            bitReader = new BitReader(new MemoryStream(buf));
                    SequenceParameterSet sps       = new SequenceParameterSet((uint)naluLen);
                    sps.Read(bitReader);
                    Width  = (int)sps.Width;
                    Height = (int)sps.Height;
                    if (sps.VUIParametersPresent)
                    {
                        AspectRatioX = sps.vuiParams.AspectRatioX;
                        AspectRatioY = sps.vuiParams.AspectRatioY;
                    }
                }

                countToZero -= ((int)naluLen + 4);
                reader.BaseStream.Position = nextPos;
            }
        }