[vlc-commits] [Git][videolan/vlc][master] avcodec: vaapi: handle the hw_frames_ctx initialization by VLC
Thomas Guillem (@tguillem)
gitlab at videolan.org
Mon Dec 6 08:24:17 UTC 2021
Thomas Guillem pushed to branch master at VideoLAN / VLC
Commits:
07ed2871 by Thomas Guillem at 2021-12-06T08:03:51+00:00
avcodec: vaapi: handle the hw_frames_ctx initialization by VLC
It's not allowed to modify ctx->hw_device_ctx after avcodec_open2().
Therefore, we need to create the hw_frames_ctx ourselves from it, and from
the get_format() callback. It can be easily done with the
avcodec_get_hw_frames_parameters() helper.
The surface frame count is now known from the Create() function,
therefore, the semaphore can be directly initialized, removing the need
for the pool_sem_init dirty hack.
- - - - -
1 changed file:
- modules/codec/avcodec/vaapi.c
Changes:
=====================================
modules/codec/avcodec/vaapi.c
=====================================
@@ -53,8 +53,7 @@
struct vaapi_vctx
{
VADisplay va_dpy;
- AVBufferRef *hwdev_ref;
- bool pool_sem_init;
+ AVBufferRef *hwframes_ref;
vlc_sem_t pool_sem;
};
@@ -139,8 +138,6 @@ static void vaapi_dec_pic_context_destroy(picture_context_t *context)
struct vaapi_vctx *vaapi_vctx =
vlc_video_context_GetPrivate(pic_ctx->ctx.s.vctx, VLC_VIDEO_CONTEXT_VAAPI);
- assert(vaapi_vctx->pool_sem_init);
-
av_frame_free(&pic_ctx->avframe);
if (!pic_ctx->cloned)
@@ -173,24 +170,9 @@ static picture_context_t *vaapi_dec_pic_context_copy(picture_context_t *src)
static int Get(vlc_va_t *va, picture_t *pic, AVCodecContext *ctx, AVFrame *frame)
{
vlc_video_context *vctx = va->sys;
- AVHWFramesContext *hwframes = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
struct vaapi_vctx *vaapi_vctx =
vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_VAAPI);
- assert(ctx->hw_frames_ctx);
-
- /* The pool size can only be known after the hw context has been
- * initialized (internally by ffmpeg), so between Create() and the first
- * Get() */
- if (!vaapi_vctx->pool_sem_init)
- {
- vlc_sem_init(&vaapi_vctx->pool_sem,
- hwframes->initial_pool_size +
- ctx->thread_count +
- 3 /* cf. ff_decode_get_hw_frames_ctx */);
- vaapi_vctx->pool_sem_init = true;
- }
-
/* If all frames are out, wait for a frame to be released. */
vlc_sem_wait(&vaapi_vctx->pool_sem);
@@ -231,7 +213,7 @@ static void vaapi_ctx_destroy(void *priv)
{
struct vaapi_vctx *vaapi_vctx = priv;
- av_buffer_unref(&vaapi_vctx->hwdev_ref);
+ av_buffer_unref(&vaapi_vctx->hwframes_ref);
}
static const struct vlc_va_operations ops = { Get, Delete, };
@@ -261,43 +243,77 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum AVPixelFormat hwfmt,
AVBufferRef *hwdev_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
if (hwdev_ref == NULL)
- goto error;
+ return VLC_EGENERIC;
AVHWDeviceContext *hwdev_ctx = (void *) hwdev_ref->data;
AVVAAPIDeviceContext *vadev_ctx = hwdev_ctx->hwctx;
vadev_ctx->display = va_dpy;
if (av_hwdevice_ctx_init(hwdev_ref) < 0)
- goto error;
+ {
+ av_buffer_unref(&hwdev_ref);
+ return VLC_EGENERIC;
+ }
+
+ AVBufferRef *hwframes_ref;
+ int ret = avcodec_get_hw_frames_parameters(ctx, hwdev_ref, hwfmt, &hwframes_ref);
+ av_buffer_unref(&hwdev_ref);
+ if (ret < 0)
+ {
+ msg_Err(va, "avcodec_get_hw_frames_parameters failed: %d", ret);
+ return VLC_EGENERIC;
+ }
+
+ AVHWFramesContext *hwframes_ctx = (AVHWFramesContext*)hwframes_ref->data;
+
+ if (hwframes_ctx->initial_pool_size)
+ {
+ // cf. ff_decode_get_hw_frames_ctx()
+ // We guarantee 4 base work surfaces. The function above guarantees 1
+ // (the absolute minimum), so add the missing count.
+ hwframes_ctx->initial_pool_size += 3;
+ }
+
+ ret = av_hwframe_ctx_init(hwframes_ref);
+ if (ret < 0)
+ {
+ msg_Err(va, "av_hwframe_ctx_init failed: %d", ret);
+ av_buffer_unref(&hwframes_ref);
+ return VLC_EGENERIC;
+ }
+
+ ctx->hw_frames_ctx = av_buffer_ref(hwframes_ref);
+ if (!ctx->hw_frames_ctx)
+ {
+ av_buffer_unref(&hwframes_ref);
+ return VLC_EGENERIC;
+ }
vlc_video_context *vctx =
vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_VAAPI,
sizeof(struct vaapi_vctx), &vaapi_ctx_ops);
if (vctx == NULL)
- goto error;
+ {
+ av_buffer_unref(&hwframes_ref);
+ av_buffer_unref(&ctx->hw_frames_ctx);
+ return VLC_EGENERIC;
+ }
struct vaapi_vctx *vaapi_vctx =
vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_VAAPI);
vaapi_vctx->va_dpy = va_dpy;
- vaapi_vctx->hwdev_ref = hwdev_ref;
- vaapi_vctx->pool_sem_init = false;
+ vaapi_vctx->hwframes_ref = hwframes_ref;
+ vlc_sem_init(&vaapi_vctx->pool_sem, hwframes_ctx->initial_pool_size);
msg_Info(va, "Using %s", vaQueryVendorString(va_dpy));
fmt_out->i_chroma = i_vlc_chroma;
- ctx->hw_device_ctx = hwdev_ref;
-
va->ops = &ops;
va->sys = vctx;
*vtcx_out = vctx;
return VLC_SUCCESS;
-
-error:
- if (hwdev_ref != NULL)
- av_buffer_unref(&hwdev_ref);
- return VLC_EGENERIC;
}
vlc_module_begin ()
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/07ed28715718fd07f46ca349c2cfd682f97969af
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/07ed28715718fd07f46ca349c2cfd682f97969af
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list