mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avcodec: Add MediaFoundation encoder wrapper
This contains encoder wrappers for H264, HEVC, AAC, AC3 and MP3. This is based on top of an original patch by wm4 <nfxjfg@googlemail.com>. The original patch supported both encoding and decoding, but this patch only includes encoding. The patch contains further changes by Paweł Wegner <pawel.wegner95@gmail.com> (primarily for splitting out the encoding parts of the original patch) and further cleanup, build compatibility fixes and tweaks for use with Qualcomm encoders by Martin Storsjö. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
b559a5882f
commit
050b72ab5e
@ -69,6 +69,7 @@ version <next>:
|
||||
- scdet filter
|
||||
- NotchLC decoder
|
||||
- gradients source video filter
|
||||
- MediaFoundation encoder wrapper
|
||||
|
||||
|
||||
version 4.2:
|
||||
|
11
configure
vendored
11
configure
vendored
@ -304,6 +304,7 @@ External library support:
|
||||
--enable-mbedtls enable mbedTLS, needed for https support
|
||||
if openssl, gnutls or libtls is not used [no]
|
||||
--enable-mediacodec enable Android MediaCodec support [no]
|
||||
--enable-mediafoundation enable encoding via MediaFoundation [auto]
|
||||
--enable-libmysofa enable libmysofa, needed for sofalizer filter [no]
|
||||
--enable-openal enable OpenAL 1.1 capture support [no]
|
||||
--enable-opencl enable OpenCL processing [no]
|
||||
@ -1704,6 +1705,7 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST="
|
||||
libxcb_shape
|
||||
libxcb_xfixes
|
||||
lzma
|
||||
mediafoundation
|
||||
schannel
|
||||
sdl2
|
||||
securetransport
|
||||
@ -3011,6 +3013,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"
|
||||
omx_deps="libdl pthreads"
|
||||
omx_rpi_select="omx"
|
||||
qsv_deps="libmfx"
|
||||
@ -3035,6 +3039,8 @@ nvenc_deps="ffnvcodec"
|
||||
nvenc_deps_any="libdl LoadLibrary"
|
||||
nvenc_encoder_deps="nvenc"
|
||||
|
||||
aac_mf_encoder_deps="mediafoundation"
|
||||
ac3_mf_encoder_deps="mediafoundation"
|
||||
h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
|
||||
h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
|
||||
h264_amf_encoder_deps="amf"
|
||||
@ -3043,6 +3049,7 @@ h264_cuvid_decoder_deps="cuvid"
|
||||
h264_cuvid_decoder_select="h264_mp4toannexb_bsf"
|
||||
h264_mediacodec_decoder_deps="mediacodec"
|
||||
h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser"
|
||||
h264_mf_encoder_deps="mediafoundation"
|
||||
h264_mmal_decoder_deps="mmal"
|
||||
h264_nvenc_encoder_deps="nvenc"
|
||||
h264_omx_encoder_deps="omx"
|
||||
@ -3059,6 +3066,7 @@ hevc_cuvid_decoder_deps="cuvid"
|
||||
hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf"
|
||||
hevc_mediacodec_decoder_deps="mediacodec"
|
||||
hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser"
|
||||
hevc_mf_encoder_deps="mediafoundation"
|
||||
hevc_nvenc_encoder_deps="nvenc"
|
||||
hevc_qsv_decoder_select="hevc_mp4toannexb_bsf qsvdec"
|
||||
hevc_qsv_encoder_select="hevcparse qsvenc"
|
||||
@ -3075,6 +3083,7 @@ mjpeg_qsv_encoder_deps="libmfx"
|
||||
mjpeg_qsv_encoder_select="qsvenc"
|
||||
mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
|
||||
mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode"
|
||||
mp3_mf_encoder_deps="mediafoundation"
|
||||
mpeg1_cuvid_decoder_deps="cuvid"
|
||||
mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m"
|
||||
mpeg2_crystalhd_decoder_select="crystalhd"
|
||||
@ -6101,6 +6110,7 @@ check_headers io.h
|
||||
check_headers linux/perf_event.h
|
||||
check_headers libcrystalhd/libcrystalhd_if.h
|
||||
check_headers malloc.h
|
||||
check_headers mftransform.h
|
||||
check_headers net/udplite.h
|
||||
check_headers poll.h
|
||||
check_headers sys/param.h
|
||||
@ -6163,6 +6173,7 @@ check_type "windows.h dxva.h" "DXVA_PicParams_VP9" -DWINAPI_FAMILY=WINAPI_FAMILY
|
||||
check_type "windows.h d3d11.h" "ID3D11VideoDecoder"
|
||||
check_type "windows.h d3d11.h" "ID3D11VideoContext"
|
||||
check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602
|
||||
check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat
|
||||
|
||||
check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
|
||||
check_type "vdpau/vdpau.h" "VdpPictureInfoVP9"
|
||||
|
@ -2725,6 +2725,14 @@ fastest.
|
||||
|
||||
@end table
|
||||
|
||||
@section MediaFoundation
|
||||
|
||||
This provides wrappers to encoders (both audio and video) in the
|
||||
MediaFoundation framework. It can access both SW and HW encoders.
|
||||
Video encoders can take input in either of nv12 or yuv420p form
|
||||
(some encoders support both, some support only either - in practice,
|
||||
nv12 is the safer choice, especially among HW encoders).
|
||||
|
||||
@section mpeg2
|
||||
|
||||
MPEG-2 video encoder.
|
||||
|
@ -170,12 +170,14 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
|
||||
aacenc_ltp.o \
|
||||
aacenc_pred.o \
|
||||
psymodel.o mpeg4audio.o kbdwin.o cbrt_data.o
|
||||
OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
|
||||
OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o
|
||||
OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o
|
||||
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \
|
||||
ac3.o kbdwin.o
|
||||
OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o
|
||||
OBJS-$(CONFIG_AC3_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_ACELP_KELVIN_DECODER) += g729dec.o lsp.o celp_math.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
|
||||
OBJS-$(CONFIG_AGM_DECODER) += agm.o
|
||||
OBJS-$(CONFIG_AIC_DECODER) += aic.o
|
||||
@ -356,6 +358,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
|
||||
OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o
|
||||
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_H264_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
|
||||
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o
|
||||
@ -378,6 +381,7 @@ OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
|
||||
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o
|
||||
OBJS-$(CONFIG_NVENC_HEVC_ENCODER) += nvenc_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o
|
||||
@ -455,6 +459,7 @@ OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \
|
||||
mpegaudiodata.o mpegaudiodsp_data.o
|
||||
OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o
|
||||
OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec_fixed.o
|
||||
OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o
|
||||
OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec_fixed.o
|
||||
OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o
|
||||
OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o
|
||||
@ -1156,6 +1161,7 @@ SKIPHEADERS-$(CONFIG_JNI) += ffjni.h
|
||||
SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h
|
||||
SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.h
|
||||
SKIPHEADERS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.h mediacodec_surface.h mediacodec_wrapper.h mediacodec_sw_buffer.h
|
||||
SKIPHEADERS-$(CONFIG_MEDIAFOUNDATION) += mf_utils.h
|
||||
SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h
|
||||
SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h
|
||||
SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h
|
||||
|
@ -677,7 +677,9 @@ extern AVCodec ff_xsub_decoder;
|
||||
/* external libraries */
|
||||
extern AVCodec ff_aac_at_encoder;
|
||||
extern AVCodec ff_aac_at_decoder;
|
||||
extern AVCodec ff_aac_mf_encoder;
|
||||
extern AVCodec ff_ac3_at_decoder;
|
||||
extern AVCodec ff_ac3_mf_encoder;
|
||||
extern AVCodec ff_adpcm_ima_qt_at_decoder;
|
||||
extern AVCodec ff_alac_at_encoder;
|
||||
extern AVCodec ff_alac_at_decoder;
|
||||
@ -689,6 +691,7 @@ extern AVCodec ff_ilbc_at_decoder;
|
||||
extern AVCodec ff_mp1_at_decoder;
|
||||
extern AVCodec ff_mp2_at_decoder;
|
||||
extern AVCodec ff_mp3_at_decoder;
|
||||
extern AVCodec ff_mp3_mf_encoder;
|
||||
extern AVCodec ff_pcm_alaw_at_encoder;
|
||||
extern AVCodec ff_pcm_alaw_at_decoder;
|
||||
extern AVCodec ff_pcm_mulaw_at_encoder;
|
||||
@ -758,6 +761,7 @@ extern AVCodec ff_libopenh264_encoder;
|
||||
extern AVCodec ff_libopenh264_decoder;
|
||||
extern AVCodec ff_h264_amf_encoder;
|
||||
extern AVCodec ff_h264_cuvid_decoder;
|
||||
extern AVCodec ff_h264_mf_encoder;
|
||||
extern AVCodec ff_h264_nvenc_encoder;
|
||||
extern AVCodec ff_h264_omx_encoder;
|
||||
extern AVCodec ff_h264_qsv_encoder;
|
||||
@ -772,6 +776,7 @@ extern AVCodec ff_nvenc_hevc_encoder;
|
||||
extern AVCodec ff_hevc_amf_encoder;
|
||||
extern AVCodec ff_hevc_cuvid_decoder;
|
||||
extern AVCodec ff_hevc_mediacodec_decoder;
|
||||
extern AVCodec ff_hevc_mf_encoder;
|
||||
extern AVCodec ff_hevc_nvenc_encoder;
|
||||
extern AVCodec ff_hevc_qsv_encoder;
|
||||
extern AVCodec ff_hevc_v4l2m2m_encoder;
|
||||
|
680
libavcodec/mf_utils.c
Normal file
680
libavcodec/mf_utils.c
Normal file
@ -0,0 +1,680 @@
|
||||
/*
|
||||
* 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
|
||||
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0602
|
||||
#endif
|
||||
|
||||
#include "mf_utils.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
|
||||
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid,
|
||||
UINT32 *pw, UINT32 *ph)
|
||||
{
|
||||
UINT64 t;
|
||||
HRESULT hr = IMFAttributes_GetUINT64(pattr, guid, &t);
|
||||
if (!FAILED(hr)) {
|
||||
*pw = t >> 32;
|
||||
*ph = (UINT32)t;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid,
|
||||
UINT32 uw, UINT32 uh)
|
||||
{
|
||||
UINT64 t = (((UINT64)uw) << 32) | uh;
|
||||
return IMFAttributes_SetUINT64(pattr, guid, t);
|
||||
}
|
||||
|
||||
#define ff_MFSetAttributeRatio ff_MFSetAttributeSize
|
||||
#define ff_MFGetAttributeRatio ff_MFGetAttributeSize
|
||||
|
||||
// MFTEnumEx was missing from mingw-w64's mfplat import library until
|
||||
// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress.
|
||||
// It's also missing in Windows Vista's mfplat.dll.
|
||||
HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags,
|
||||
const MFT_REGISTER_TYPE_INFO *pInputType,
|
||||
const MFT_REGISTER_TYPE_INFO *pOutputType,
|
||||
IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate)
|
||||
{
|
||||
HRESULT (WINAPI *MFTEnumEx_ptr)(GUID guidCategory, UINT32 Flags,
|
||||
const MFT_REGISTER_TYPE_INFO *pInputType,
|
||||
const MFT_REGISTER_TYPE_INFO *pOutputType,
|
||||
IMFActivate ***pppMFTActivate,
|
||||
UINT32 *pnumMFTActivate) = NULL;
|
||||
#if !HAVE_UWP
|
||||
HANDLE lib = GetModuleHandleW(L"mfplat.dll");
|
||||
if (lib)
|
||||
MFTEnumEx_ptr = (void *)GetProcAddress(lib, "MFTEnumEx");
|
||||
#else
|
||||
// In UWP (which lacks GetModuleHandle), just link directly against
|
||||
// the functions - this requires building with new/complete enough
|
||||
// import libraries.
|
||||
MFTEnumEx_ptr = MFTEnumEx;
|
||||
#endif
|
||||
if (!MFTEnumEx_ptr)
|
||||
return E_FAIL;
|
||||
return MFTEnumEx_ptr(guidCategory,
|
||||
Flags,
|
||||
pInputType,
|
||||
pOutputType,
|
||||
pppMFTActivate,
|
||||
pnumMFTActivate);
|
||||
}
|
||||
|
||||
char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
|
||||
{
|
||||
#define HR(x) case x: return (char *) # x;
|
||||
switch (hr) {
|
||||
HR(S_OK)
|
||||
HR(E_UNEXPECTED)
|
||||
HR(MF_E_INVALIDMEDIATYPE)
|
||||
HR(MF_E_INVALIDSTREAMNUMBER)
|
||||
HR(MF_E_INVALIDTYPE)
|
||||
HR(MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING)
|
||||
HR(MF_E_TRANSFORM_TYPE_NOT_SET)
|
||||
HR(MF_E_UNSUPPORTED_D3D_TYPE)
|
||||
HR(MF_E_TRANSFORM_NEED_MORE_INPUT)
|
||||
HR(MF_E_TRANSFORM_STREAM_CHANGE)
|
||||
HR(MF_E_NOTACCEPTING)
|
||||
HR(MF_E_NO_SAMPLE_TIMESTAMP)
|
||||
HR(MF_E_NO_SAMPLE_DURATION)
|
||||
#undef HR
|
||||
}
|
||||
snprintf(buf, size, "%x", (unsigned)hr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMFSample *sample;
|
||||
IMFMediaBuffer *buffer;
|
||||
|
||||
hr = MFCreateSample(&sample);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
align = FFMAX(align, 16); // 16 is "recommended", even if not required
|
||||
|
||||
hr = MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
if (fill_data) {
|
||||
BYTE *tmp;
|
||||
|
||||
hr = IMFMediaBuffer_Lock(buffer, &tmp, NULL, NULL);
|
||||
if (FAILED(hr)) {
|
||||
IMFMediaBuffer_Release(buffer);
|
||||
IMFSample_Release(sample);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(tmp, fill_data, size);
|
||||
|
||||
IMFMediaBuffer_SetCurrentLength(buffer, size);
|
||||
IMFMediaBuffer_Unlock(buffer);
|
||||
}
|
||||
|
||||
IMFSample_AddBuffer(sample, buffer);
|
||||
IMFMediaBuffer_Release(buffer);
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT32 bits;
|
||||
GUID subtype;
|
||||
|
||||
hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits);
|
||||
if (FAILED(hr))
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
|
||||
hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
|
||||
if (FAILED(hr))
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
|
||||
if (IsEqualGUID(&subtype, &MFAudioFormat_PCM)) {
|
||||
switch (bits) {
|
||||
case 8: return AV_SAMPLE_FMT_U8;
|
||||
case 16: return AV_SAMPLE_FMT_S16;
|
||||
case 32: return AV_SAMPLE_FMT_S32;
|
||||
}
|
||||
} else if (IsEqualGUID(&subtype, &MFAudioFormat_Float)) {
|
||||
switch (bits) {
|
||||
case 32: return AV_SAMPLE_FMT_FLT;
|
||||
case 64: return AV_SAMPLE_FMT_DBL;
|
||||
}
|
||||
}
|
||||
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
}
|
||||
|
||||
struct mf_pix_fmt_entry {
|
||||
const GUID *guid;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
};
|
||||
|
||||
static const struct mf_pix_fmt_entry mf_pix_fmts[] = {
|
||||
{&MFVideoFormat_IYUV, AV_PIX_FMT_YUV420P},
|
||||
{&MFVideoFormat_I420, AV_PIX_FMT_YUV420P},
|
||||
{&MFVideoFormat_NV12, AV_PIX_FMT_NV12},
|
||||
{&MFVideoFormat_P010, AV_PIX_FMT_P010},
|
||||
{&MFVideoFormat_P016, AV_PIX_FMT_P010}, // not equal, but compatible
|
||||
{&MFVideoFormat_YUY2, AV_PIX_FMT_YUYV422},
|
||||
};
|
||||
|
||||
enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type)
|
||||
{
|
||||
HRESULT hr;
|
||||
GUID subtype;
|
||||
int i;
|
||||
|
||||
hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
|
||||
if (FAILED(hr))
|
||||
return AV_PIX_FMT_NONE;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
|
||||
if (IsEqualGUID(&subtype, mf_pix_fmts[i].guid))
|
||||
return mf_pix_fmts[i].pix_fmt;
|
||||
}
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
|
||||
if (mf_pix_fmts[i].pix_fmt == pix_fmt)
|
||||
return mf_pix_fmts[i].guid;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If this GUID is of the form XXXXXXXX-0000-0010-8000-00AA00389B71, then
|
||||
// extract the XXXXXXXX prefix as FourCC (oh the pain).
|
||||
int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc)
|
||||
{
|
||||
if (guid->Data2 == 0 && guid->Data3 == 0x0010 &&
|
||||
guid->Data4[0] == 0x80 &&
|
||||
guid->Data4[1] == 0x00 &&
|
||||
guid->Data4[2] == 0x00 &&
|
||||
guid->Data4[3] == 0xAA &&
|
||||
guid->Data4[4] == 0x00 &&
|
||||
guid->Data4[5] == 0x38 &&
|
||||
guid->Data4[6] == 0x9B &&
|
||||
guid->Data4[7] == 0x71) {
|
||||
*out_fourcc = guid->Data1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_fourcc = 0;
|
||||
return AVERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
struct GUID_Entry {
|
||||
const GUID *guid;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#define GUID_ENTRY(var) {&(var), # var}
|
||||
|
||||
static struct GUID_Entry guid_names[] = {
|
||||
GUID_ENTRY(MFT_FRIENDLY_NAME_Attribute),
|
||||
GUID_ENTRY(MFT_TRANSFORM_CLSID_Attribute),
|
||||
GUID_ENTRY(MFT_ENUM_HARDWARE_URL_Attribute),
|
||||
GUID_ENTRY(MFT_CONNECTED_STREAM_ATTRIBUTE),
|
||||
GUID_ENTRY(MFT_CONNECTED_TO_HW_STREAM),
|
||||
GUID_ENTRY(MF_SA_D3D_AWARE),
|
||||
GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
|
||||
GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
|
||||
GUID_ENTRY(ff_MF_SA_D3D11_BINDFLAGS),
|
||||
GUID_ENTRY(ff_MF_SA_D3D11_USAGE),
|
||||
GUID_ENTRY(ff_MF_SA_D3D11_AWARE),
|
||||
GUID_ENTRY(ff_MF_SA_D3D11_SHARED),
|
||||
GUID_ENTRY(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
|
||||
GUID_ENTRY(MF_MT_SUBTYPE),
|
||||
GUID_ENTRY(MF_MT_MAJOR_TYPE),
|
||||
GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
|
||||
GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
|
||||
GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
|
||||
GUID_ENTRY(MF_MT_FRAME_SIZE),
|
||||
GUID_ENTRY(MF_MT_INTERLACE_MODE),
|
||||
GUID_ENTRY(MF_MT_USER_DATA),
|
||||
GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
|
||||
GUID_ENTRY(MFMediaType_Audio),
|
||||
GUID_ENTRY(MFMediaType_Video),
|
||||
GUID_ENTRY(MFAudioFormat_PCM),
|
||||
GUID_ENTRY(MFAudioFormat_Float),
|
||||
GUID_ENTRY(MFVideoFormat_H264),
|
||||
GUID_ENTRY(MFVideoFormat_H264_ES),
|
||||
GUID_ENTRY(ff_MFVideoFormat_HEVC),
|
||||
GUID_ENTRY(ff_MFVideoFormat_HEVC_ES),
|
||||
GUID_ENTRY(MFVideoFormat_MPEG2),
|
||||
GUID_ENTRY(MFVideoFormat_MP43),
|
||||
GUID_ENTRY(MFVideoFormat_MP4V),
|
||||
GUID_ENTRY(MFVideoFormat_WMV1),
|
||||
GUID_ENTRY(MFVideoFormat_WMV2),
|
||||
GUID_ENTRY(MFVideoFormat_WMV3),
|
||||
GUID_ENTRY(MFVideoFormat_WVC1),
|
||||
GUID_ENTRY(MFAudioFormat_Dolby_AC3),
|
||||
GUID_ENTRY(MFAudioFormat_Dolby_DDPlus),
|
||||
GUID_ENTRY(MFAudioFormat_AAC),
|
||||
GUID_ENTRY(MFAudioFormat_MP3),
|
||||
GUID_ENTRY(MFAudioFormat_MSP1),
|
||||
GUID_ENTRY(MFAudioFormat_WMAudioV8),
|
||||
GUID_ENTRY(MFAudioFormat_WMAudioV9),
|
||||
GUID_ENTRY(MFAudioFormat_WMAudio_Lossless),
|
||||
GUID_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT),
|
||||
GUID_ENTRY(MF_MT_COMPRESSED),
|
||||
GUID_ENTRY(MF_MT_FIXED_SIZE_SAMPLES),
|
||||
GUID_ENTRY(MF_MT_SAMPLE_SIZE),
|
||||
GUID_ENTRY(MF_MT_WRAPPED_TYPE),
|
||||
GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
|
||||
GUID_ENTRY(MF_MT_AAC_PAYLOAD_TYPE),
|
||||
GUID_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
|
||||
GUID_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE),
|
||||
GUID_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT),
|
||||
GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
|
||||
GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
|
||||
GUID_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX),
|
||||
GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
|
||||
GUID_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
|
||||
GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
|
||||
GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
|
||||
GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
|
||||
GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF),
|
||||
GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET),
|
||||
GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF),
|
||||
GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET),
|
||||
GUID_ENTRY(MF_MT_AVG_BIT_ERROR_RATE),
|
||||
GUID_ENTRY(MF_MT_AVG_BITRATE),
|
||||
GUID_ENTRY(MF_MT_DEFAULT_STRIDE),
|
||||
GUID_ENTRY(MF_MT_DRM_FLAGS),
|
||||
GUID_ENTRY(MF_MT_FRAME_RATE),
|
||||
GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX),
|
||||
GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN),
|
||||
GUID_ENTRY(MF_MT_FRAME_SIZE),
|
||||
GUID_ENTRY(MF_MT_GEOMETRIC_APERTURE),
|
||||
GUID_ENTRY(MF_MT_INTERLACE_MODE),
|
||||
GUID_ENTRY(MF_MT_MAX_KEYFRAME_SPACING),
|
||||
GUID_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE),
|
||||
GUID_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER),
|
||||
GUID_ENTRY(MF_MT_MPEG_START_TIME_CODE),
|
||||
GUID_ENTRY(MF_MT_MPEG2_FLAGS),
|
||||
GUID_ENTRY(MF_MT_MPEG2_LEVEL),
|
||||
GUID_ENTRY(MF_MT_MPEG2_PROFILE),
|
||||
GUID_ENTRY(MF_MT_PAD_CONTROL_FLAGS),
|
||||
GUID_ENTRY(MF_MT_PALETTE),
|
||||
GUID_ENTRY(MF_MT_PAN_SCAN_APERTURE),
|
||||
GUID_ENTRY(MF_MT_PAN_SCAN_ENABLED),
|
||||
GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
|
||||
GUID_ENTRY(MF_MT_SOURCE_CONTENT_HINT),
|
||||
GUID_ENTRY(MF_MT_TRANSFER_FUNCTION),
|
||||
GUID_ENTRY(MF_MT_VIDEO_CHROMA_SITING),
|
||||
GUID_ENTRY(MF_MT_VIDEO_LIGHTING),
|
||||
GUID_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE),
|
||||
GUID_ENTRY(MF_MT_VIDEO_PRIMARIES),
|
||||
GUID_ENTRY(MF_MT_VIDEO_ROTATION),
|
||||
GUID_ENTRY(MF_MT_YUV_MATRIX),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
|
||||
GUID_ENTRY(ff_CODECAPI_AVLowLatencyMode),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoCodecType),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVAMode),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVABusEncryption),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoSWPowerLevel),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedWidth),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedHeight),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecNumWorkerThreads),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecSoftwareDynamicFormatChange),
|
||||
GUID_ENTRY(ff_CODECAPI_AVDecDisableVideoPostProcessing),
|
||||
};
|
||||
|
||||
char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
|
||||
{
|
||||
uint32_t fourcc;
|
||||
int n;
|
||||
for (n = 0; n < FF_ARRAY_ELEMS(guid_names); n++) {
|
||||
if (IsEqualGUID(guid, guid_names[n].guid)) {
|
||||
snprintf(buf, buf_size, "%s", guid_names[n].name);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
if (ff_fourcc_from_guid(guid, &fourcc) >= 0) {
|
||||
snprintf(buf, buf_size, "<FourCC %s>", av_fourcc2str(fourcc));
|
||||
return buf;
|
||||
}
|
||||
|
||||
snprintf(buf, buf_size,
|
||||
"{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
|
||||
(unsigned) guid->Data1, guid->Data2, guid->Data3,
|
||||
guid->Data4[0], guid->Data4[1],
|
||||
guid->Data4[2], guid->Data4[3],
|
||||
guid->Data4[4], guid->Data4[5],
|
||||
guid->Data4[6], guid->Data4[7]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ff_attributes_dump(void *log, IMFAttributes *attrs)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT32 count;
|
||||
int n;
|
||||
|
||||
hr = IMFAttributes_GetCount(attrs, &count);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
GUID key;
|
||||
MF_ATTRIBUTE_TYPE type;
|
||||
char extra[80] = {0};
|
||||
const char *name = NULL;
|
||||
|
||||
hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
|
||||
name = ff_guid_str(&key);
|
||||
|
||||
if (IsEqualGUID(&key, &MF_MT_AUDIO_CHANNEL_MASK)) {
|
||||
UINT32 v;
|
||||
hr = IMFAttributes_GetUINT32(attrs, &key, &v);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
snprintf(extra, sizeof(extra), " (0x%x)", (unsigned)v);
|
||||
} else if (IsEqualGUID(&key, &MF_MT_FRAME_SIZE)) {
|
||||
UINT32 w, h;
|
||||
|
||||
hr = ff_MFGetAttributeSize(attrs, &MF_MT_FRAME_SIZE, &w, &h);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
snprintf(extra, sizeof(extra), " (%dx%d)", (int)w, (int)h);
|
||||
} else if (IsEqualGUID(&key, &MF_MT_PIXEL_ASPECT_RATIO) ||
|
||||
IsEqualGUID(&key, &MF_MT_FRAME_RATE)) {
|
||||
UINT32 num, den;
|
||||
|
||||
hr = ff_MFGetAttributeRatio(attrs, &key, &num, &den);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
snprintf(extra, sizeof(extra), " (%d:%d)", (int)num, (int)den);
|
||||
}
|
||||
|
||||
hr = IMFAttributes_GetItemType(attrs, &key, &type);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
|
||||
switch (type) {
|
||||
case MF_ATTRIBUTE_UINT32: {
|
||||
UINT32 v;
|
||||
hr = IMFAttributes_GetUINT32(attrs, &key, &v);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=%d%s\n", name, (int)v, extra);
|
||||
break;
|
||||
case MF_ATTRIBUTE_UINT64: {
|
||||
UINT64 v;
|
||||
hr = IMFAttributes_GetUINT64(attrs, &key, &v);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=%lld%s\n", name, (long long)v, extra);
|
||||
break;
|
||||
}
|
||||
case MF_ATTRIBUTE_DOUBLE: {
|
||||
DOUBLE v;
|
||||
hr = IMFAttributes_GetDouble(attrs, &key, &v);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=%f%s\n", name, (double)v, extra);
|
||||
break;
|
||||
}
|
||||
case MF_ATTRIBUTE_STRING: {
|
||||
wchar_t s[512]; // being lazy here
|
||||
hr = IMFAttributes_GetString(attrs, &key, s, sizeof(s), NULL);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s='%ls'%s\n", name, s, extra);
|
||||
break;
|
||||
}
|
||||
case MF_ATTRIBUTE_GUID: {
|
||||
GUID v;
|
||||
hr = IMFAttributes_GetGUID(attrs, &key, &v);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=%s%s\n", name, ff_guid_str(&v), extra);
|
||||
break;
|
||||
}
|
||||
case MF_ATTRIBUTE_BLOB: {
|
||||
UINT32 sz;
|
||||
UINT8 buffer[100];
|
||||
hr = IMFAttributes_GetBlobSize(attrs, &key, &sz);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
if (sz <= sizeof(buffer)) {
|
||||
// hex-dump it
|
||||
char str[512] = {0};
|
||||
size_t pos = 0;
|
||||
hr = IMFAttributes_GetBlob(attrs, &key, buffer, sizeof(buffer), &sz);
|
||||
if (FAILED(hr))
|
||||
goto err;
|
||||
for (pos = 0; pos < sz; pos++) {
|
||||
const char *hex = "0123456789ABCDEF";
|
||||
if (pos * 3 + 3 > sizeof(str))
|
||||
break;
|
||||
str[pos * 3 + 0] = hex[buffer[pos] >> 4];
|
||||
str[pos * 3 + 1] = hex[buffer[pos] & 15];
|
||||
str[pos * 3 + 2] = ' ';
|
||||
}
|
||||
str[pos * 3 + 0] = 0;
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d: %s>%s\n", name, (int)sz, str, extra);
|
||||
} else {
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d>%s\n", name, (int)sz, extra);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MF_ATTRIBUTE_IUNKNOWN: {
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=<IUnknown>%s\n", name, extra);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=<unknown type>%s\n", name, extra);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) {
|
||||
const char *fmt;
|
||||
fmt = av_get_sample_fmt_name(ff_media_type_to_sample_fmt(attrs));
|
||||
if (fmt)
|
||||
av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt);
|
||||
|
||||
fmt = av_get_pix_fmt_name(ff_media_type_to_pix_fmt(attrs));
|
||||
if (fmt)
|
||||
av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt);
|
||||
}
|
||||
|
||||
continue;
|
||||
err:
|
||||
av_log(log, AV_LOG_VERBOSE, " %s=<failed to get value>\n", name ? name : "?");
|
||||
}
|
||||
}
|
||||
|
||||
void ff_media_type_dump(void *log, IMFMediaType *type)
|
||||
{
|
||||
ff_attributes_dump(log, (IMFAttributes *)type);
|
||||
}
|
||||
|
||||
const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec)
|
||||
{
|
||||
switch (codec) {
|
||||
case AV_CODEC_ID_H264: return &MFVideoFormat_H264;
|
||||
case AV_CODEC_ID_HEVC: return &ff_MFVideoFormat_HEVC;
|
||||
case AV_CODEC_ID_AC3: return &MFAudioFormat_Dolby_AC3;
|
||||
case AV_CODEC_ID_AAC: return &MFAudioFormat_AAC;
|
||||
case AV_CODEC_ID_MP3: return &MFAudioFormat_MP3;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int init_com_mf(void *log)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (hr == RPC_E_CHANGED_MODE) {
|
||||
av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n");
|
||||
return AVERROR(EINVAL);
|
||||
} else if (FAILED(hr)) {
|
||||
av_log(log, AV_LOG_ERROR, "could not initialize COM\n");
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
|
||||
if (FAILED(hr)) {
|
||||
av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n");
|
||||
CoUninitialize();
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uninit_com_mf(void)
|
||||
{
|
||||
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,
|
||||
GUID category,
|
||||
MFT_REGISTER_TYPE_INFO *in_type,
|
||||
MFT_REGISTER_TYPE_INFO *out_type,
|
||||
int use_hw,
|
||||
IMFTransform **res)
|
||||
{
|
||||
HRESULT hr;
|
||||
int n;
|
||||
int ret;
|
||||
IMFActivate **activate;
|
||||
UINT32 num_activate;
|
||||
IMFActivate *winner = 0;
|
||||
UINT32 flags;
|
||||
|
||||
ret = init_com_mf(log);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
flags = MFT_ENUM_FLAG_SORTANDFILTER;
|
||||
|
||||
if (use_hw) {
|
||||
flags |= MFT_ENUM_FLAG_HARDWARE;
|
||||
} else {
|
||||
flags |= MFT_ENUM_FLAG_SYNCMFT;
|
||||
}
|
||||
|
||||
hr = ff_MFTEnumEx(category, flags, in_type, out_type, &activate,
|
||||
&num_activate);
|
||||
if (FAILED(hr))
|
||||
goto error_uninit_mf;
|
||||
|
||||
if (log) {
|
||||
if (!num_activate)
|
||||
av_log(log, AV_LOG_ERROR, "could not find any MFT for the given media type\n");
|
||||
|
||||
for (n = 0; n < num_activate; n++) {
|
||||
av_log(log, AV_LOG_VERBOSE, "MF %d attributes:\n", n);
|
||||
ff_attributes_dump(log, (IMFAttributes *)activate[n]);
|
||||
}
|
||||
}
|
||||
|
||||
*res = NULL;
|
||||
for (n = 0; n < num_activate; n++) {
|
||||
if (log)
|
||||
av_log(log, AV_LOG_VERBOSE, "activate MFT %d\n", n);
|
||||
hr = IMFActivate_ActivateObject(activate[n], &IID_IMFTransform,
|
||||
(void **)res);
|
||||
if (*res) {
|
||||
winner = activate[n];
|
||||
IMFActivate_AddRef(winner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0; n < num_activate; n++)
|
||||
IMFActivate_Release(activate[n]);
|
||||
CoTaskMemFree(activate);
|
||||
|
||||
if (!*res) {
|
||||
if (log)
|
||||
av_log(log, AV_LOG_ERROR, "could not create MFT\n");
|
||||
goto error_uninit_mf;
|
||||
}
|
||||
|
||||
if (log) {
|
||||
wchar_t s[512]; // being lazy here
|
||||
IMFAttributes *attrs;
|
||||
hr = IMFTransform_GetAttributes(*res, &attrs);
|
||||
if (!FAILED(hr) && attrs) {
|
||||
|
||||
av_log(log, AV_LOG_VERBOSE, "MFT attributes\n");
|
||||
ff_attributes_dump(log, attrs);
|
||||
IMFAttributes_Release(attrs);
|
||||
}
|
||||
|
||||
hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute, s,
|
||||
sizeof(s), NULL);
|
||||
if (!FAILED(hr))
|
||||
av_log(log, AV_LOG_INFO, "MFT name: '%ls'\n", s);
|
||||
|
||||
}
|
||||
|
||||
IMFActivate_Release(winner);
|
||||
|
||||
return 0;
|
||||
|
||||
error_uninit_mf:
|
||||
uninit_com_mf();
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
void ff_free_mf(IMFTransform **mft)
|
||||
{
|
||||
if (*mft)
|
||||
IMFTransform_Release(*mft);
|
||||
*mft = NULL;
|
||||
uninit_com_mf();
|
||||
}
|
159
libavcodec/mf_utils.h
Normal file
159
libavcodec/mf_utils.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_MF_UTILS_H
|
||||
#define AVCODEC_MF_UTILS_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
#ifdef _MSC_VER
|
||||
// The official way of including codecapi (via dshow.h) makes the ICodecAPI
|
||||
// interface unavailable in UWP mode, but including icodecapi.h + codecapi.h
|
||||
// seems to be equivalent. (These headers conflict with the official way
|
||||
// of including it though, through strmif.h via dshow.h. And on mingw, the
|
||||
// mf*.h headers below indirectly include strmif.h.)
|
||||
#include <icodecapi.h>
|
||||
#else
|
||||
#include <dshow.h>
|
||||
#endif
|
||||
// Older versions of mingw-w64 need codecapi.h explicitly included, while newer
|
||||
// ones include it implicitly from dshow.h (via uuids.h).
|
||||
#include <codecapi.h>
|
||||
#include <mfapi.h>
|
||||
#include <mferror.h>
|
||||
#include <mfobjects.h>
|
||||
#include <mftransform.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
// These functions do exist in mfapi.h, but are only available within
|
||||
// __cplusplus ifdefs.
|
||||
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid,
|
||||
UINT32 *pw, UINT32 *ph);
|
||||
HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid,
|
||||
UINT32 uw, UINT32 uh);
|
||||
#define ff_MFSetAttributeRatio ff_MFSetAttributeSize
|
||||
#define ff_MFGetAttributeRatio ff_MFGetAttributeSize
|
||||
|
||||
// MFTEnumEx was missing from mingw-w64's mfplat import library until
|
||||
// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress.
|
||||
// It's also missing in Windows Vista's mfplat.dll.
|
||||
HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags,
|
||||
const MFT_REGISTER_TYPE_INFO *pInputType,
|
||||
const MFT_REGISTER_TYPE_INFO *pOutputType,
|
||||
IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate);
|
||||
|
||||
|
||||
// These do exist in mingw-w64's codecapi.h, but they aren't properly defined
|
||||
// by the header until after mingw-w64 v7.0.0.
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoThumbnailGenerationMode, 0x2efd8eee,0x1150,0x4328,0x9c,0xf5,0x66,0xdc,0xe9,0x33,0xfc,0xf4);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoDropPicWithMissingRef, 0xf8226383,0x14c2,0x4567,0x97,0x34,0x50,0x04,0xe9,0x6f,0xf8,0x87);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode, 0x0c08d1ce,0x9ced,0x4540,0xba,0xe3,0xce,0xb3,0x80,0x14,0x11,0x09);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoFastDecodeMode, 0x6b529f7d,0xd3b1,0x49c6,0xa9,0x99,0x9e,0xc6,0x91,0x1b,0xed,0xbf);
|
||||
DEFINE_GUID(ff_CODECAPI_AVLowLatencyMode, 0x9c27891a,0xed7a,0x40e1,0x88,0xe8,0xb2,0x27,0x27,0xa0,0x24,0xee);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoH264ErrorConcealment, 0xececace8,0x3436,0x462c,0x92,0x94,0xcd,0x7b,0xac,0xd7,0x58,0xa9);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment, 0x9d2bfe18,0x728d,0x48d2,0xb3,0x58,0xbc,0x7e,0x43,0x6c,0x66,0x74);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoCodecType, 0x434528e5,0x21f0,0x46b6,0xb6,0x2c,0x9b,0x1b,0x6b,0x65,0x8c,0xd1);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoDXVAMode, 0xf758f09e,0x7337,0x4ae7,0x83,0x87,0x73,0xdc,0x2d,0x54,0xe6,0x7d);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoDXVABusEncryption, 0x42153c8b,0xfd0b,0x4765,0xa4,0x62,0xdd,0xd9,0xe8,0xbc,0xc3,0x88);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoSWPowerLevel, 0xfb5d2347,0x4dd8,0x4509,0xae,0xd0,0xdb,0x5f,0xa9,0xaa,0x93,0xf4);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoMaxCodedWidth, 0x5ae557b8,0x77af,0x41f5,0x9f,0xa6,0x4d,0xb2,0xfe,0x1d,0x4b,0xca);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecVideoMaxCodedHeight, 0x7262a16a,0xd2dc,0x4e75,0x9b,0xa8,0x65,0xc0,0xc6,0xd3,0x2b,0x13);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecNumWorkerThreads, 0x9561c3e8,0xea9e,0x4435,0x9b,0x1e,0xa9,0x3e,0x69,0x18,0x94,0xd8);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecSoftwareDynamicFormatChange, 0x862e2f0a,0x507b,0x47ff,0xaf,0x47,0x01,0xe2,0x62,0x42,0x98,0xb7);
|
||||
DEFINE_GUID(ff_CODECAPI_AVDecDisableVideoPostProcessing, 0xf8749193,0x667a,0x4f2c,0xa9,0xe8,0x5d,0x4a,0xf9,0x24,0xf0,0x8f);
|
||||
|
||||
// These are missing from mingw-w64's headers until after mingw-w64 v7.0.0.
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncCommonRateControlMode, 0x1c0608e9, 0x370c, 0x4710, 0x8a, 0x58, 0xcb, 0x61, 0x81, 0xc4, 0x24, 0x23);
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncCommonQuality, 0xfcbf57a3, 0x7ea5, 0x4b0c, 0x96, 0x44, 0x69, 0xb4, 0x0c, 0x39, 0xc3, 0x91);
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncCommonMeanBitRate, 0xf7222374, 0x2144, 0x4815, 0xb5, 0x50, 0xa3, 0x7f, 0x8e, 0x12, 0xee, 0x52);
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncH264CABACEnable, 0xee6cad62, 0xd305, 0x4248, 0xa5, 0xe, 0xe1, 0xb2, 0x55, 0xf7, 0xca, 0xf8);
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncVideoForceKeyFrame, 0x398c1b98, 0x8353, 0x475a, 0x9e, 0xf2, 0x8f, 0x26, 0x5d, 0x26, 0x3, 0x45);
|
||||
DEFINE_GUID(ff_CODECAPI_AVEncMPVDefaultBPictureCount, 0x8d390aac, 0xdc5c, 0x4200, 0xb5, 0x7f, 0x81, 0x4d, 0x04, 0xba, 0xba, 0xb2);
|
||||
DEFINE_GUID(ff_CODECAPI_AVScenarioInfo, 0xb28a6e64,0x3ff9,0x446a,0x8a,0x4b,0x0d,0x7a,0x53,0x41,0x32,0x36);
|
||||
|
||||
DEFINE_GUID(ff_MF_SA_D3D11_BINDFLAGS, 0xeacf97ad, 0x065c, 0x4408, 0xbe, 0xe3, 0xfd, 0xcb, 0xfd, 0x12, 0x8b, 0xe2);
|
||||
DEFINE_GUID(ff_MF_SA_D3D11_USAGE, 0xe85fe442, 0x2ca3, 0x486e, 0xa9, 0xc7, 0x10, 0x9d, 0xda, 0x60, 0x98, 0x80);
|
||||
DEFINE_GUID(ff_MF_SA_D3D11_AWARE, 0x206b4fc8, 0xfcf9, 0x4c51, 0xaf, 0xe3, 0x97, 0x64, 0x36, 0x9e, 0x33, 0xa0);
|
||||
DEFINE_GUID(ff_MF_SA_D3D11_SHARED, 0x7b8f32c3, 0x6d96, 0x4b89, 0x92, 0x3, 0xdd, 0x38, 0xb6, 0x14, 0x14, 0xf3);
|
||||
DEFINE_GUID(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX, 0x39dbd44d, 0x2e44, 0x4931, 0xa4, 0xc8, 0x35, 0x2d, 0x3d, 0xc4, 0x21, 0x15);
|
||||
DEFINE_GUID(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, 0x851745d5, 0xc3d6, 0x476d, 0x95, 0x27, 0x49, 0x8e, 0xf2, 0xd1, 0xd, 0x18);
|
||||
DEFINE_GUID(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE, 0xf5523a5, 0x1cb2, 0x47c5, 0xa5, 0x50, 0x2e, 0xeb, 0x84, 0xb4, 0xd1, 0x4a);
|
||||
|
||||
DEFINE_MEDIATYPE_GUID(ff_MFVideoFormat_HEVC, 0x43564548); // FCC('HEVC')
|
||||
DEFINE_MEDIATYPE_GUID(ff_MFVideoFormat_HEVC_ES, 0x53564548); // FCC('HEVS')
|
||||
|
||||
|
||||
// This enum is missing from mingw-w64's codecapi.h by v7.0.0.
|
||||
enum ff_eAVEncCommonRateControlMode {
|
||||
ff_eAVEncCommonRateControlMode_CBR = 0,
|
||||
ff_eAVEncCommonRateControlMode_PeakConstrainedVBR = 1,
|
||||
ff_eAVEncCommonRateControlMode_UnconstrainedVBR = 2,
|
||||
ff_eAVEncCommonRateControlMode_Quality = 3,
|
||||
ff_eAVEncCommonRateControlMode_LowDelayVBR = 4,
|
||||
ff_eAVEncCommonRateControlMode_GlobalVBR = 5,
|
||||
ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR = 6
|
||||
};
|
||||
|
||||
enum ff_eAVScenarioInfo {
|
||||
ff_eAVScenarioInfo_Unknown = 0,
|
||||
ff_eAVScenarioInfo_DisplayRemoting = 1,
|
||||
ff_eAVScenarioInfo_VideoConference = 2,
|
||||
ff_eAVScenarioInfo_Archive = 3,
|
||||
ff_eAVScenarioInfo_LiveStreaming = 4,
|
||||
ff_eAVScenarioInfo_CameraRecord = 5,
|
||||
ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap = 6
|
||||
};
|
||||
|
||||
// These do exist in mingw-w64's mfobjects.idl, but are missing from
|
||||
// mfobjects.h that is generated from the former, due to incorrect use of
|
||||
// ifdefs in the IDL file.
|
||||
enum {
|
||||
ff_METransformUnknown = 600,
|
||||
ff_METransformNeedInput,
|
||||
ff_METransformHaveOutput,
|
||||
ff_METransformDrainComplete,
|
||||
ff_METransformMarker,
|
||||
};
|
||||
|
||||
char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr);
|
||||
#define ff_hr_str(hr) ff_hr_str_buf((char[80]){0}, 80, hr)
|
||||
|
||||
// Possibly compiler-dependent; the MS/MinGW definition for this is just crazy.
|
||||
#define FF_VARIANT_VALUE(type, contents) &(VARIANT){ .vt = (type), contents }
|
||||
|
||||
#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);
|
||||
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);
|
||||
int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc);
|
||||
char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid);
|
||||
#define ff_guid_str(guid) ff_guid_str_buf((char[80]){0}, 80, 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,
|
||||
MFT_REGISTER_TYPE_INFO *in_type,
|
||||
MFT_REGISTER_TYPE_INFO *out_type,
|
||||
int use_hw, IMFTransform **res);
|
||||
void ff_free_mf(IMFTransform **mft);
|
||||
|
||||
#endif
|
1192
libavcodec/mfenc.c
Normal file
1192
libavcodec/mfenc.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 58
|
||||
#define LIBAVCODEC_VERSION_MINOR 85
|
||||
#define LIBAVCODEC_VERSION_MINOR 86
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user