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); }
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); }
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); }
/// <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; } }