FFmpeg
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
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
GLint GLenum type
Definition: opengl_enc.c:104
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:448
AV_SAMPLE_FMT_U8
#define ff_MFGetAttributeRatio
Definition: mf_utils.c:48
filter_frame For filters that do not use the activate() callback
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
static const struct mf_pix_fmt_entry mf_pix_fmts[]
Definition: mf_utils.c:181
ptrdiff_t size
Definition: opengl_enc.c:100
const GUID * guid
Definition: mf_utils.c:242
signed 32 bits
Definition: samplefmt.h:62
#define av_log(a,...)
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:194
unsigned int pos
Definition: spdifenc.c:410
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:412
#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
GLsizei count
Definition: opengl_enc.c:108
#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
uint8_t w
Definition: llviddspenc.c:38
#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:205
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
#define snprintf
Definition: snprintf.h:34
#define flags(name, subs,...)
Definition: cbs_av1.c:560
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:2489
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 *pw, UINT32 *ph)
Definition: mf_utils.c:28
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
#define HR(x)
int i
Definition: input.c:407
GLuint buffer
Definition: opengl_enc.c:101
const char * name
Definition: opengl_enc.c:102
static uint8_t tmp[11]
Definition: aes_ctr.c:26