FFmpeg  4.3
mf_utils.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #define COBJMACROS
20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
21 #undef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0602
23 #endif
24 
25 #include "mf_utils.h"
26 #include "libavutil/pixdesc.h"
27 
28 HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid,
29  UINT32 *pw, UINT32 *ph)
30 {
31  UINT64 t;
32  HRESULT hr = IMFAttributes_GetUINT64(pattr, guid, &t);
33  if (!FAILED(hr)) {
34  *pw = t >> 32;
35  *ph = (UINT32)t;
36  }
37  return hr;
38 }
39 
40 HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid,
41  UINT32 uw, UINT32 uh)
42 {
43  UINT64 t = (((UINT64)uw) << 32) | uh;
44  return IMFAttributes_SetUINT64(pattr, guid, t);
45 }
46 
47 #define ff_MFSetAttributeRatio ff_MFSetAttributeSize
48 #define ff_MFGetAttributeRatio ff_MFGetAttributeSize
49 
50 // MFTEnumEx was missing from mingw-w64's mfplat import library until
51 // mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress.
52 // It's also missing in Windows Vista's mfplat.dll.
53 HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags,
54  const MFT_REGISTER_TYPE_INFO *pInputType,
55  const MFT_REGISTER_TYPE_INFO *pOutputType,
56  IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate)
57 {
58  HRESULT (WINAPI *MFTEnumEx_ptr)(GUID guidCategory, UINT32 Flags,
59  const MFT_REGISTER_TYPE_INFO *pInputType,
60  const MFT_REGISTER_TYPE_INFO *pOutputType,
61  IMFActivate ***pppMFTActivate,
62  UINT32 *pnumMFTActivate) = NULL;
63 #if !HAVE_UWP
64  HANDLE lib = GetModuleHandleW(L"mfplat.dll");
65  if (lib)
66  MFTEnumEx_ptr = (void *)GetProcAddress(lib, "MFTEnumEx");
67 #else
68  // In UWP (which lacks GetModuleHandle), just link directly against
69  // the functions - this requires building with new/complete enough
70  // import libraries.
71  MFTEnumEx_ptr = MFTEnumEx;
72 #endif
73  if (!MFTEnumEx_ptr)
74  return E_FAIL;
75  return MFTEnumEx_ptr(guidCategory,
76  Flags,
77  pInputType,
78  pOutputType,
79  pppMFTActivate,
80  pnumMFTActivate);
81 }
82 
83 char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
84 {
85 #define HR(x) case x: return (char *) # x;
86  switch (hr) {
87  HR(S_OK)
88  HR(E_UNEXPECTED)
89  HR(MF_E_INVALIDMEDIATYPE)
90  HR(MF_E_INVALIDSTREAMNUMBER)
91  HR(MF_E_INVALIDTYPE)
92  HR(MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING)
93  HR(MF_E_TRANSFORM_TYPE_NOT_SET)
94  HR(MF_E_UNSUPPORTED_D3D_TYPE)
95  HR(MF_E_TRANSFORM_NEED_MORE_INPUT)
96  HR(MF_E_TRANSFORM_STREAM_CHANGE)
97  HR(MF_E_NOTACCEPTING)
98  HR(MF_E_NO_SAMPLE_TIMESTAMP)
99  HR(MF_E_NO_SAMPLE_DURATION)
100 #undef HR
101  }
102  snprintf(buf, size, "%x", (unsigned)hr);
103  return buf;
104 }
105 
106 // If fill_data!=NULL, initialize the buffer and set the length. (This is a
107 // subtle but important difference: some decoders want CurrentLength==0 on
108 // provided output buffers.)
109 IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t align)
110 {
111  HRESULT hr;
112  IMFSample *sample;
113  IMFMediaBuffer *buffer;
114 
115  hr = MFCreateSample(&sample);
116  if (FAILED(hr))
117  return NULL;
118 
119  align = FFMAX(align, 16); // 16 is "recommended", even if not required
120 
121  hr = MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
122  if (FAILED(hr))
123  return NULL;
124 
125  if (fill_data) {
126  BYTE *tmp;
127 
128  hr = IMFMediaBuffer_Lock(buffer, &tmp, NULL, NULL);
129  if (FAILED(hr)) {
130  IMFMediaBuffer_Release(buffer);
131  IMFSample_Release(sample);
132  return NULL;
133  }
134  memcpy(tmp, fill_data, size);
135 
136  IMFMediaBuffer_SetCurrentLength(buffer, size);
137  IMFMediaBuffer_Unlock(buffer);
138  }
139 
140  IMFSample_AddBuffer(sample, buffer);
141  IMFMediaBuffer_Release(buffer);
142 
143  return sample;
144 }
145 
147 {
148  HRESULT hr;
149  UINT32 bits;
150  GUID subtype;
151 
152  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits);
153  if (FAILED(hr))
154  return AV_SAMPLE_FMT_NONE;
155 
156  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
157  if (FAILED(hr))
158  return AV_SAMPLE_FMT_NONE;
159 
160  if (IsEqualGUID(&subtype, &MFAudioFormat_PCM)) {
161  switch (bits) {
162  case 8: return AV_SAMPLE_FMT_U8;
163  case 16: return AV_SAMPLE_FMT_S16;
164  case 32: return AV_SAMPLE_FMT_S32;
165  }
166  } else if (IsEqualGUID(&subtype, &MFAudioFormat_Float)) {
167  switch (bits) {
168  case 32: return AV_SAMPLE_FMT_FLT;
169  case 64: return AV_SAMPLE_FMT_DBL;
170  }
171  }
172 
173  return AV_SAMPLE_FMT_NONE;
174 }
175 
177  const GUID *guid;
179 };
180 
181 static const struct mf_pix_fmt_entry mf_pix_fmts[] = {
182  {&MFVideoFormat_IYUV, AV_PIX_FMT_YUV420P},
183  {&MFVideoFormat_I420, AV_PIX_FMT_YUV420P},
184  {&MFVideoFormat_NV12, AV_PIX_FMT_NV12},
185  {&MFVideoFormat_P010, AV_PIX_FMT_P010},
186  {&MFVideoFormat_P016, AV_PIX_FMT_P010}, // not equal, but compatible
187  {&MFVideoFormat_YUY2, AV_PIX_FMT_YUYV422},
188 };
189 
191 {
192  HRESULT hr;
193  GUID subtype;
194  int i;
195 
196  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
197  if (FAILED(hr))
198  return AV_PIX_FMT_NONE;
199 
200  for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
201  if (IsEqualGUID(&subtype, mf_pix_fmts[i].guid))
202  return mf_pix_fmts[i].pix_fmt;
203  }
204 
205  return AV_PIX_FMT_NONE;
206 }
207 
209 {
210  int i;
211 
212  for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) {
213  if (mf_pix_fmts[i].pix_fmt == pix_fmt)
214  return mf_pix_fmts[i].guid;
215  }
216 
217  return NULL;
218 }
219 
220 // If this GUID is of the form XXXXXXXX-0000-0010-8000-00AA00389B71, then
221 // extract the XXXXXXXX prefix as FourCC (oh the pain).
222 int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc)
223 {
224  if (guid->Data2 == 0 && guid->Data3 == 0x0010 &&
225  guid->Data4[0] == 0x80 &&
226  guid->Data4[1] == 0x00 &&
227  guid->Data4[2] == 0x00 &&
228  guid->Data4[3] == 0xAA &&
229  guid->Data4[4] == 0x00 &&
230  guid->Data4[5] == 0x38 &&
231  guid->Data4[6] == 0x9B &&
232  guid->Data4[7] == 0x71) {
233  *out_fourcc = guid->Data1;
234  return 0;
235  }
236 
237  *out_fourcc = 0;
238  return AVERROR_UNKNOWN;
239 }
240 
241 struct GUID_Entry {
242  const GUID *guid;
243  const char *name;
244 };
245 
246 #define GUID_ENTRY(var) {&(var), # var}
247 
248 static struct GUID_Entry guid_names[] = {
249  GUID_ENTRY(MFT_FRIENDLY_NAME_Attribute),
250  GUID_ENTRY(MFT_TRANSFORM_CLSID_Attribute),
251  GUID_ENTRY(MFT_ENUM_HARDWARE_URL_Attribute),
252  GUID_ENTRY(MFT_CONNECTED_STREAM_ATTRIBUTE),
253  GUID_ENTRY(MFT_CONNECTED_TO_HW_STREAM),
254  GUID_ENTRY(MF_SA_D3D_AWARE),
255  GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
256  GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
257  GUID_ENTRY(ff_MF_SA_D3D11_BINDFLAGS),
258  GUID_ENTRY(ff_MF_SA_D3D11_USAGE),
259  GUID_ENTRY(ff_MF_SA_D3D11_AWARE),
260  GUID_ENTRY(ff_MF_SA_D3D11_SHARED),
261  GUID_ENTRY(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
262  GUID_ENTRY(MF_MT_SUBTYPE),
263  GUID_ENTRY(MF_MT_MAJOR_TYPE),
264  GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
265  GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
266  GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
267  GUID_ENTRY(MF_MT_FRAME_SIZE),
268  GUID_ENTRY(MF_MT_INTERLACE_MODE),
269  GUID_ENTRY(MF_MT_USER_DATA),
270  GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
271  GUID_ENTRY(MFMediaType_Audio),
272  GUID_ENTRY(MFMediaType_Video),
273  GUID_ENTRY(MFAudioFormat_PCM),
274  GUID_ENTRY(MFAudioFormat_Float),
275  GUID_ENTRY(MFVideoFormat_H264),
276  GUID_ENTRY(MFVideoFormat_H264_ES),
277  GUID_ENTRY(ff_MFVideoFormat_HEVC),
278  GUID_ENTRY(ff_MFVideoFormat_HEVC_ES),
279  GUID_ENTRY(MFVideoFormat_MPEG2),
280  GUID_ENTRY(MFVideoFormat_MP43),
281  GUID_ENTRY(MFVideoFormat_MP4V),
282  GUID_ENTRY(MFVideoFormat_WMV1),
283  GUID_ENTRY(MFVideoFormat_WMV2),
284  GUID_ENTRY(MFVideoFormat_WMV3),
285  GUID_ENTRY(MFVideoFormat_WVC1),
286  GUID_ENTRY(MFAudioFormat_Dolby_AC3),
287  GUID_ENTRY(MFAudioFormat_Dolby_DDPlus),
288  GUID_ENTRY(MFAudioFormat_AAC),
289  GUID_ENTRY(MFAudioFormat_MP3),
290  GUID_ENTRY(MFAudioFormat_MSP1),
291  GUID_ENTRY(MFAudioFormat_WMAudioV8),
292  GUID_ENTRY(MFAudioFormat_WMAudioV9),
293  GUID_ENTRY(MFAudioFormat_WMAudio_Lossless),
294  GUID_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT),
295  GUID_ENTRY(MF_MT_COMPRESSED),
296  GUID_ENTRY(MF_MT_FIXED_SIZE_SAMPLES),
297  GUID_ENTRY(MF_MT_SAMPLE_SIZE),
298  GUID_ENTRY(MF_MT_WRAPPED_TYPE),
299  GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
300  GUID_ENTRY(MF_MT_AAC_PAYLOAD_TYPE),
301  GUID_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
302  GUID_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE),
303  GUID_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT),
304  GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
305  GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
306  GUID_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX),
307  GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
308  GUID_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
309  GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
310  GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
311  GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
312  GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF),
313  GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET),
314  GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF),
315  GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET),
316  GUID_ENTRY(MF_MT_AVG_BIT_ERROR_RATE),
317  GUID_ENTRY(MF_MT_AVG_BITRATE),
318  GUID_ENTRY(MF_MT_DEFAULT_STRIDE),
319  GUID_ENTRY(MF_MT_DRM_FLAGS),
320  GUID_ENTRY(MF_MT_FRAME_RATE),
321  GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX),
322  GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN),
323  GUID_ENTRY(MF_MT_FRAME_SIZE),
324  GUID_ENTRY(MF_MT_GEOMETRIC_APERTURE),
325  GUID_ENTRY(MF_MT_INTERLACE_MODE),
326  GUID_ENTRY(MF_MT_MAX_KEYFRAME_SPACING),
327  GUID_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE),
328  GUID_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER),
329  GUID_ENTRY(MF_MT_MPEG_START_TIME_CODE),
330  GUID_ENTRY(MF_MT_MPEG2_FLAGS),
331  GUID_ENTRY(MF_MT_MPEG2_LEVEL),
332  GUID_ENTRY(MF_MT_MPEG2_PROFILE),
333  GUID_ENTRY(MF_MT_PAD_CONTROL_FLAGS),
334  GUID_ENTRY(MF_MT_PALETTE),
335  GUID_ENTRY(MF_MT_PAN_SCAN_APERTURE),
336  GUID_ENTRY(MF_MT_PAN_SCAN_ENABLED),
337  GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
338  GUID_ENTRY(MF_MT_SOURCE_CONTENT_HINT),
339  GUID_ENTRY(MF_MT_TRANSFER_FUNCTION),
340  GUID_ENTRY(MF_MT_VIDEO_CHROMA_SITING),
341  GUID_ENTRY(MF_MT_VIDEO_LIGHTING),
342  GUID_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE),
343  GUID_ENTRY(MF_MT_VIDEO_PRIMARIES),
344  GUID_ENTRY(MF_MT_VIDEO_ROTATION),
345  GUID_ENTRY(MF_MT_YUV_MATRIX),
346  GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
347  GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
348  GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
349  GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
350  GUID_ENTRY(ff_CODECAPI_AVLowLatencyMode),
351  GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
352  GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
353  GUID_ENTRY(ff_CODECAPI_AVDecVideoCodecType),
354  GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVAMode),
355  GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVABusEncryption),
356  GUID_ENTRY(ff_CODECAPI_AVDecVideoSWPowerLevel),
357  GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedWidth),
358  GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedHeight),
359  GUID_ENTRY(ff_CODECAPI_AVDecNumWorkerThreads),
360  GUID_ENTRY(ff_CODECAPI_AVDecSoftwareDynamicFormatChange),
361  GUID_ENTRY(ff_CODECAPI_AVDecDisableVideoPostProcessing),
362 };
363 
364 char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
365 {
366  uint32_t fourcc;
367  int n;
368  for (n = 0; n < FF_ARRAY_ELEMS(guid_names); n++) {
369  if (IsEqualGUID(guid, guid_names[n].guid)) {
370  snprintf(buf, buf_size, "%s", guid_names[n].name);
371  return buf;
372  }
373  }
374 
375  if (ff_fourcc_from_guid(guid, &fourcc) >= 0) {
376  snprintf(buf, buf_size, "<FourCC %s>", av_fourcc2str(fourcc));
377  return buf;
378  }
379 
380  snprintf(buf, buf_size,
381  "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
382  (unsigned) guid->Data1, guid->Data2, guid->Data3,
383  guid->Data4[0], guid->Data4[1],
384  guid->Data4[2], guid->Data4[3],
385  guid->Data4[4], guid->Data4[5],
386  guid->Data4[6], guid->Data4[7]);
387  return buf;
388 }
389 
390 void ff_attributes_dump(void *log, IMFAttributes *attrs)
391 {
392  HRESULT hr;
393  UINT32 count;
394  int n;
395 
396  hr = IMFAttributes_GetCount(attrs, &count);
397  if (FAILED(hr))
398  return;
399 
400  for (n = 0; n < count; n++) {
401  GUID key;
402  MF_ATTRIBUTE_TYPE type;
403  char extra[80] = {0};
404  const char *name = NULL;
405 
406  hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL);
407  if (FAILED(hr))
408  goto err;
409 
410  name = ff_guid_str(&key);
411 
412  if (IsEqualGUID(&key, &MF_MT_AUDIO_CHANNEL_MASK)) {
413  UINT32 v;
414  hr = IMFAttributes_GetUINT32(attrs, &key, &v);
415  if (FAILED(hr))
416  goto err;
417  snprintf(extra, sizeof(extra), " (0x%x)", (unsigned)v);
418  } else if (IsEqualGUID(&key, &MF_MT_FRAME_SIZE)) {
419  UINT32 w, h;
420 
421  hr = ff_MFGetAttributeSize(attrs, &MF_MT_FRAME_SIZE, &w, &h);
422  if (FAILED(hr))
423  goto err;
424  snprintf(extra, sizeof(extra), " (%dx%d)", (int)w, (int)h);
425  } else if (IsEqualGUID(&key, &MF_MT_PIXEL_ASPECT_RATIO) ||
426  IsEqualGUID(&key, &MF_MT_FRAME_RATE)) {
427  UINT32 num, den;
428 
429  hr = ff_MFGetAttributeRatio(attrs, &key, &num, &den);
430  if (FAILED(hr))
431  goto err;
432  snprintf(extra, sizeof(extra), " (%d:%d)", (int)num, (int)den);
433  }
434 
435  hr = IMFAttributes_GetItemType(attrs, &key, &type);
436  if (FAILED(hr))
437  goto err;
438 
439  switch (type) {
440  case MF_ATTRIBUTE_UINT32: {
441  UINT32 v;
442  hr = IMFAttributes_GetUINT32(attrs, &key, &v);
443  if (FAILED(hr))
444  goto err;
445  av_log(log, AV_LOG_VERBOSE, " %s=%d%s\n", name, (int)v, extra);
446  break;
447  case MF_ATTRIBUTE_UINT64: {
448  UINT64 v;
449  hr = IMFAttributes_GetUINT64(attrs, &key, &v);
450  if (FAILED(hr))
451  goto err;
452  av_log(log, AV_LOG_VERBOSE, " %s=%lld%s\n", name, (long long)v, extra);
453  break;
454  }
455  case MF_ATTRIBUTE_DOUBLE: {
456  DOUBLE v;
457  hr = IMFAttributes_GetDouble(attrs, &key, &v);
458  if (FAILED(hr))
459  goto err;
460  av_log(log, AV_LOG_VERBOSE, " %s=%f%s\n", name, (double)v, extra);
461  break;
462  }
463  case MF_ATTRIBUTE_STRING: {
464  wchar_t s[512]; // being lazy here
465  hr = IMFAttributes_GetString(attrs, &key, s, sizeof(s), NULL);
466  if (FAILED(hr))
467  goto err;
468  av_log(log, AV_LOG_VERBOSE, " %s='%ls'%s\n", name, s, extra);
469  break;
470  }
471  case MF_ATTRIBUTE_GUID: {
472  GUID v;
473  hr = IMFAttributes_GetGUID(attrs, &key, &v);
474  if (FAILED(hr))
475  goto err;
476  av_log(log, AV_LOG_VERBOSE, " %s=%s%s\n", name, ff_guid_str(&v), extra);
477  break;
478  }
479  case MF_ATTRIBUTE_BLOB: {
480  UINT32 sz;
481  UINT8 buffer[100];
482  hr = IMFAttributes_GetBlobSize(attrs, &key, &sz);
483  if (FAILED(hr))
484  goto err;
485  if (sz <= sizeof(buffer)) {
486  // hex-dump it
487  char str[512] = {0};
488  size_t pos = 0;
489  hr = IMFAttributes_GetBlob(attrs, &key, buffer, sizeof(buffer), &sz);
490  if (FAILED(hr))
491  goto err;
492  for (pos = 0; pos < sz; pos++) {
493  const char *hex = "0123456789ABCDEF";
494  if (pos * 3 + 3 > sizeof(str))
495  break;
496  str[pos * 3 + 0] = hex[buffer[pos] >> 4];
497  str[pos * 3 + 1] = hex[buffer[pos] & 15];
498  str[pos * 3 + 2] = ' ';
499  }
500  str[pos * 3 + 0] = 0;
501  av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d: %s>%s\n", name, (int)sz, str, extra);
502  } else {
503  av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d>%s\n", name, (int)sz, extra);
504  }
505  break;
506  }
507  case MF_ATTRIBUTE_IUNKNOWN: {
508  av_log(log, AV_LOG_VERBOSE, " %s=<IUnknown>%s\n", name, extra);
509  break;
510  }
511  default:
512  av_log(log, AV_LOG_VERBOSE, " %s=<unknown type>%s\n", name, extra);
513  break;
514  }
515  }
516 
517  if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) {
518  const char *fmt;
520  if (fmt)
521  av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt);
522 
524  if (fmt)
525  av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt);
526  }
527 
528  continue;
529  err:
530  av_log(log, AV_LOG_VERBOSE, " %s=<failed to get value>\n", name ? name : "?");
531  }
532 }
533 
534 void ff_media_type_dump(void *log, IMFMediaType *type)
535 {
536  ff_attributes_dump(log, (IMFAttributes *)type);
537 }
538 
539 const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec)
540 {
541  switch (codec) {
542  case AV_CODEC_ID_H264: return &MFVideoFormat_H264;
543  case AV_CODEC_ID_HEVC: return &ff_MFVideoFormat_HEVC;
544  case AV_CODEC_ID_AC3: return &MFAudioFormat_Dolby_AC3;
545  case AV_CODEC_ID_AAC: return &MFAudioFormat_AAC;
546  case AV_CODEC_ID_MP3: return &MFAudioFormat_MP3;
547  default: return NULL;
548  }
549 }
550 
551 static int init_com_mf(void *log)
552 {
553  HRESULT hr;
554 
555  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
556  if (hr == RPC_E_CHANGED_MODE) {
557  av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n");
558  return AVERROR(EINVAL);
559  } else if (FAILED(hr)) {
560  av_log(log, AV_LOG_ERROR, "could not initialize COM\n");
561  return AVERROR(ENOSYS);
562  }
563 
564  hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
565  if (FAILED(hr)) {
566  av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n");
567  CoUninitialize();
568  return AVERROR(ENOSYS);
569  }
570 
571  return 0;
572 }
573 
574 static void uninit_com_mf(void)
575 {
576  MFShutdown();
577  CoUninitialize();
578 }
579 
580 // Find and create a IMFTransform with the given input/output types. When done,
581 // you should use ff_free_mf() to destroy it, which will also uninit COM.
582 int ff_instantiate_mf(void *log,
583  GUID category,
584  MFT_REGISTER_TYPE_INFO *in_type,
585  MFT_REGISTER_TYPE_INFO *out_type,
586  int use_hw,
587  IMFTransform **res)
588 {
589  HRESULT hr;
590  int n;
591  int ret;
592  IMFActivate **activate;
593  UINT32 num_activate;
594  IMFActivate *winner = 0;
595  UINT32 flags;
596 
597  ret = init_com_mf(log);
598  if (ret < 0)
599  return ret;
600 
601  flags = MFT_ENUM_FLAG_SORTANDFILTER;
602 
603  if (use_hw) {
604  flags |= MFT_ENUM_FLAG_HARDWARE;
605  } else {
606  flags |= MFT_ENUM_FLAG_SYNCMFT;
607  }
608 
609  hr = ff_MFTEnumEx(category, flags, in_type, out_type, &activate,
610  &num_activate);
611  if (FAILED(hr))
612  goto error_uninit_mf;
613 
614  if (log) {
615  if (!num_activate)
616  av_log(log, AV_LOG_ERROR, "could not find any MFT for the given media type\n");
617 
618  for (n = 0; n < num_activate; n++) {
619  av_log(log, AV_LOG_VERBOSE, "MF %d attributes:\n", n);
620  ff_attributes_dump(log, (IMFAttributes *)activate[n]);
621  }
622  }
623 
624  *res = NULL;
625  for (n = 0; n < num_activate; n++) {
626  if (log)
627  av_log(log, AV_LOG_VERBOSE, "activate MFT %d\n", n);
628  hr = IMFActivate_ActivateObject(activate[n], &IID_IMFTransform,
629  (void **)res);
630  if (*res) {
631  winner = activate[n];
632  IMFActivate_AddRef(winner);
633  break;
634  }
635  }
636 
637  for (n = 0; n < num_activate; n++)
638  IMFActivate_Release(activate[n]);
639  CoTaskMemFree(activate);
640 
641  if (!*res) {
642  if (log)
643  av_log(log, AV_LOG_ERROR, "could not create MFT\n");
644  goto error_uninit_mf;
645  }
646 
647  if (log) {
648  wchar_t s[512]; // being lazy here
649  IMFAttributes *attrs;
650  hr = IMFTransform_GetAttributes(*res, &attrs);
651  if (!FAILED(hr) && attrs) {
652 
653  av_log(log, AV_LOG_VERBOSE, "MFT attributes\n");
654  ff_attributes_dump(log, attrs);
655  IMFAttributes_Release(attrs);
656  }
657 
658  hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute, s,
659  sizeof(s), NULL);
660  if (!FAILED(hr))
661  av_log(log, AV_LOG_INFO, "MFT name: '%ls'\n", s);
662 
663  }
664 
665  IMFActivate_Release(winner);
666 
667  return 0;
668 
669 error_uninit_mf:
670  uninit_com_mf();
671  return AVERROR(ENOSYS);
672 }
673 
674 void ff_free_mf(IMFTransform **mft)
675 {
676  if (*mft)
677  IMFTransform_Release(*mft);
678  *mft = NULL;
679  uninit_com_mf();
680 }
category
Definition: openal-dec.c:248
#define NULL
Definition: coverity.c:32
void ff_media_type_dump(void *log, IMFMediaType *type)
Definition: mf_utils.c:534
int size
static int init_com_mf(void *log)
Definition: mf_utils.c:551
uint32_t fourcc
Definition: vaapi_decode.c:239
#define ff_guid_str(guid)
Definition: mf_utils.h:159
const GUID * guid
Definition: mf_utils.c:177
enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type)
Definition: mf_utils.c:190
Definition: mf_utils.c:176
const char * key
#define sample
const char * name
Definition: mf_utils.c:243
enum AVPixelFormat pix_fmt
Definition: mf_utils.c:178
#define GUID_ENTRY(var)
Definition: mf_utils.c:246
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)
Definition: mf_utils.c:582
void ff_attributes_dump(void *log, IMFAttributes *attrs)
Definition: mf_utils.c:390
#define AV_PIX_FMT_P010
Definition: pixfmt.h:446
static char buffer[20]
Definition: seek.c:32
AV_SAMPLE_FMT_U8
#define ff_MFGetAttributeRatio
Definition: mf_utils.c:48
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
static const struct mf_pix_fmt_entry mf_pix_fmts[]
Definition: mf_utils.c:181
const GUID * guid
Definition: mf_utils.c:242
signed 32 bits
Definition: samplefmt.h:62
#define av_log(a,...)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
unsigned int pos
Definition: spdifenc.c:410
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:411
#define av_fourcc2str(fourcc)
Definition: avutil.h:348
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
uint8_t bits
Definition: vp3data.h:202
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition: samplefmt.c:49
#define FFMAX(a, b)
Definition: common.h:94
char * ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
Definition: mf_utils.c:364
const char * name
Definition: qsvenc.c:46
uint8_t w
Definition: llviddspenc.c:38
static int activate(AVFilterContext *ctx)
Definition: af_adeclick.c:622
#define s(width, name)
Definition: cbs_vp9.c:257
#define L(x)
Definition: vp56_arith.h:36
#define FF_ARRAY_ELEMS(a)
IMFSample * ff_create_memory_sample(void *fill_data, size_t size, size_t align)
Definition: mf_utils.c:109
static void uninit_com_mf(void)
Definition: mf_utils.c:574
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
char * ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
Definition: mf_utils.c:83
const GUID * ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt)
Definition: mf_utils.c:208
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type)
Definition: mf_utils.c:146
void ff_free_mf(IMFTransform **mft)
Definition: mf_utils.c:674
cl_device_type type
#define snprintf
Definition: snprintf.h:34
#define flags(name, subs,...)
Definition: cbs_av1.c:564
Definition: mf_utils.c:241
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
signed 16 bits
Definition: samplefmt.h:61
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 uw, UINT32 uh)
Definition: mf_utils.c:40
const CLSID * ff_codec_to_mf_subtype(enum AVCodecID codec)
Definition: mf_utils.c:539
int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc)
Definition: mf_utils.c:222
static struct GUID_Entry guid_names[]
Definition: mf_utils.c:248
HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags, const MFT_REGISTER_TYPE_INFO *pInputType, const MFT_REGISTER_TYPE_INFO *pOutputType, IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate)
Definition: mf_utils.c:53
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2465
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 *pw, UINT32 *ph)
Definition: mf_utils.c:28
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
#define HR(x)
static uint8_t tmp[11]
Definition: aes_ctr.c:26