avformat/mpeg: demux ivtv captions
[ffmpeg.git] / libavcodec / mf_utils.c
blobff44130ca9563edcd021020304ca8a5b8a3886bb
1 /*
2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #define COBJMACROS
20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
21 #undef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0602
23 #endif
25 #include "mf_utils.h"
26 #include "libavutil/pixdesc.h"
28 HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid,
29 UINT32 *pw, UINT32 *ph)
31 UINT64 t;
32 HRESULT hr = IMFAttributes_GetUINT64(pattr, guid, &t);
33 if (!FAILED(hr)) {
34 *pw = t >> 32;
35 *ph = (UINT32)t;
37 return hr;
40 HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid,
41 UINT32 uw, UINT32 uh)
43 UINT64 t = (((UINT64)uw) << 32) | uh;
44 return IMFAttributes_SetUINT64(pattr, guid, t);
47 #define ff_MFSetAttributeRatio ff_MFSetAttributeSize
48 #define ff_MFGetAttributeRatio ff_MFGetAttributeSize
50 char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
52 #define HR(x) case x: return (char *) # x;
53 switch (hr) {
54 HR(S_OK)
55 HR(E_UNEXPECTED)
56 HR(MF_E_INVALIDMEDIATYPE)
57 HR(MF_E_INVALIDSTREAMNUMBER)
58 HR(MF_E_INVALIDTYPE)
59 HR(MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING)
60 HR(MF_E_TRANSFORM_TYPE_NOT_SET)
61 HR(MF_E_UNSUPPORTED_D3D_TYPE)
62 HR(MF_E_TRANSFORM_NEED_MORE_INPUT)
63 HR(MF_E_TRANSFORM_STREAM_CHANGE)
64 HR(MF_E_NOTACCEPTING)
65 HR(MF_E_NO_SAMPLE_TIMESTAMP)
66 HR(MF_E_NO_SAMPLE_DURATION)
67 #undef HR
69 snprintf(buf, size, "%x", (unsigned)hr);
70 return buf;
73 // If fill_data!=NULL, initialize the buffer and set the length. (This is a
74 // subtle but important difference: some decoders want CurrentLength==0 on
75 // provided output buffers.)
76 IMFSample *ff_create_memory_sample(MFFunctions *f,void *fill_data, size_t size,
77 size_t align)
79 HRESULT hr;
80 IMFSample *sample;
81 IMFMediaBuffer *buffer;
83 hr = f->MFCreateSample(&sample);
84 if (FAILED(hr))
85 return NULL;
87 align = FFMAX(align, 16); // 16 is "recommended", even if not required
89 hr = f->MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
90 if (FAILED(hr))
91 return NULL;
93 if (fill_data) {
94 BYTE *tmp;
96 hr = IMFMediaBuffer_Lock(buffer, &tmp, NULL, NULL);
97 if (FAILED(hr)) {
98 IMFMediaBuffer_Release(buffer);
99 IMFSample_Release(sample);
100 return NULL;
102 memcpy(tmp, fill_data, size);
104 IMFMediaBuffer_SetCurrentLength(buffer, size);
105 IMFMediaBuffer_Unlock(buffer);
108 IMFSample_AddBuffer(sample, buffer);
109 IMFMediaBuffer_Release(buffer);
111 return sample;
114 enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type)
116 HRESULT hr;
117 UINT32 bits;
118 GUID subtype;
120 hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits);
121 if (FAILED(hr))
122 return AV_SAMPLE_FMT_NONE;
124 hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
125 if (FAILED(hr))
126 return AV_SAMPLE_FMT_NONE;
128 if (IsEqualGUID(&subtype, &MFAudioFormat_PCM)) {
129 switch (bits) {
130 case 8: return AV_SAMPLE_FMT_U8;
131 case 16: return AV_SAMPLE_FMT_S16;
132 case 32: return AV_SAMPLE_FMT_S32;
134 } else if (IsEqualGUID(&subtype, &MFAudioFormat_Float)) {
135 switch (bits) {
136 case 32: return AV_SAMPLE_FMT_FLT;
137 case 64: return AV_SAMPLE_FMT_DBL;
141 return AV_SAMPLE_FMT_NONE;
144 struct mf_pix_fmt_entry {
145 const GUID *guid;
146 enum AVPixelFormat pix_fmt;
149 static const struct mf_pix_fmt_entry mf_pix_fmts[] = {
150 {&MFVideoFormat_IYUV, AV_PIX_FMT_YUV420P},
151 {&MFVideoFormat_I420, AV_PIX_FMT_YUV420P},
152 {&MFVideoFormat_NV12, AV_PIX_FMT_NV12},
153 {&MFVideoFormat_P010, AV_PIX_FMT_P010},
154 {&MFVideoFormat_P016, AV_PIX_FMT_P010}, // not equal, but compatible
155 {&MFVideoFormat_YUY2, AV_PIX_FMT_YUYV422},
158 enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type)
160 HRESULT hr;
161 GUID subtype;
162 int i;
164 hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
165 if (FAILED(hr))
166 return AV_PIX_FMT_NONE;
168 for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
169 if (IsEqualGUID(&subtype, mf_pix_fmts[i].guid))
170 return mf_pix_fmts[i].pix_fmt;
173 return AV_PIX_FMT_NONE;
176 const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt)
178 int i;
180 for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
181 if (mf_pix_fmts[i].pix_fmt == pix_fmt)
182 return mf_pix_fmts[i].guid;
185 return NULL;
188 // If this GUID is of the form XXXXXXXX-0000-0010-8000-00AA00389B71, then
189 // extract the XXXXXXXX prefix as FourCC (oh the pain).
190 int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc)
192 if (guid->Data2 == 0 && guid->Data3 == 0x0010 &&
193 guid->Data4[0] == 0x80 &&
194 guid->Data4[1] == 0x00 &&
195 guid->Data4[2] == 0x00 &&
196 guid->Data4[3] == 0xAA &&
197 guid->Data4[4] == 0x00 &&
198 guid->Data4[5] == 0x38 &&
199 guid->Data4[6] == 0x9B &&
200 guid->Data4[7] == 0x71) {
201 *out_fourcc = guid->Data1;
202 return 0;
205 *out_fourcc = 0;
206 return AVERROR_UNKNOWN;
209 struct GUID_Entry {
210 const GUID *guid;
211 const char *name;
214 #define GUID_ENTRY(var) {&(var), # var}
216 static struct GUID_Entry guid_names[] = {
217 GUID_ENTRY(MFT_FRIENDLY_NAME_Attribute),
218 GUID_ENTRY(MFT_TRANSFORM_CLSID_Attribute),
219 GUID_ENTRY(MFT_ENUM_HARDWARE_URL_Attribute),
220 GUID_ENTRY(MFT_CONNECTED_STREAM_ATTRIBUTE),
221 GUID_ENTRY(MFT_CONNECTED_TO_HW_STREAM),
222 GUID_ENTRY(MF_SA_D3D_AWARE),
223 GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
224 GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
225 GUID_ENTRY(ff_MF_SA_D3D11_BINDFLAGS),
226 GUID_ENTRY(ff_MF_SA_D3D11_USAGE),
227 GUID_ENTRY(ff_MF_SA_D3D11_AWARE),
228 GUID_ENTRY(ff_MF_SA_D3D11_SHARED),
229 GUID_ENTRY(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
230 GUID_ENTRY(MF_MT_SUBTYPE),
231 GUID_ENTRY(MF_MT_MAJOR_TYPE),
232 GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
233 GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
234 GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
235 GUID_ENTRY(MF_MT_FRAME_SIZE),
236 GUID_ENTRY(MF_MT_INTERLACE_MODE),
237 GUID_ENTRY(MF_MT_USER_DATA),
238 GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
239 GUID_ENTRY(MFMediaType_Audio),
240 GUID_ENTRY(MFMediaType_Video),
241 GUID_ENTRY(MFAudioFormat_PCM),
242 GUID_ENTRY(MFAudioFormat_Float),
243 GUID_ENTRY(ff_MFVideoFormat_AV1),
244 GUID_ENTRY(MFVideoFormat_H264),
245 GUID_ENTRY(MFVideoFormat_H264_ES),
246 GUID_ENTRY(ff_MFVideoFormat_HEVC),
247 GUID_ENTRY(ff_MFVideoFormat_HEVC_ES),
248 GUID_ENTRY(MFVideoFormat_MPEG2),
249 GUID_ENTRY(MFVideoFormat_MP43),
250 GUID_ENTRY(MFVideoFormat_MP4V),
251 GUID_ENTRY(MFVideoFormat_WMV1),
252 GUID_ENTRY(MFVideoFormat_WMV2),
253 GUID_ENTRY(MFVideoFormat_WMV3),
254 GUID_ENTRY(MFVideoFormat_WVC1),
255 GUID_ENTRY(MFAudioFormat_Dolby_AC3),
256 GUID_ENTRY(MFAudioFormat_Dolby_DDPlus),
257 GUID_ENTRY(MFAudioFormat_AAC),
258 GUID_ENTRY(MFAudioFormat_MP3),
259 GUID_ENTRY(MFAudioFormat_MSP1),
260 GUID_ENTRY(MFAudioFormat_WMAudioV8),
261 GUID_ENTRY(MFAudioFormat_WMAudioV9),
262 GUID_ENTRY(MFAudioFormat_WMAudio_Lossless),
263 GUID_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT),
264 GUID_ENTRY(MF_MT_COMPRESSED),
265 GUID_ENTRY(MF_MT_FIXED_SIZE_SAMPLES),
266 GUID_ENTRY(MF_MT_SAMPLE_SIZE),
267 GUID_ENTRY(MF_MT_WRAPPED_TYPE),
268 GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
269 GUID_ENTRY(MF_MT_AAC_PAYLOAD_TYPE),
270 GUID_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
271 GUID_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE),
272 GUID_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT),
273 GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
274 GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
275 GUID_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX),
276 GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
277 GUID_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
278 GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
279 GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
280 GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
281 GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF),
282 GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET),
283 GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF),
284 GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET),
285 GUID_ENTRY(MF_MT_AVG_BIT_ERROR_RATE),
286 GUID_ENTRY(MF_MT_AVG_BITRATE),
287 GUID_ENTRY(MF_MT_DEFAULT_STRIDE),
288 GUID_ENTRY(MF_MT_DRM_FLAGS),
289 GUID_ENTRY(MF_MT_FRAME_RATE),
290 GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX),
291 GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN),
292 GUID_ENTRY(MF_MT_FRAME_SIZE),
293 GUID_ENTRY(MF_MT_GEOMETRIC_APERTURE),
294 GUID_ENTRY(MF_MT_INTERLACE_MODE),
295 GUID_ENTRY(MF_MT_MAX_KEYFRAME_SPACING),
296 GUID_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE),
297 GUID_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER),
298 GUID_ENTRY(MF_MT_MPEG_START_TIME_CODE),
299 GUID_ENTRY(MF_MT_MPEG2_FLAGS),
300 GUID_ENTRY(MF_MT_MPEG2_LEVEL),
301 GUID_ENTRY(MF_MT_MPEG2_PROFILE),
302 GUID_ENTRY(MF_MT_PAD_CONTROL_FLAGS),
303 GUID_ENTRY(MF_MT_PALETTE),
304 GUID_ENTRY(MF_MT_PAN_SCAN_APERTURE),
305 GUID_ENTRY(MF_MT_PAN_SCAN_ENABLED),
306 GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
307 GUID_ENTRY(MF_MT_SOURCE_CONTENT_HINT),
308 GUID_ENTRY(MF_MT_TRANSFER_FUNCTION),
309 GUID_ENTRY(MF_MT_VIDEO_CHROMA_SITING),
310 GUID_ENTRY(MF_MT_VIDEO_LIGHTING),
311 GUID_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE),
312 GUID_ENTRY(MF_MT_VIDEO_PRIMARIES),
313 GUID_ENTRY(MF_MT_VIDEO_ROTATION),
314 GUID_ENTRY(MF_MT_YUV_MATRIX),
315 GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
316 GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
317 GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
318 GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
319 GUID_ENTRY(ff_CODECAPI_AVLowLatencyMode),
320 GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
321 GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
322 GUID_ENTRY(ff_CODECAPI_AVDecVideoCodecType),
323 GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVAMode),
324 GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVABusEncryption),
325 GUID_ENTRY(ff_CODECAPI_AVDecVideoSWPowerLevel),
326 GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedWidth),
327 GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedHeight),
328 GUID_ENTRY(ff_CODECAPI_AVDecNumWorkerThreads),
329 GUID_ENTRY(ff_CODECAPI_AVDecSoftwareDynamicFormatChange),
330 GUID_ENTRY(ff_CODECAPI_AVDecDisableVideoPostProcessing),
333 char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
335 uint32_t fourcc;
336 int n;
337 for (n = 0; n < FF_ARRAY_ELEMS(guid_names); n++) {
338 if (IsEqualGUID(guid, guid_names[n].guid)) {
339 snprintf(buf, buf_size, "%s", guid_names[n].name);
340 return buf;
344 if (ff_fourcc_from_guid(guid, &fourcc) >= 0) {
345 snprintf(buf, buf_size, "<FourCC %s>", av_fourcc2str(fourcc));
346 return buf;
349 snprintf(buf, buf_size,
350 "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
351 (unsigned) guid->Data1, guid->Data2, guid->Data3,
352 guid->Data4[0], guid->Data4[1],
353 guid->Data4[2], guid->Data4[3],
354 guid->Data4[4], guid->Data4[5],
355 guid->Data4[6], guid->Data4[7]);
356 return buf;
359 void ff_attributes_dump(void *log, IMFAttributes *attrs)
361 HRESULT hr;
362 UINT32 count;
363 int n;
365 hr = IMFAttributes_GetCount(attrs, &count);
366 if (FAILED(hr))
367 return;
369 for (n = 0; n < count; n++) {
370 GUID key;
371 MF_ATTRIBUTE_TYPE type;
372 char extra[80] = {0};
373 const char *name = NULL;
375 hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL);
376 if (FAILED(hr))
377 goto err;
379 name = ff_guid_str(&key);
381 if (IsEqualGUID(&key, &MF_MT_AUDIO_CHANNEL_MASK)) {
382 UINT32 v;
383 hr = IMFAttributes_GetUINT32(attrs, &key, &v);
384 if (FAILED(hr))
385 goto err;
386 snprintf(extra, sizeof(extra), " (0x%x)", (unsigned)v);
387 } else if (IsEqualGUID(&key, &MF_MT_FRAME_SIZE)) {
388 UINT32 w, h;
390 hr = ff_MFGetAttributeSize(attrs, &MF_MT_FRAME_SIZE, &w, &h);
391 if (FAILED(hr))
392 goto err;
393 snprintf(extra, sizeof(extra), " (%dx%d)", (int)w, (int)h);
394 } else if (IsEqualGUID(&key, &MF_MT_PIXEL_ASPECT_RATIO) ||
395 IsEqualGUID(&key, &MF_MT_FRAME_RATE)) {
396 UINT32 num, den;
398 hr = ff_MFGetAttributeRatio(attrs, &key, &num, &den);
399 if (FAILED(hr))
400 goto err;
401 snprintf(extra, sizeof(extra), " (%d:%d)", (int)num, (int)den);
404 hr = IMFAttributes_GetItemType(attrs, &key, &type);
405 if (FAILED(hr))
406 goto err;
408 switch (type) {
409 case MF_ATTRIBUTE_UINT32: {
410 UINT32 v;
411 hr = IMFAttributes_GetUINT32(attrs, &key, &v);
412 if (FAILED(hr))
413 goto err;
414 av_log(log, AV_LOG_VERBOSE, " %s=%d%s\n", name, (int)v, extra);
415 break;
416 case MF_ATTRIBUTE_UINT64: {
417 UINT64 v;
418 hr = IMFAttributes_GetUINT64(attrs, &key, &v);
419 if (FAILED(hr))
420 goto err;
421 av_log(log, AV_LOG_VERBOSE, " %s=%lld%s\n", name, (long long)v, extra);
422 break;
424 case MF_ATTRIBUTE_DOUBLE: {
425 DOUBLE v;
426 hr = IMFAttributes_GetDouble(attrs, &key, &v);
427 if (FAILED(hr))
428 goto err;
429 av_log(log, AV_LOG_VERBOSE, " %s=%f%s\n", name, (double)v, extra);
430 break;
432 case MF_ATTRIBUTE_STRING: {
433 wchar_t s[512]; // being lazy here
434 hr = IMFAttributes_GetString(attrs, &key, s, sizeof(s), NULL);
435 if (FAILED(hr))
436 goto err;
437 av_log(log, AV_LOG_VERBOSE, " %s='%ls'%s\n", name, s, extra);
438 break;
440 case MF_ATTRIBUTE_GUID: {
441 GUID v;
442 hr = IMFAttributes_GetGUID(attrs, &key, &v);
443 if (FAILED(hr))
444 goto err;
445 av_log(log, AV_LOG_VERBOSE, " %s=%s%s\n", name, ff_guid_str(&v), extra);
446 break;
448 case MF_ATTRIBUTE_BLOB: {
449 UINT32 sz;
450 UINT8 buffer[100];
451 hr = IMFAttributes_GetBlobSize(attrs, &key, &sz);
452 if (FAILED(hr))
453 goto err;
454 if (sz <= sizeof(buffer)) {
455 // hex-dump it
456 char str[512] = {0};
457 size_t pos = 0;
458 hr = IMFAttributes_GetBlob(attrs, &key, buffer, sizeof(buffer), &sz);
459 if (FAILED(hr))
460 goto err;
461 for (pos = 0; pos < sz; pos++) {
462 const char *hex = "0123456789ABCDEF";
463 if (pos * 3 + 3 > sizeof(str))
464 break;
465 str[pos * 3 + 0] = hex[buffer[pos] >> 4];
466 str[pos * 3 + 1] = hex[buffer[pos] & 15];
467 str[pos * 3 + 2] = ' ';
469 str[pos * 3 + 0] = 0;
470 av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d: %s>%s\n", name, (int)sz, str, extra);
471 } else {
472 av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d>%s\n", name, (int)sz, extra);
474 break;
476 case MF_ATTRIBUTE_IUNKNOWN: {
477 av_log(log, AV_LOG_VERBOSE, " %s=<IUnknown>%s\n", name, extra);
478 break;
480 default:
481 av_log(log, AV_LOG_VERBOSE, " %s=<unknown type>%s\n", name, extra);
482 break;
486 if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) {
487 const char *fmt;
488 fmt = av_get_sample_fmt_name(ff_media_type_to_sample_fmt(attrs));
489 if (fmt)
490 av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt);
492 fmt = av_get_pix_fmt_name(ff_media_type_to_pix_fmt(attrs));
493 if (fmt)
494 av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt);
497 continue;
498 err:
499 av_log(log, AV_LOG_VERBOSE, " %s=<failed to get value>\n", name ? name : "?");
503 void ff_media_type_dump(void *log, IMFMediaType *type)
505 ff_attributes_dump(log, (IMFAttributes *)type);
508 const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec)
510 switch (codec) {
511 case AV_CODEC_ID_AV1: return &ff_MFVideoFormat_AV1;
512 case AV_CODEC_ID_H264: return &MFVideoFormat_H264;
513 case AV_CODEC_ID_HEVC: return &ff_MFVideoFormat_HEVC;
514 case AV_CODEC_ID_AC3: return &MFAudioFormat_Dolby_AC3;
515 case AV_CODEC_ID_AAC: return &MFAudioFormat_AAC;
516 case AV_CODEC_ID_MP3: return &MFAudioFormat_MP3;
517 default: return NULL;
521 static int init_com_mf(void *log, MFFunctions *f)
523 HRESULT hr;
525 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
526 if (hr == RPC_E_CHANGED_MODE) {
527 av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n");
528 return AVERROR(EINVAL);
529 } else if (FAILED(hr)) {
530 av_log(log, AV_LOG_ERROR, "could not initialize COM\n");
531 return AVERROR(ENOSYS);
534 hr = f->MFStartup(MF_VERSION, MFSTARTUP_FULL);
535 if (FAILED(hr)) {
536 av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n");
537 CoUninitialize();
538 return AVERROR(ENOSYS);
541 return 0;
544 static void uninit_com_mf(MFFunctions *f)
546 f->MFShutdown();
547 CoUninitialize();
550 // Find and create a IMFTransform with the given input/output types. When done,
551 // you should use ff_free_mf() to destroy it, which will also uninit COM.
552 int ff_instantiate_mf(void *log,
553 MFFunctions *f,
554 GUID category,
555 MFT_REGISTER_TYPE_INFO *in_type,
556 MFT_REGISTER_TYPE_INFO *out_type,
557 int use_hw,
558 IMFTransform **res)
560 HRESULT hr;
561 int n;
562 int ret;
563 IMFActivate **activate;
564 UINT32 num_activate;
565 IMFActivate *winner = 0;
566 UINT32 flags;
568 ret = init_com_mf(log, f);
569 if (ret < 0)
570 return ret;
572 flags = MFT_ENUM_FLAG_SORTANDFILTER;
574 if (use_hw) {
575 flags |= MFT_ENUM_FLAG_HARDWARE;
576 } else {
577 flags |= MFT_ENUM_FLAG_SYNCMFT;
580 hr = f->MFTEnumEx(category, flags, in_type, out_type, &activate,
581 &num_activate);
582 if (FAILED(hr))
583 goto error_uninit_mf;
585 if (log) {
586 if (!num_activate)
587 av_log(log, AV_LOG_ERROR, "could not find any MFT for the given media type\n");
589 for (n = 0; n < num_activate; n++) {
590 av_log(log, AV_LOG_VERBOSE, "MF %d attributes:\n", n);
591 ff_attributes_dump(log, (IMFAttributes *)activate[n]);
595 *res = NULL;
596 for (n = 0; n < num_activate; n++) {
597 if (log)
598 av_log(log, AV_LOG_VERBOSE, "activate MFT %d\n", n);
599 hr = IMFActivate_ActivateObject(activate[n], &IID_IMFTransform,
600 (void **)res);
601 if (*res) {
602 winner = activate[n];
603 IMFActivate_AddRef(winner);
604 break;
608 for (n = 0; n < num_activate; n++)
609 IMFActivate_Release(activate[n]);
610 CoTaskMemFree(activate);
612 if (!*res) {
613 if (log)
614 av_log(log, AV_LOG_ERROR, "could not create MFT\n");
615 goto error_uninit_mf;
618 if (log) {
619 wchar_t s[512]; // being lazy here
620 IMFAttributes *attrs;
621 hr = IMFTransform_GetAttributes(*res, &attrs);
622 if (!FAILED(hr) && attrs) {
624 av_log(log, AV_LOG_VERBOSE, "MFT attributes\n");
625 ff_attributes_dump(log, attrs);
626 IMFAttributes_Release(attrs);
629 hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute, s,
630 sizeof(s), NULL);
631 if (!FAILED(hr))
632 av_log(log, AV_LOG_INFO, "MFT name: '%ls'\n", s);
636 IMFActivate_Release(winner);
638 return 0;
640 error_uninit_mf:
641 uninit_com_mf(f);
642 return AVERROR(ENOSYS);
645 void ff_free_mf(MFFunctions *f, IMFTransform **mft)
647 if (*mft)
648 IMFTransform_Release(*mft);
649 *mft = NULL;
650 uninit_com_mf(f);