From 6c953438f5ad9ab78114bf3d9e5a6e9b1d913b80 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Sat, 2 Feb 2019 13:26:32 +0800 Subject: [PATCH] msdkdec: Release occupied surface for MFX_ERR_MORE_DATA An output surface is returned but without sync point when when MFXVideoDECODE_DecodeFrameAsync () returns MFX_ERR_MORE_DATA, this surface should be released too, otherwise the surface is occupied and it is easy to exhaust all pre-allocated mfx surfaces. Example pipeline (input_vp8.webm contains lots of frame with show_frame set to 0): gst-launch-1.0 filesrc location=input_vp8.webm ! matroskademux ! msdkvp8dec ! msdkvpp ! fakesink 0:00:05.995959693 19866 0x563f30f14590 ERROR default gstmsdkvideomemory.c:77:gst_msdk_video_allocator_get_surface: failed to get surface available ERROR: from element /GstPipeline:pipeline0/GstMatroskaDemux:matroskademux0: Internal data stream error. --- sys/msdk/gstmsdkdec.c | 14 ++++++++++++-- sys/msdk/gstmsdkdec.h | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sys/msdk/gstmsdkdec.c b/sys/msdk/gstmsdkdec.c index 9cc5e28..db58112 100644 --- a/sys/msdk/gstmsdkdec.c +++ b/sys/msdk/gstmsdkdec.c @@ -611,9 +611,12 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) GST_ERROR_OBJECT (thiz, "failed to do sync operation"); return GST_FLOW_ERROR; } + } + + if (G_LIKELY (task->sync_point || (task->surface && task->decode_only))) { + gboolean decode_only = task->decode_only; frame = gst_msdkdec_get_oldest_frame (decoder); - task->sync_point = NULL; l = g_list_find_custom (thiz->decoded_msdk_surfaces, task->surface, _find_msdk_surface); @@ -634,11 +637,16 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) } free_surface (thiz, surface); + task->sync_point = NULL; + task->surface = NULL; + task->decode_only = FALSE; if (!frame) return GST_FLOW_FLUSHING; gst_video_codec_frame_unref (frame); + if (decode_only) + GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); flow = gst_video_decoder_finish_frame (decoder, frame); return flow; } @@ -1017,9 +1025,11 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) break; } } else if (status == MFX_ERR_MORE_DATA) { + task->decode_only = TRUE; + thiz->next_task = (thiz->next_task + 1) % thiz->tasks->len; if (surface->surface->Data.Locked > 0) surface = NULL; - flow = GST_FLOW_OK; + flow = GST_VIDEO_DECODER_FLOW_NEED_DATA; break; } else if (status == MFX_ERR_MORE_SURFACE) { surface = NULL; diff --git a/sys/msdk/gstmsdkdec.h b/sys/msdk/gstmsdkdec.h index 36f73e6..fc82415 100644 --- a/sys/msdk/gstmsdkdec.h +++ b/sys/msdk/gstmsdkdec.h @@ -113,6 +113,8 @@ struct _MsdkDecTask { mfxFrameSurface1 *surface; mfxSyncPoint sync_point; + + gboolean decode_only; }; GType gst_msdkdec_get_type (void); -- 2.7.4