codecs: vp9decoder: Allow decoding start with intra-only frame
authorSeungha Yang <seungha@centricular.com>
Tue, 30 Mar 2021 08:24:38 +0000 (17:24 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 7 Apr 2021 19:32:29 +0000 (19:32 +0000)
As per spec "7.2 Uncompressed header semantics" and
"8.2 Frame order constraints", decoding can start with intra-only
frame. This commit is for fixing vp90-2-16-intra-only.webm
bitstream test failure.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2112>

gst-libs/gst/codecs/gstvp9decoder.c

index e5e3959..94f4aea 100644 (file)
@@ -270,6 +270,8 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
   GstVp9ParserResult pres;
   GstMapInfo map;
   GstFlowReturn ret = GST_FLOW_OK;
+  gboolean intra_only = FALSE;
+  gboolean check_codec_change = FALSE;
 
   GST_LOG_OBJECT (self, "handle frame %" GST_PTR_FORMAT, in_buf);
 
@@ -286,8 +288,25 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
     goto unmap_and_error;
   }
 
-  if (priv->wait_keyframe && (frame_hdr.frame_type != GST_VP9_KEY_FRAME
-          || frame_hdr.show_existing_frame)) {
+  if (frame_hdr.show_existing_frame) {
+    /* This is a non-intra, dummy frame */
+    intra_only = FALSE;
+  } else if (frame_hdr.frame_type == GST_VP9_KEY_FRAME || frame_hdr.intra_only) {
+    intra_only = TRUE;
+  }
+
+  if (intra_only) {
+    if (frame_hdr.frame_type == GST_VP9_KEY_FRAME) {
+      /* Always check codec change per keyframe */
+      check_codec_change = TRUE;
+    } else if (priv->wait_keyframe) {
+      /* Or, if we are waiting for leading keyframe, but this is intra-only,
+       * try decoding this frame, it's allowed as per spec */
+      check_codec_change = TRUE;
+    }
+  }
+
+  if (priv->wait_keyframe && !intra_only) {
     GST_DEBUG_OBJECT (self, "Drop frame before initial keyframe");
     gst_buffer_unmap (in_buf, &map);
 
@@ -296,8 +315,7 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
     return GST_FLOW_OK;
   }
 
-  if (frame_hdr.frame_type == GST_VP9_KEY_FRAME &&
-      !frame_hdr.show_existing_frame &&
+  if (check_codec_change &&
       !gst_vp9_decoder_check_codec_change (self, &frame_hdr)) {
     GST_ERROR_OBJECT (self, "codec change error");
     goto unmap_and_error;