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 char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
51 {
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
68  }
69  snprintf(buf, size, "%x", (unsigned)hr);
70  return buf;
71 }
72 
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)
78 {
79  HRESULT hr;
80  IMFSample *sample;
81  IMFMediaBuffer *buffer;
82 
83  hr = f->MFCreateSample(&sample);
84  if (FAILED(hr))
85  return NULL;
86 
87  align = FFMAX(align, 16); // 16 is "recommended", even if not required
88 
89  hr = f->MFCreateAlignedMemoryBuffer(size, align - 1, &buffer);
90  if (FAILED(hr))
91  return NULL;
92 
93  if (fill_data) {
94  BYTE *tmp;
95 
96  hr = IMFMediaBuffer_Lock(buffer, &tmp, NULL, NULL);
97  if (FAILED(hr)) {
98  IMFMediaBuffer_Release(buffer);
99  IMFSample_Release(sample);
100  return NULL;
101  }
102  memcpy(tmp, fill_data, size);
103 
104  IMFMediaBuffer_SetCurrentLength(buffer, size);
105  IMFMediaBuffer_Unlock(buffer);
106  }
107 
108  IMFSample_AddBuffer(sample, buffer);
109  IMFMediaBuffer_Release(buffer);
110 
111  return sample;
112 }
113 
115 {
116  HRESULT hr;
117  UINT32 bits;
118  GUID subtype;
119 
120  hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits);
121  if (FAILED(hr))
122  return AV_SAMPLE_FMT_NONE;
123 
124  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
125  if (FAILED(hr))
126  return AV_SAMPLE_FMT_NONE;
127 
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;
133  }
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;
138  }
139  }
140 
141  return AV_SAMPLE_FMT_NONE;
142 }
143 
145  const GUID *guid;
147 };
148 
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},
156 };
157 
159 {
160  HRESULT hr;
161  GUID subtype;
162  int i;
163 
164  hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
165  if (FAILED(hr))
166  return AV_PIX_FMT_NONE;
167 
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;
171  }
172 
173  return AV_PIX_FMT_NONE;
174 }
175 
177 {
178  int i;
179 
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;
183  }
184 
185  return NULL;
186 }
187 
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)
191 {
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;
203  }
204 
205  *out_fourcc = 0;
206  return AVERROR_UNKNOWN;
207 }
208 
209 struct GUID_Entry {
210  const GUID *guid;
211  const char *name;
212 };
213 
214 #define GUID_ENTRY(var) {&(var), # var}
215 
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),
331 };
332 
333 char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
334 {
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;
341  }
342  }
343 
344  if (ff_fourcc_from_guid(guid, &fourcc) >= 0) {
345  snprintf(buf, buf_size, "<FourCC %s>", av_fourcc2str(fourcc));
346  return buf;
347  }
348 
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;
357 }
358 
359 void ff_attributes_dump(void *log, IMFAttributes *attrs)
360 {
361  HRESULT hr;
362  UINT32 count;
363  int n;
364 
365  hr = IMFAttributes_GetCount(attrs, &count);
366  if (FAILED(hr))
367  return;
368 
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;
374 
375  hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL);
376  if (FAILED(hr))
377  goto err;
378 
379  name = ff_guid_str(&key);
380 
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;
389 
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;
397 
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);
402  }
403 
404  hr = IMFAttributes_GetItemType(attrs, &key, &type);
405  if (FAILED(hr))
406  goto err;
407 
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;
423  }
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;
431  }
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;
439  }
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;
447  }
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] = ' ';
468  }
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);
473  }
474  break;
475  }
476  case MF_ATTRIBUTE_IUNKNOWN: {
477  av_log(log, AV_LOG_VERBOSE, " %s=<IUnknown>%s\n", name, extra);
478  break;
479  }
480  default:
481  av_log(log, AV_LOG_VERBOSE, " %s=<unknown type>%s\n", name, extra);
482  break;
483  }
484  }
485 
486  if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) {
487  const char *fmt;
489  if (fmt)
490  av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt);
491 
493  if (fmt)
494  av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt);
495  }
496 
497  continue;
498  err:
499  av_log(log, AV_LOG_VERBOSE, " %s=<failed to get value>\n", name ? name : "?");
500  }
501 }
502 
503 void ff_media_type_dump(void *log, IMFMediaType *type)
504 {
505  ff_attributes_dump(log, (IMFAttributes *)type);
506 }
507 
508 const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec)
509 {
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;
518  }
519 }
520 
521 static int init_com_mf(void *log, MFFunctions *f)
522 {
523  HRESULT hr;
524 
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);
532  }
533 
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);
539  }
540 
541  return 0;
542 }
543 
545 {
546  f->MFShutdown();
547  CoUninitialize();
548 }
549 
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.
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)
559 {
560  HRESULT hr;
561  int n;
562  int ret;
563  IMFActivate **activate;
564  UINT32 num_activate;
565  IMFActivate *winner = 0;
566  UINT32 flags;
567 
568  ret = init_com_mf(log, f);
569  if (ret < 0)
570  return ret;
571 
572  flags = MFT_ENUM_FLAG_SORTANDFILTER;
573 
574  if (use_hw) {
575  flags |= MFT_ENUM_FLAG_HARDWARE;
576  } else {
577  flags |= MFT_ENUM_FLAG_SYNCMFT;
578  }
579 
580  hr = f->MFTEnumEx(category, flags, in_type, out_type, &activate,
581  &num_activate);
582  if (FAILED(hr))
583  goto error_uninit_mf;
584 
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");
588 
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]);
592  }
593  }
594 
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;
605  }
606  }
607 
608  for (n = 0; n < num_activate; n++)
609  IMFActivate_Release(activate[n]);
610  CoTaskMemFree(activate);
611 
612  if (!*res) {
613  if (log)
614  av_log(log, AV_LOG_ERROR, "could not create MFT\n");
615  goto error_uninit_mf;
616  }
617 
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) {
623 
624  av_log(log, AV_LOG_VERBOSE, "MFT attributes\n");
625  ff_attributes_dump(log, attrs);
626  IMFAttributes_Release(attrs);
627  }
628 
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);
633 
634  }
635 
636  IMFActivate_Release(winner);
637 
638  return 0;
639 
640 error_uninit_mf:
641  uninit_com_mf(f);
642  return AVERROR(ENOSYS);
643 }
644 
645 void ff_free_mf(MFFunctions *f, IMFTransform **mft)
646 {
647  if (*mft)
648  IMFTransform_Release(*mft);
649  *mft = NULL;
650  uninit_com_mf(f);
651 }
GUID_Entry::guid
const GUID * guid
Definition: mf_utils.c:210
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
AV_CODEC_ID_AC3
@ AV_CODEC_ID_AC3
Definition: codec_id.h:449
uninit_com_mf
static void uninit_com_mf(MFFunctions *f)
Definition: mf_utils.c:544
AVERROR
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
ff_guid_str_buf
char * ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
Definition: mf_utils.c:333
ff_pix_fmt_to_guid
const GUID * ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt)
Definition: mf_utils.c:176
ff_attributes_dump
void ff_attributes_dump(void *log, IMFAttributes *attrs)
Definition: mf_utils.c:359
normalize.log
log
Definition: normalize.py:21
ff_codec_to_mf_subtype
const CLSID * ff_codec_to_mf_subtype(enum AVCodecID codec)
Definition: mf_utils.c:508
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3043
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
GUID_ENTRY
#define GUID_ENTRY(var)
Definition: mf_utils.c:214
ff_guid_str
#define ff_guid_str(guid)
Definition: mf_utils.h:177
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
category
category
Definition: openal-dec.c:249
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
ff_MFSetAttributeSize
HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 uw, UINT32 uh)
Definition: mf_utils.c:40
HR
#define HR(x)
ff_hr_str_buf
char * ff_hr_str_buf(char *buf, size_t size, HRESULT hr)
Definition: mf_utils.c:50
ff_media_type_to_sample_fmt
enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type)
Definition: mf_utils.c:114
mf_utils.h
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
AV_CODEC_ID_MP3
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:447
ff_fourcc_from_guid
int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc)
Definition: mf_utils.c:190
ff_instantiate_mf
int ff_instantiate_mf(void *log, MFFunctions *f, GUID category, MFT_REGISTER_TYPE_INFO *in_type, MFT_REGISTER_TYPE_INFO *out_type, int use_hw, IMFTransform **res)
Definition: mf_utils.c:552
ff_free_mf
void ff_free_mf(MFFunctions *f, IMFTransform **mft)
Definition: mf_utils.c:645
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
s
#define s(width, name)
Definition: cbs_vp9.c:198
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
bits
uint8_t bits
Definition: vp3data.h:128
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
av_get_sample_fmt_name
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:51
key
const char * key
Definition: hwcontext_opencl.c:189
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
NULL
#define NULL
Definition: coverity.c:32
AV_CODEC_ID_AV1
@ AV_CODEC_ID_AV1
Definition: codec_id.h:284
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
activate
filter_frame For filters that do not use the activate() callback
mf_pix_fmt_entry::guid
const GUID * guid
Definition: mf_utils.c:145
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
mf_pix_fmt_entry::pix_fmt
enum AVPixelFormat pix_fmt
Definition: mf_utils.c:146
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:448
ff_media_type_to_pix_fmt
enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type)
Definition: mf_utils.c:158
MFFunctions
Definition: mf_utils.h:48
f
f
Definition: af_crystalizer.c:122
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
sample
#define sample
Definition: flacdsp_template.c:44
size
int size
Definition: twinvq_data.h:10344
align
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
Definition: bitstream_template.h:411
mf_pix_fmts
static const struct mf_pix_fmt_entry mf_pix_fmts[]
Definition: mf_utils.c:149
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
GUID_Entry::name
const char * name
Definition: mf_utils.c:211
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
mf_pix_fmt_entry
Definition: mf_utils.c:144
AV_SAMPLE_FMT_U8
@ AV_SAMPLE_FMT_U8
unsigned 8 bits
Definition: samplefmt.h:57
init_com_mf
static int init_com_mf(void *log, MFFunctions *f)
Definition: mf_utils.c:521
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
AV_SAMPLE_FMT_S16
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition: samplefmt.h:58
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
pos
unsigned int pos
Definition: spdifenc.c:414
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
GUID_Entry
Definition: mf_utils.c:209
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:552
guid_names
static struct GUID_Entry guid_names[]
Definition: mf_utils.c:216
ff_media_type_dump
void ff_media_type_dump(void *log, IMFMediaType *type)
Definition: mf_utils.c:503
ff_MFGetAttributeSize
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 *pw, UINT32 *ph)
Definition: mf_utils.c:28
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
ff_MFGetAttributeRatio
#define ff_MFGetAttributeRatio
Definition: mf_utils.c:48
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
AV_SAMPLE_FMT_DBL
@ AV_SAMPLE_FMT_DBL
double
Definition: samplefmt.h:61
AV_SAMPLE_FMT_S32
@ AV_SAMPLE_FMT_S32
signed 32 bits
Definition: samplefmt.h:59
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:263
snprintf
#define snprintf
Definition: snprintf.h:34
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
av_get_pix_fmt_name
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:3090
ff_create_memory_sample
IMFSample * ff_create_memory_sample(MFFunctions *f, void *fill_data, size_t size, size_t align)
Definition: mf_utils.c:76
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:348