h265decoder: Drain decoder on new_sequence()
authorSeungha Yang <seungha@centricular.com>
Fri, 11 Mar 2022 19:45:22 +0000 (04:45 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 15 Mar 2022 21:08:06 +0000 (21:08 +0000)
Holding previously decoded but not outputted pictures even after
new_sequence is not a safe approach in various aspect.
However, we cannot drain out DPB on new_sequence() unconditionally,
because there is a case where decoder should drop decoded pictures
if NoOutputOfPriorPicsFlag is set.

To detect NoOutputOfPriorPicsFlag before the new_sequence() call,
this patch splits decoding process into two path, one for nal unit parsing
in order to detect NoOutputOfPriorPicsFlag and then each nal unit
will be decoded.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1937>

subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265decoder.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265picture.h

index d37d59f..f04df38 100644 (file)
@@ -82,6 +82,8 @@ struct _GstH265DecoderPrivate
   guint8 cur_source_scan_type;
   guint8 cur_duplicate_flag;
 
+  gboolean no_output_of_prior_pics_flag;
+
   /* vps/sps/pps of the current slice */
   const GstH265VPS *active_vps;
   const GstH265SPS *active_sps;
@@ -123,8 +125,20 @@ struct _GstH265DecoderPrivate
   GArray *ref_pic_list_tmp;
   GArray *ref_pic_list0;
   GArray *ref_pic_list1;
+
+  GArray *nalu;
 };
 
+typedef struct
+{
+  union
+  {
+    GstH265SPS sps;
+    GstH265Slice slice;
+  } unit;
+  gboolean is_slice;
+} GstH265DecoderNalUnit;
+
 #define UPDATE_FLOW_RETURN(ret,new_ret) G_STMT_START { \
   if (*(ret) == GST_FLOW_OK) \
     *(ret) = new_ret; \
@@ -156,6 +170,7 @@ static void gst_h265_decoder_clear_dpb (GstH265Decoder * self, gboolean flush);
 static GstFlowReturn gst_h265_decoder_drain_internal (GstH265Decoder * self);
 static GstFlowReturn
 gst_h265_decoder_start_current_picture (GstH265Decoder * self);
+static void gst_h265_decoder_clear_nalu (GstH265DecoderNalUnit * nalu);
 
 static void
 gst_h265_decoder_class_init (GstH265DecoderClass * klass)
@@ -192,6 +207,10 @@ gst_h265_decoder_init (GstH265Decoder * self)
       sizeof (GstH265Picture *), 32);
   priv->ref_pic_list1 = g_array_sized_new (FALSE, TRUE,
       sizeof (GstH265Picture *), 32);
+  priv->nalu = g_array_sized_new (FALSE, TRUE, sizeof (GstH265DecoderNalUnit),
+      8);
+  g_array_set_clear_func (priv->nalu,
+      (GDestroyNotify) gst_h265_decoder_clear_nalu);
 }
 
 static void
@@ -203,6 +222,7 @@ gst_h265_decoder_finalize (GObject * object)
   g_array_unref (priv->ref_pic_list_tmp);
   g_array_unref (priv->ref_pic_list0);
   g_array_unref (priv->ref_pic_list1);
+  g_array_unref (priv->nalu);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -249,24 +269,6 @@ gst_h265_decoder_stop (GstVideoDecoder * decoder)
   return TRUE;
 }
 
-static GstFlowReturn
-gst_h265_decoder_parse_vps (GstH265Decoder * self, GstH265NalUnit * nalu)
-{
-  GstH265DecoderPrivate *priv = self->priv;
-  GstH265VPS vps;
-  GstH265ParserResult pres;
-
-  pres = gst_h265_parser_parse_vps (priv->parser, nalu, &vps);
-  if (pres != GST_H265_PARSER_OK) {
-    GST_WARNING_OBJECT (self, "Failed to parse VPS, result %d", pres);
-    return GST_FLOW_ERROR;
-  }
-
-  GST_LOG_OBJECT (self, "VPS parsed");
-
-  return GST_FLOW_OK;
-}
-
 static gboolean
 gst_h265_decoder_is_crop_rect_changed (GstH265Decoder * self, GstH265SPS * sps)
 {
@@ -340,6 +342,14 @@ gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
 
     g_assert (klass->new_sequence);
 
+    if (priv->no_output_of_prior_pics_flag) {
+      gst_h265_decoder_clear_dpb (self, FALSE);
+    } else {
+      ret = gst_h265_decoder_drain_internal (self);
+      if (ret != GST_FLOW_OK)
+        return ret;
+    }
+
     ret = klass->new_sequence (self, sps, max_dpb_size);
     if (ret != GST_FLOW_OK) {
       GST_WARNING_OBJECT (self, "subclass does not want accept new sequence");
@@ -371,53 +381,7 @@ gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
   return GST_FLOW_OK;
 }
 
-static GstFlowReturn
-gst_h265_decoder_parse_sps (GstH265Decoder * self, GstH265NalUnit * nalu)
-{
-  GstH265DecoderPrivate *priv = self->priv;
-  GstH265SPS sps;
-  GstH265ParserResult pres;
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  pres = gst_h265_parse_sps (priv->parser, nalu, &sps, TRUE);
-  if (pres != GST_H265_PARSER_OK) {
-    GST_WARNING_OBJECT (self, "Failed to parse SPS, result %d", pres);
-    return GST_FLOW_ERROR;
-  }
-
-  GST_LOG_OBJECT (self, "SPS parsed");
-
-  ret = gst_h265_decoder_process_sps (self, &sps);
-  if (ret != GST_FLOW_OK) {
-    GST_WARNING_OBJECT (self, "Failed to process SPS");
-  } else if (gst_h265_parser_update_sps (priv->parser,
-          &sps) != GST_H265_PARSER_OK) {
-    GST_WARNING_OBJECT (self, "Failed to update SPS");
-    ret = GST_FLOW_ERROR;
-  }
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_h265_decoder_parse_pps (GstH265Decoder * self, GstH265NalUnit * nalu)
-{
-  GstH265DecoderPrivate *priv = self->priv;
-  GstH265PPS pps;
-  GstH265ParserResult pres;
-
-  pres = gst_h265_parser_parse_pps (priv->parser, nalu, &pps);
-  if (pres != GST_H265_PARSER_OK) {
-    GST_WARNING_OBJECT (self, "Failed to parse PPS, result %d", pres);
-    return GST_FLOW_ERROR;
-  }
-
-  GST_LOG_OBJECT (self, "PPS parsed");
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
+static GstH265ParserResult
 gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
 {
   GstH265DecoderPrivate *priv = self->priv;
@@ -432,7 +396,7 @@ gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
     /* XXX: Ignore error from SEI parsing, it might be malformed bitstream,
      * or our fault. But shouldn't be critical  */
     g_clear_pointer (&messages, g_array_unref);
-    return GST_FLOW_OK;
+    return GST_H265_PARSER_OK;
   }
 
   for (i = 0; i < messages->len; i++) {
@@ -457,7 +421,7 @@ gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
   g_array_free (messages, TRUE);
   GST_LOG_OBJECT (self, "SEI parsed");
 
-  return GST_FLOW_OK;
+  return GST_H265_PARSER_OK;
 }
 
 static void
@@ -631,31 +595,12 @@ gst_h265_decoder_preprocess_slice (GstH265Decoder * self, GstH265Slice * slice)
 }
 
 static GstFlowReturn
-gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
+gst_h265_decoder_process_slice (GstH265Decoder * self, GstH265Slice * slice)
 {
   GstH265DecoderPrivate *priv = self->priv;
-  GstH265ParserResult pres = GST_H265_PARSER_OK;
   GstFlowReturn ret = GST_FLOW_OK;
 
-  memset (&priv->current_slice, 0, sizeof (GstH265Slice));
-
-  pres = gst_h265_parser_parse_slice_hdr (priv->parser, nalu,
-      &priv->current_slice.header);
-
-  if (pres != GST_H265_PARSER_OK) {
-    GST_ERROR_OBJECT (self, "Failed to parse slice header, ret %d", pres);
-    memset (&priv->current_slice, 0, sizeof (GstH265Slice));
-
-    return GST_FLOW_ERROR;
-  }
-
-  /* NOTE: gst_h265_parser_parse_slice_hdr() allocates array
-   * GstH265SliceHdr::entry_point_offset_minus1 but we don't use it
-   * in this h265decoder baseclass at the moment
-   */
-  gst_h265_slice_hdr_free (&priv->current_slice.header);
-
-  priv->current_slice.nalu = *nalu;
+  priv->current_slice = *slice;
 
   if (priv->current_slice.header.dependent_slice_segment_flag) {
     GstH265SliceHdr *slice_hdr = &priv->current_slice.header;
@@ -713,24 +658,99 @@ gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
   return gst_h265_decoder_decode_slice (self);
 }
 
-static GstFlowReturn
-gst_h265_decoder_decode_nal (GstH265Decoder * self, GstH265NalUnit * nalu)
+static GstH265ParserResult
+gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
 {
   GstH265DecoderPrivate *priv = self->priv;
-  GstFlowReturn ret = GST_FLOW_OK;
+  GstH265ParserResult pres;
+  GstH265Slice slice;
+  GstH265DecoderNalUnit decoder_nalu;
+
+  memset (&slice, 0, sizeof (GstH265Slice));
+
+  pres = gst_h265_parser_parse_slice_hdr (priv->parser, nalu, &slice.header);
+  if (pres != GST_H265_PARSER_OK)
+    return pres;
+
+  /* NOTE: gst_h265_parser_parse_slice_hdr() allocates array
+   * GstH265SliceHdr::entry_point_offset_minus1 but we don't use it
+   * in this h265decoder baseclass at the moment
+   */
+  gst_h265_slice_hdr_free (&priv->current_slice.header);
+  slice.nalu = *nalu;
+
+  if (nalu->type >= GST_H265_NAL_SLICE_BLA_W_LP &&
+      nalu->type <= GST_H265_NAL_SLICE_CRA_NUT) {
+    slice.rap_pic_flag = TRUE;
+  }
+
+  /* NoRaslOutputFlag == 1 if the current picture is
+   * 1) an IDR picture
+   * 2) a BLA picture
+   * 3) a CRA picture that is the first access unit in the bitstream
+   * 4) first picture that follows an end of sequence NAL unit in decoding order
+   * 5) has HandleCraAsBlaFlag == 1 (set by external means, so not considering )
+   */
+  if (GST_H265_IS_NAL_TYPE_IDR (nalu->type) ||
+      GST_H265_IS_NAL_TYPE_BLA (nalu->type) ||
+      (GST_H265_IS_NAL_TYPE_CRA (nalu->type) && priv->new_bitstream) ||
+      priv->prev_nal_is_eos) {
+    slice.no_rasl_output_flag = TRUE;
+  }
+
+  if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type)) {
+    slice.intra_pic_flag = TRUE;
+
+    if (slice.no_rasl_output_flag && !priv->new_bitstream) {
+      /* C 3.2 */
+      slice.clear_dpb = TRUE;
+      if (nalu->type == GST_H265_NAL_SLICE_CRA_NUT) {
+        slice.no_output_of_prior_pics_flag = TRUE;
+      } else {
+        slice.no_output_of_prior_pics_flag =
+            slice.header.no_output_of_prior_pics_flag;
+      }
+    }
+  }
+
+  if (slice.no_output_of_prior_pics_flag)
+    priv->no_output_of_prior_pics_flag = TRUE;
+
+  decoder_nalu.unit.slice = slice;
+  decoder_nalu.is_slice = TRUE;
+  g_array_append_val (priv->nalu, decoder_nalu);
+
+  return GST_H265_PARSER_OK;
+}
+
+static GstH265ParserResult
+gst_h265_decoder_parse_nalu (GstH265Decoder * self, GstH265NalUnit * nalu)
+{
+  GstH265DecoderPrivate *priv = self->priv;
+  GstH265VPS vps;
+  GstH265SPS sps;
+  GstH265PPS pps;
+  GstH265ParserResult ret = GST_H265_PARSER_OK;
+  GstH265DecoderNalUnit decoder_nalu;
 
   GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d",
       nalu->type, nalu->offset, nalu->size);
 
   switch (nalu->type) {
     case GST_H265_NAL_VPS:
-      ret = gst_h265_decoder_parse_vps (self, nalu);
+      ret = gst_h265_parser_parse_vps (priv->parser, nalu, &vps);
       break;
     case GST_H265_NAL_SPS:
-      ret = gst_h265_decoder_parse_sps (self, nalu);
+      ret = gst_h265_parser_parse_sps (priv->parser, nalu, &sps, TRUE);
+      if (ret != GST_H265_PARSER_OK)
+        break;
+
+      memset (&decoder_nalu, 0, sizeof (GstH265DecoderNalUnit));
+      decoder_nalu.unit.sps = sps;
+      g_array_append_val (priv->nalu, decoder_nalu);
       break;
     case GST_H265_NAL_PPS:
-      ret = gst_h265_decoder_parse_pps (self, nalu);
+      ret = gst_h265_parser_parse_pps (priv->parser, nalu, &pps);
       break;
     case GST_H265_NAL_PREFIX_SEI:
     case GST_H265_NAL_SUFFIX_SEI:
@@ -769,6 +789,16 @@ gst_h265_decoder_decode_nal (GstH265Decoder * self, GstH265NalUnit * nalu)
   return ret;
 }
 
+static GstFlowReturn
+gst_h265_decoder_decode_nalu (GstH265Decoder * self,
+    GstH265DecoderNalUnit * nalu)
+{
+  if (!nalu->is_slice)
+    return gst_h265_decoder_process_sps (self, &nalu->unit.sps);
+
+  return gst_h265_decoder_process_slice (self, &nalu->unit.slice);
+}
+
 static void
 gst_h265_decoder_format_from_caps (GstH265Decoder * self, GstCaps * caps,
     GstH265DecoderFormat * format, GstH265DecoderAlign * align)
@@ -823,6 +853,9 @@ gst_h265_decoder_parse_codec_data (GstH265Decoder * self, const guint8 * data,
   GstH265ParserResult pres;
   GstH265NalUnit nalu;
   GstFlowReturn ret = GST_FLOW_OK;
+  GstH265VPS vps;
+  GstH265SPS sps;
+  GstH265PPS pps;
 
   /* parse the hvcC data */
   if (size < 23) {
@@ -860,24 +893,30 @@ gst_h265_decoder_parse_codec_data (GstH265Decoder * self, const guint8 * data,
 
       switch (nalu.type) {
         case GST_H265_NAL_VPS:
-          ret = gst_h265_decoder_parse_vps (self, &nalu);
-          if (ret != GST_FLOW_OK) {
+          pres = gst_h265_parser_parse_vps (priv->parser, &nalu, &vps);
+          if (pres != GST_H265_PARSER_OK) {
             GST_WARNING_OBJECT (self, "Failed to parse VPS");
-            return ret;
+            return GST_FLOW_ERROR;
           }
           break;
         case GST_H265_NAL_SPS:
-          ret = gst_h265_decoder_parse_sps (self, &nalu);
-          if (ret != GST_FLOW_OK) {
+          pres = gst_h265_parser_parse_sps (priv->parser, &nalu, &sps, TRUE);
+          if (pres != GST_H265_PARSER_OK) {
             GST_WARNING_OBJECT (self, "Failed to parse SPS");
+            return GST_FLOW_ERROR;
+          }
+
+          ret = gst_h265_decoder_process_sps (self, &sps);
+          if (ret != GST_FLOW_OK) {
+            GST_WARNING_OBJECT (self, "Failed to process SPS");
             return ret;
           }
           break;
         case GST_H265_NAL_PPS:
-          ret = gst_h265_decoder_parse_pps (self, &nalu);
-          if (ret != GST_FLOW_OK) {
+          pres = gst_h265_parser_parse_pps (priv->parser, &nalu, &pps);
+          if (pres != GST_H265_PARSER_OK) {
             GST_WARNING_OBJECT (self, "Failed to parse PPS");
-            return ret;
+            return GST_FLOW_ERROR;
           }
           break;
         default:
@@ -1010,26 +1049,11 @@ gst_h265_decoder_fill_picture_from_slice (GstH265Decoder * self,
   const GstH265SliceHdr *slice_hdr = &slice->header;
   const GstH265NalUnit *nalu = &slice->nalu;
 
-  if (nalu->type >= GST_H265_NAL_SLICE_BLA_W_LP &&
-      nalu->type <= GST_H265_NAL_SLICE_CRA_NUT)
-    picture->RapPicFlag = TRUE;
-
-  /* NoRaslOutputFlag == 1 if the current picture is
-   * 1) an IDR picture
-   * 2) a BLA picture
-   * 3) a CRA picture that is the first access unit in the bitstream
-   * 4) first picture that follows an end of sequence NAL unit in decoding order
-   * 5) has HandleCraAsBlaFlag == 1 (set by external means, so not considering )
-   */
-  if (GST_H265_IS_NAL_TYPE_IDR (nalu->type) ||
-      GST_H265_IS_NAL_TYPE_BLA (nalu->type) ||
-      (GST_H265_IS_NAL_TYPE_CRA (nalu->type) && priv->new_bitstream) ||
-      priv->prev_nal_is_eos) {
-    picture->NoRaslOutputFlag = TRUE;
-  }
-
-  if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type)) {
-    picture->IntraPicFlag = TRUE;
+  picture->RapPicFlag = slice->rap_pic_flag;
+  picture->NoRaslOutputFlag = slice->no_rasl_output_flag;
+  picture->IntraPicFlag = slice->intra_pic_flag;
+  picture->NoOutputOfPriorPicsFlag = slice->no_output_of_prior_pics_flag;
+  if (picture->IntraPicFlag) {
     priv->associated_irap_NoRaslOutputFlag = picture->NoRaslOutputFlag;
   }
 
@@ -1555,21 +1579,12 @@ gst_h265_decoder_dpb_init (GstH265Decoder * self, const GstH265Slice * slice,
     GstH265Picture * picture)
 {
   GstH265DecoderPrivate *priv = self->priv;
-  const GstH265SliceHdr *slice_hdr = &slice->header;
-  const GstH265NalUnit *nalu = &slice->nalu;
   const GstH265SPS *sps = priv->active_sps;
   GstH265Picture *to_output;
   GstFlowReturn ret = GST_FLOW_OK;
 
   /* C 3.2 */
-  if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type) && picture->NoRaslOutputFlag
-      && !priv->new_bitstream) {
-    if (nalu->type == GST_H265_NAL_SLICE_CRA_NUT)
-      picture->NoOutputOfPriorPicsFlag = TRUE;
-    else
-      picture->NoOutputOfPriorPicsFlag =
-          slice_hdr->no_output_of_prior_pics_flag;
-
+  if (slice->clear_dpb) {
     if (picture->NoOutputOfPriorPicsFlag) {
       GST_DEBUG_OBJECT (self, "Clear dpb");
       gst_h265_decoder_clear_dpb (self, FALSE);
@@ -1742,6 +1757,9 @@ gst_h265_decoder_reset_frame_state (GstH265Decoder * self)
   priv->cur_pic_struct = GST_H265_SEI_PIC_STRUCT_FRAME;
   priv->cur_source_scan_type = 2;
   priv->cur_duplicate_flag = 0;
+  priv->no_output_of_prior_pics_flag = FALSE;
+  priv->current_frame = NULL;
+  g_array_set_size (priv->nalu, 0);
 }
 
 static GstFlowReturn
@@ -1755,16 +1773,17 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
   GstH265ParserResult pres;
   GstMapInfo map;
   GstFlowReturn decode_ret = GST_FLOW_OK;
+  guint i;
 
   GST_LOG_OBJECT (self,
       "handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
       GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
 
-  priv->current_frame = frame;
-
   gst_h265_decoder_reset_frame_state (self);
 
+  priv->current_frame = frame;
+
   if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
     GST_ELEMENT_ERROR (self, RESOURCE, READ,
         ("Failed to map memory for reading"), (NULL));
@@ -1776,8 +1795,10 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
     pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
         map.data, 0, map.size, priv->nal_length_size, &nalu);
 
-    while (pres == GST_H265_PARSER_OK && decode_ret == GST_FLOW_OK) {
-      decode_ret = gst_h265_decoder_decode_nal (self, &nalu);
+    while (pres == GST_H265_PARSER_OK) {
+      pres = gst_h265_decoder_parse_nalu (self, &nalu);
+      if (pres != GST_H265_PARSER_OK)
+        break;
 
       pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
           map.data, nalu.offset + nalu.size, map.size, priv->nal_length_size,
@@ -1790,19 +1811,26 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
     if (pres == GST_H265_PARSER_NO_NAL_END)
       pres = GST_H265_PARSER_OK;
 
-    while (pres == GST_H265_PARSER_OK && decode_ret == GST_FLOW_OK) {
-      decode_ret = gst_h265_decoder_decode_nal (self, &nalu);
+    while (pres == GST_H265_PARSER_OK) {
+      pres = gst_h265_decoder_parse_nalu (self, &nalu);
+      if (pres != GST_H265_PARSER_OK)
+        break;
 
       pres = gst_h265_parser_identify_nalu (priv->parser,
           map.data, nalu.offset + nalu.size, map.size, &nalu);
-
       if (pres == GST_H265_PARSER_NO_NAL_END)
         pres = GST_H265_PARSER_OK;
     }
   }
 
+  for (i = 0; i < priv->nalu->len && decode_ret == GST_FLOW_OK; i++) {
+    GstH265DecoderNalUnit *decoder_nalu =
+        &g_array_index (priv->nalu, GstH265DecoderNalUnit, i);
+    decode_ret = gst_h265_decoder_decode_nalu (self, decoder_nalu);
+  }
+
   gst_buffer_unmap (in_buf, &map);
-  priv->current_frame = NULL;
+  gst_h265_decoder_reset_frame_state (self);
 
   if (decode_ret != GST_FLOW_OK) {
     if (decode_ret == GST_FLOW_ERROR) {
@@ -1832,6 +1860,15 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
   return decode_ret;
 }
 
+static void
+gst_h265_decoder_clear_nalu (GstH265DecoderNalUnit * nalu)
+{
+  if (!nalu)
+    return;
+
+  memset (nalu, 0, sizeof (GstH265DecoderNalUnit));
+}
+
 /**
  * gst_h265_decoder_set_process_ref_pic_lists:
  * @decoder: a #GstH265Decoder
index 524354c..a96a162 100644 (file)
@@ -48,6 +48,13 @@ struct _GstH265Slice
 
   /* parsed nal unit (doesn't take ownership of raw data) */
   GstH265NalUnit nalu;
+
+  /*< private >*/
+  gboolean rap_pic_flag;
+  gboolean no_rasl_output_flag;
+  gboolean no_output_of_prior_pics_flag;
+  gboolean clear_dpb;
+  gboolean intra_pic_flag;
 };
 
 struct _GstH265Picture