From patchwork Fri May 20 19:44:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trystan Mata X-Patchwork-Id: 35854 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:9992:b0:82:461d:f3b with SMTP id ve18csp760160pzb; Fri, 20 May 2022 12:44:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz3z28PWIvWPP5Po2mnnykpxl4eGTKNqsU3IuMz8FQJ7yMyQ/W2OIsr1TtdgBoKiM5MSzNA X-Received: by 2002:a17:907:9717:b0:6fe:b4cd:e0a with SMTP id jg23-20020a170907971700b006feb4cd0e0amr2923327ejc.152.1653075874407; Fri, 20 May 2022 12:44:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1653075874; cv=none; d=google.com; s=arc-20160816; b=binWnt3n0j5nZWyFzLMH7oYadwlSaBwKNnou1MYAIDuajnQ1KB0LCgjKXuJfg7dGLq bTb72FWelBLUDftbvKJKlegoG9s/E7sqpndPw97jg89yRGB/bPtIO15kzDraUaN6Sfgv ROTIWnDasmjHRsHlbWC2zimJoiHQqA6F52Nf8ct1uUvifh6oczAeDGLZG6QUjUpy22Jt mwNHSkITbPhh6Wq16zNwT/QdpcPZ3KfdIRSK+v2eNVwNMAfq+1wsSz17HYsLo0vxop4k IEYiUhSiGGRfzVumvqEwMJ8mvYnrEkbYqbc0HSlaxFmKg5Y4tATwoaCNaXsDz0pk078C se7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :content-language:to:from:mime-version:date:message-id :dkim-signature:delivered-to; bh=aupPqu+iW6DwanrRCSvlTXlgODA6zg9oyb69Sgw6OGo=; b=0xepHh80JDec0TB1PXIvyvQo03qrUVYgH5uTNadr+STW4tbLJ0KmNCN0k6uCjhLhet b4ND20En/lE0iwqq1bShNRHaJ10FqOfP0oDouZ4Saalqp7XPMLCW3p+hL5VwEGNqS5sD xRIAPTQNHGFLgUfAd8VUmobhADAgxoMDGWOezTyGA6E557MDliugF2CC3uUdeDWHP1Pa a+vp+mjEUToIsIQCTOJcPiBkviQ+Fbv1eCWWzZNS5reV3Rh8/vR/jtDVcm3p485BsGb8 MxhjUCqJSwZndM/xgF4/lhkwkOax64zag8kKvszQo1CaRSU41oueV7SZsd+xfpJvdIMY cvrg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@tytanium.xyz header.s=mail header.b=BwDQvTQZ; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=tytanium.xyz Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b2-20020aa7d482000000b00425b38d4de3si5541078edr.178.2022.05.20.12.44.33; Fri, 20 May 2022 12:44:34 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@tytanium.xyz header.s=mail header.b=BwDQvTQZ; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=tytanium.xyz Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5478068B48A; Fri, 20 May 2022 22:44:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from tytanium.xyz (82-64-195-121.subs.proxad.net [82.64.195.121]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2421C68B234 for ; Fri, 20 May 2022 22:44:23 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tytanium.xyz; s=mail; t=1653075862; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding:in-reply-to: references; bh=TBne3mXpdiTdNIZAP/4LRl3tB5rM2FDEIZFbEWN+WJc=; b=BwDQvTQZcGlp+//+TZJkc5EvE9W5Gu3wftBAzTcOgI384oV761XBAU5UBU239akn0qcNnn icC1Yl+iC/1HbILG6PeA/mboy0J6QoGljdJjlQjOZ6ziiLcguCaBTNJ+gkrap7CVIKkFux 3VdluvGWmnQllD3fsrKWjVqtAcJ1i90= Message-ID: Date: Fri, 20 May 2022 21:44:18 +0200 MIME-Version: 1.0 From: Trystan Mata To: ffmpeg-devel@ffmpeg.org Content-Language: en-US X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: [FFmpeg-devel] [PATCH v3] avcodec/mfenc: Dynamically load MFPlat.DLL X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: He8kiiLhc3Dk From 2bdef1bdb93efa40b7d3fe21270f9f23465bee90 Mon Sep 17 00:00:00 2001 From: Trystan Mata 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 --- 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