diff options
author | Trystan Mata <trystan.mata@tytanium.xyz> | 2022-05-25 12:54:01 +0200 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2022-05-25 23:45:42 +0300 |
commit | 1cb601ad10313981209a5918fc36a968068fc0ec (patch) | |
tree | 3e72921c9fc9930807cb5f16e44960715f9aa948 /libavcodec/mfenc.c | |
parent | 478e1a98a289bbc777bddc02fdcefeaa3c416a63 (diff) | |
download | ffmpeg-1cb601ad10313981209a5918fc36a968068fc0ec.tar.gz |
avcodec/mfenc: Dynamically load MFPlat.DLL
Allows non-UWP builds of FFmpeg with MediaFoundation to work on
N editions of Windows which are without MediaFoundation by default.
On UWP target, FFmpeg is linked directly against MediaFoundation since
LoadLibrary is not available.
This commit adresses https://trac.ffmpeg.org/ticket/9788
Signed-off-by: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavcodec/mfenc.c')
-rw-r--r-- | libavcodec/mfenc.c | 93 |
1 files changed, 84 insertions, 9 deletions
diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c index 280941cf2e..17d0ec60bd 100644 --- a/libavcodec/mfenc.c +++ b/libavcodec/mfenc.c @@ -32,6 +32,8 @@ typedef struct MFContext { AVClass *av_class; + HMODULE library; + MFFunctions functions; AVFrame *frame; int is_video, is_audio; GUID main_subtype; @@ -292,7 +294,8 @@ static IMFSample *mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f bps = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels; len = frame->nb_samples * bps; - sample = ff_create_memory_sample(frame->data[0], len, c->in_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, frame->data[0], len, + c->in_info.cbAlignment); if (sample) IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->nb_samples)); return sample; @@ -312,7 +315,8 @@ static IMFSample *mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f if (size < 0) return NULL; - sample = ff_create_memory_sample(NULL, size, c->in_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, NULL, size, + c->in_info.cbAlignment); if (!sample) return NULL; @@ -422,7 +426,9 @@ static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample) } if (!c->out_stream_provides_samples) { - sample = ff_create_memory_sample(NULL, c->out_info.cbSize, c->out_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, NULL, + c->out_info.cbSize, + c->out_info.cbAlignment); if (!sample) return AVERROR(ENOMEM); } @@ -777,7 +783,7 @@ static int mf_choose_output_type(AVCodecContext *avctx) if (out_type) { av_log(avctx, AV_LOG_VERBOSE, "picking output type %d.\n", out_type_index); } else { - hr = MFCreateMediaType(&out_type); + hr = c->functions.MFCreateMediaType(&out_type); if (FAILED(hr)) { ret = AVERROR(ENOMEM); goto done; @@ -1005,7 +1011,8 @@ err: return res; } -static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int use_hw) +static int mf_create(void *log, MFFunctions *f, IMFTransform **mft, + const AVCodec *codec, int use_hw) { int is_audio = codec->type == AVMEDIA_TYPE_AUDIO; const CLSID *subtype = ff_codec_to_mf_subtype(codec->id); @@ -1028,13 +1035,13 @@ static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int us category = MFT_CATEGORY_VIDEO_ENCODER; } - if ((ret = ff_instantiate_mf(log, category, NULL, ®, use_hw, mft)) < 0) + if ((ret = ff_instantiate_mf(log, f, category, NULL, ®, use_hw, mft)) < 0) return ret; return 0; } -static int mf_init(AVCodecContext *avctx) +static int mf_init_encoder(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; HRESULT hr; @@ -1058,7 +1065,7 @@ static int mf_init(AVCodecContext *avctx) c->main_subtype = *subtype; - if ((ret = mf_create(avctx, &c->mft, avctx->codec, use_hw)) < 0) + if ((ret = mf_create(avctx, &c->functions, &c->mft, avctx->codec, use_hw)) < 0) return ret; if ((ret = mf_unlock_async(avctx)) < 0) @@ -1122,6 +1129,54 @@ static int mf_init(AVCodecContext *avctx) return 0; } +#if !HAVE_UWP +#define LOAD_MF_FUNCTION(context, func_name) \ + context->functions.func_name = (void *)GetProcAddress(context->library, #func_name); \ + if (!context->functions.func_name) { \ + av_log(context, AV_LOG_ERROR, "DLL mfplat.dll failed to find function "\ + #func_name "\n"); \ + return AVERROR_UNKNOWN; \ + } +#else +// In UWP (which lacks LoadLibrary), just link directly against +// the functions - this requires building with new/complete enough +// import libraries. +#define LOAD_MF_FUNCTION(context, func_name) \ + context->functions.func_name = func_name; \ + if (!context->functions.func_name) { \ + av_log(context, AV_LOG_ERROR, "Failed to find function " #func_name \ + "\n"); \ + return AVERROR_UNKNOWN; \ + } +#endif + +// Windows N editions does not provide MediaFoundation by default. +// So to avoid DLL loading error, MediaFoundation is dynamically loaded except +// on UWP build since LoadLibrary is not available on it. +static int mf_load_library(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + +#if !HAVE_UWP + c->library = LoadLibraryA("mfplat.dll"); + + if (!c->library) { + av_log(c, AV_LOG_ERROR, "DLL mfplat.dll failed to open\n"); + return AVERROR_UNKNOWN; + } +#endif + + LOAD_MF_FUNCTION(c, MFStartup); + LOAD_MF_FUNCTION(c, MFShutdown); + LOAD_MF_FUNCTION(c, MFCreateAlignedMemoryBuffer); + LOAD_MF_FUNCTION(c, MFCreateSample); + LOAD_MF_FUNCTION(c, MFCreateMediaType); + // MFTEnumEx is missing in Windows Vista's mfplat.dll. + LOAD_MF_FUNCTION(c, MFTEnumEx); + + return 0; +} + static int mf_close(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; @@ -1132,7 +1187,15 @@ static int mf_close(AVCodecContext *avctx) if (c->async_events) IMFMediaEventGenerator_Release(c->async_events); - ff_free_mf(&c->mft); +#if !HAVE_UWP + if (c->library) + ff_free_mf(&c->functions, &c->mft); + + FreeLibrary(c->library); + c->library = NULL; +#else + ff_free_mf(&c->functions, &c->mft); +#endif av_frame_free(&c->frame); @@ -1142,6 +1205,18 @@ static int mf_close(AVCodecContext *avctx) return 0; } +static int mf_init(AVCodecContext *avctx) +{ + int ret; + if ((ret = mf_load_library(avctx)) == 0) { + if ((ret = mf_init_encoder(avctx)) == 0) { + return 0; + } + } + mf_close(avctx); + return ret; +} + #define OFFSET(x) offsetof(MFContext, x) #define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \ |