[vlc-commits] [Git][videolan/vlc][master] 5 commits: avcodec: split ffmpeg_OpenVa
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Dec 17 11:19:21 UTC 2024
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
15a5fcc9 by Thomas Guillem at 2024-12-17T10:58:02+00:00
avcodec: split ffmpeg_OpenVa
Into lavc_UpdateHWVideoFormat() + ffmpeg_OpenVa().
lavc_UpdateHWVideoFormat() call lavc_UpdateVideoFormat() and create
the decoder device that is now passed to ffmpeg_OpenVa().
This will be needed to restart vlc_va when keeping the same decoder
device.
- - - - -
095a093c by Thomas Guillem at 2024-12-17T10:58:02+00:00
avcodec: remove dec_device from lavc_UpdateVideoFormat()
It is needed only from lavc_UpdateHWVideoFormat()
- - - - -
4f293243 by Thomas Guillem at 2024-12-17T10:58:02+00:00
avcodec: add ffmpeg_CloseVa
- - - - -
f587d349 by Thomas Guillem at 2024-12-17T10:58:02+00:00
avcodec: va: recreate module if use_hwframes
- - - - -
acf6f375 by Thomas Guillem at 2024-12-17T10:58:02+00:00
avcodec: vaapi: set use_hwframes
- - - - -
3 changed files:
- modules/codec/avcodec/va.h
- modules/codec/avcodec/vaapi.c
- modules/codec/avcodec/video.c
Changes:
=====================================
modules/codec/avcodec/va.h
=====================================
@@ -66,6 +66,13 @@ struct vlc_va_cfg
* to this pointer.
*/
vlc_video_context *vctx_out;
+
+ /**
+ * Indicate if the module is using the new AVHWFramesContext API
+ *
+ * False, by default, set to true if the module is using this API
+ */
+ bool use_hwframes;
};
struct vlc_va_operations {
=====================================
modules/codec/avcodec/vaapi.c
=====================================
@@ -283,6 +283,7 @@ static int Create(vlc_va_t *va, struct vlc_va_cfg *cfg)
va->ops = &ops;
va->sys = vctx;
cfg->vctx_out = vctx;
+ cfg->use_hwframes = true;
return VLC_SUCCESS;
}
=====================================
modules/codec/avcodec/video.c
=====================================
@@ -128,6 +128,7 @@ typedef struct
int profile;
int level;
vlc_video_context *vctx_out;
+ bool use_hwframes;
// decoder output seen by lavc, regardless of texture padding
unsigned decoder_width;
@@ -363,8 +364,7 @@ static int lavc_GetVideoFormat(decoder_t *dec, video_format_t *restrict fmt,
static int lavc_UpdateVideoFormat(decoder_t *dec, AVCodecContext *ctx,
enum AVPixelFormat fmt,
- enum AVPixelFormat swfmt,
- vlc_decoder_device **pp_dec_device)
+ enum AVPixelFormat swfmt)
{
video_format_t fmt_out;
int val;
@@ -408,11 +408,6 @@ static int lavc_UpdateVideoFormat(decoder_t *dec, AVCodecContext *ctx,
p_sys->decoder_width = dec->fmt_out.video.i_width;
p_sys->decoder_height = dec->fmt_out.video.i_height;
- if (pp_dec_device)
- {
- *pp_dec_device = decoder_GetDecoderDevice(dec);
- return *pp_dec_device == NULL;
- }
return 0;
}
@@ -713,12 +708,10 @@ static int InitVideoDecCommon( decoder_t *p_dec )
return VLC_SUCCESS;
}
-static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
- enum AVPixelFormat hwfmt, enum AVPixelFormat swfmt,
- const AVPixFmtDescriptor *src_desc)
+static int lavc_UpdateHWVideoFormat(decoder_t *p_dec, AVCodecContext *p_context,
+ enum AVPixelFormat hwfmt, enum AVPixelFormat swfmt,
+ vlc_decoder_device **pp_dec_device)
{
- decoder_sys_t *p_sys = p_dec->p_sys;
-
if( hwfmt == AV_PIX_FMT_NONE )
return VLC_EGENERIC;
@@ -730,24 +723,52 @@ static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
return VLC_EGENERIC;
}
const AVPixFmtDescriptor *dsc = av_pix_fmt_desc_get(hwfmt);
- vlc_decoder_device *init_device = NULL;
msg_Dbg(p_dec, "trying format %s", dsc ? dsc->name : "unknown");
- if (lavc_UpdateVideoFormat(p_dec, p_context, hwfmt, swfmt, &init_device))
+ if (lavc_UpdateVideoFormat(p_dec, p_context, hwfmt, swfmt))
return VLC_EGENERIC; /* Unsupported brand of hardware acceleration */
+ *pp_dec_device = decoder_GetDecoderDevice(p_dec);
+ if (*pp_dec_device == NULL)
+ return VLC_EGENERIC;
+
+ return VLC_SUCCESS;
+}
+
+static void ffmpeg_CloseVa(decoder_t *p_dec, AVCodecContext *context)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ assert(p_sys->p_va != NULL);
+ assert(p_sys->vctx_out != NULL);
+
+ vlc_va_Delete(p_sys->p_va, NULL);
+ p_sys->p_va = NULL;
+ vlc_video_context_Release(p_sys->vctx_out);
+ p_sys->vctx_out = NULL;
+ p_sys->use_hwframes = false;
+
+ if (context != NULL)
+ context->hwaccel_context = NULL;
+}
+
+static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
+ enum AVPixelFormat hwfmt,
+ const AVPixFmtDescriptor *src_desc,
+ vlc_decoder_device *dec_device)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
p_dec->fmt_out.video.i_chroma = 0; // make sure the va sets its output chroma
struct vlc_va_cfg cfg = {
.avctx = p_context,
.hwfmt = hwfmt,
.desc = src_desc,
.fmt_in = p_dec->fmt_in,
- .dec_device = init_device,
+ .dec_device = dec_device,
.video_fmt_out = &p_dec->fmt_out.video,
.vctx_out = NULL,
+ .use_hwframes = false,
};
vlc_va_t *va = vlc_va_New(VLC_OBJECT(p_dec), &cfg);
- if (init_device)
- vlc_decoder_device_Release(init_device);
if (va == NULL)
return VLC_EGENERIC; /* Unsupported codec profile or such */
@@ -764,9 +785,30 @@ static int ffmpeg_OpenVa(decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_va = va;
p_sys->vctx_out = vlc_video_context_Hold( cfg.vctx_out );
p_sys->pix_fmt = hwfmt;
+ p_sys->use_hwframes = cfg.use_hwframes;
return VLC_SUCCESS;
}
+static int ffmpeg_RecreateVa(decoder_t *p_dec, AVCodecContext *p_context,
+ enum AVPixelFormat hwfmt, enum AVPixelFormat swfmt)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ assert(p_sys->vctx_out != NULL);
+
+ vlc_decoder_device *dec_device =
+ vlc_video_context_HoldDevice(p_sys->vctx_out);
+
+ ffmpeg_CloseVa(p_dec, p_context);
+
+ const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(swfmt);
+
+ int ret = ffmpeg_OpenVa(p_dec, p_context, p_sys->pix_fmt,
+ src_desc, dec_device);
+ if (dec_device != NULL)
+ vlc_decoder_device_Release(dec_device);
+ return ret;
+}
+
static const enum AVPixelFormat hwfmts[] =
{
#ifdef _WIN32
@@ -874,7 +916,17 @@ int InitVideoHwDec( vlc_object_t *obj )
for( size_t i = 0; hwfmts[i] != AV_PIX_FMT_NONE; i++ )
{
- if (ffmpeg_OpenVa(p_dec, p_context, hwfmts[i], p_context->sw_pix_fmt, src_desc) == VLC_SUCCESS)
+ vlc_decoder_device *dec_device;
+ int ret = lavc_UpdateHWVideoFormat(p_dec, p_context, hwfmts[i],
+ p_context->sw_pix_fmt, &dec_device);
+ if (ret != VLC_SUCCESS)
+ continue;
+
+ ret = ffmpeg_OpenVa(p_dec, p_context, hwfmts[i], src_desc, dec_device);
+ if (dec_device != NULL)
+ vlc_decoder_device_Release(dec_device);
+
+ if (ret == VLC_SUCCESS)
// we have a matching hardware decoder
return VLC_SUCCESS;
}
@@ -1562,7 +1614,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
* then picture buffer can be allocated. */
if (p_sys->p_va == NULL
&& lavc_UpdateVideoFormat(p_dec, p_context, p_context->pix_fmt,
- p_context->pix_fmt, NULL) == 0
+ p_context->pix_fmt) == 0
&& decoder_UpdateVideoOutput(p_dec, NULL) == 0)
p_pic = decoder_NewPicture(p_dec);
@@ -1694,11 +1746,7 @@ void EndVideoDec( vlc_object_t *obj )
avcodec_free_context( &ctx );
if( p_sys->p_va )
- {
- vlc_va_Delete( p_sys->p_va, NULL );
- vlc_video_context_Release( p_sys->vctx_out );
- p_sys->vctx_out = NULL;
- }
+ ffmpeg_CloseVa(p_dec, NULL);
free( p_sys );
}
@@ -1928,7 +1976,7 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
/* Most unaccelerated decoders do not call get_format(), so we need to
* update the output video format here. The MT semaphore must be held
* to protect p_dec->fmt_out. */
- if (lavc_UpdateVideoFormat(dec, ctx, ctx->pix_fmt, ctx->pix_fmt, NULL) ||
+ if (lavc_UpdateVideoFormat(dec, ctx, ctx->pix_fmt, ctx->pix_fmt) ||
decoder_UpdateVideoOutput(dec, NULL))
{
vlc_mutex_unlock(&sys->lock);
@@ -1961,6 +2009,7 @@ static enum AVPixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
/* Enumerate available formats */
enum AVPixelFormat defaultfmt = avcodec_default_get_format(p_context, pi_fmt);
enum AVPixelFormat swfmt = AV_PIX_FMT_NONE;
+ enum AVPixelFormat skipfmt = AV_PIX_FMT_NONE;
bool can_hwaccel = false;
for (size_t i = 0; pi_fmt[i] != AV_PIX_FMT_NONE; i++)
@@ -2029,7 +2078,25 @@ static enum AVPixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
for (size_t i = 0; pi_fmt[i] != AV_PIX_FMT_NONE; i++)
if (pi_fmt[i] == p_sys->pix_fmt)
{
- msg_Dbg(p_dec, "reusing decoder output format %d", pi_fmt[i]);
+ if (p_sys->use_hwframes)
+ {
+ /* When using hwframes API, ffmpeg is reseting the hardware
+ * context of the AVCodecContext before calling the
+ * `get_format` callback. Therefore, the va context need to be
+ * closed and opened again. */
+ msg_Dbg(p_dec, "recreating decoder output format %d", pi_fmt[i]);
+ int ret = ffmpeg_RecreateVa(p_dec, p_context, p_sys->pix_fmt,
+ swfmt);
+ if (ret != VLC_SUCCESS)
+ {
+ msg_Err(p_dec, "error restarting va module");
+ skipfmt = p_sys->pix_fmt; /* Don't retry this fmt */
+ p_sys->pix_fmt = AV_PIX_FMT_NONE;
+ goto no_reuse;
+ }
+ }
+ else
+ msg_Dbg(p_dec, "reusing decoder output format %d", pi_fmt[i]);
return p_sys->pix_fmt;
}
@@ -2041,11 +2108,7 @@ no_reuse:
// switching to a software decoder will not silently decode nothing
// (get_format will fail to use AV_PIX_FMT_NONE)
assert(!p_sys->b_hardware_only);
- vlc_va_Delete(p_sys->p_va, NULL);
- p_sys->p_va = NULL;
- vlc_video_context_Release( p_sys->vctx_out );
- p_sys->vctx_out = NULL;
- p_context->hwaccel_context = NULL;
+ ffmpeg_CloseVa(p_dec, p_context);
}
p_sys->profile = p_context->profile;
@@ -2063,7 +2126,20 @@ no_reuse:
if( hwfmts[i] == pi_fmt[j] )
hwfmt = hwfmts[i];
- if (ffmpeg_OpenVa(p_dec, p_context, hwfmt, swfmt, src_desc) != VLC_SUCCESS)
+ if (hwfmt == skipfmt)
+ continue;
+
+ vlc_decoder_device *dec_device;
+ int ret = lavc_UpdateHWVideoFormat(p_dec, p_context, hwfmt, swfmt,
+ &dec_device);
+ if (ret != VLC_SUCCESS)
+ continue;
+
+ ret = ffmpeg_OpenVa(p_dec, p_context, hwfmt, src_desc, dec_device);
+ if (dec_device != NULL)
+ vlc_decoder_device_Release(dec_device);
+
+ if (ret != VLC_SUCCESS)
continue;
return hwfmt;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ec2645d1accbd2f666577fca8f74d61d6045f4d4...acf6f37533e59da1750e9c4285edbc7e60c964ce
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ec2645d1accbd2f666577fca8f74d61d6045f4d4...acf6f37533e59da1750e9c4285edbc7e60c964ce
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list