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
42 #include <vlc_common.h>
43 #include <vlc_plugin.h>
44 #include <vlc_codec.h>
46 #define _VIDEOINFOHEADER_
47 #include <vlc_codecs.h>
50 #include <mftransform.h>
52 #include <mfobjects.h>
54 static int Open(vlc_object_t *);
55 static void Close(vlc_object_t *);
58 set_description(N_("Media Foundation Transform decoder"))
60 set_capability("decoder", 1)
61 set_callbacks(Open, Close)
62 set_category(CAT_INPUT)
63 set_subcategory(SUBCAT_INPUT_VCODEC)
69 HRESULT (STDCALL *fptr_MFTEnumEx)(GUID guidCategory, UINT32 Flags,
70 const MFT_REGISTER_TYPE_INFO *pInputType,
71 const MFT_REGISTER_TYPE_INFO *pOutputType,
72 IMFActivate ***pppMFTActivate, UINT32 *pcMFTActivate);
73 HRESULT (STDCALL *fptr_MFCreateSample)(IMFSample **ppIMFSample);
74 HRESULT (STDCALL *fptr_MFCreateMemoryBuffer)(DWORD cbMaxLength, IMFMediaBuffer **ppBuffer);
75 HRESULT (STDCALL *fptr_MFCreateAlignedMemoryBuffer)(DWORD cbMaxLength, DWORD fAlignmentFlags, IMFMediaBuffer **ppBuffer);
84 const GUID* major_type;
87 /* For asynchronous MFT */
89 IMFMediaEventGenerator *event_generator;
90 int pending_input_events;
91 int pending_output_events;
94 DWORD input_stream_id;
95 IMFMediaType *input_type;
98 DWORD output_stream_id;
99 IMFSample *output_sample;
100 IMFMediaType *output_type;
106 static const int pi_channels_maps[9] =
110 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
111 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
112 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
113 | AOUT_CHAN_REARRIGHT,
114 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
115 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
116 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
117 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
118 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
119 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
120 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
121 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
122 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
126 /* Possibly missing from mingw headers */
127 #ifndef MF_E_TRANSFORM_NEED_MORE_INPUT
128 # define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72)
131 #ifndef MF_E_TRANSFORM_STREAM_CHANGE
132 # define MF_E_TRANSFORM_STREAM_CHANGE _HRESULT_TYPEDEF_(0xc00d6d61)
135 #ifndef MF_E_NO_EVENTS_AVAILABLE
136 # define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xC00D3E80L)
139 #ifndef MF_EVENT_FLAG_NO_WAIT
140 # define MF_EVENT_FLAG_NO_WAIT 0x00000001
144 * The MFTransformXXX values might not be defined in mingw headers,
145 * thus we use our own enum with the VLC prefix.
149 VLC_METransformUnknown = 600,
150 VLC_METransformNeedInput,
151 VLC_METransformHaveOutput,
152 VLC_METransformDrainComplete,
153 VLC_METransformMarker,
163 * We need this table since the FOURCC used for GUID is not the same
164 * as the FOURCC used by VLC, for instance h264 vs H264.
166 static const pair_format_guid video_format_table[] =
168 { VLC_CODEC_H264, &MFVideoFormat_H264 },
169 { VLC_CODEC_MJPG, &MFVideoFormat_MJPG },
170 { VLC_CODEC_WMV1, &MFVideoFormat_WMV1 },
171 { VLC_CODEC_WMV2, &MFVideoFormat_WMV2 },
172 { VLC_CODEC_WMV3, &MFVideoFormat_WMV3 },
173 { VLC_CODEC_VC1, &MFVideoFormat_WVC1 },
177 #if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 4
178 DEFINE_GUID(MFAudioFormat_Dolby_AC3, 0xe06d802c, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
181 * We cannot use the FOURCC code for audio either since the
182 * WAVE_FORMAT value is used to create the GUID.
184 static const pair_format_guid audio_format_table[] =
186 { VLC_CODEC_MPGA, &MFAudioFormat_MPEG },
187 { VLC_CODEC_MP3, &MFAudioFormat_MP3 },
188 { VLC_CODEC_DTS, &MFAudioFormat_DTS },
189 { VLC_CODEC_MP4A, &MFAudioFormat_AAC },
190 { VLC_CODEC_WMA2, &MFAudioFormat_WMAudioV8 },
191 { VLC_CODEC_A52, &MFAudioFormat_Dolby_AC3 },
195 static const GUID *FormatToGUID(const pair_format_guid table[], vlc_fourcc_t fourcc)
197 for (int i = 0; table[i].fourcc; ++i)
198 if (table[i].fourcc == fourcc)
199 return table[i].guid;
205 * Low latency mode for Windows 8. Without this option, the H264
206 * decoder will fill *all* its internal buffers before returning a
207 * frame. Because of this behavior, the decoder might return no frame
208 * for more than 500 ms, making it unusable for playback.
210 DEFINE_GUID(CODECAPI_AVLowLatencyMode, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
212 static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
214 decoder_sys_t *p_sys = p_dec->p_sys;
219 IMFMediaType *input_media_type = NULL;
221 /* Search a suitable input type for the MFT. */
222 int input_type_index = 0;
224 for (int i = 0; !found; ++i)
226 hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, i, &input_media_type);
227 if (hr == MF_E_NO_MORE_TYPES)
229 else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
231 /* The output type must be set before setting the input type for this MFT. */
238 hr = IMFMediaType_GetGUID(input_media_type, &MF_MT_SUBTYPE, &subtype);
242 if (IsEqualGUID(&subtype, p_sys->subtype))
246 input_type_index = i;
248 IMFMediaType_Release(input_media_type);
249 input_media_type = NULL;
254 hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, input_type_index, &input_media_type);
258 if (p_dec->fmt_in.i_cat == VIDEO_ES)
260 UINT64 width = p_dec->fmt_in.video.i_width;
261 UINT64 height = p_dec->fmt_in.video.i_height;
262 UINT64 frame_size = (width << 32) | height;
263 hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_SIZE, frame_size);
269 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1);
272 if (p_dec->fmt_in.audio.i_rate)
274 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate);
278 if (p_dec->fmt_in.audio.i_channels)
280 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels);
284 if (p_dec->fmt_in.audio.i_bitspersample)
286 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample);
290 if (p_dec->fmt_in.audio.i_blockalign)
292 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign);
296 if (p_dec->fmt_in.i_bitrate)
298 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8);
304 if (p_dec->fmt_in.i_extra > 0)
306 UINT32 blob_size = 0;
307 hr = IMFMediaType_GetBlobSize(input_media_type, &MF_MT_USER_DATA, &blob_size);
309 * Do not overwrite existing user data in the input type, this
310 * can cause the MFT to reject the type.
312 if (hr == MF_E_ATTRIBUTENOTFOUND)
314 hr = IMFMediaType_SetBlob(input_media_type, &MF_MT_USER_DATA,
315 (const UINT8*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
321 hr = IMFTransform_SetInputType(p_sys->mft, stream_id, input_media_type, 0);
325 *result = input_media_type;
330 msg_Err(p_dec, "Error in SetInputType()");
331 if (input_media_type)
332 IMFMediaType_Release(input_media_type);
336 static int SetOutputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
338 decoder_sys_t *p_sys = p_dec->p_sys;
343 IMFMediaType *output_media_type = NULL;
346 * Enumerate available output types. The list is ordered by
347 * preference thus we will use the first one unless YV12/I420 is
348 * available for video or float32 for audio.
350 int output_type_index = 0;
352 for (int i = 0; !found; ++i)
354 hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, i, &output_media_type);
355 if (hr == MF_E_NO_MORE_TYPES)
357 else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
359 /* The input type must be set before setting the output type for this MFT. */
366 hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
370 if (p_dec->fmt_in.i_cat == VIDEO_ES)
372 if (IsEqualGUID(&subtype, &MFVideoFormat_YV12) || IsEqualGUID(&subtype, &MFVideoFormat_I420))
377 UINT32 bits_per_sample;
378 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
381 if (bits_per_sample == 32 && IsEqualGUID(&subtype, &MFAudioFormat_Float))
386 output_type_index = i;
388 IMFMediaType_Release(output_media_type);
389 output_media_type = NULL;
392 * It's not an error if we don't find the output type we were
393 * looking for, in this case we use the first available type which
394 * is the "preferred" output type for this MFT.
397 hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, output_type_index, &output_media_type);
401 hr = IMFTransform_SetOutputType(p_sys->mft, stream_id, output_media_type, 0);
406 hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
410 if (p_dec->fmt_in.i_cat == VIDEO_ES)
412 p_dec->fmt_out.video = p_dec->fmt_in.video;
413 p_dec->fmt_out.i_codec = vlc_fourcc_GetCodec(p_dec->fmt_in.i_cat, subtype.Data1);
417 p_dec->fmt_out.audio = p_dec->fmt_in.audio;
419 UINT32 bitspersample = 0;
420 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample);
421 if (SUCCEEDED(hr) && bitspersample)
422 p_dec->fmt_out.audio.i_bitspersample = bitspersample;
425 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
426 if (SUCCEEDED(hr) && channels)
427 p_dec->fmt_out.audio.i_channels = channels;
430 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
431 if (SUCCEEDED(hr) && rate)
432 p_dec->fmt_out.audio.i_rate = rate;
435 wf_tag_to_fourcc(subtype.Data1, &fourcc, NULL);
436 p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio(fourcc, p_dec->fmt_out.audio.i_bitspersample);
438 p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels];
439 p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels;
442 *result = output_media_type;
447 msg_Err(p_dec, "Error in SetOutputType()");
448 if (output_media_type)
449 IMFMediaType_Release(output_media_type);
453 static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** result, DWORD size)
455 decoder_sys_t *p_sys = p_dec->p_sys;
456 MFHandle *mf = &p_sys->mf_handle;
461 IMFSample *input_sample = NULL;
463 MFT_INPUT_STREAM_INFO input_info;
464 hr = IMFTransform_GetInputStreamInfo(p_sys->mft, stream_id, &input_info);
468 hr = mf->fptr_MFCreateSample(&input_sample);
472 IMFMediaBuffer *input_media_buffer = NULL;
473 DWORD allocation_size = __MAX(input_info.cbSize, size);
474 hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &input_media_buffer);
478 hr = IMFSample_AddBuffer(input_sample, input_media_buffer);
479 IMFMediaBuffer_Release(input_media_buffer);
483 *result = input_sample;
488 msg_Err(p_dec, "Error in AllocateInputSample()");
490 IMFSample_Release(input_sample);
491 if (input_media_buffer)
492 IMFMediaBuffer_Release(input_media_buffer);
496 static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **result)
498 decoder_sys_t *p_sys = p_dec->p_sys;
499 MFHandle *mf = &p_sys->mf_handle;
504 IMFSample *output_sample = NULL;
506 MFT_OUTPUT_STREAM_INFO output_info;
507 hr = IMFTransform_GetOutputStreamInfo(p_sys->mft, stream_id, &output_info);
511 if (output_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES))
513 /* The MFT will provide an allocated sample. */
517 DWORD expected_flags = 0;
518 if (p_dec->fmt_in.i_cat == VIDEO_ES)
519 expected_flags |= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
520 | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
521 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
522 if ((output_info.dwFlags & expected_flags) != expected_flags)
525 hr = mf->fptr_MFCreateSample(&output_sample);
529 IMFMediaBuffer *output_media_buffer = NULL;
530 DWORD allocation_size = output_info.cbSize;
531 DWORD alignment = output_info.cbAlignment;
533 hr = mf->fptr_MFCreateAlignedMemoryBuffer(allocation_size, alignment - 1, &output_media_buffer);
535 hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &output_media_buffer);
539 hr = IMFSample_AddBuffer(output_sample, output_media_buffer);
543 *result = output_sample;
548 msg_Err(p_dec, "Error in AllocateOutputSample()");
550 IMFSample_Release(output_sample);
554 static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_block)
556 decoder_sys_t *p_sys = p_dec->p_sys;
558 IMFSample *input_sample = NULL;
560 if (AllocateInputSample(p_dec, stream_id, &input_sample, p_block->i_buffer))
563 IMFMediaBuffer *input_media_buffer = NULL;
564 hr = IMFSample_GetBufferByIndex(input_sample, 0, &input_media_buffer);
569 hr = IMFMediaBuffer_Lock(input_media_buffer, &buffer_start, NULL, NULL);
573 memcpy(buffer_start, p_block->p_buffer, p_block->i_buffer);
575 if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
577 /* in-place NAL to annex B conversion. */
578 struct H264ConvertState convert_state = { 0, 0 };
579 convert_h264_to_annexb(buffer_start, p_block->i_buffer, p_sys->nal_size, &convert_state);
582 hr = IMFMediaBuffer_Unlock(input_media_buffer);
586 hr = IMFMediaBuffer_SetCurrentLength(input_media_buffer, p_block->i_buffer);
590 LONGLONG ts = p_block->i_pts;
591 if (!ts && p_block->i_dts)
594 /* Convert from microseconds to 100 nanoseconds unit. */
595 hr = IMFSample_SetSampleTime(input_sample, ts * 10);
599 hr = IMFTransform_ProcessInput(p_sys->mft, stream_id, input_sample, 0);
603 IMFMediaBuffer_Release(input_media_buffer);
604 IMFSample_Release(input_sample);
609 msg_Err(p_dec, "Error in ProcessInputStream()");
611 IMFSample_Release(input_sample);
615 /* Copy a packed buffer (no padding) to a picture_t */
616 static void CopyPackedBufferToPicture(picture_t *p_pic, const uint8_t *p_src)
618 for (int i = 0; i < p_pic->i_planes; ++i)
620 uint8_t *p_dst = p_pic->p[i].p_pixels;
622 if (p_pic->p[i].i_visible_pitch == p_pic->p[i].i_pitch)
624 /* Plane is packed, only one memcpy is needed. */
625 uint32_t plane_size = p_pic->p[i].i_pitch * p_pic->p[i].i_visible_lines;
626 memcpy(p_dst, p_src, plane_size);
631 for (int i_line = 0; i_line < p_pic->p[i].i_visible_lines; i_line++)
633 memcpy(p_dst, p_src, p_pic->p[i].i_visible_pitch);
634 p_src += p_pic->p[i].i_visible_pitch;
635 p_dst += p_pic->p[i].i_pitch;
640 static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, void **result)
642 decoder_sys_t *p_sys = p_dec->p_sys;
644 picture_t *picture = NULL;
645 block_t *aout_buffer = NULL;
649 DWORD output_status = 0;
650 MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
651 hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status);
652 if (output_buffer.pEvents)
653 IMFCollection_Release(output_buffer.pEvents);
654 /* Use the returned sample since it can be provided by the MFT. */
655 IMFSample *output_sample = output_buffer.pSample;
662 LONGLONG sample_time;
663 hr = IMFSample_GetSampleTime(output_sample, &sample_time);
666 /* Convert from 100 nanoseconds unit to microseconds. */
669 DWORD total_length = 0;
670 hr = IMFSample_GetTotalLength(output_sample, &total_length);
674 if (p_dec->fmt_in.i_cat == VIDEO_ES)
676 picture = decoder_NewPicture(p_dec);
680 UINT32 interlaced = false;
681 hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced);
682 picture->b_progressive = !interlaced;
684 picture->date = sample_time;
688 if (p_dec->fmt_out.audio.i_bitspersample == 0 || p_dec->fmt_out.audio.i_channels == 0)
690 int samples = total_length / (p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8);
691 aout_buffer = decoder_NewAudioBuffer(p_dec, samples);
694 if (aout_buffer->i_buffer < total_length)
697 aout_buffer->i_pts = sample_time;
700 IMFMediaBuffer *output_media_buffer = NULL;
701 hr = IMFSample_GetBufferByIndex(output_sample, 0, &output_media_buffer);
704 hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
708 if (p_dec->fmt_in.i_cat == VIDEO_ES)
709 CopyPackedBufferToPicture(picture, buffer_start);
711 memcpy(aout_buffer->p_buffer, buffer_start, total_length);
713 hr = IMFMediaBuffer_Unlock(output_media_buffer);
714 IMFSample_Release(output_media_buffer);
718 if (p_sys->output_sample)
720 /* Sample is not provided by the MFT: clear its content. */
721 hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0);
727 /* Sample is provided by the MFT: decrease refcount. */
728 IMFSample_Release(output_sample);
731 else if (hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_TYPE_NOT_SET)
733 if (p_sys->output_type)
734 IMFMediaType_Release(p_sys->output_type);
735 if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
738 /* Reallocate output sample. */
739 if (p_sys->output_sample)
740 IMFSample_Release(p_sys->output_sample);
741 p_sys->output_sample = NULL;
742 if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
746 else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
750 else /* An error not listed above occurred */
752 msg_Err(p_dec, "Unexpected error in IMFTransform::ProcessOutput: %#lx",
757 if (p_dec->fmt_in.i_cat == VIDEO_ES)
760 *result = aout_buffer;
765 msg_Err(p_dec, "Error in ProcessOutputStream()");
767 picture_Release(picture);
769 block_Release(aout_buffer);
773 static void *DecodeSync(decoder_t *p_dec, block_t **pp_block)
775 decoder_sys_t *p_sys = p_dec->p_sys;
777 if (!pp_block || !*pp_block)
780 block_t *p_block = *pp_block;
781 if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED))
783 block_Release(p_block);
787 /* Drain the output stream before sending the input packet. */
789 if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
794 if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
797 block_Release(p_block);
803 msg_Err(p_dec, "Error in DecodeSync()");
805 block_Release(p_block);
809 static HRESULT DequeueMediaEvent(decoder_t *p_dec)
811 decoder_sys_t *p_sys = p_dec->p_sys;
814 IMFMediaEvent *event = NULL;
815 hr = IMFMediaEventGenerator_GetEvent(p_sys->event_generator, MF_EVENT_FLAG_NO_WAIT, &event);
818 MediaEventType event_type;
819 hr = IMFMediaEvent_GetType(event, &event_type);
820 IMFMediaEvent_Release(event);
824 if (event_type == VLC_METransformNeedInput)
825 p_sys->pending_input_events += 1;
826 else if (event_type == VLC_METransformHaveOutput)
827 p_sys->pending_output_events += 1;
829 msg_Err(p_dec, "Unsupported asynchronous event.");
834 static void *DecodeAsync(decoder_t *p_dec, block_t **pp_block)
836 decoder_sys_t *p_sys = p_dec->p_sys;
839 if (!pp_block || !*pp_block)
842 block_t *p_block = *pp_block;
843 if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED))
845 block_Release(p_block);
850 /* Dequeue all pending media events. */
851 while ((hr = DequeueMediaEvent(p_dec)) == S_OK)
853 if (hr != MF_E_NO_EVENTS_AVAILABLE && FAILED(hr))
856 /* Drain the output stream of the MFT before sending the input packet. */
857 if (p_sys->pending_output_events > 0)
859 p_sys->pending_output_events -= 1;
861 if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
866 /* Poll the MFT and return decoded frames until the input stream is ready. */
867 while (p_sys->pending_input_events == 0)
869 hr = DequeueMediaEvent(p_dec);
870 if (hr == MF_E_NO_EVENTS_AVAILABLE)
872 /* Sleep for 1 ms to avoid excessive polling. */
879 if (p_sys->pending_output_events > 0)
881 p_sys->pending_output_events -= 1;
883 if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
889 p_sys->pending_input_events -= 1;
890 if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
893 block_Release(p_block);
899 msg_Err(p_dec, "Error in DecodeAsync()");
900 block_Release(p_block);
904 static void DestroyMFT(decoder_t *p_dec);
906 static int InitializeMFT(decoder_t *p_dec)
908 decoder_sys_t *p_sys = p_dec->p_sys;
911 IMFAttributes *attributes = NULL;
912 hr = IMFTransform_GetAttributes(p_sys->mft, &attributes);
913 if (hr != E_NOTIMPL && FAILED(hr))
917 UINT32 is_async = false;
918 hr = IMFAttributes_GetUINT32(attributes, &MF_TRANSFORM_ASYNC, &is_async);
919 if (hr != MF_E_ATTRIBUTENOTFOUND && FAILED(hr))
921 p_sys->is_async = is_async;
924 hr = IMFAttributes_SetUINT32(attributes, &MF_TRANSFORM_ASYNC_UNLOCK, true);
927 hr = IMFTransform_QueryInterface(p_sys->mft, &IID_IMFMediaEventGenerator, (void**)&p_sys->event_generator);
933 DWORD input_streams_count;
934 DWORD output_streams_count;
935 hr = IMFTransform_GetStreamCount(p_sys->mft, &input_streams_count, &output_streams_count);
938 if (input_streams_count != 1 || output_streams_count != 1)
940 msg_Err(p_dec, "MFT decoder should have 1 input stream and 1 output stream.");
944 hr = IMFTransform_GetStreamIDs(p_sys->mft, 1, &p_sys->input_stream_id, 1, &p_sys->output_stream_id);
948 * This is not an error, it happens if:
949 * - there is a fixed number of streams.
951 * - streams are numbered consecutively from 0 to N-1.
953 p_sys->input_stream_id = 0;
954 p_sys->output_stream_id = 0;
959 if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type))
962 if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
966 * The input type was not set by the previous call to
967 * SetInputType, try again after setting the output type.
969 if (!p_sys->input_type)
970 if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type) || !p_sys->input_type)
973 /* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
974 hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, (ULONG_PTR)0);
978 /* This event is required for asynchronous MFTs, optional otherwise. */
979 hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, (ULONG_PTR)0);
983 if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
985 /* It's not an error if the following call fails. */
986 IMFAttributes_SetUINT32(attributes, &CODECAPI_AVLowLatencyMode, true);
988 if (p_dec->fmt_in.i_extra)
990 int buf_size = p_dec->fmt_in.i_extra + 20;
991 uint32_t size = p_dec->fmt_in.i_extra;
992 uint8_t *buf = malloc(buf_size);
993 if (((uint8_t*)p_dec->fmt_in.p_extra)[0] == 1)
995 convert_sps_pps(p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra,
997 &size, &p_sys->nal_size);
1005 msg_Err(p_dec, "Error in InitializeMFT()");
1007 return VLC_EGENERIC;
1010 static void DestroyMFT(decoder_t *p_dec)
1012 decoder_sys_t *p_sys = p_dec->p_sys;
1014 if (p_sys->event_generator)
1015 IMFMediaEventGenerator_Release(p_sys->event_generator);
1016 if (p_sys->input_type)
1017 IMFMediaType_Release(p_sys->input_type);
1018 if (p_sys->output_sample)
1020 IMFMediaBuffer *output_media_buffer = NULL;
1021 HRESULT hr = IMFSample_GetBufferByIndex(p_sys->output_sample, 0, &output_media_buffer);
1023 IMFSample_Release(output_media_buffer);
1024 IMFSample_Release(p_sys->output_sample);
1026 if (p_sys->output_type)
1027 IMFMediaType_Release(p_sys->output_type);
1029 IMFTransform_Release(p_sys->mft);
1031 p_sys->event_generator = NULL;
1032 p_sys->input_type = NULL;
1033 p_sys->output_sample = NULL;
1034 p_sys->output_type = NULL;
1038 static int FindMFT(decoder_t *p_dec)
1040 decoder_sys_t *p_sys = p_dec->p_sys;
1041 MFHandle *mf = &p_sys->mf_handle;
1044 /* Try to create a MFT using MFTEnumEx. */
1046 if (p_dec->fmt_in.i_cat == VIDEO_ES)
1048 category = MFT_CATEGORY_VIDEO_DECODER;
1049 p_sys->major_type = &MFMediaType_Video;
1050 p_sys->subtype = FormatToGUID(video_format_table, p_dec->fmt_in.i_codec);
1054 category = MFT_CATEGORY_AUDIO_DECODER;
1055 p_sys->major_type = &MFMediaType_Audio;
1056 p_sys->subtype = FormatToGUID(audio_format_table, p_dec->fmt_in.i_codec);
1058 if (!p_sys->subtype)
1059 return VLC_EGENERIC;
1061 UINT32 flags = MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_LOCALMFT
1062 | MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT
1063 | MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_TRANSCODE_ONLY;
1064 MFT_REGISTER_TYPE_INFO input_type = { *p_sys->major_type, *p_sys->subtype };
1065 IMFActivate **activate_objects = NULL;
1066 UINT32 activate_objects_count = 0;
1067 hr = mf->fptr_MFTEnumEx(category, flags, &input_type, NULL, &activate_objects, &activate_objects_count);
1069 return VLC_EGENERIC;
1071 msg_Dbg(p_dec, "Found %d available MFT module(s)", activate_objects_count);
1072 if (activate_objects_count == 0)
1073 return VLC_EGENERIC;
1075 for (UINT32 i = 0; i < activate_objects_count; ++i)
1077 hr = IMFActivate_ActivateObject(activate_objects[i], &IID_IMFTransform, (void**)&p_sys->mft);
1078 IMFActivate_Release(activate_objects[i]);
1082 if (InitializeMFT(p_dec) == VLC_SUCCESS)
1084 CoTaskMemFree(activate_objects);
1088 CoTaskMemFree(activate_objects);
1090 return VLC_EGENERIC;
1093 static int LoadMFTLibrary(MFHandle *mf)
1095 #if _WIN32_WINNT < 0x601
1096 mf->mfplat_dll = LoadLibrary(TEXT("mfplat.dll"));
1097 if (!mf->mfplat_dll)
1098 return VLC_EGENERIC;
1100 mf->fptr_MFTEnumEx = (void*)GetProcAddress(mf->mfplat_dll, "MFTEnumEx");
1101 mf->fptr_MFCreateSample = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateSample");
1102 mf->fptr_MFCreateMemoryBuffer = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateMemoryBuffer");
1103 mf->fptr_MFCreateAlignedMemoryBuffer = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateAlignedMemoryBuffer");
1104 if (!mf->fptr_MFTEnumEx || !mf->fptr_MFCreateSample || !mf->fptr_MFCreateMemoryBuffer || !mf->fptr_MFCreateAlignedMemoryBuffer)
1105 return VLC_EGENERIC;
1107 mf->fptr_MFTEnumEx = &MFTEnumEx;
1108 mf->fptr_MFCreateSample = &MFCreateSample;
1109 mf->fptr_MFCreateMemoryBuffer = &MFCreateMemoryBuffer;
1110 mf->fptr_MFCreateAlignedMemoryBuffer = &MFCreateAlignedMemoryBuffer;
1116 int Open(vlc_object_t *p_this)
1118 decoder_t *p_dec = (decoder_t *)p_this;
1119 decoder_sys_t *p_sys;
1121 if (p_dec->fmt_in.i_cat != VIDEO_ES && p_dec->fmt_in.i_cat != AUDIO_ES)
1122 return VLC_EGENERIC;
1124 p_sys = p_dec->p_sys = calloc(1, sizeof(*p_sys));
1128 if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
1129 vlc_assert_unreachable();
1131 if (LoadMFTLibrary(&p_sys->mf_handle))
1133 msg_Err(p_dec, "Failed to load MFT library.");
1139 msg_Err(p_dec, "Could not find suitable MFT decoder");
1143 /* Only one output sample is needed, we can allocate one and reuse it. */
1144 if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
1147 if (p_sys->is_async)
1149 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeAsync;
1150 p_dec->pf_decode_audio = (block_t *(*)(decoder_t *, block_t **))DecodeAsync;
1154 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeSync;
1155 p_dec->pf_decode_audio = (block_t *(*)(decoder_t *, block_t **))DecodeSync;
1158 p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
1159 p_dec->b_need_packetized = true;
1165 return VLC_EGENERIC;
1168 void Close(vlc_object_t *p_this)
1170 decoder_t *p_dec = (decoder_t *)p_this;
1171 decoder_sys_t *p_sys = p_dec->p_sys;
1172 MFHandle *mf = &p_sys->mf_handle;
1177 FreeLibrary(mf->mfplat_dll);