videoparsers: vp9: Need to process the first frame even not key.
authorHe Junyan <junyan.he@intel.com>
Fri, 23 Jul 2021 08:49:49 +0000 (16:49 +0800)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 23 Jul 2021 13:33:24 +0000 (13:33 +0000)
Some cut VP9 streams begin with a non key frame. The current code
just bail out the parse_process_frame() if not a key frame. Because
of this, we do not set the valid caps before we push the data of the
first frame(even this first frame will be discarded by the downstream
decoder because it is not a key frame).

The pipeline such as:
gst-launch-1.0 filesrc location=some.ivf ! ivfparse ! vp9parse !
  vavp9dec ! fakesink
will get a negotiation error and the pipeline can not continue. The
correct behaviour should be: the decoder discard the first frame and
continue to decode later frames successfully.

So, when the parse does not have valid stream info(should be the first
frame case), we should continue and report caps.

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

gst/videoparsers/gstvp9parse.c

index a8d2d1e..81b2879 100644 (file)
@@ -291,6 +291,24 @@ gst_vp9_parse_negotiate (GstVp9Parse * self, GstVp9ParseAligment in_align,
 }
 
 static gboolean
+gst_vp9_parse_is_info_valid (GstVp9Parse * self)
+{
+  if (self->width <= 0 || self->height <= 0)
+    return FALSE;
+
+  if (self->subsampling_x < 0 || self->subsampling_y < 0)
+    return FALSE;
+
+  if (self->profile == GST_VP9_PROFILE_UNDEFINED)
+    return FALSE;
+
+  if (self->bit_depth < (GstVp9BitDepth) GST_VP9_BIT_DEPTH_8)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
 gst_vp9_parse_process_frame (GstVp9Parse * self, GstVp9FrameHdr * frame_hdr)
 {
   GstVp9Parser *parser = self->parser;
@@ -299,7 +317,9 @@ gst_vp9_parse_process_frame (GstVp9Parse * self, GstVp9FrameHdr * frame_hdr)
   /* the resolution might be varying. Update our status per key frame */
   if (frame_hdr->frame_type != GST_VP9_KEY_FRAME ||
       frame_hdr->show_existing_frame) {
-    return TRUE;
+    /* Need to continue to get some valid info. */
+    if (gst_vp9_parse_is_info_valid (self))
+      return TRUE;
   }
 
   width = frame_hdr->width;