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),
268 GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
274 GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
280 GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
315 GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode),
316 GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef),
317 GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode),
318 GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode),
320 GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment),
321 GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment),
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
334 {
336 int n;
340 return buf;
341 }
342 }
343
346 return buf;
347 }
348
350 "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
356 return buf;
357 }
358
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++) {
371 MF_ATTRIBUTE_TYPE
type;
372 char extra[80] = {0};
374
375 hr = IMFAttributes_GetItemByIndex(attrs, n, &
key,
NULL);
376 if (FAILED(hr))
377 goto err;
378
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)) {
389
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
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
409 case MF_ATTRIBUTE_UINT32: {
410 UINT32 v;
411 hr = IMFAttributes_GetUINT32(attrs, &
key, &v);
412 if (FAILED(hr))
413 goto err;
415 break;
416 case MF_ATTRIBUTE_UINT64: {
417 UINT64 v;
418 hr = IMFAttributes_GetUINT64(attrs, &
key, &v);
419 if (FAILED(hr))
420 goto err;
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;
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;
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;
446 break;
447 }
448 case MF_ATTRIBUTE_BLOB: {
449 UINT32 sz;
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};
459 if (FAILED(hr))
460 goto err;
462 const char *hex = "0123456789ABCDEF";
463 if (
pos * 3 + 3 >
sizeof(str))
464 break;
467 str[
pos * 3 + 2] =
' ';
468 }
469 str[
pos * 3 + 0] = 0;
471 } else {
473 }
474 break;
475 }
476 case MF_ATTRIBUTE_IUNKNOWN: {
478 break;
479 }
480 default:
482 break;
483 }
484 }
485
486 if (IsEqualGUID(&
key, &MF_MT_SUBTYPE)) {
487 const char *fmt;
489 if (fmt)
491
493 if (fmt)
495 }
496
497 continue;
498 err:
500 }
501 }
502
504 {
506 }
507
509 {
510 switch (codec) {
517 default:
return NULL;
518 }
519 }
520
522 {
523 HRESULT hr;
524
525 hr = CoInitializeEx(
NULL, COINIT_MULTITHREADED);
526 if (hr == RPC_E_CHANGED_MODE) {
529 } else if (FAILED(hr)) {
532 }
533
534 hr =
f->MFStartup(MF_VERSION, MFSTARTUP_FULL);
535 if (FAILED(hr)) {
537 CoUninitialize();
539 }
540
541 return 0;
542 }
543
545 {
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.
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;
564 UINT32 num_activate;
565 IMFActivate *winner = 0;
567
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
581 &num_activate);
582 if (FAILED(hr))
583 goto error_uninit_mf;
584
586 if (!num_activate)
588
589 for (n = 0; n < num_activate; n++) {
592 }
593 }
594
596 for (n = 0; n < num_activate; n++) {
599 hr = IMFActivate_ActivateObject(
activate[n], &IID_IMFTransform,
600 (void **)res);
601 if (*res) {
603 IMFActivate_AddRef(winner);
604 break;
605 }
606 }
607
608 for (n = 0; n < num_activate; n++)
611
612 if (!*res) {
615 goto error_uninit_mf;
616 }
617
619 wchar_t s[512];
// being lazy here
620 IMFAttributes *attrs;
621 hr = IMFTransform_GetAttributes(*res, &attrs);
622 if (!FAILED(hr) && attrs) {
623
626 IMFAttributes_Release(attrs);
627 }
628
629 hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute,
s,
631 if (!FAILED(hr))
633
634 }
635
636 IMFActivate_Release(winner);
637
638 return 0;
639
640 error_uninit_mf:
643 }
644
646 {
647 if (*mft)
648 IMFTransform_Release(*mft);
651 }