va: vp9dec: We need to check the resolution changes for every frame.

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>
This commit is contained in:
He Junyan 2021-07-14 22:36:52 +08:00 committed by Víctor Manuel Jáquez Leal
parent 458ac4a693
commit ff0e42eb30

View 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);