va: vp9dec: We need to check the resolution changes for every frame.
authorHe Junyan <junyan.he@intel.com>
Wed, 14 Jul 2021 14:36:52 +0000 (22:36 +0800)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Thu, 15 Jul 2021 09:42:51 +0000 (09:42 +0000)
The VP9 streams have the ability to change the resolution dynamically
at any time point. It does not send ad KEY frame before change the
resolution, even the INTER frame can change the resolution immediately.
So we need to check the resolution change for each frame and do the
re-negiotiation if needed.

Some insaned stream may play in resolution A first and then dynamically
changes to B, and after 1 or 2 frames, it use a show_existing_frame to
repeat the old frame of resolution A before. So, not only new_picture(),
but also duplicate_picture() need to check this.

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

sys/va/gstvavp9dec.c

index a66e764bfaf9a2455fa93af0cef61abf66a9ec94..606938f17fb67914f078cea2de931a5f08018195 100644 (file)
@@ -188,6 +188,27 @@ gst_va_vp9_new_sequence (GstVp9Decoder * decoder,
   return TRUE;
 }
 
+static gboolean
+_check_resolution_change (GstVaVp9Dec * self, GstVp9Picture * picture)
+{
+  GstVaBaseDec *base = GST_VA_BASE_DEC (self);
+  const GstVp9FrameHeader *frame_hdr = &picture->frame_hdr;
+
+  if ((base->width != frame_hdr->width) || base->height != frame_hdr->height) {
+    base->width = frame_hdr->width;
+    base->height = frame_hdr->height;
+
+    self->need_negotiation = TRUE;
+    if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+      GST_ERROR_OBJECT (self, "Resolution changes, but failed to"
+          " negotiate with downstream");
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
 static gboolean
 gst_va_vp9_dec_new_picture (GstVp9Decoder * decoder,
     GstVideoCodecFrame * frame, GstVp9Picture * picture)
@@ -198,6 +219,9 @@ gst_va_vp9_dec_new_picture (GstVp9Decoder * decoder,
   GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
 
+  if (!_check_resolution_change (self, picture))
+    return FALSE;
+
   ret = gst_video_decoder_allocate_output_frame (vdec, frame);
   if (ret != GST_FLOW_OK)
     goto error;
@@ -486,6 +510,9 @@ gst_va_vp9_dec_duplicate_picture (GstVp9Decoder * decoder,
   GstVaDecodePicture *va_pic, *va_dup;
   GstVp9Picture *new_picture;
 
+  if (!_check_resolution_change (GST_VA_VP9_DEC (decoder), picture))
+    return NULL;
+
   va_pic = gst_vp9_picture_get_user_data (picture);
   va_dup = gst_va_decode_picture_dup (va_pic);