h264parser: Make GstH264PicTiming self-containing all the syntax information
authorSeungha Yang <seungha@centricular.com>
Tue, 7 Apr 2020 10:32:29 +0000 (19:32 +0900)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 8 Apr 2020 15:39:12 +0000 (15:39 +0000)
... and store all parsed values.

We are storing pic_struct_present_flag although it's not part of
this SEI message but GstH264PicTiming includes it to clarify
following syntax values.
In addition to that, by adding CpbDpbDelaysPresentFlag, we don't need to
refer to VUI anymore.

gst-libs/gst/codecparsers/gsth264parser.c
gst-libs/gst/codecparsers/gsth264parser.h

index d488148..83eca65 100644 (file)
@@ -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) {
+      hrd = &vui->vcl_hrd_parameters;
+    }
+
+    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,
-          vui->vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1);
+          tim->cpb_removal_delay_length_minus1 + 1);
       READ_UINT32 (nr, tim->dpb_output_delay,
-          vui->vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1);
+          tim->dpb_output_delay_length_minus1 + 1);
     }
 
-    if (pic_struct_present_flag) {
+    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;
index 8ffcc45..f86f21a 100644 (file)
@@ -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;
 };
 
 /**