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.
_______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits