@@ -3129,8 +3129,8 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
# hardware-accelerated codecs
-mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer"
-mediafoundation_extralibs="-lmfplat -lmfuuid -lole32 -lstrmiids"
+mediafoundation_deps="LoadLibrary mftransform_h
MFCreateAlignedMemoryBuffer"
+mediafoundation_extralibs="-lole32 -lstrmiids"
omx_deps="libdl pthreads"
omx_rpi_select="omx"
qsv_deps="libmfx"
@@ -106,19 +106,20 @@ char *ff_hr_str_buf(char *buf, size_t size,
HRESULT hr)
// If fill_data!=NULL, initialize the buffer and set the length. (This
is a
// subtle but important difference: some decoders want CurrentLength==0 on
// provided output buffers.)
-IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t
align)
+IMFSample *ff_create_memory_sample(const MFSymbols *symbols, void
*fill_data,
+ size_t size, size_t align)
{
HRESULT hr;
IMFSample *sample;
IMFMediaBuffer *buffer;
- hr = MFCreateSample(&sample);
+ hr = symbols->MFCreateSample(&sample);
if (FAILED(hr))
return NULL;
align = FFMAX(align, 16); // 16 is "recommended", even if not
required
- hr = MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
+ hr = symbols->MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
if (FAILED(hr))
return NULL;
@@ -548,7 +549,7 @@ const CLSID *ff_codec_to_mf_subtype(enum AVCodecID
codec)
}
}
-static int init_com_mf(void *log)
+static int init_com_mf(const MFSymbols *symbols, void *log)
{
HRESULT hr;
@@ -561,7 +562,7 @@ static int init_com_mf(void *log)
return AVERROR(ENOSYS);
}
- hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ hr = symbols->MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (FAILED(hr)) {
av_log(log, AV_LOG_ERROR, "could not initialize
MediaFoundation\n");
CoUninitialize();
@@ -571,15 +572,16 @@ static int init_com_mf(void *log)
return 0;
}
-static void uninit_com_mf(void)
+static void uninit_com_mf(const MFSymbols *symbols)
{
- MFShutdown();
+ symbols->MFShutdown();
CoUninitialize();
}
// Find and create a IMFTransform with the given input/output types.
When done,
// you should use ff_free_mf() to destroy it, which will also uninit COM.
-int ff_instantiate_mf(void *log,
+int ff_instantiate_mf(const MFSymbols *symbols,
+ void *log,
GUID category,
MFT_REGISTER_TYPE_INFO *in_type,
MFT_REGISTER_TYPE_INFO *out_type,
@@ -594,7 +596,7 @@ int ff_instantiate_mf(void *log,
IMFActivate *winner = 0;
UINT32 flags;
- ret = init_com_mf(log);
+ ret = init_com_mf(symbols, log);
if (ret < 0)
return ret;
@@ -667,14 +669,14 @@ int ff_instantiate_mf(void *log,
return 0;
error_uninit_mf:
- uninit_com_mf();
+ uninit_com_mf(symbols);
return AVERROR(ENOSYS);
}
-void ff_free_mf(IMFTransform **mft)
+void ff_free_mf(const MFSymbols *symbols, IMFTransform **mft)
{
if (*mft)
IMFTransform_Release(*mft);
*mft = NULL;
- uninit_com_mf();
+ uninit_com_mf(symbols);
}
@@ -41,6 +41,15 @@
#include "avcodec.h"
+typedef struct MFSymbols {
+ HRESULT (*MFCreateSample) (IMFSample **ppIMFSample);
+ HRESULT (*MFCreateAlignedMemoryBuffer) (DWORD cbMaxLength, DWORD
cbAligment,
+ IMFMediaBuffer **ppBuffer);
+ HRESULT (*MFStartup) (ULONG Version, DWORD dwFlags);
+ HRESULT (*MFShutdown) (void);
+ HRESULT (*MFCreateMediaType) (IMFMediaType **ppMFType);
+} MFSymbols;
+
// These functions do exist in mfapi.h, but are only available within
// __cplusplus ifdefs.
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid,
@@ -150,7 +159,8 @@ char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr);
#define FF_VAL_VT_UI4(v) FF_VARIANT_VALUE(VT_UI4, .ulVal = (v))
#define FF_VAL_VT_BOOL(v) FF_VARIANT_VALUE(VT_BOOL, .boolVal = (v))
-IMFSample *ff_create_memory_sample(void *fill_data, size_t size,
size_t align);
+IMFSample *ff_create_memory_sample(const MFSymbols *symbols, void
*fill_data,
+ size_t size, size_t align);
enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type);
enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type);
const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt);
@@ -160,10 +170,10 @@ char *ff_guid_str_buf(char *buf, size_t buf_size,
const GUID *guid);
void ff_attributes_dump(void *log, IMFAttributes *attrs);
void ff_media_type_dump(void *log, IMFMediaType *type);
const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec);
-int ff_instantiate_mf(void *log, GUID category,
+int ff_instantiate_mf(const MFSymbols *symbols, void *log, GUID category,
MFT_REGISTER_TYPE_INFO *in_type,
MFT_REGISTER_TYPE_INFO *out_type,
int use_hw, IMFTransform **res);
-void ff_free_mf(IMFTransform **mft);
+void ff_free_mf(const MFSymbols *symbols, IMFTransform **mft);
#endif
@@ -29,9 +29,13 @@
#include "libavutil/time.h"
#include "codec_internal.h"
#include "internal.h"
+#include "compat/w32dlfcn.h"
typedef struct MFContext {
AVClass *av_class;
+ void *library;
+ MFSymbols symbols;
+ AVFrame *frame;
int is_video, is_audio;
GUID main_subtype;
@@ -292,7 +296,7 @@ static IMFSample
*mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f
Allow builds of FFmpeg with MediaFoundation to work under N editions of Windows which are without MediaFoundation by default. Signed-off-by: Trystan Mata <trystan.mata@tytanium.xyz> --- configure | 4 +- libavcodec/mf_utils.c | 26 ++++++------ libavcodec/mf_utils.h | 16 ++++++-- libavcodec/mfenc.c | 92 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 108 insertions(+), 30 deletions(-) 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->symbols, 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 +316,7 @@ 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->symbols, NULL, size, c->in_info.cbAlignment); if (!sample) return NULL; @@ -422,7 +426,7 @@ 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->symbols, NULL, c->out_info.cbSize, c->out_info.cbAlignment); if (!sample) return AVERROR(ENOMEM); } @@ -777,7 +781,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->symbols.MFCreateMediaType(&out_type); if (FAILED(hr)) { ret = AVERROR(ENOMEM); goto done; @@ -1005,7 +1009,7 @@ err: return res; } -static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int use_hw) +static int mf_create(const MFSymbols *symbols, void *log, 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 +1032,57 @@ 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(symbols, log, category, NULL, ®, use_hw, mft)) < 0) return ret; return 0; } -static int mf_init(AVCodecContext *avctx) +static int mf_load_library(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + + c->library = dlopen("MFPlat.DLL", RTLD_NOW | RTLD_LOCAL); + + if (c->library == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to open\n"); + return AVERROR_UNKNOWN; + } + + c->symbols.MFCreateSample = dlsym(c->library, "MFCreateSample"); + if (c->symbols.MFCreateSample == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to find function MFCreateSample\n"); + return AVERROR_UNKNOWN; + } + + c->symbols.MFCreateAlignedMemoryBuffer = dlsym(c->library, "MFCreateAlignedMemoryBuffer"); + if (c->symbols.MFCreateAlignedMemoryBuffer == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to find function MFCreateAlignedMemoryBuffer\n"); + return AVERROR_UNKNOWN; + } + + c->symbols.MFStartup = dlsym(c->library, "MFStartup"); + if (c->symbols.MFStartup == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to find function MFStartup\n"); + return AVERROR_UNKNOWN; + } + + c->symbols.MFShutdown = dlsym(c->library, "MFShutdown"); + if (c->symbols.MFShutdown == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to find function MFShutdown\n"); + return AVERROR_UNKNOWN; + } + + c->symbols.MFCreateMediaType = dlsym(c->library, "MFCreateMediaType"); + if (c->symbols.MFCreateMediaType == NULL) { + av_log(c, AV_LOG_ERROR, "DLL MFPlat.DLL failed to find function MFCreateMediaType\n"); + return AVERROR_UNKNOWN; + } + + return 0; +}; + +static int mf_init_encoder(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; HRESULT hr; @@ -1058,7 +1106,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(&c->symbols, avctx, &c->mft, avctx->codec, use_hw)) < 0) return ret; if ((ret = mf_unlock_async(avctx)) < 0) @@ -1126,13 +1174,18 @@ static int mf_close(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; - if (c->codec_api) - ICodecAPI_Release(c->codec_api); + if (c->library) { + if (c->codec_api) + ICodecAPI_Release(c->codec_api); - if (c->async_events) - IMFMediaEventGenerator_Release(c->async_events); + if (c->async_events) + IMFMediaEventGenerator_Release(c->async_events); - ff_free_mf(&c->mft); + ff_free_mf(&c->symbols, &c->mft); + + dlclose(c->library); + c->library = NULL; + } av_frame_free(&c->frame); @@ -1142,6 +1195,19 @@ 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) \