msdkdec: Check available surfaces when all pre-allocated surfaces are in use

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3439>
This commit is contained in:
Mengkejiergeli Ba 2022-08-23 14:20:35 +08:00 committed by Haihao Xiang
parent 3062f1b6b0
commit 799c6ff860

View file

@ -154,8 +154,9 @@ free_surface (GstMsdkSurface * s)
g_slice_free (GstMsdkSurface, s); g_slice_free (GstMsdkSurface, s);
} }
static void static gboolean
gst_msdkdec_free_unlocked_msdk_surfaces (GstMsdkDec * thiz) gst_msdkdec_free_unlocked_msdk_surfaces (GstMsdkDec * thiz,
gboolean check_avail_surface)
{ {
GList *l; GList *l;
GstMsdkSurface *surface; GstMsdkSurface *surface;
@ -163,13 +164,27 @@ gst_msdkdec_free_unlocked_msdk_surfaces (GstMsdkDec * thiz)
for (l = thiz->locked_msdk_surfaces; l;) { for (l = thiz->locked_msdk_surfaces; l;) {
GList *next = l->next; GList *next = l->next;
surface = l->data; surface = l->data;
if (surface->surface->Data.Locked == 0) { if (surface->surface->Data.Locked == 0 &&
GST_MINI_OBJECT_REFCOUNT_VALUE (surface->buf) == 1) {
free_surface (surface); free_surface (surface);
thiz->locked_msdk_surfaces = thiz->locked_msdk_surfaces =
g_list_delete_link (thiz->locked_msdk_surfaces, l); g_list_delete_link (thiz->locked_msdk_surfaces, l);
/* When check_avail_surface flag is enabled, it means we only
* need to find one available surface instead of releasing all
* the unlocked surfaces, so we can return TEUR here.
*/
if (check_avail_surface)
return TRUE;
} }
l = next; l = next;
} }
/* We need to check if all surfaces are in used */
if (g_list_length (thiz->locked_msdk_surfaces) ==
thiz->alloc_resp.NumFrameActual)
return FALSE;
else
return TRUE;
} }
static GstMsdkSurface * static GstMsdkSurface *
@ -181,10 +196,28 @@ allocate_output_surface (GstMsdkDec * thiz)
GstMemory *mem = NULL; GstMemory *mem = NULL;
mfxFrameSurface1 *mfx_surface = NULL; mfxFrameSurface1 *mfx_surface = NULL;
#endif #endif
gint n = 0;
guint retry_times = gst_util_uint64_scale_ceil (GST_USECOND,
thiz->param.mfx.FrameInfo.FrameRateExtD,
thiz->param.mfx.FrameInfo.FrameRateExtN);
/* Free un-unsed msdk surfaces firstly, hence the associated mfx /* Free un-unsed msdk surfaces firstly, hence the associated mfx
* surfaces will be moved from used list to available list */ * surfaces will be moved from used list to available list */
gst_msdkdec_free_unlocked_msdk_surfaces (thiz); if (!gst_msdkdec_free_unlocked_msdk_surfaces (thiz, FALSE)) {
while (n < retry_times) {
/* It is MediaSDK/oneVPL's requirement that only the pre-allocated
* surfaces can be used during the whole decoding process.
* In the case of decoder plus multi-encoders, it is possible
* that all surfaces are used by downstreams and no more surfaces
* available for decoder. So here we need to wait until there is at
* least one surface is free for decoder.
*/
n++;
g_usleep (1000);
if (gst_msdkdec_free_unlocked_msdk_surfaces (thiz, TRUE))
break;
}
}
#ifndef _WIN32 #ifndef _WIN32
if ((gst_buffer_pool_acquire_buffer (thiz->alloc_pool, &out_buffer, NULL)) if ((gst_buffer_pool_acquire_buffer (thiz->alloc_pool, &out_buffer, NULL))
!= GST_FLOW_OK) { != GST_FLOW_OK) {
@ -1126,7 +1159,7 @@ release_msdk_surfaces (GstMsdkDec * thiz)
GList *l; GList *l;
GstMsdkSurface *surface; GstMsdkSurface *surface;
gint locked = 0; gint locked = 0;
gst_msdkdec_free_unlocked_msdk_surfaces (thiz); gst_msdkdec_free_unlocked_msdk_surfaces (thiz, FALSE);
for (l = thiz->locked_msdk_surfaces; l; l = l->next) { for (l = thiz->locked_msdk_surfaces; l; l = l->next) {
surface = (GstMsdkSurface *) l->data; surface = (GstMsdkSurface *) l->data;