msdkdec: Release occupied surface for MFX_ERR_MORE_DATA
authorHaihao Xiang <haihao.xiang@intel.com>
Sat, 2 Feb 2019 05:26:32 +0000 (13:26 +0800)
committerHaihao Xiang <haihao.xiang@intel.com>
Sun, 3 Feb 2019 05:44:56 +0000 (13:44 +0800)
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
sys/msdk/gstmsdkdec.h

index 9cc5e28..db58112 100644 (file)
@@ -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;
index 36f73e6..fc82415 100644 (file)
@@ -113,6 +113,8 @@ struct _MsdkDecTask
 {
   mfxFrameSurface1 *surface;
   mfxSyncPoint sync_point;
+
+  gboolean decode_only;
 };
 
 GType gst_msdkdec_get_type (void);