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.m...@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(-)

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..1260fa30ea 100644
--- a/libavcodec/mfenc.c
+++ b/libavcodec/mfenc.c
@@ -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 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, &reg, use_hw, mft)) < 0) + if ((ret = ff_instantiate_mf(symbols, log, category, NULL, &reg, 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) \
--
2.36.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to