[FFmpeg-devel] [PATCH] Add MediaFoundation wrapper

James Almer jamrial at gmail.com
Sat Apr 1 18:13:45 EEST 2017


On 4/1/2017 8:28 AM, wm4 wrote:
> Can do audio decoding, audio encoding, video decoding, video encoding,
> video HW encoding. I also had video HW decoding, but removed it for now,
> as thw hwframes integration wasn't very sane.
> 
> Some of the MS codecs aren't well tested, and might not work properly.
> ---
>  configure              |   34 +
>  libavcodec/Makefile    |    1 +
>  libavcodec/allcodecs.c |   23 +
>  libavcodec/mf.c        | 1950 ++++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/mf_utils.c  |  693 +++++++++++++++++
>  libavcodec/mf_utils.h  |  200 +++++
>  6 files changed, 2901 insertions(+)
>  create mode 100644 libavcodec/mf.c
>  create mode 100644 libavcodec/mf_utils.c
>  create mode 100644 libavcodec/mf_utils.h
> 
> diff --git a/configure b/configure
> index 6d76cf7e1e..9909e7ab77 100755
> --- a/configure
> +++ b/configure
> @@ -280,6 +280,7 @@ External library support:
>    --disable-lzma           disable lzma [autodetect]
>    --enable-decklink        enable Blackmagic DeckLink I/O support [no]
>    --enable-mediacodec      enable Android MediaCodec support [no]
> +  --enable-mf              enable decoding via MediaFoundation [no]
>    --enable-netcdf          enable NetCDF, needed for sofalizer filter [no]
>    --enable-openal          enable OpenAL 1.1 capture support [no]
>    --enable-opencl          enable OpenCL code
> @@ -1582,6 +1583,7 @@ EXTERNAL_LIBRARY_LIST="
>      libzmq
>      libzvbi
>      mediacodec
> +    mf
>      netcdf
>      openal
>      opencl
> @@ -2124,6 +2126,7 @@ CONFIG_EXTRA="
>      lpc
>      lzf
>      me_cmp
> +    mf
>      mpeg_er
>      mpegaudio
>      mpegaudiodsp
> @@ -2584,6 +2587,8 @@ zmbv_encoder_select="zlib"
>  # platform codecs
>  audiotoolbox_deps="AudioToolbox_AudioToolbox_h"
>  audiotoolbox_extralibs="-framework CoreFoundation -framework AudioToolbox -framework CoreMedia"
> +mf_deps="mftransform_h"
> +mf_extralibs="-lmfplat -lole32 -lstrmiids -luuid -loleaut32 -lshlwapi"
>  
>  # hardware accelerators
>  crystalhd_deps="libcrystalhd_libcrystalhd_if_h"
> @@ -2892,6 +2897,34 @@ libx265_encoder_deps="libx265"
>  libxavs_encoder_deps="libxavs"
>  libxvid_encoder_deps="libxvid"
>  libzvbi_teletext_decoder_deps="libzvbi"
> +aac_mf_decoder_deps="mf"
> +aac_mf_encoder_deps="mf"
> +ac3_mf_decoder_deps="mf"
> +ac3_mf_encoder_deps="mf"
> +eac3_mf_decoder_deps="mf"
> +h264_mf_decoder_deps="mf"
> +h264_mf_encoder_deps="mf"
> +hevc_mf_decoder_deps="mf"
> +hevc_mf_encoder_deps="mf"
> +mjpeg_mf_decoder_deps="mf"
> +mp1_mf_decoder_deps="mf"
> +mp2_mf_decoder_deps="mf"
> +mp3_mf_decoder_deps="mf"
> +mp3_mf_encoder_deps="mf"
> +mpeg2_mf_decoder_deps="mf"
> +mpeg4_mf_decoder_deps="mf"
> +msmpeg4v1_mf_decoder_deps="mf"
> +msmpeg4v2_mf_decoder_deps="mf"
> +msmpeg4v3_mf_decoder_deps="mf"
> +vc1_mf_decoder_deps="mf"
> +wmav1_mf_decoder_deps="mf"
> +wmav2_mf_decoder_deps="mf"
> +wmalossless_mf_decoder_deps="mf"
> +wmapro_mf_decoder_deps="mf"
> +wmavoice_mf_decoder_deps="mf"
> +wmv1_mf_decoder_deps="mf"
> +wmv2_mf_decoder_deps="mf"
> +wmv3_mf_decoder_deps="mf"
>  videotoolbox_deps="VideoToolbox_VideoToolbox_h"
>  videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo"
>  videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames"
> @@ -5632,6 +5665,7 @@ check_header io.h
>  check_header libcrystalhd/libcrystalhd_if.h
>  check_header mach/mach_time.h
>  check_header malloc.h
> +check_header mftransform.h
>  check_header net/udplite.h
>  check_header poll.h
>  check_header sys/mman.h
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 876a69e013..d26124f60c 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -915,6 +915,7 @@ OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
>  OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
>  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
>  OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
> +OBJS-$(CONFIG_MF)                         += mf.o mf_utils.o mpeg4audio.o
>  
>  # parsers
>  OBJS-$(CONFIG_AAC_LATM_PARSER)         += latm_parser.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index b7d03ad601..c8704a267b 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -631,6 +631,29 @@ static void register_all(void)
>      REGISTER_ENCODER(LIBXAVS,           libxavs);
>      REGISTER_ENCODER(LIBXVID,           libxvid);
>      REGISTER_DECODER(LIBZVBI_TELETEXT,  libzvbi_teletext);
> +    REGISTER_ENCDEC (AAC_MF,            aac_mf);
> +    REGISTER_ENCDEC (AC3_MF,            ac3_mf);
> +    REGISTER_DECODER(EAC3_MF,           eac3_mf);
> +    REGISTER_ENCDEC (H264_MF,           h264_mf);
> +    REGISTER_ENCDEC (HEVC_MF,           hevc_mf);
> +    REGISTER_DECODER(MJPEG_MF,          mjpeg_mf);
> +    REGISTER_DECODER(MP1_MF,            mp1_mf);
> +    REGISTER_DECODER(MP2_MF,            mp2_mf);
> +    REGISTER_ENCDEC (MP3_MF,            mp3_mf);
> +    REGISTER_DECODER(MPEG2_MF,          mpeg2_mf);
> +    REGISTER_DECODER(MPEG4_MF,          mpeg4_mf);
> +    REGISTER_DECODER(MSMPEG4V1_MF,      msmpeg4v1_mf);
> +    REGISTER_DECODER(MSMPEG4V2_MF,      msmpeg4v2_mf);
> +    REGISTER_DECODER(MSMPEG4V3_MF,      msmpeg4v3_mf);
> +    REGISTER_DECODER(VC1_MF,            vc1_mf);
> +    REGISTER_DECODER(WMALOSSLESS_MF,    wmalossless_mf);
> +    REGISTER_DECODER(WMAPRO_MF,         wmapro_mf);
> +    REGISTER_DECODER(WMAV1_MF,          wmav1_mf);
> +    REGISTER_DECODER(WMAV2_MF,          wmav2_mf);
> +    REGISTER_DECODER(WMAVOICE_MF,       wmavoice_mf);
> +    REGISTER_DECODER(WMV1_MF,           wmv1_mf);
> +    REGISTER_DECODER(WMV2_MF,           wmv2_mf);
> +    REGISTER_DECODER(WMV3_MF,           wmv3_mf);
>  
>      /* text */
>      REGISTER_DECODER(BINTEXT,           bintext);
> diff --git a/libavcodec/mf.c b/libavcodec/mf.c
> new file mode 100644
> index 0000000000..baf5c19a2f
> --- /dev/null
> +++ b/libavcodec/mf.c
> @@ -0,0 +1,1950 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +#define COBJMACROS
> +#define _WIN32_WINNT 0x0601

#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0601
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601
#endif

> +
> +#include "mf_utils.h"
> +
> +// Include after mf_utils.h due to Windows include mess.
> +#include "libavutil/hwcontext.h"
> +#include "libavutil/hwcontext_mf.h"

CC      libavcodec/mf.o
/ffmpeg/src/libavcodec/mf.c:24:36: fatal error: libavutil/hwcontext_mf.h: No such file or directory
 #include "libavutil/hwcontext_mf.h"
                                    ^
compilation terminated.
make: *** [/ffmpeg/src/common.mak:60: libavcodec/mf.o] Error 1

[...]

> +#define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \
> +    static const AVClass ff_ ## NAME ## _mf_encoder_class = {                  \
> +        .class_name = #NAME "_mf",                                             \
> +        .item_name  = av_default_item_name,                                    \
> +        .option     = OPTS,                                                    \
> +        .version    = LIBAVUTIL_VERSION_INT,                                   \
> +    };                                                                         \
> +    AVCodec ff_ ## NAME ## _mf_encoder = {                                     \
> +        .priv_class     = &ff_ ## NAME ## _mf_encoder_class,                   \
> +        .name           = #NAME "_mf",                                         \
> +        .long_name      = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"),    \
> +        .type           = AVMEDIA_TYPE_ ## MEDIATYPE,                          \
> +        .id             = AV_CODEC_ID_ ## ID,                                  \
> +        .priv_data_size = sizeof(MFContext),                                   \
> +        .init           = mf_init,                                             \
> +        .close          = mf_close,                                            \
> +        .send_frame     = mf_send_frame,                                       \
> +        .receive_packet = mf_receive_packet,                                   \
> +        EXTRA                                                                  \
> +        .capabilities   = AV_CODEC_CAP_DELAY,                                  \

AV_CODEC_CAP_AVOID_PROBING maybe?

> +        .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |                       \
> +                          FF_CODEC_CAP_INIT_CLEANUP,                           \
> +    };
> +
> +#define AFMTS \
> +        .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,    \
> +                                                         AV_SAMPLE_FMT_NONE },
> +
> +MF_ENCODER(AUDIO, aac,         AAC, NULL, AFMTS);
> +MF_ENCODER(AUDIO, ac3,         AC3, NULL, AFMTS);
> +MF_ENCODER(AUDIO, mp3,         MP3, NULL, AFMTS);
> +
> +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
> +static const AVOption venc_opts[] = {
> +    {"rate_control",  "Select rate control mode", OFFSET(opt_enc_rc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "rate_control"},
> +    { "default",      "Default mode", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "rate_control"},
> +    { "cbr",          "CBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_CBR}, 0, 0, VE, "rate_control"},
> +    { "pc_vbr",       "Peak constrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_PeakConstrainedVBR}, 0, 0, VE, "rate_control"},
> +    { "u_vbr",        "Unconstrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_UnconstrainedVBR}, 0, 0, VE, "rate_control"},
> +    { "quality",      "Quality mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_Quality}, 0, 0, VE, "rate_control" },
> +    // The following rate_control modes require Windows 8.
> +    { "ld_vbr",       "Low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_LowDelayVBR}, 0, 0, VE, "rate_control"},
> +    { "g_vbr",        "Global VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalVBR}, 0, 0, VE, "rate_control" },
> +    { "gld_vbr",      "Global low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR}, 0, 0, VE, "rate_control"},
> +    {"quality",       "Quality", OFFSET(opt_enc_quality), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE},
> +    {"hw_encoding",   "Force hardware encoding", OFFSET(opt_enc_d3d), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE, "hw_encoding"},
> +    {NULL}
> +};
> +
> +#define VFMTS \
> +        .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,       \
> +                                                        AV_PIX_FMT_YUV420P,    \
> +                                                        AV_PIX_FMT_NONE },
> +
> +MF_ENCODER(VIDEO, h264,        H264, venc_opts, VFMTS);
> +MF_ENCODER(VIDEO, hevc,        HEVC, venc_opts, VFMTS);
> diff --git a/libavcodec/mf_utils.c b/libavcodec/mf_utils.c
> new file mode 100644
> index 0000000000..1a69e49581
> --- /dev/null
> +++ b/libavcodec/mf_utils.c
> @@ -0,0 +1,693 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +#define COBJMACROS
> +#define _WIN32_WINNT 0x0601

Ditto



More information about the ffmpeg-devel mailing list