msdkdec: postpone surface free for VC1

For a skipped frame in VC1, MSDK returns the mfx surface of the reference
frame, so we have to make sure the corresponding surface for the
reference frame is not freed. In this fix, we postpone surface free because
we don't know whether a surface is referenced

Before this fix, the error is like as below:

New clock: GstSystemClock
0:00:00.181793130 23098 0x55f8a9d622d0 ERROR                msdkdec
gstmsdkdec.c:622:gst_msdkdec_finish_task:<msdkvc1dec0> Couldn't find the
cached MSDK surface

Sample pipeline:
gst-launch-1.0 filesrc location=input_has_skipped_frame.wmv ! asfdemux !
vc1parse ! msdkvc1dec ! glimagesink
This commit is contained in:
Haihao Xiang 2019-07-02 15:21:24 +08:00 committed by Víctor Manuel Jáquez Leal
parent c689c94458
commit f840e304f3
3 changed files with 26 additions and 1 deletions

View file

@ -589,6 +589,22 @@ _find_msdk_surface (gconstpointer msdk_surface, gconstpointer comp_surface)
return cached_surface ? cached_surface->surface != _surface : -1;
}
static void
gst_msdkdec_free_unlocked_msdk_surfaces (GstMsdkDec * thiz,
MsdkSurface * curr_surface)
{
GList *l;
MsdkSurface *surface;
for (l = thiz->decoded_msdk_surfaces; l;) {
surface = l->data;
l = l->next;
if (surface != curr_surface && surface->surface->Data.Locked == 0)
free_surface (thiz, surface);
}
}
static GstFlowReturn
gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task)
{
@ -632,7 +648,8 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task)
}
}
free_surface (thiz, surface);
if (!thiz->postpone_free_surface)
free_surface (thiz, surface);
task->sync_point = NULL;
task->surface = NULL;
task->decode_only = FALSE;
@ -995,6 +1012,8 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
}
for (;;) {
if (thiz->postpone_free_surface)
gst_msdkdec_free_unlocked_msdk_surfaces (thiz, surface);
task = &g_array_index (thiz->tasks, MsdkDecTask, thiz->next_task);
flow = gst_msdkdec_finish_task (thiz, task);
if (flow != GST_FLOW_OK)
@ -1376,6 +1395,8 @@ gst_msdkdec_drain (GstVideoDecoder * decoder)
session = gst_msdk_context_get_session (thiz->context);
for (;;) {
if (thiz->postpone_free_surface)
gst_msdkdec_free_unlocked_msdk_surfaces (thiz, surface);
task = &g_array_index (thiz->tasks, MsdkDecTask, thiz->next_task);
if ((flow = gst_msdkdec_finish_task (thiz, task)) != GST_FLOW_OK) {
if (flow != GST_FLOW_FLUSHING)
@ -1599,5 +1620,6 @@ gst_msdkdec_init (GstMsdkDec * thiz)
thiz->do_renego = TRUE;
thiz->do_realloc = TRUE;
thiz->force_reset_on_res_change = TRUE;
thiz->postpone_free_surface = FALSE;
thiz->adapter = gst_adapter_new ();
}

View file

@ -86,6 +86,8 @@ struct _GstMsdkDec
* include downstream requirement, msdk suggestion and extra
* surface allocation for smooth display in render pipeline */
guint min_prealloc_buffers;
/* postpone surface free */
gboolean postpone_free_surface;
/* MFX context */
GstMsdkContext *context;

View file

@ -82,6 +82,7 @@ gst_msdkvc1dec_configure (GstMsdkDec * decoder)
if (!structure)
return FALSE;
decoder->postpone_free_surface = TRUE;
decoder->param.mfx.CodecId = MFX_CODEC_VC1;
profile_str = gst_structure_get_string (structure, "profile");