1 /*****************************************************************************
2 * mft.c : Media Foundation Transform audio/video decoder
3 *****************************************************************************
4 * Copyright (C) 2014 VLC authors and VideoLAN
6 * Author: Felix Abecassis <felix.abecassis@gmail.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
30 /* Needed for many mingw macros. */
33 /* Avoid having GUIDs being defined as "extern". */
37 # define STDCALL __stdcall
40 #include <winapifamily.h>
42 #define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
46 #include <vlc_common.h>
47 #include <vlc_plugin.h>
48 #include <vlc_codec.h>
49 #include "../packetizer/h264_nal.h"
50 #define _VIDEOINFOHEADER_
51 #include <vlc_codecs.h>
54 #include <mftransform.h>
56 #include <mfobjects.h>
58 static int Open(vlc_object_t
*);
59 static void Close(vlc_object_t
*);
62 set_description(N_("Media Foundation Transform decoder"))
64 set_capability("video decoder", 1)
65 set_callbacks(Open
, Close
)
66 set_category(CAT_INPUT
)
67 set_subcategory(SUBCAT_INPUT_VCODEC
)
71 set_capability("audio decoder", 1)
72 set_callbacks(Open
, Close
)
78 HRESULT (STDCALL
*fptr_MFTEnumEx
)(GUID guidCategory
, UINT32 Flags
,
79 const MFT_REGISTER_TYPE_INFO
*pInputType
,
80 const MFT_REGISTER_TYPE_INFO
*pOutputType
,
81 IMFActivate
***pppMFTActivate
, UINT32
*pcMFTActivate
);
82 HRESULT (STDCALL
*fptr_MFCreateSample
)(IMFSample
**ppIMFSample
);
83 HRESULT (STDCALL
*fptr_MFCreateMemoryBuffer
)(DWORD cbMaxLength
, IMFMediaBuffer
**ppBuffer
);
84 HRESULT (STDCALL
*fptr_MFCreateAlignedMemoryBuffer
)(DWORD cbMaxLength
, DWORD fAlignmentFlags
, IMFMediaBuffer
**ppBuffer
);
93 const GUID
* major_type
;
95 /* Container for a dynamically constructed subtype */
98 /* For asynchronous MFT */
100 IMFMediaEventGenerator
*event_generator
;
101 int pending_input_events
;
102 int pending_output_events
;
105 DWORD input_stream_id
;
106 IMFMediaType
*input_type
;
109 DWORD output_stream_id
;
110 IMFSample
*output_sample
;
111 IMFMediaType
*output_type
;
114 uint8_t nal_length_size
;
117 static const int pi_channels_maps
[9] =
121 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
122 AOUT_CHAN_CENTER
| AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
123 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT
124 | AOUT_CHAN_REARRIGHT
,
125 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
126 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
,
127 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
128 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
,
129 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
130 | AOUT_CHAN_REARCENTER
| AOUT_CHAN_MIDDLELEFT
131 | AOUT_CHAN_MIDDLERIGHT
| AOUT_CHAN_LFE
,
132 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT
133 | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT
137 /* Possibly missing from mingw headers */
138 #ifndef MF_E_TRANSFORM_NEED_MORE_INPUT
139 # define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72)
142 #ifndef MF_E_TRANSFORM_STREAM_CHANGE
143 # define MF_E_TRANSFORM_STREAM_CHANGE _HRESULT_TYPEDEF_(0xc00d6d61)
146 #ifndef MF_E_NO_EVENTS_AVAILABLE
147 # define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xC00D3E80L)
150 #ifndef MF_EVENT_FLAG_NO_WAIT
151 # define MF_EVENT_FLAG_NO_WAIT 0x00000001
155 * The MFTransformXXX values might not be defined in mingw headers,
156 * thus we use our own enum with the VLC prefix.
160 VLC_METransformUnknown
= 600,
161 VLC_METransformNeedInput
,
162 VLC_METransformHaveOutput
,
163 VLC_METransformDrainComplete
,
164 VLC_METransformMarker
,
174 * We need this table since the FOURCC used for GUID is not the same
175 * as the FOURCC used by VLC, for instance h264 vs H264.
177 static const pair_format_guid video_format_table
[] =
179 { VLC_CODEC_H264
, &MFVideoFormat_H264
},
180 { VLC_CODEC_MJPG
, &MFVideoFormat_MJPG
},
181 { VLC_CODEC_WMV1
, &MFVideoFormat_WMV1
},
182 { VLC_CODEC_WMV2
, &MFVideoFormat_WMV2
},
183 { VLC_CODEC_WMV3
, &MFVideoFormat_WMV3
},
184 { VLC_CODEC_VC1
, &MFVideoFormat_WVC1
},
188 // 8-bit luminance only
189 DEFINE_MEDIATYPE_GUID (MFVideoFormat_L8
, 50);
192 * Table to map MF Transform raw 3D3 output formats to native VLC FourCC
194 static const pair_format_guid d3d_format_table
[] = {
195 { VLC_CODEC_RGB32
, &MFVideoFormat_RGB32
},
196 { VLC_CODEC_RGB24
, &MFVideoFormat_RGB24
},
197 { VLC_CODEC_RGBA
, &MFVideoFormat_ARGB32
},
198 { VLC_CODEC_GREY
, &MFVideoFormat_L8
},
202 #if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 4
203 DEFINE_GUID(MFAudioFormat_Dolby_AC3
, 0xe06d802c, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
206 * We cannot use the FOURCC code for audio either since the
207 * WAVE_FORMAT value is used to create the GUID.
209 static const pair_format_guid audio_format_table
[] =
211 { VLC_CODEC_MPGA
, &MFAudioFormat_MPEG
},
212 { VLC_CODEC_MP3
, &MFAudioFormat_MP3
},
213 { VLC_CODEC_DTS
, &MFAudioFormat_DTS
},
214 { VLC_CODEC_MP4A
, &MFAudioFormat_AAC
},
215 { VLC_CODEC_WMA2
, &MFAudioFormat_WMAudioV8
},
216 { VLC_CODEC_A52
, &MFAudioFormat_Dolby_AC3
},
220 static const GUID
*FormatToGUID(const pair_format_guid table
[], vlc_fourcc_t fourcc
)
222 for (int i
= 0; table
[i
].fourcc
; ++i
)
223 if (table
[i
].fourcc
== fourcc
)
224 return table
[i
].guid
;
229 static vlc_fourcc_t
GUIDToFormat(const pair_format_guid table
[], const GUID
* guid
)
231 for (int i
= 0; table
[i
].fourcc
; ++i
)
232 if (IsEqualGUID(table
[i
].guid
, guid
))
233 return table
[i
].fourcc
;
239 * Low latency mode for Windows 8. Without this option, the H264
240 * decoder will fill *all* its internal buffers before returning a
241 * frame. Because of this behavior, the decoder might return no frame
242 * for more than 500 ms, making it unusable for playback.
244 DEFINE_GUID(CODECAPI_AVLowLatencyMode
, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
246 static int SetInputType(decoder_t
*p_dec
, DWORD stream_id
, IMFMediaType
**result
)
248 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
253 IMFMediaType
*input_media_type
= NULL
;
255 /* Search a suitable input type for the MFT. */
256 int input_type_index
= 0;
258 for (int i
= 0; !found
; ++i
)
260 hr
= IMFTransform_GetInputAvailableType(p_sys
->mft
, stream_id
, i
, &input_media_type
);
261 if (hr
== MF_E_NO_MORE_TYPES
)
263 else if (hr
== MF_E_TRANSFORM_TYPE_NOT_SET
)
265 /* The output type must be set before setting the input type for this MFT. */
272 hr
= IMFMediaType_GetGUID(input_media_type
, &MF_MT_SUBTYPE
, &subtype
);
276 if (IsEqualGUID(&subtype
, p_sys
->subtype
))
280 input_type_index
= i
;
282 IMFMediaType_Release(input_media_type
);
283 input_media_type
= NULL
;
288 hr
= IMFTransform_GetInputAvailableType(p_sys
->mft
, stream_id
, input_type_index
, &input_media_type
);
292 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
294 UINT64 width
= p_dec
->fmt_in
.video
.i_width
;
295 UINT64 height
= p_dec
->fmt_in
.video
.i_height
;
296 UINT64 frame_size
= (width
<< 32) | height
;
297 hr
= IMFMediaType_SetUINT64(input_media_type
, &MF_MT_FRAME_SIZE
, frame_size
);
301 /* Some transforms like to know the frame rate and may reject the input type otherwise. */
302 UINT64 frame_ratio_num
= p_dec
->fmt_in
.video
.i_frame_rate
;
303 UINT64 frame_ratio_dem
= p_dec
->fmt_in
.video
.i_frame_rate_base
;
304 if(frame_ratio_num
&& frame_ratio_dem
) {
305 UINT64 frame_rate
= (frame_ratio_num
<< 32) | frame_ratio_dem
;
306 hr
= IMFMediaType_SetUINT64(input_media_type
, &MF_MT_FRAME_RATE
, frame_rate
);
313 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG
, p_sys
->subtype
->Data1
);
316 if (p_dec
->fmt_in
.audio
.i_rate
)
318 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, p_dec
->fmt_in
.audio
.i_rate
);
322 if (p_dec
->fmt_in
.audio
.i_channels
)
324 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, p_dec
->fmt_in
.audio
.i_channels
);
328 if (p_dec
->fmt_in
.audio
.i_bitspersample
)
330 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, p_dec
->fmt_in
.audio
.i_bitspersample
);
334 if (p_dec
->fmt_in
.audio
.i_blockalign
)
336 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, p_dec
->fmt_in
.audio
.i_blockalign
);
340 if (p_dec
->fmt_in
.i_bitrate
)
342 hr
= IMFMediaType_SetUINT32(input_media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, p_dec
->fmt_in
.i_bitrate
/ 8);
348 if (p_dec
->fmt_in
.i_extra
> 0)
350 UINT32 blob_size
= 0;
351 hr
= IMFMediaType_GetBlobSize(input_media_type
, &MF_MT_USER_DATA
, &blob_size
);
353 * Do not overwrite existing user data in the input type, this
354 * can cause the MFT to reject the type.
356 if (hr
== MF_E_ATTRIBUTENOTFOUND
)
358 hr
= IMFMediaType_SetBlob(input_media_type
, &MF_MT_USER_DATA
,
359 (const UINT8
*)p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
365 hr
= IMFTransform_SetInputType(p_sys
->mft
, stream_id
, input_media_type
, 0);
369 *result
= input_media_type
;
374 msg_Err(p_dec
, "Error in SetInputType()");
375 if (input_media_type
)
376 IMFMediaType_Release(input_media_type
);
380 static int SetOutputType(decoder_t
*p_dec
, DWORD stream_id
, IMFMediaType
**result
)
382 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
387 IMFMediaType
*output_media_type
= NULL
;
390 * Enumerate available output types. The list is ordered by
391 * preference thus we will use the first one unless YV12/I420 is
392 * available for video or float32 for audio.
394 int output_type_index
= -1;
396 for (int i
= 0; !found
; ++i
)
398 hr
= IMFTransform_GetOutputAvailableType(p_sys
->mft
, stream_id
, i
, &output_media_type
);
399 if (hr
== MF_E_NO_MORE_TYPES
)
401 else if (hr
== MF_E_TRANSFORM_TYPE_NOT_SET
)
403 /* The input type must be set before setting the output type for this MFT. */
410 hr
= IMFMediaType_GetGUID(output_media_type
, &MF_MT_SUBTYPE
, &subtype
);
414 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
416 if (IsEqualGUID(&subtype
, &MFVideoFormat_YV12
) || IsEqualGUID(&subtype
, &MFVideoFormat_I420
))
418 /* Transform might offer output in a D3DFMT propietary FCC. If we can
419 * use it, fall back to it in case we do not find YV12 or I420 */
420 else if(output_type_index
< 0 && GUIDToFormat(d3d_format_table
, &subtype
) > 0)
421 output_type_index
= i
;
425 UINT32 bits_per_sample
;
426 hr
= IMFMediaType_GetUINT32(output_media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &bits_per_sample
);
429 if (bits_per_sample
== 32 && IsEqualGUID(&subtype
, &MFAudioFormat_Float
))
434 output_type_index
= i
;
436 IMFMediaType_Release(output_media_type
);
437 output_media_type
= NULL
;
440 * It's not an error if we don't find the output type we were
441 * looking for, in this case we use the first available type.
443 if(output_type_index
< 0)
444 /* No output format found we prefer, just pick the first one preferred
446 output_type_index
= 0;
448 hr
= IMFTransform_GetOutputAvailableType(p_sys
->mft
, stream_id
, output_type_index
, &output_media_type
);
452 hr
= IMFTransform_SetOutputType(p_sys
->mft
, stream_id
, output_media_type
, 0);
457 hr
= IMFMediaType_GetGUID(output_media_type
, &MF_MT_SUBTYPE
, &subtype
);
461 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
463 video_format_Copy( &p_dec
->fmt_out
.video
, &p_dec
->fmt_in
.video
);
465 /* Transform might offer output in a D3DFMT propietary FCC */
466 vlc_fourcc_t fcc
= GUIDToFormat(d3d_format_table
, &subtype
);
468 /* D3D formats are upside down */
469 p_dec
->fmt_out
.video
.orientation
= ORIENT_BOTTOM_LEFT
;
471 fcc
= vlc_fourcc_GetCodec(p_dec
->fmt_in
.i_cat
, subtype
.Data1
);
474 p_dec
->fmt_out
.i_codec
= fcc
;
478 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
480 UINT32 bitspersample
= 0;
481 hr
= IMFMediaType_GetUINT32(output_media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &bitspersample
);
482 if (SUCCEEDED(hr
) && bitspersample
)
483 p_dec
->fmt_out
.audio
.i_bitspersample
= bitspersample
;
486 hr
= IMFMediaType_GetUINT32(output_media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channels
);
487 if (SUCCEEDED(hr
) && channels
)
488 p_dec
->fmt_out
.audio
.i_channels
= channels
;
491 hr
= IMFMediaType_GetUINT32(output_media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
);
492 if (SUCCEEDED(hr
) && rate
)
493 p_dec
->fmt_out
.audio
.i_rate
= rate
;
496 wf_tag_to_fourcc(subtype
.Data1
, &fourcc
, NULL
);
497 p_dec
->fmt_out
.i_codec
= vlc_fourcc_GetCodecAudio(fourcc
, p_dec
->fmt_out
.audio
.i_bitspersample
);
499 p_dec
->fmt_out
.audio
.i_physical_channels
= pi_channels_maps
[p_dec
->fmt_out
.audio
.i_channels
];
502 *result
= output_media_type
;
507 msg_Err(p_dec
, "Error in SetOutputType()");
508 if (output_media_type
)
509 IMFMediaType_Release(output_media_type
);
513 static int AllocateInputSample(decoder_t
*p_dec
, DWORD stream_id
, IMFSample
** result
, DWORD size
)
515 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
516 MFHandle
*mf
= &p_sys
->mf_handle
;
521 IMFSample
*input_sample
= NULL
;
523 MFT_INPUT_STREAM_INFO input_info
;
524 hr
= IMFTransform_GetInputStreamInfo(p_sys
->mft
, stream_id
, &input_info
);
528 hr
= mf
->fptr_MFCreateSample(&input_sample
);
532 IMFMediaBuffer
*input_media_buffer
= NULL
;
533 DWORD allocation_size
= __MAX(input_info
.cbSize
, size
);
534 hr
= mf
->fptr_MFCreateMemoryBuffer(allocation_size
, &input_media_buffer
);
538 hr
= IMFSample_AddBuffer(input_sample
, input_media_buffer
);
539 IMFMediaBuffer_Release(input_media_buffer
);
543 *result
= input_sample
;
548 msg_Err(p_dec
, "Error in AllocateInputSample()");
550 IMFSample_Release(input_sample
);
551 if (input_media_buffer
)
552 IMFMediaBuffer_Release(input_media_buffer
);
556 static int AllocateOutputSample(decoder_t
*p_dec
, DWORD stream_id
, IMFSample
**result
)
558 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
559 MFHandle
*mf
= &p_sys
->mf_handle
;
564 IMFSample
*output_sample
= NULL
;
566 MFT_OUTPUT_STREAM_INFO output_info
;
567 hr
= IMFTransform_GetOutputStreamInfo(p_sys
->mft
, stream_id
, &output_info
);
571 if (output_info
.dwFlags
& (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
| MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
))
573 /* The MFT will provide an allocated sample. */
577 DWORD expected_flags
= 0;
578 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
579 expected_flags
|= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
580 | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
581 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
;
582 if ((output_info
.dwFlags
& expected_flags
) != expected_flags
)
585 hr
= mf
->fptr_MFCreateSample(&output_sample
);
589 IMFMediaBuffer
*output_media_buffer
= NULL
;
590 DWORD allocation_size
= output_info
.cbSize
;
591 DWORD alignment
= output_info
.cbAlignment
;
593 hr
= mf
->fptr_MFCreateAlignedMemoryBuffer(allocation_size
, alignment
- 1, &output_media_buffer
);
595 hr
= mf
->fptr_MFCreateMemoryBuffer(allocation_size
, &output_media_buffer
);
599 hr
= IMFSample_AddBuffer(output_sample
, output_media_buffer
);
603 *result
= output_sample
;
608 msg_Err(p_dec
, "Error in AllocateOutputSample()");
610 IMFSample_Release(output_sample
);
614 static int ProcessInputStream(decoder_t
*p_dec
, DWORD stream_id
, block_t
*p_block
)
616 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
618 IMFSample
*input_sample
= NULL
;
620 if (AllocateInputSample(p_dec
, stream_id
, &input_sample
, p_block
->i_buffer
))
623 IMFMediaBuffer
*input_media_buffer
= NULL
;
624 hr
= IMFSample_GetBufferByIndex(input_sample
, 0, &input_media_buffer
);
629 hr
= IMFMediaBuffer_Lock(input_media_buffer
, &buffer_start
, NULL
, NULL
);
633 memcpy(buffer_start
, p_block
->p_buffer
, p_block
->i_buffer
);
635 if (p_dec
->fmt_in
.i_codec
== VLC_CODEC_H264
)
637 /* in-place NAL to annex B conversion. */
638 h264_AVC_to_AnnexB(buffer_start
, p_block
->i_buffer
, p_sys
->nal_length_size
);
641 hr
= IMFMediaBuffer_Unlock(input_media_buffer
);
645 hr
= IMFMediaBuffer_SetCurrentLength(input_media_buffer
, p_block
->i_buffer
);
649 vlc_tick_t ts
= p_block
->i_pts
== VLC_TICK_INVALID
? p_block
->i_dts
: p_block
->i_pts
;
651 /* Convert from microseconds to 100 nanoseconds unit. */
652 hr
= IMFSample_SetSampleTime(input_sample
, MSFTIME_FROM_VLC_TICK(ts
));
656 hr
= IMFTransform_ProcessInput(p_sys
->mft
, stream_id
, input_sample
, 0);
660 IMFMediaBuffer_Release(input_media_buffer
);
661 IMFSample_Release(input_sample
);
666 msg_Err(p_dec
, "Error in ProcessInputStream()");
668 IMFSample_Release(input_sample
);
672 /* Copy a packed buffer (no padding) to a picture_t */
673 static void CopyPackedBufferToPicture(picture_t
*p_pic
, const uint8_t *p_src
)
675 for (int i
= 0; i
< p_pic
->i_planes
; ++i
)
677 uint8_t *p_dst
= p_pic
->p
[i
].p_pixels
;
679 if (p_pic
->p
[i
].i_visible_pitch
== p_pic
->p
[i
].i_pitch
)
681 /* Plane is packed, only one memcpy is needed. */
682 uint32_t plane_size
= p_pic
->p
[i
].i_pitch
* p_pic
->p
[i
].i_visible_lines
;
683 memcpy(p_dst
, p_src
, plane_size
);
688 for (int i_line
= 0; i_line
< p_pic
->p
[i
].i_visible_lines
; i_line
++)
690 memcpy(p_dst
, p_src
, p_pic
->p
[i
].i_visible_pitch
);
691 p_src
+= p_pic
->p
[i
].i_visible_pitch
;
692 p_dst
+= p_pic
->p
[i
].i_pitch
;
697 static int ProcessOutputStream(decoder_t
*p_dec
, DWORD stream_id
)
699 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
701 picture_t
*picture
= NULL
;
702 block_t
*aout_buffer
= NULL
;
704 DWORD output_status
= 0;
705 MFT_OUTPUT_DATA_BUFFER output_buffer
= { stream_id
, p_sys
->output_sample
, 0, NULL
};
706 hr
= IMFTransform_ProcessOutput(p_sys
->mft
, 0, 1, &output_buffer
, &output_status
);
707 if (output_buffer
.pEvents
)
708 IMFCollection_Release(output_buffer
.pEvents
);
709 /* Use the returned sample since it can be provided by the MFT. */
710 IMFSample
*output_sample
= output_buffer
.pSample
;
717 LONGLONG sample_time
;
718 hr
= IMFSample_GetSampleTime(output_sample
, &sample_time
);
721 /* Convert from 100 nanoseconds unit to microseconds. */
722 vlc_tick_t samp_time
= VLC_TICK_FROM_MSFTIME(sample_time
);
724 DWORD total_length
= 0;
725 hr
= IMFSample_GetTotalLength(output_sample
, &total_length
);
729 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
731 if (decoder_UpdateVideoFormat(p_dec
))
733 picture
= decoder_NewPicture(p_dec
);
737 UINT32 interlaced
= false;
738 hr
= IMFSample_GetUINT32(output_sample
, &MFSampleExtension_Interlaced
, &interlaced
);
739 picture
->b_progressive
= !interlaced
;
741 picture
->date
= samp_time
;
745 if (decoder_UpdateAudioFormat(p_dec
))
747 if (p_dec
->fmt_out
.audio
.i_bitspersample
== 0 || p_dec
->fmt_out
.audio
.i_channels
== 0)
749 int samples
= total_length
/ (p_dec
->fmt_out
.audio
.i_bitspersample
* p_dec
->fmt_out
.audio
.i_channels
/ 8);
750 aout_buffer
= decoder_NewAudioBuffer(p_dec
, samples
);
753 if (aout_buffer
->i_buffer
< total_length
)
756 aout_buffer
->i_pts
= samp_time
;
759 IMFMediaBuffer
*output_media_buffer
= NULL
;
760 hr
= IMFSample_GetBufferByIndex(output_sample
, 0, &output_media_buffer
);
763 hr
= IMFMediaBuffer_Lock(output_media_buffer
, &buffer_start
, NULL
, NULL
);
767 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
768 CopyPackedBufferToPicture(picture
, buffer_start
);
770 memcpy(aout_buffer
->p_buffer
, buffer_start
, total_length
);
772 hr
= IMFMediaBuffer_Unlock(output_media_buffer
);
773 IMFSample_Release(output_media_buffer
);
777 if (p_sys
->output_sample
)
779 /* Sample is not provided by the MFT: clear its content. */
780 hr
= IMFMediaBuffer_SetCurrentLength(output_media_buffer
, 0);
786 /* Sample is provided by the MFT: decrease refcount. */
787 IMFSample_Release(output_sample
);
790 else if (hr
== MF_E_TRANSFORM_STREAM_CHANGE
|| hr
== MF_E_TRANSFORM_TYPE_NOT_SET
)
792 if (p_sys
->output_type
)
793 IMFMediaType_Release(p_sys
->output_type
);
794 if (SetOutputType(p_dec
, p_sys
->output_stream_id
, &p_sys
->output_type
))
797 /* Reallocate output sample. */
798 if (p_sys
->output_sample
)
799 IMFSample_Release(p_sys
->output_sample
);
800 p_sys
->output_sample
= NULL
;
801 if (AllocateOutputSample(p_dec
, 0, &p_sys
->output_sample
))
805 else if (hr
== MF_E_TRANSFORM_NEED_MORE_INPUT
)
809 else /* An error not listed above occurred */
811 msg_Err(p_dec
, "Unexpected error in IMFTransform::ProcessOutput: %#lx",
816 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
817 decoder_QueueVideo(p_dec
, picture
);
819 decoder_QueueAudio(p_dec
, aout_buffer
);
824 msg_Err(p_dec
, "Error in ProcessOutputStream()");
826 picture_Release(picture
);
828 block_Release(aout_buffer
);
832 static int DecodeSync(decoder_t
*p_dec
, block_t
*p_block
)
834 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
836 if (!p_block
) /* No Drain */
837 return VLCDEC_SUCCESS
;
839 if (p_block
->i_flags
& (BLOCK_FLAG_CORRUPTED
))
841 block_Release(p_block
);
842 return VLCDEC_SUCCESS
;
845 /* Drain the output stream before sending the input packet. */
846 if (ProcessOutputStream(p_dec
, p_sys
->output_stream_id
))
848 if (ProcessInputStream(p_dec
, p_sys
->input_stream_id
, p_block
))
850 block_Release(p_block
);
852 return VLCDEC_SUCCESS
;
855 msg_Err(p_dec
, "Error in DecodeSync()");
856 block_Release(p_block
);
857 return VLCDEC_SUCCESS
;
860 static HRESULT
DequeueMediaEvent(decoder_t
*p_dec
)
862 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
865 IMFMediaEvent
*event
= NULL
;
866 hr
= IMFMediaEventGenerator_GetEvent(p_sys
->event_generator
, MF_EVENT_FLAG_NO_WAIT
, &event
);
869 MediaEventType event_type
;
870 hr
= IMFMediaEvent_GetType(event
, &event_type
);
871 IMFMediaEvent_Release(event
);
875 if (event_type
== VLC_METransformNeedInput
)
876 p_sys
->pending_input_events
+= 1;
877 else if (event_type
== VLC_METransformHaveOutput
)
878 p_sys
->pending_output_events
+= 1;
880 msg_Err(p_dec
, "Unsupported asynchronous event.");
885 static int DecodeAsync(decoder_t
*p_dec
, block_t
*p_block
)
887 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
890 if (!p_block
) /* No Drain */
891 return VLCDEC_SUCCESS
;
893 if (p_block
->i_flags
& (BLOCK_FLAG_CORRUPTED
))
895 block_Release(p_block
);
896 return VLCDEC_SUCCESS
;
899 /* Dequeue all pending media events. */
900 while ((hr
= DequeueMediaEvent(p_dec
)) == S_OK
)
902 if (hr
!= MF_E_NO_EVENTS_AVAILABLE
&& FAILED(hr
))
905 /* Drain the output stream of the MFT before sending the input packet. */
906 if (p_sys
->pending_output_events
> 0)
908 p_sys
->pending_output_events
-= 1;
909 if (ProcessOutputStream(p_dec
, p_sys
->output_stream_id
))
913 /* Poll the MFT and return decoded frames until the input stream is ready. */
914 while (p_sys
->pending_input_events
== 0)
916 hr
= DequeueMediaEvent(p_dec
);
917 if (hr
== MF_E_NO_EVENTS_AVAILABLE
)
919 /* Sleep for 1 ms to avoid excessive polling. */
926 if (p_sys
->pending_output_events
> 0)
928 p_sys
->pending_output_events
-= 1;
929 if (ProcessOutputStream(p_dec
, p_sys
->output_stream_id
))
935 p_sys
->pending_input_events
-= 1;
936 if (ProcessInputStream(p_dec
, p_sys
->input_stream_id
, p_block
))
939 block_Release(p_block
);
941 return VLCDEC_SUCCESS
;
944 msg_Err(p_dec
, "Error in DecodeAsync()");
945 block_Release(p_block
);
946 return VLCDEC_SUCCESS
;
949 static void DestroyMFT(decoder_t
*p_dec
);
951 static int InitializeMFT(decoder_t
*p_dec
)
953 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
956 IMFAttributes
*attributes
= NULL
;
957 hr
= IMFTransform_GetAttributes(p_sys
->mft
, &attributes
);
958 if (hr
!= E_NOTIMPL
&& FAILED(hr
))
962 UINT32 is_async
= false;
963 hr
= IMFAttributes_GetUINT32(attributes
, &MF_TRANSFORM_ASYNC
, &is_async
);
964 if (hr
!= MF_E_ATTRIBUTENOTFOUND
&& FAILED(hr
))
966 p_sys
->is_async
= is_async
;
969 hr
= IMFAttributes_SetUINT32(attributes
, &MF_TRANSFORM_ASYNC_UNLOCK
, true);
972 hr
= IMFTransform_QueryInterface(p_sys
->mft
, &IID_IMFMediaEventGenerator
, (void**)&p_sys
->event_generator
);
978 DWORD input_streams_count
;
979 DWORD output_streams_count
;
980 hr
= IMFTransform_GetStreamCount(p_sys
->mft
, &input_streams_count
, &output_streams_count
);
983 if (input_streams_count
!= 1 || output_streams_count
!= 1)
985 msg_Err(p_dec
, "MFT decoder should have 1 input stream and 1 output stream.");
989 hr
= IMFTransform_GetStreamIDs(p_sys
->mft
, 1, &p_sys
->input_stream_id
, 1, &p_sys
->output_stream_id
);
993 * This is not an error, it happens if:
994 * - there is a fixed number of streams.
996 * - streams are numbered consecutively from 0 to N-1.
998 p_sys
->input_stream_id
= 0;
999 p_sys
->output_stream_id
= 0;
1001 else if (FAILED(hr
))
1004 if (SetInputType(p_dec
, p_sys
->input_stream_id
, &p_sys
->input_type
))
1007 if (SetOutputType(p_dec
, p_sys
->output_stream_id
, &p_sys
->output_type
))
1011 * The input type was not set by the previous call to
1012 * SetInputType, try again after setting the output type.
1014 if (!p_sys
->input_type
)
1015 if (SetInputType(p_dec
, p_sys
->input_stream_id
, &p_sys
->input_type
) || !p_sys
->input_type
)
1018 /* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
1019 hr
= IMFTransform_ProcessMessage(p_sys
->mft
, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
, (ULONG_PTR
)0);
1023 /* This event is required for asynchronous MFTs, optional otherwise. */
1024 hr
= IMFTransform_ProcessMessage(p_sys
->mft
, MFT_MESSAGE_NOTIFY_START_OF_STREAM
, (ULONG_PTR
)0);
1028 if (p_dec
->fmt_in
.i_codec
== VLC_CODEC_H264
)
1030 /* It's not an error if the following call fails. */
1031 IMFAttributes_SetUINT32(attributes
, &CODECAPI_AVLowLatencyMode
, true);
1033 if (p_dec
->fmt_in
.i_extra
)
1035 if (h264_isavcC((uint8_t*)p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
))
1038 uint8_t *buf
= h264_avcC_to_AnnexB_NAL(p_dec
->fmt_in
.p_extra
,
1039 p_dec
->fmt_in
.i_extra
,
1040 &i_buf
, &p_sys
->nal_length_size
);
1043 free(p_dec
->fmt_in
.p_extra
);
1044 p_dec
->fmt_in
.p_extra
= buf
;
1045 p_dec
->fmt_in
.i_extra
= i_buf
;
1053 msg_Err(p_dec
, "Error in InitializeMFT()");
1055 return VLC_EGENERIC
;
1058 static void DestroyMFT(decoder_t
*p_dec
)
1060 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1062 if (p_sys
->event_generator
)
1063 IMFMediaEventGenerator_Release(p_sys
->event_generator
);
1064 if (p_sys
->input_type
)
1065 IMFMediaType_Release(p_sys
->input_type
);
1066 if (p_sys
->output_sample
)
1068 IMFMediaBuffer
*output_media_buffer
= NULL
;
1069 HRESULT hr
= IMFSample_GetBufferByIndex(p_sys
->output_sample
, 0, &output_media_buffer
);
1071 IMFSample_Release(output_media_buffer
);
1072 IMFSample_Release(p_sys
->output_sample
);
1074 if (p_sys
->output_type
)
1075 IMFMediaType_Release(p_sys
->output_type
);
1077 IMFTransform_Release(p_sys
->mft
);
1079 p_sys
->event_generator
= NULL
;
1080 p_sys
->input_type
= NULL
;
1081 p_sys
->output_sample
= NULL
;
1082 p_sys
->output_type
= NULL
;
1086 static int FindMFT(decoder_t
*p_dec
)
1088 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1089 MFHandle
*mf
= &p_sys
->mf_handle
;
1092 /* Try to create a MFT using MFTEnumEx. */
1094 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
1096 category
= MFT_CATEGORY_VIDEO_DECODER
;
1097 p_sys
->major_type
= &MFMediaType_Video
;
1098 p_sys
->subtype
= FormatToGUID(video_format_table
, p_dec
->fmt_in
.i_codec
);
1099 if(!p_sys
->subtype
) {
1100 /* Codec is not well known. Construct a MF transform subtype from the fourcc */
1101 p_sys
->custom_subtype
= MFVideoFormat_Base
;
1102 p_sys
->custom_subtype
.Data1
= p_dec
->fmt_in
.i_codec
;
1103 p_sys
->subtype
= &p_sys
->custom_subtype
;
1108 category
= MFT_CATEGORY_AUDIO_DECODER
;
1109 p_sys
->major_type
= &MFMediaType_Audio
;
1110 p_sys
->subtype
= FormatToGUID(audio_format_table
, p_dec
->fmt_in
.i_codec
);
1112 if (!p_sys
->subtype
)
1113 return VLC_EGENERIC
;
1115 UINT32 flags
= MFT_ENUM_FLAG_SORTANDFILTER
| MFT_ENUM_FLAG_LOCALMFT
1116 | MFT_ENUM_FLAG_SYNCMFT
| MFT_ENUM_FLAG_ASYNCMFT
1117 | MFT_ENUM_FLAG_HARDWARE
| MFT_ENUM_FLAG_TRANSCODE_ONLY
;
1118 MFT_REGISTER_TYPE_INFO input_type
= { *p_sys
->major_type
, *p_sys
->subtype
};
1119 IMFActivate
**activate_objects
= NULL
;
1120 UINT32 activate_objects_count
= 0;
1121 hr
= mf
->fptr_MFTEnumEx(category
, flags
, &input_type
, NULL
, &activate_objects
, &activate_objects_count
);
1123 return VLC_EGENERIC
;
1125 msg_Dbg(p_dec
, "Found %d available MFT module(s)", activate_objects_count
);
1126 if (activate_objects_count
== 0)
1127 return VLC_EGENERIC
;
1129 for (UINT32 i
= 0; i
< activate_objects_count
; ++i
)
1131 hr
= IMFActivate_ActivateObject(activate_objects
[i
], &IID_IMFTransform
, (void**)&p_sys
->mft
);
1132 IMFActivate_Release(activate_objects
[i
]);
1136 if (InitializeMFT(p_dec
) == VLC_SUCCESS
)
1138 CoTaskMemFree(activate_objects
);
1142 CoTaskMemFree(activate_objects
);
1144 return VLC_EGENERIC
;
1147 static int LoadMFTLibrary(MFHandle
*mf
)
1149 #if _WIN32_WINNT < _WIN32_WINNT_WIN7 || VLC_WINSTORE_APP || __MINGW64_VERSION_MAJOR < 6
1150 mf
->mfplat_dll
= LoadLibrary(TEXT("mfplat.dll"));
1151 if (!mf
->mfplat_dll
)
1152 return VLC_EGENERIC
;
1154 mf
->fptr_MFTEnumEx
= (void*)GetProcAddress(mf
->mfplat_dll
, "MFTEnumEx");
1155 mf
->fptr_MFCreateSample
= (void*)GetProcAddress(mf
->mfplat_dll
, "MFCreateSample");
1156 mf
->fptr_MFCreateMemoryBuffer
= (void*)GetProcAddress(mf
->mfplat_dll
, "MFCreateMemoryBuffer");
1157 mf
->fptr_MFCreateAlignedMemoryBuffer
= (void*)GetProcAddress(mf
->mfplat_dll
, "MFCreateAlignedMemoryBuffer");
1158 if (!mf
->fptr_MFTEnumEx
|| !mf
->fptr_MFCreateSample
|| !mf
->fptr_MFCreateMemoryBuffer
|| !mf
->fptr_MFCreateAlignedMemoryBuffer
)
1159 return VLC_EGENERIC
;
1161 mf
->fptr_MFTEnumEx
= &MFTEnumEx
;
1162 mf
->fptr_MFCreateSample
= &MFCreateSample
;
1163 mf
->fptr_MFCreateMemoryBuffer
= &MFCreateMemoryBuffer
;
1164 mf
->fptr_MFCreateAlignedMemoryBuffer
= &MFCreateAlignedMemoryBuffer
;
1170 static int Open(vlc_object_t
*p_this
)
1172 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1173 decoder_sys_t
*p_sys
;
1175 p_sys
= p_dec
->p_sys
= calloc(1, sizeof(*p_sys
));
1179 if( FAILED(CoInitializeEx(NULL
, COINIT_MULTITHREADED
)) )
1182 return VLC_EGENERIC
;
1185 if (LoadMFTLibrary(&p_sys
->mf_handle
))
1187 msg_Err(p_dec
, "Failed to load MFT library.");
1193 msg_Err(p_dec
, "Could not find suitable MFT decoder");
1197 /* Only one output sample is needed, we can allocate one and reuse it. */
1198 if (AllocateOutputSample(p_dec
, 0, &p_sys
->output_sample
))
1201 p_dec
->pf_decode
= p_sys
->is_async
? DecodeAsync
: DecodeSync
;
1207 return VLC_EGENERIC
;
1210 static void Close(vlc_object_t
*p_this
)
1212 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1213 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1214 MFHandle
*mf
= &p_sys
->mf_handle
;
1219 FreeLibrary(mf
->mfplat_dll
);