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
20 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
21 #undef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0602
23 #endif
24
27
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;
36 }
37 return hr;
38 }
39
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
51 {
52 #define HR(x) case x: return (char *) # x;
53 switch (hr) {
56 HR(MF_E_INVALIDMEDIATYPE)
57 HR(MF_E_INVALIDSTREAMNUMBER)
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)
65 HR(MF_E_NO_SAMPLE_TIMESTAMP)
66 HR(MF_E_NO_SAMPLE_DURATION)
67 #undef HR
68 }
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.)
78 {
79 HRESULT hr;
82
83 hr =
f->MFCreateSample(&
sample);
84 if (FAILED(hr))
86
88
90 if (FAILED(hr))
92
93 if (fill_data) {
95
97 if (FAILED(hr)) {
98 IMFMediaBuffer_Release(
buffer);
101 }
103
104 IMFMediaBuffer_SetCurrentLength(
buffer,
size);
105 IMFMediaBuffer_Unlock(
buffer);
106 }
107
109 IMFMediaBuffer_Release(
buffer);
110
112 }
113
115 {
116 HRESULT hr;
118 GUID subtype;
119
120 hr = IMFAttributes_GetUINT32(
type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &
bits);
121 if (FAILED(hr))
123
124 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &subtype);
125 if (FAILED(hr))
127
128 if (IsEqualGUID(&subtype, &MFAudioFormat_PCM)) {
133 }
134 } else if (IsEqualGUID(&subtype, &MFAudioFormat_Float)) {
138 }
139 }
140
142 }
143
147 };
148
156 };
157
159 {
160 HRESULT hr;
161 GUID subtype;
163
164 hr = IMFAttributes_GetGUID(
type, &MF_MT_SUBTYPE, &subtype);
165 if (FAILED(hr))
167
171 }
172
174 }
175
177 {
179
183 }
184
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).
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;
207 }
208
212 };
213
214 #define GUID_ENTRY(var) {&(var), # var}
215
223 GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT),
224 GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE),
229 GUID_ENTRY(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX),
267 GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
273 GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
279 GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
314 GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
315 GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
316 GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
317 GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
319 GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
320 GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
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
333 {
335 int n;
339 return buf;
340 }
341 }
342
345 return buf;
346 }
347
349 "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
355 return buf;
356 }
357
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++) {
370 MF_ATTRIBUTE_TYPE
type;
371 char extra[80] = {0};
373
374 hr = IMFAttributes_GetItemByIndex(attrs, n, &
key,
NULL);
375 if (FAILED(hr))
376 goto err;
377
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)) {
388
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
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
408 case MF_ATTRIBUTE_UINT32: {
409 UINT32 v;
410 hr = IMFAttributes_GetUINT32(attrs, &
key, &v);
411 if (FAILED(hr))
412 goto err;
414 break;
415 case MF_ATTRIBUTE_UINT64: {
416 UINT64 v;
417 hr = IMFAttributes_GetUINT64(attrs, &
key, &v);
418 if (FAILED(hr))
419 goto err;
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;
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;
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;
445 break;
446 }
447 case MF_ATTRIBUTE_BLOB: {
448 UINT32 sz;
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};
458 if (FAILED(hr))
459 goto err;
461 const char *hex = "0123456789ABCDEF";
462 if (
pos * 3 + 3 >
sizeof(str))
463 break;
466 str[
pos * 3 + 2] =
' ';
467 }
468 str[
pos * 3 + 0] = 0;
470 } else {
472 }
473 break;
474 }
475 case MF_ATTRIBUTE_IUNKNOWN: {
477 break;
478 }
479 default:
481 break;
482 }
483 }
484
485 if (IsEqualGUID(&
key, &MF_MT_SUBTYPE)) {
486 const char *fmt;
488 if (fmt)
490
492 if (fmt)
494 }
495
496 continue;
497 err:
499 }
500 }
501
503 {
505 }
506
508 {
509 switch (codec) {
515 default:
return NULL;
516 }
517 }
518
520 {
521 HRESULT hr;
522
523 hr = CoInitializeEx(
NULL, COINIT_MULTITHREADED);
524 if (hr == RPC_E_CHANGED_MODE) {
527 } else if (FAILED(hr)) {
530 }
531
532 hr =
f->MFStartup(MF_VERSION, MFSTARTUP_FULL);
533 if (FAILED(hr)) {
535 CoUninitialize();
537 }
538
539 return 0;
540 }
541
543 {
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.
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;
562 UINT32 num_activate;
563 IMFActivate *winner = 0;
565
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
579 &num_activate);
580 if (FAILED(hr))
581 goto error_uninit_mf;
582
584 if (!num_activate)
586
587 for (n = 0; n < num_activate; n++) {
590 }
591 }
592
594 for (n = 0; n < num_activate; n++) {
597 hr = IMFActivate_ActivateObject(
activate[n], &IID_IMFTransform,
598 (void **)res);
599 if (*res) {
601 IMFActivate_AddRef(winner);
602 break;
603 }
604 }
605
606 for (n = 0; n < num_activate; n++)
609
610 if (!*res) {
613 goto error_uninit_mf;
614 }
615
617 wchar_t s[512];
// being lazy here
618 IMFAttributes *attrs;
619 hr = IMFTransform_GetAttributes(*res, &attrs);
620 if (!FAILED(hr) && attrs) {
621
624 IMFAttributes_Release(attrs);
625 }
626
627 hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute,
s,
629 if (!FAILED(hr))
631
632 }
633
634 IMFActivate_Release(winner);
635
636 return 0;
637
638 error_uninit_mf:
641 }
642
644 {
645 if (*mft)
646 IMFTransform_Release(*mft);
649 }