diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index d4881483b1..83eca656cd 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -908,11 +908,8 @@ error: static gboolean gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim, - GstH264VUIParams * vui, NalReader * nr) + guint8 time_offset_length, NalReader * nr) { - guint8 full_timestamp_flag; - guint8 time_offset_length; - GST_DEBUG ("parsing \"Clock timestamp\""); /* default values */ @@ -921,12 +918,12 @@ gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim, READ_UINT8 (nr, tim->ct_type, 2); READ_UINT8 (nr, tim->nuit_field_based_flag, 1); READ_UINT8 (nr, tim->counting_type, 5); - READ_UINT8 (nr, full_timestamp_flag, 1); + READ_UINT8 (nr, tim->full_timestamp_flag, 1); READ_UINT8 (nr, tim->discontinuity_flag, 1); READ_UINT8 (nr, tim->cnt_dropped_flag, 1); READ_UINT8 (nr, tim->n_frames, 8); - if (full_timestamp_flag) { + if (tim->full_timestamp_flag) { tim->seconds_flag = TRUE; READ_UINT8 (nr, tim->seconds_value, 6); @@ -949,12 +946,6 @@ gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim, } } - time_offset_length = 24; - if (vui->nal_hrd_parameters_present_flag) - time_offset_length = vui->nal_hrd_parameters.time_offset_length; - else if (vui->vcl_hrd_parameters_present_flag) - time_offset_length = vui->vcl_hrd_parameters.time_offset_length; - if (time_offset_length > 0) READ_UINT32 (nr, tim->time_offset, time_offset_length); @@ -970,8 +961,6 @@ gst_h264_parser_parse_pic_timing (GstH264NalParser * nalparser, GstH264PicTiming * tim, NalReader * nr) { GstH264ParserResult error = GST_H264_PARSER_ERROR; - gboolean CpbDpbDelaysPresentFlag = FALSE; - gboolean pic_struct_present_flag = FALSE; GST_DEBUG ("parsing \"Picture timing\""); if (!nalparser->last_sps || !nalparser->last_sps->valid) { @@ -983,25 +972,29 @@ gst_h264_parser_parse_pic_timing (GstH264NalParser * nalparser, if (nalparser->last_sps->vui_parameters_present_flag) { GstH264VUIParams *vui = &nalparser->last_sps->vui_parameters; - - CpbDpbDelaysPresentFlag = vui->nal_hrd_parameters_present_flag - || vui->vcl_hrd_parameters_present_flag; - tim->pic_struct_present_flag = pic_struct_present_flag = - vui->pic_struct_present_flag; + GstH264HRDParams *hrd = NULL; if (vui->nal_hrd_parameters_present_flag) { - READ_UINT32 (nr, tim->cpb_removal_delay, - vui->nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1); - READ_UINT32 (nr, tim->dpb_output_delay, - vui->nal_hrd_parameters.dpb_output_delay_length_minus1 + 1); + hrd = &vui->nal_hrd_parameters; } else if (vui->vcl_hrd_parameters_present_flag) { - READ_UINT32 (nr, tim->cpb_removal_delay, - vui->vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1); - READ_UINT32 (nr, tim->dpb_output_delay, - vui->vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1); + hrd = &vui->vcl_hrd_parameters; } - if (pic_struct_present_flag) { + tim->CpbDpbDelaysPresentFlag = ! !hrd; + tim->pic_struct_present_flag = vui->pic_struct_present_flag; + + if (tim->CpbDpbDelaysPresentFlag) { + tim->cpb_removal_delay_length_minus1 = + hrd->cpb_removal_delay_length_minus1; + tim->dpb_output_delay_length_minus1 = hrd->dpb_output_delay_length_minus1; + + READ_UINT32 (nr, tim->cpb_removal_delay, + tim->cpb_removal_delay_length_minus1 + 1); + READ_UINT32 (nr, tim->dpb_output_delay, + tim->dpb_output_delay_length_minus1 + 1); + } + + if (tim->pic_struct_present_flag) { const guint8 num_clock_ts_table[9] = { 1, 1, 1, 2, 2, 3, 3, 2, 3 }; @@ -1011,19 +1004,23 @@ gst_h264_parser_parse_pic_timing (GstH264NalParser * nalparser, READ_UINT8 (nr, tim->pic_struct, 4); CHECK_ALLOWED ((gint8) tim->pic_struct, 0, 8); + tim->time_offset_length = 24; + if (hrd) + tim->time_offset_length = hrd->time_offset_length; + num_clock_num_ts = num_clock_ts_table[tim->pic_struct]; for (i = 0; i < num_clock_num_ts; i++) { READ_UINT8 (nr, tim->clock_timestamp_flag[i], 1); if (tim->clock_timestamp_flag[i]) { - if (!gst_h264_parse_clock_timestamp (&tim->clock_timestamp[i], vui, - nr)) + if (!gst_h264_parse_clock_timestamp (&tim->clock_timestamp[i], + tim->time_offset_length, nr)) goto error; } } } } - if (!CpbDpbDelaysPresentFlag && !pic_struct_present_flag) { + if (!tim->CpbDpbDelaysPresentFlag && !tim->pic_struct_present_flag) { GST_WARNING ("Invalid pic_timing SEI NAL with neither CpbDpbDelays nor pic_struct"); return GST_H264_PARSER_BROKEN_DATA; diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index 8ffcc45bb7..f86f21aa3d 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -955,12 +955,38 @@ struct _GstH264SliceHdr guint pic_order_cnt_bit_size; }; - +/** + * GstH264ClockTimestamp: + * @ct_type: indicates the scan type, 0: progressive, 1: interlaced, 2: unknown, + * 3: reserved + * @nuit_field_based_flag: used in calculating clockTimestamp + * @counting_type: specifies the method of dropping values of the n_frames + * @full_timestamp_flag: equal to 1 specifies that the n_frames syntax element + * is followed by seconds_value, minutes_value, and hours_value (Since 1.18) + * @discontinuity_flag: indicates whether the difference between the current + * value of clockTimestamp and the value of clockTimestamp computed from the + * previous clock timestamp can be interpreted as the time difference or not. + * @cnt_dropped_flag: specifies the skipping of one or more values of n_frames + * using the counting method specified by counting_type + * @n_frames: specifies the value of nFrames used to compute clockTimestamp + * @seconds_flag: equal to 1 specifies that @seconds_value and minutes_flag are + * present when @full_timestamp_flag is equal to 0 + * @seconds_value: specifies the value of seconds to compute clockTimestamp + * @minutes_flag: equal to 1 specifies that @minutes_value and hours_flag are + * present when @full_timestamp_flag is equal to 0 and @seconds_flag is + * equal to 1 + * @minutes_value: specifies the value of minutes to compute clockTimestamp + * @hours_flag: equal to 1 specifies that @hours_value is present when + * @full_timestamp_flag is equal to 0 and @seconds_flag is equal to 1 and + * @minutes_flag is equal to 1 + * @time_offset: specifies the value of tOffset used to compute clockTimestamp + */ struct _GstH264ClockTimestamp { guint8 ct_type; guint8 nuit_field_based_flag; guint8 counting_type; + guint8 full_timestamp_flag; guint8 discontinuity_flag; guint8 cnt_dropped_flag; guint8 n_frames; @@ -1017,8 +1043,36 @@ struct _GstH264StereoVideoInfo guint8 right_view_self_contained_flag; }; +/** + * GstH264PicTiming: + * @CpbDpbDelaysPresentFlag: non-zero if linked + * GstH264VUIParams::nal_hrd_parameters_present_flag or + * GstH264VUIParams::vcl_hrd_parameters_present_flag is non-zero (Since: 1.18) + * @cpb_removal_delay_length_minus1: specifies the length of @cpb_removal_delay + * in bits (Since 1.18) + * @dpb_output_delay_length_minus1: specifies the length of @dpb_output_delay + * in bits (Since 1.18) + * @cpb_removal_delay: specifies how many clock ticks to wait after removal from + * the CPB of the access unit associated with the most recent buffering period + * SEI message in a preceding access unit before removing from the + * buffer the access unit data associated with the picture timing SEI message + * @dpb_output_delay: used to compute the DPB output time of the picture + * @pic_struct_present_flag: GstH264VUIParams::pic_struct_present_flag + * @pic_struct: indicates whether a picture should be displayed as a frame or + * one or more fields + * @clock_timestamp_flag: equal to 1 indicates that a number of clock timestamp + * syntax elements are present + * @clock_timestamp: a #GstH264ClockTimestamp + * @time_offset_length: specifies the length time_offset of + * #GstH264ClockTimestamp in bits (Since 1.18) + */ struct _GstH264PicTiming { + /* from vui */ + guint8 CpbDpbDelaysPresentFlag; + /* if CpbDpbDelaysPresentFlag */ + guint8 cpb_removal_delay_length_minus1; + guint8 dpb_output_delay_length_minus1; guint32 cpb_removal_delay; guint32 dpb_output_delay; @@ -1028,6 +1082,7 @@ struct _GstH264PicTiming guint8 clock_timestamp_flag[3]; GstH264ClockTimestamp clock_timestamp[3]; + guint8 time_offset_length; }; /**