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(MFVideoFormat_H264),
244  GUID_ENTRY(MFVideoFormat_H264_ES),
245  GUID_ENTRY(ff_MFVideoFormat_HEVC),
246  GUID_ENTRY(ff_MFVideoFormat_HEVC_ES),
247  GUID_ENTRY(MFVideoFormat_MPEG2),
248  GUID_ENTRY(MFVideoFormat_MP43),
249  GUID_ENTRY(MFVideoFormat_MP4V),
250  GUID_ENTRY(MFVideoFormat_WMV1),
251  GUID_ENTRY(MFVideoFormat_WMV2),
252  GUID_ENTRY(MFVideoFormat_WMV3),
253  GUID_ENTRY(MFVideoFormat_WVC1),
254  GUID_ENTRY(MFAudioFormat_Dolby_AC3),
255  GUID_ENTRY(MFAudioFormat_Dolby_DDPlus),
256  GUID_ENTRY(MFAudioFormat_AAC),
257  GUID_ENTRY(MFAudioFormat_MP3),
258  GUID_ENTRY(MFAudioFormat_MSP1),
259  GUID_ENTRY(MFAudioFormat_WMAudioV8),
260  GUID_ENTRY(MFAudioFormat_WMAudioV9),
261  GUID_ENTRY(MFAudioFormat_WMAudio_Lossless),
262  GUID_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT),
263  GUID_ENTRY(MF_MT_COMPRESSED),
264  GUID_ENTRY(MF_MT_FIXED_SIZE_SAMPLES),
265  GUID_ENTRY(MF_MT_SAMPLE_SIZE),
266  GUID_ENTRY(MF_MT_WRAPPED_TYPE),
267  GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
268  GUID_ENTRY(MF_MT_AAC_PAYLOAD_TYPE),
269  GUID_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
270  GUID_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE),
271  GUID_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT),
272  GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
273  GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
274  GUID_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX),
275  GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
276  GUID_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
277  GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
278  GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
279  GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
280  GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF),
281  GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET),
282  GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF),
283  GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET),
284  GUID_ENTRY(MF_MT_AVG_BIT_ERROR_RATE),
285  GUID_ENTRY(MF_MT_AVG_BITRATE),
286  GUID_ENTRY(MF_MT_DEFAULT_STRIDE),
287  GUID_ENTRY(MF_MT_DRM_FLAGS),
288  GUID_ENTRY(MF_MT_FRAME_RATE),
289  GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX),
290  GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN),
291  GUID_ENTRY(MF_MT_FRAME_SIZE),
292  GUID_ENTRY(MF_MT_GEOMETRIC_APERTURE),
293  GUID_ENTRY(MF_MT_INTERLACE_MODE),
294  GUID_ENTRY(MF_MT_MAX_KEYFRAME_SPACING),
295  GUID_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE),
296  GUID_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER),
297  GUID_ENTRY(MF_MT_MPEG_START_TIME_CODE),
298  GUID_ENTRY(MF_MT_MPEG2_FLAGS),
299  GUID_ENTRY(MF_MT_MPEG2_LEVEL),
300  GUID_ENTRY(MF_MT_MPEG2_PROFILE),
301  GUID_ENTRY(MF_MT_PAD_CONTROL_FLAGS),
302  GUID_ENTRY(MF_MT_PALETTE),
303  GUID_ENTRY(MF_MT_PAN_SCAN_APERTURE),
304  GUID_ENTRY(MF_MT_PAN_SCAN_ENABLED),
305  GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
306  GUID_ENTRY(MF_MT_SOURCE_CONTENT_HINT),
307  GUID_ENTRY(MF_MT_TRANSFER_FUNCTION),
308  GUID_ENTRY(MF_MT_VIDEO_CHROMA_SITING),
309  GUID_ENTRY(MF_MT_VIDEO_LIGHTING),
310  GUID_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE),
311  GUID_ENTRY(MF_MT_VIDEO_PRIMARIES),
312  GUID_ENTRY(MF_MT_VIDEO_ROTATION),
313  GUID_ENTRY(MF_MT_YUV_MATRIX),
314  GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
315  GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
316  GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
317  GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
318  GUID_ENTRY(ff_CODECAPI_AVLowLatencyMode),
319  GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
320  GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
321  GUID_ENTRY(ff_CODECAPI_AVDecVideoCodecType),
322  GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVAMode),
323  GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVABusEncryption),
324  GUID_ENTRY(ff_CODECAPI_AVDecVideoSWPowerLevel),
325  GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedWidth),
326  GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedHeight),
327  GUID_ENTRY(ff_CODECAPI_AVDecNumWorkerThreads),
328  GUID_ENTRY(ff_CODECAPI_AVDecSoftwareDynamicFormatChange),
329  GUID_ENTRY(ff_CODECAPI_AVDecDisableVideoPostProcessing),
330 };
331 
332 char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid)
333 {
334  uint32_t fourcc;
335  int n;
336  for (n = 0; n < FF_ARRAY_ELEMS(guid_names); n++) {
337  if (IsEqualGUID(guid, guid_names[n].guid)) {
338  snprintf(buf, buf_size, "%s", guid_names[n].name);
339  return buf;
340  }
341  }
342 
343  if (ff_fourcc_from_guid(guid, &fourcc) >= 0) {
344  snprintf(buf, buf_size, "<FourCC %s>", av_fourcc2str(fourcc));
345  return buf;
346  }
347 
348  snprintf(buf, buf_size,
349  "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
350  (unsigned) guid->Data1, guid->Data2, guid->Data3,
351  guid->Data4[0], guid->Data4[1],
352  guid->Data4[2], guid->Data4[3],
353  guid->Data4[4], guid->Data4[5],
354  guid->Data4[6], guid->Data4[7]);
355  return buf;
356 }
357 
358 void ff_attributes_dump(void *log, IMFAttributes *attrs)
359 {
360  HRESULT hr;
361  UINT32 count;
362  int n;
363 
364  hr = IMFAttributes_GetCount(attrs, &count);
365  if (FAILED(hr))
366  return;
367 
368  for (n = 0; n < count; n++) {
369  GUID key;
370  MF_ATTRIBUTE_TYPE type;
371  char extra[80] = {0};
372  const char *name = NULL;
373 
374  hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL);
375  if (FAILED(hr))
376  goto err;
377 
378  name = ff_guid_str(&key);
379 
380  if (IsEqualGUID(&key, &MF_MT_AUDIO_CHANNEL_MASK)) {
381  UINT32 v;
382  hr = IMFAttributes_GetUINT32(attrs, &key, &v);
383  if (FAILED(hr))
384  goto err;
385  snprintf(extra, sizeof(extra), " (0x%x)", (unsigned)v);
386  } else if (IsEqualGUID(&key, &MF_MT_FRAME_SIZE)) {
387  UINT32 w, h;
388 
389  hr = ff_MFGetAttributeSize(attrs, &MF_MT_FRAME_SIZE, &w, &h);
390  if (FAILED(hr))
391  goto err;
392  snprintf(extra, sizeof(extra), " (%dx%d)", (int)w, (int)h);
393  } else if (IsEqualGUID(&key, &MF_MT_PIXEL_ASPECT_RATIO) ||
394  IsEqualGUID(&key, &MF_MT_FRAME_RATE)) {
395  UINT32 num, den;
396 
397  hr = ff_MFGetAttributeRatio(attrs, &key, &num, &den);
398  if (FAILED(hr))
399  goto err;
400  snprintf(extra, sizeof(extra), " (%d:%d)", (int)num, (int)den);
401  }
402 
403  hr = IMFAttributes_GetItemType(attrs, &key, &type);
404  if (FAILED(hr))
405  goto err;
406 
407  switch (type) {
408  case MF_ATTRIBUTE_UINT32: {
409  UINT32 v;
410  hr = IMFAttributes_GetUINT32(attrs, &key, &v);
411  if (FAILED(hr))
412  goto err;
413  av_log(log, AV_LOG_VERBOSE, " %s=%d%s\n", name, (int)v, extra);
414  break;
415  case MF_ATTRIBUTE_UINT64: {
416  UINT64 v;
417  hr = IMFAttributes_GetUINT64(attrs, &key, &v);
418  if (FAILED(hr))
419  goto err;
420  av_log(log, AV_LOG_VERBOSE, " %s=%lld%s\n", name, (long long)v, extra);
421  break;
422  }
423  case MF_ATTRIBUTE_DOUBLE: {
424  DOUBLE v;
425  hr = IMFAttributes_GetDouble(attrs, &key, &v);
426  if (FAILED(hr))
427  goto err;
428  av_log(log, AV_LOG_VERBOSE, " %s=%f%s\n", name, (double)v, extra);
429  break;
430  }
431  case MF_ATTRIBUTE_STRING: {
432  wchar_t s[512]; // being lazy here
433  hr = IMFAttributes_GetString(attrs, &key, s, sizeof(s), NULL);
434  if (FAILED(hr))
435  goto err;
436  av_log(log, AV_LOG_VERBOSE, " %s='%ls'%s\n", name, s, extra);
437  break;
438  }
439  case MF_ATTRIBUTE_GUID: {
440  GUID v;
441  hr = IMFAttributes_GetGUID(attrs, &key, &v);
442  if (FAILED(hr))
443  goto err;
444  av_log(log, AV_LOG_VERBOSE, " %s=%s%s\n", name, ff_guid_str(&v), extra);
445  break;
446  }
447  case MF_ATTRIBUTE_BLOB: {
448  UINT32 sz;
449  UINT8 buffer[100];
450  hr = IMFAttributes_GetBlobSize(attrs, &key, &sz);
451  if (FAILED(hr))
452  goto err;
453  if (sz <= sizeof(buffer)) {
454  // hex-dump it
455  char str[512] = {0};
456  size_t pos = 0;
457  hr = IMFAttributes_GetBlob(attrs, &key, buffer, sizeof(buffer), &sz);
458  if (FAILED(hr))
459  goto err;
460  for (pos = 0; pos < sz; pos++) {
461  const char *hex = "0123456789ABCDEF";
462  if (pos * 3 + 3 > sizeof(str))
463  break;
464  str[pos * 3 + 0] = hex[buffer[pos] >> 4];
465  str[pos * 3 + 1] = hex[buffer[pos] & 15];
466  str[pos * 3 + 2] = ' ';
467  }
468  str[pos * 3 + 0] = 0;
469  av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d: %s>%s\n", name, (int)sz, str, extra);
470  } else {
471  av_log(log, AV_LOG_VERBOSE, " %s=<blob size %d>%s\n", name, (int)sz, extra);
472  }
473  break;
474  }
475  case MF_ATTRIBUTE_IUNKNOWN: {
476  av_log(log, AV_LOG_VERBOSE, " %s=<IUnknown>%s\n", name, extra);
477  break;
478  }
479  default:
480  av_log(log, AV_LOG_VERBOSE, " %s=<unknown type>%s\n", name, extra);
481  break;
482  }
483  }
484 
485  if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) {
486  const char *fmt;
488  if (fmt)
489  av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt);
490 
492  if (fmt)
493  av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt);
494  }
495 
496  continue;
497  err:
498  av_log(log, AV_LOG_VERBOSE, " %s=<failed to get value>\n", name ? name : "?");
499  }
500 }
501 
502 void ff_media_type_dump(void *log, IMFMediaType *type)
503 {
504  ff_attributes_dump(log, (IMFAttributes *)type);
505 }
506 
507 const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec)
508 {
509  switch (codec) {
510  case AV_CODEC_ID_H264: return &MFVideoFormat_H264;
511  case AV_CODEC_ID_HEVC: return &ff_MFVideoFormat_HEVC;
512  case AV_CODEC_ID_AC3: return &MFAudioFormat_Dolby_AC3;
513  case AV_CODEC_ID_AAC: return &MFAudioFormat_AAC;
514  case AV_CODEC_ID_MP3: return &MFAudioFormat_MP3;
515  default: return NULL;
516  }
517 }
518 
519 static int init_com_mf(void *log, MFFunctions *f)
520 {
521  HRESULT hr;
522 
523  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
524  if (hr == RPC_E_CHANGED_MODE) {
525  av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n");
526  return AVERROR(EINVAL);
527  } else if (FAILED(hr)) {
528  av_log(log, AV_LOG_ERROR, "could not initialize COM\n");
529  return AVERROR(ENOSYS);
530  }
531 
532  hr = f->MFStartup(MF_VERSION, MFSTARTUP_FULL);
533  if (FAILED(hr)) {
534  av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n");
535  CoUninitialize();
536  return AVERROR(ENOSYS);
537  }
538 
539  return 0;
540 }
541 
543 {
544  f->MFShutdown();
545  CoUninitialize();
546 }
547 
548 // Find and create a IMFTransform with the given input/output types. When done,
549 // you should use ff_free_mf() to destroy it, which will also uninit COM.
550 int ff_instantiate_mf(void *log,
551  MFFunctions *f,
552  GUID category,
553  MFT_REGISTER_TYPE_INFO *in_type,
554  MFT_REGISTER_TYPE_INFO *out_type,
555  int use_hw,
556  IMFTransform **res)
557 {
558  HRESULT hr;
559  int n;
560  int ret;
561  IMFActivate **activate;
562  UINT32 num_activate;
563  IMFActivate *winner = 0;
564  UINT32 flags;
565 
566  ret = init_com_mf(log, f);
567  if (ret < 0)
568  return ret;
569 
570  flags = MFT_ENUM_FLAG_SORTANDFILTER;
571 
572  if (use_hw) {
573  flags |= MFT_ENUM_FLAG_HARDWARE;
574  } else {
575  flags |= MFT_ENUM_FLAG_SYNCMFT;
576  }
577 
578  hr = f->MFTEnumEx(category, flags, in_type, out_type, &activate,
579  &num_activate);
580  if (FAILED(hr))
581  goto error_uninit_mf;
582 
583  if (log) {
584  if (!num_activate)
585  av_log(log, AV_LOG_ERROR, "could not find any MFT for the given media type\n");
586 
587  for (n = 0; n < num_activate; n++) {
588  av_log(log, AV_LOG_VERBOSE, "MF %d attributes:\n", n);
589  ff_attributes_dump(log, (IMFAttributes *)activate[n]);
590  }
591  }
592 
593  *res = NULL;
594  for (n = 0; n < num_activate; n++) {
595  if (log)
596  av_log(log, AV_LOG_VERBOSE, "activate MFT %d\n", n);
597  hr = IMFActivate_ActivateObject(activate[n], &IID_IMFTransform,
598  (void **)res);
599  if (*res) {
600  winner = activate[n];
601  IMFActivate_AddRef(winner);
602  break;
603  }
604  }
605 
606  for (n = 0; n < num_activate; n++)
607  IMFActivate_Release(activate[n]);
608  CoTaskMemFree(activate);
609 
610  if (!*res) {
611  if (log)
612  av_log(log, AV_LOG_ERROR, "could not create MFT\n");
613  goto error_uninit_mf;
614  }
615 
616  if (log) {
617  wchar_t s[512]; // being lazy here
618  IMFAttributes *attrs;
619  hr = IMFTransform_GetAttributes(*res, &attrs);
620  if (!FAILED(hr) && attrs) {
621 
622  av_log(log, AV_LOG_VERBOSE, "MFT attributes\n");
623  ff_attributes_dump(log, attrs);
624  IMFAttributes_Release(attrs);
625  }
626 
627  hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute, s,
628  sizeof(s), NULL);
629  if (!FAILED(hr))
630  av_log(log, AV_LOG_INFO, "MFT name: '%ls'\n", s);
631 
632  }
633 
634  IMFActivate_Release(winner);
635 
636  return 0;
637 
638 error_uninit_mf:
639  uninit_com_mf(f);
640  return AVERROR(ENOSYS);
641 }
642 
643 void ff_free_mf(MFFunctions *f, IMFTransform **mft)
644 {
645  if (*mft)
646  IMFTransform_Release(*mft);
647  *mft = NULL;
648  uninit_com_mf(f);
649 }
GUID_Entry::guid
const GUID * guid
Definition: mf_utils.c:210
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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:429
uninit_com_mf
static void uninit_com_mf(MFFunctions *f)
Definition: mf_utils.c:542
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:332
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:358
ff_codec_to_mf_subtype
const CLSID * ff_codec_to_mf_subtype(enum AVCodecID codec)
Definition: mf_utils.c:507
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:171
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
category
category
Definition: openal-dec.c:248
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:427
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:550
ff_free_mf
void ff_free_mf(MFFunctions *f, IMFTransform **mft)
Definition: mf_utils.c:643
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
s
#define s(width, name)
Definition: cbs_vp9.c:256
bits
uint8_t bits
Definition: vp3data.h:141
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
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:66
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:174
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:77
NULL
#define NULL
Definition: coverity.c:32
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
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:47
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:428
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
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:191
GUID_Entry::name
const char * name
Definition: mf_utils.c:211
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
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:519
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:224
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:89
pos
unsigned int pos
Definition: spdifenc.c:412
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:65
GUID_Entry
Definition: mf_utils.c:209
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:455
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:502
ff_MFGetAttributeSize
HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, UINT32 *pw, UINT32 *ph)
Definition: mf_utils.c:28
convert_header.str
string str
Definition: convert_header.py:20
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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:2038
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:241
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:2582
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:354