codecs: av1decoder: Add the highest_spatial_layer field.
authorHe Junyan <junyan.he@intel.com>
Thu, 12 May 2022 02:12:37 +0000 (10:12 +0800)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 16 Sep 2022 09:45:00 +0000 (09:45 +0000)
As SPEC says, when multi spatial layer exists, we should only output
one frame with the highest spatial id from each TU. We now store the
highest spatial layer information in the base class in order to let
the sub class handle different layers easily.

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

subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.h

index 4339e9427995ab623401905d3ba276c5b560dab1..7208821dfdb2eb8215607b7fafe1be0186bdd25e 100644 (file)
@@ -140,6 +140,8 @@ gst_av1_decoder_reset (GstAV1Decoder * self)
 {
   GstAV1DecoderPrivate *priv = self->priv;
 
+  self->highest_spatial_layer = 0;
+
   priv->max_width = 0;
   priv->max_height = 0;
   gst_clear_av1_picture (&priv->current_picture);
@@ -379,6 +381,13 @@ gst_av1_decoder_process_sequence (GstAV1Decoder * self, GstAV1OBU * obu)
     priv->preferred_output_delay = 0;
   }
 
+  if (priv->parser->state.operating_point_idc) {
+    self->highest_spatial_layer =
+        _floor_log2 (priv->parser->state.operating_point_idc >> 8);
+    GST_INFO_OBJECT (self, "set highest spatial layer to %d",
+        self->highest_spatial_layer);
+  }
+
   ret = klass->new_sequence (self, &seq_header,
       GST_AV1_TOTAL_REFS_PER_FRAME + priv->preferred_output_delay);
   if (ret != GST_FLOW_OK) {
@@ -475,6 +484,9 @@ gst_av1_decoder_decode_frame_header (GstAV1Decoder * self,
     picture->temporal_id = obu->header.obu_temporal_id;
     picture->spatial_id = obu->header.obu_spatial_id;
 
+    g_assert (picture->spatial_id <= self->highest_spatial_layer);
+    g_assert (self->highest_spatial_layer < GST_AV1_MAX_NUM_SPATIAL_LAYERS);
+
     if (!frame_header->show_frame && !frame_header->showable_frame)
       GST_VIDEO_CODEC_FRAME_FLAG_SET (priv->current_frame,
           GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
@@ -683,6 +695,15 @@ gst_av1_decoder_handle_frame (GstVideoDecoder * decoder,
     goto out;
   }
 
+  if (priv->current_picture->temporal_id > self->highest_spatial_layer) {
+    ret = GST_FLOW_ERROR;
+    GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
+        ("current picture temporal_id %d should not be higher than "
+            "highest spatial layer %d", priv->current_picture->temporal_id,
+            self->highest_spatial_layer), (NULL), ret);
+    goto out;
+  }
+
   if (!priv->current_picture->frame_hdr.show_existing_frame) {
     if (klass->end_picture) {
       ret = klass->end_picture (self, priv->current_picture);
@@ -704,9 +725,7 @@ out:
       /* Only output one frame with the highest spatial id from each TU
        * when there are multiple spatial layers.
        */
-      if (priv->parser->state.operating_point_idc &&
-          obu.header.obu_spatial_id <
-          _floor_log2 (priv->parser->state.operating_point_idc >> 8)) {
+      if (obu.header.obu_spatial_id < self->highest_spatial_layer) {
         gst_av1_picture_unref (priv->current_picture);
         gst_video_decoder_release_frame (decoder, frame);
       } else {
index faa760ecee10e5d956e38bde128ab52aca6c79b0..e249d54266439478c9922e0511d4421d487e58a1 100644 (file)
@@ -53,6 +53,7 @@ struct _GstAV1Decoder
 
   /*< protected >*/
   GstVideoCodecState * input_state;
+  guint highest_spatial_layer;
 
   /*< private >*/
   GstAV1DecoderPrivate *priv;