* [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL
@ 2022-05-20 19:44 Trystan Mata
2022-05-20 20:05 ` Martin Storsjö
0 siblings, 1 reply; 3+ messages in thread
From: Trystan Mata @ 2022-05-20 19:44 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: 0001-avcodec-mfenc-Dynamically-load-MFPlat.DLL.patch --]
[-- Type: text/x-patch, Size: 12259 bytes --]
From 2bdef1bdb93efa40b7d3fe21270f9f23465bee90 Mon Sep 17 00:00:00 2001
From: Trystan Mata <trystan.mata@tytanium.xyz>
Date: Fri, 20 May 2022 14:26:49 +0200
Subject: [PATCH] avcodec/mfenc: Dynamically load MFPlat.DLL
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 | 91 ++++++++++++++++++++++++++++++++++++-------
4 files changed, 107 insertions(+), 30 deletions(-)
diff --git a/configure b/configure
index f115b21064..f16fbb320a 100755
--- a/configure
+++ b/configure
@@ -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"
diff --git a/libavcodec/mf_utils.c b/libavcodec/mf_utils.c
index eeabd0ce0b..9a83f71692 100644
--- a/libavcodec/mf_utils.c
+++ b/libavcodec/mf_utils.c
@@ -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);
}
diff --git a/libavcodec/mf_utils.h b/libavcodec/mf_utils.h
index d514723c3b..1b1041bb29 100644
--- a/libavcodec/mf_utils.h
+++ b/libavcodec/mf_utils.h
@@ -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
diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c
index 280941cf2e..0444d5af38 100644
--- a/libavcodec/mfenc.c
+++ b/libavcodec/mfenc.c
@@ -29,9 +29,12 @@
#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 +295,7 @@ 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->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 +315,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 +425,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 +780,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 +1008,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 +1031,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 +1105,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 +1173,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 +1194,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) \
--
2.33.1.windows.1
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL
2022-05-20 19:44 [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL Trystan Mata
@ 2022-05-20 20:05 ` Martin Storsjö
2022-05-20 20:48 ` Trystan Mata
0 siblings, 1 reply; 3+ messages in thread
From: Martin Storsjö @ 2022-05-20 20:05 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Fri, 20 May 2022, Trystan Mata wrote:
> From 2bdef1bdb93efa40b7d3fe21270f9f23465bee90 Mon Sep 17 00:00:00 2001
> From: Trystan Mata <trystan.mata@tytanium.xyz>
> Date: Fri, 20 May 2022 14:26:49 +0200
> Subject: [PATCH] avcodec/mfenc: Dynamically load MFPlat.DLL
>
> 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 | 91 ++++++++++++++++++++++++++++++++++++-------
> 4 files changed, 107 insertions(+), 30 deletions(-)
This patch on its own breaks builds for UWP targets (where LoadLibrary
isn't available). Or more precisely, previously mfenc was enabled, now it
no longer is available.
For such targets, one can unconditionally assume that the functions are
available and can link directly against them. See ff_MFTEnumEx in
mf_utils.c how that's done so far. Doing the same instead of LoadLibrary
probably shouldn't be an issue for you, but I think we'd need to drop the
dependency on LoadLibrary in configure. (I think that's fine, we don't
really lose anything by doing that.)
Btw, when sending updates to an earlier posted patch, it'd be nice if
you'd mention somewhere what changed compared to the previous revision of
the patch.
// Martin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL
2022-05-20 20:05 ` Martin Storsjö
@ 2022-05-20 20:48 ` Trystan Mata
0 siblings, 0 replies; 3+ messages in thread
From: Trystan Mata @ 2022-05-20 20:48 UTC (permalink / raw)
To: ffmpeg-devel
Firstly, I'm sorry about those patches without changes mentioned.
As changes, there was just a whitespace that I removed.
I'm not used at all to sending matches through mailing list. And Patchwork
failed to apply my patches, so I resend it trying to see if the way I sent the
patch was wrong.
If I understood correctly, I need to change my patch to link FFmpeg against
MFPlat.DLL on UWP targets.
And for the symbols, I try to "load" them à la ff_MFTEnumEx. And so dynamically
load MFPlat.DLL on non-UWP targets.
Thank you for your review and you time.
// Trystan
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-05-20 20:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-20 19:44 [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL Trystan Mata
2022-05-20 20:05 ` Martin Storsjö
2022-05-20 20:48 ` Trystan Mata
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git