]> git.sesse.net Git - vlc/blob - modules/codec/mft.c
win32: add assertions for unchecked CoInitializeEx() calls
[vlc] / modules / codec / mft.c
1 /*****************************************************************************
2  * mft.c : Media Foundation Transform audio/video decoder
3  *****************************************************************************
4  * Copyright (C) 2014 VLC authors and VideoLAN
5  *
6  * Author: Felix Abecassis <felix.abecassis@gmail.com>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #undef WINVER
28 #define WINVER 0x0601
29
30 /* Needed for many mingw macros. */
31 #define COBJMACROS
32
33 /* Avoid having GUIDs being defined as "extern". */
34 #define INITGUID
35
36 #ifndef STDCALL
37 # define STDCALL __stdcall
38 #endif
39
40 #include <assert.h>
41
42 #include <vlc_common.h>
43 #include <vlc_plugin.h>
44 #include <vlc_codec.h>
45 #include <h264_nal.h>
46 #define _VIDEOINFOHEADER_
47 #include <vlc_codecs.h>
48
49 #include <mfapi.h>
50 #include <mftransform.h>
51 #include <mferror.h>
52 #include <mfobjects.h>
53
54 static int  Open(vlc_object_t *);
55 static void Close(vlc_object_t *);
56
57 vlc_module_begin()
58     set_description(N_("Media Foundation Transform decoder"))
59     add_shortcut("mft")
60     set_capability("decoder", 1)
61     set_callbacks(Open, Close)
62     set_category(CAT_INPUT)
63     set_subcategory(SUBCAT_INPUT_VCODEC)
64 vlc_module_end()
65
66 typedef struct
67 {
68     HINSTANCE mfplat_dll;
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);
76 } MFHandle;
77
78 struct decoder_sys_t
79 {
80     MFHandle mf_handle;
81
82     IMFTransform *mft;
83
84     const GUID* major_type;
85     const GUID* subtype;
86
87     /* For asynchronous MFT */
88     bool is_async;
89     IMFMediaEventGenerator *event_generator;
90     int pending_input_events;
91     int pending_output_events;
92
93     /* Input stream */
94     DWORD input_stream_id;
95     IMFMediaType *input_type;
96
97     /* Output stream */
98     DWORD output_stream_id;
99     IMFSample *output_sample;
100     IMFMediaType *output_type;
101
102     /* H264 only. */
103     uint32_t nal_size;
104 };
105
106 static const int pi_channels_maps[9] =
107 {
108     0,
109     AOUT_CHAN_CENTER,
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
123      | AOUT_CHAN_LFE,
124 };
125
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)
129 #endif
130
131 #ifndef MF_E_TRANSFORM_STREAM_CHANGE
132 # define MF_E_TRANSFORM_STREAM_CHANGE _HRESULT_TYPEDEF_(0xc00d6d61)
133 #endif
134
135 #ifndef MF_E_NO_EVENTS_AVAILABLE
136 # define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xC00D3E80L)
137 #endif
138
139 #ifndef MF_EVENT_FLAG_NO_WAIT
140 # define MF_EVENT_FLAG_NO_WAIT 0x00000001
141 #endif
142
143 /*
144  * The MFTransformXXX values might not be defined in mingw headers,
145  * thus we use our own enum with the VLC prefix.
146  */
147 enum
148 {
149     VLC_METransformUnknown = 600,
150     VLC_METransformNeedInput,
151     VLC_METransformHaveOutput,
152     VLC_METransformDrainComplete,
153     VLC_METransformMarker,
154 };
155
156 typedef struct
157 {
158     vlc_fourcc_t fourcc;
159     const GUID   *guid;
160 } pair_format_guid;
161
162 /*
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.
165  */
166 static const pair_format_guid video_format_table[] =
167 {
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 },
174     { 0, NULL }
175 };
176
177 DEFINE_GUID(MFAudioFormat_Dolby_AC3, 0xe06d802c, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
178 /*
179  * We cannot use the FOURCC code for audio either since the
180  * WAVE_FORMAT value is used to create the GUID.
181  */
182 static const pair_format_guid audio_format_table[] =
183 {
184     { VLC_CODEC_MPGA, &MFAudioFormat_MPEG      },
185     { VLC_CODEC_MP3,  &MFAudioFormat_MP3       },
186     { VLC_CODEC_DTS,  &MFAudioFormat_DTS       },
187     { VLC_CODEC_MP4A, &MFAudioFormat_AAC       },
188     { VLC_CODEC_WMA2, &MFAudioFormat_WMAudioV8 },
189     { VLC_CODEC_A52,  &MFAudioFormat_Dolby_AC3 },
190     { 0, NULL }
191 };
192
193 static const GUID *FormatToGUID(const pair_format_guid table[], vlc_fourcc_t fourcc)
194 {
195     for (int i = 0; table[i].fourcc; ++i)
196         if (table[i].fourcc == fourcc)
197             return table[i].guid;
198
199     return NULL;
200 }
201
202 /*
203  * Low latency mode for Windows 8. Without this option, the H264
204  * decoder will fill *all* its internal buffers before returning a
205  * frame. Because of this behavior, the decoder might return no frame
206  * for more than 500 ms, making it unusable for playback.
207  */
208 DEFINE_GUID(CODECAPI_AVLowLatencyMode, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
209
210 static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
211 {
212     decoder_sys_t *p_sys = p_dec->p_sys;
213     HRESULT hr;
214
215     *result = NULL;
216
217     IMFMediaType *input_media_type = NULL;
218
219     /* Search a suitable input type for the MFT. */
220     int input_type_index = 0;
221     bool found = false;
222     for (int i = 0; !found; ++i)
223     {
224         hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, i, &input_media_type);
225         if (hr == MF_E_NO_MORE_TYPES)
226             break;
227         else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
228         {
229             /* The output type must be set before setting the input type for this MFT. */
230             return VLC_SUCCESS;
231         }
232         else if (FAILED(hr))
233             goto error;
234
235         GUID subtype;
236         hr = IMFMediaType_GetGUID(input_media_type, &MF_MT_SUBTYPE, &subtype);
237         if (FAILED(hr))
238             goto error;
239
240         if (IsEqualGUID(&subtype, p_sys->subtype))
241             found = true;
242
243         if (found)
244             input_type_index = i;
245
246         IMFMediaType_Release(input_media_type);
247         input_media_type = NULL;
248     }
249     if (!found)
250         goto error;
251
252     hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, input_type_index, &input_media_type);
253     if (FAILED(hr))
254         goto error;
255
256     if (p_dec->fmt_in.i_cat == VIDEO_ES)
257     {
258         UINT64 width = p_dec->fmt_in.video.i_width;
259         UINT64 height = p_dec->fmt_in.video.i_height;
260         UINT64 frame_size = (width << 32) | height;
261         hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_SIZE, frame_size);
262         if (FAILED(hr))
263             goto error;
264     }
265     else
266     {
267         hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1);
268         if (FAILED(hr))
269             goto error;
270         if (p_dec->fmt_in.audio.i_rate)
271         {
272             hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate);
273             if (FAILED(hr))
274                 goto error;
275         }
276         if (p_dec->fmt_in.audio.i_channels)
277         {
278             hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels);
279             if (FAILED(hr))
280                 goto error;
281         }
282         if (p_dec->fmt_in.audio.i_bitspersample)
283         {
284             hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample);
285             if (FAILED(hr))
286                 goto error;
287         }
288         if (p_dec->fmt_in.audio.i_blockalign)
289         {
290             hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign);
291             if (FAILED(hr))
292                 goto error;
293         }
294         if (p_dec->fmt_in.i_bitrate)
295         {
296             hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8);
297             if (FAILED(hr))
298                 goto error;
299         }
300     }
301
302     if (p_dec->fmt_in.i_extra > 0)
303     {
304         UINT32 blob_size = 0;
305         hr = IMFMediaType_GetBlobSize(input_media_type, &MF_MT_USER_DATA, &blob_size);
306         /*
307          * Do not overwrite existing user data in the input type, this
308          * can cause the MFT to reject the type.
309          */
310         if (hr == MF_E_ATTRIBUTENOTFOUND)
311         {
312             hr = IMFMediaType_SetBlob(input_media_type, &MF_MT_USER_DATA,
313                                       (const UINT8*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
314             if (FAILED(hr))
315                 goto error;
316         }
317     }
318
319     hr = IMFTransform_SetInputType(p_sys->mft, stream_id, input_media_type, 0);
320     if (FAILED(hr))
321         goto error;
322
323     *result = input_media_type;
324
325     return VLC_SUCCESS;
326
327 error:
328     msg_Err(p_dec, "Error in SetInputType()");
329     if (input_media_type)
330         IMFMediaType_Release(input_media_type);
331     return VLC_EGENERIC;
332 }
333
334 static int SetOutputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
335 {
336     decoder_sys_t *p_sys = p_dec->p_sys;
337     HRESULT hr;
338
339     *result = NULL;
340
341     IMFMediaType *output_media_type = NULL;
342
343     /*
344      * Enumerate available output types. The list is ordered by
345      * preference thus we will use the first one unless YV12/I420 is
346      * available for video or float32 for audio.
347      */
348     int output_type_index = 0;
349     bool found = false;
350     for (int i = 0; !found; ++i)
351     {
352         hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, i, &output_media_type);
353         if (hr == MF_E_NO_MORE_TYPES)
354             break;
355         else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
356         {
357             /* The input type must be set before setting the output type for this MFT. */
358             return VLC_SUCCESS;
359         }
360         else if (FAILED(hr))
361             goto error;
362
363         GUID subtype;
364         hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
365         if (FAILED(hr))
366             goto error;
367
368         if (p_dec->fmt_in.i_cat == VIDEO_ES)
369         {
370             if (IsEqualGUID(&subtype, &MFVideoFormat_YV12) || IsEqualGUID(&subtype, &MFVideoFormat_I420))
371                 found = true;
372         }
373         else
374         {
375             UINT32 bits_per_sample;
376             hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
377             if (FAILED(hr))
378                 continue;
379             if (bits_per_sample == 32 && IsEqualGUID(&subtype, &MFAudioFormat_Float))
380                 found = true;
381         }
382
383         if (found)
384             output_type_index = i;
385
386         IMFMediaType_Release(output_media_type);
387         output_media_type = NULL;
388     }
389     /*
390      * It's not an error if we don't find the output type we were
391      * looking for, in this case we use the first available type which
392      * is the "preferred" output type for this MFT.
393      */
394
395     hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, output_type_index, &output_media_type);
396     if (FAILED(hr))
397         goto error;
398
399     hr = IMFTransform_SetOutputType(p_sys->mft, stream_id, output_media_type, 0);
400     if (FAILED(hr))
401         goto error;
402
403     GUID subtype;
404     hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
405     if (FAILED(hr))
406         goto error;
407
408     if (p_dec->fmt_in.i_cat == VIDEO_ES)
409     {
410         p_dec->fmt_out.video = p_dec->fmt_in.video;
411         p_dec->fmt_out.i_codec = vlc_fourcc_GetCodec(p_dec->fmt_in.i_cat, subtype.Data1);
412     }
413     else
414     {
415         p_dec->fmt_out.audio = p_dec->fmt_in.audio;
416
417         UINT32 bitspersample = 0;
418         hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample);
419         if (SUCCEEDED(hr) && bitspersample)
420             p_dec->fmt_out.audio.i_bitspersample = bitspersample;
421
422         UINT32 channels = 0;
423         hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
424         if (SUCCEEDED(hr) && channels)
425             p_dec->fmt_out.audio.i_channels = channels;
426
427         UINT32 rate = 0;
428         hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
429         if (SUCCEEDED(hr) && rate)
430             p_dec->fmt_out.audio.i_rate = rate;
431
432         vlc_fourcc_t fourcc;
433         wf_tag_to_fourcc(subtype.Data1, &fourcc, NULL);
434         p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio(fourcc, p_dec->fmt_out.audio.i_bitspersample);
435
436         p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels];
437         p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels;
438     }
439
440     *result = output_media_type;
441
442     return VLC_SUCCESS;
443
444 error:
445     msg_Err(p_dec, "Error in SetOutputType()");
446     if (output_media_type)
447         IMFMediaType_Release(output_media_type);
448     return VLC_EGENERIC;
449 }
450
451 static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** result, DWORD size)
452 {
453     decoder_sys_t *p_sys = p_dec->p_sys;
454     MFHandle *mf = &p_sys->mf_handle;
455     HRESULT hr;
456
457     *result = NULL;
458
459     IMFSample *input_sample = NULL;
460
461     MFT_INPUT_STREAM_INFO input_info;
462     hr = IMFTransform_GetInputStreamInfo(p_sys->mft, stream_id, &input_info);
463     if (FAILED(hr))
464         goto error;
465
466     hr = mf->fptr_MFCreateSample(&input_sample);
467     if (FAILED(hr))
468         goto error;
469
470     IMFMediaBuffer *input_media_buffer = NULL;
471     DWORD allocation_size = __MAX(input_info.cbSize, size);
472     hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &input_media_buffer);
473     if (FAILED(hr))
474         goto error;
475
476     hr = IMFSample_AddBuffer(input_sample, input_media_buffer);
477     IMFMediaBuffer_Release(input_media_buffer);
478     if (FAILED(hr))
479         goto error;
480
481     *result = input_sample;
482
483     return VLC_SUCCESS;
484
485 error:
486     msg_Err(p_dec, "Error in AllocateInputSample()");
487     if (input_sample)
488         IMFSample_Release(input_sample);
489     if (input_media_buffer)
490         IMFMediaBuffer_Release(input_media_buffer);
491     return VLC_EGENERIC;
492 }
493
494 static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **result)
495 {
496     decoder_sys_t *p_sys = p_dec->p_sys;
497     MFHandle *mf = &p_sys->mf_handle;
498     HRESULT hr;
499
500     *result = NULL;
501
502     IMFSample *output_sample = NULL;
503
504     MFT_OUTPUT_STREAM_INFO output_info;
505     hr = IMFTransform_GetOutputStreamInfo(p_sys->mft, stream_id, &output_info);
506     if (FAILED(hr))
507         goto error;
508
509     if (output_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES))
510     {
511         /* The MFT will provide an allocated sample. */
512         return VLC_SUCCESS;
513     }
514
515     DWORD expected_flags = 0;
516     if (p_dec->fmt_in.i_cat == VIDEO_ES)
517         expected_flags |= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
518                         | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
519                         | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
520     if ((output_info.dwFlags & expected_flags) != expected_flags)
521         goto error;
522
523     hr = mf->fptr_MFCreateSample(&output_sample);
524     if (FAILED(hr))
525         goto error;
526
527     IMFMediaBuffer *output_media_buffer = NULL;
528     DWORD allocation_size = output_info.cbSize;
529     DWORD alignment = output_info.cbAlignment;
530     if (alignment > 0)
531         hr = mf->fptr_MFCreateAlignedMemoryBuffer(allocation_size, alignment - 1, &output_media_buffer);
532     else
533         hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &output_media_buffer);
534     if (FAILED(hr))
535         goto error;
536
537     hr = IMFSample_AddBuffer(output_sample, output_media_buffer);
538     if (FAILED(hr))
539         goto error;
540
541     *result = output_sample;
542
543     return VLC_SUCCESS;
544
545 error:
546     msg_Err(p_dec, "Error in AllocateOutputSample()");
547     if (output_sample)
548         IMFSample_Release(output_sample);
549     return VLC_EGENERIC;
550 }
551
552 static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_block)
553 {
554     decoder_sys_t *p_sys = p_dec->p_sys;
555     HRESULT hr;
556     IMFSample *input_sample = NULL;
557
558     if (AllocateInputSample(p_dec, stream_id, &input_sample, p_block->i_buffer))
559         goto error;
560
561     IMFMediaBuffer *input_media_buffer = NULL;
562     hr = IMFSample_GetBufferByIndex(input_sample, 0, &input_media_buffer);
563     if (FAILED(hr))
564         goto error;
565
566     BYTE *buffer_start;
567     hr = IMFMediaBuffer_Lock(input_media_buffer, &buffer_start, NULL, NULL);
568     if (FAILED(hr))
569         goto error;
570
571     memcpy(buffer_start, p_block->p_buffer, p_block->i_buffer);
572
573     if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
574     {
575         /* in-place NAL to annex B conversion. */
576         struct H264ConvertState convert_state = { 0, 0 };
577         convert_h264_to_annexb(buffer_start, p_block->i_buffer, p_sys->nal_size, &convert_state);
578     }
579
580     hr = IMFMediaBuffer_Unlock(input_media_buffer);
581     if (FAILED(hr))
582         goto error;
583
584     hr = IMFMediaBuffer_SetCurrentLength(input_media_buffer, p_block->i_buffer);
585     if (FAILED(hr))
586         goto error;
587
588     LONGLONG ts = p_block->i_pts;
589     if (!ts && p_block->i_dts)
590         ts = p_block->i_dts;
591
592     /* Convert from microseconds to 100 nanoseconds unit. */
593     hr = IMFSample_SetSampleTime(input_sample, ts * 10);
594     if (FAILED(hr))
595         goto error;
596
597     hr = IMFTransform_ProcessInput(p_sys->mft, stream_id, input_sample, 0);
598     if (FAILED(hr))
599         goto error;
600
601     IMFMediaBuffer_Release(input_media_buffer);
602     IMFSample_Release(input_sample);
603
604     return VLC_SUCCESS;
605
606 error:
607     msg_Err(p_dec, "Error in ProcessInputStream()");
608     if (input_sample)
609         IMFSample_Release(input_sample);
610     return VLC_EGENERIC;
611 }
612
613 /* Copy a packed buffer (no padding) to a picture_t */
614 static void CopyPackedBufferToPicture(picture_t *p_pic, const uint8_t *p_src)
615 {
616     for (int i = 0; i < p_pic->i_planes; ++i)
617     {
618         uint8_t *p_dst = p_pic->p[i].p_pixels;
619
620         if (p_pic->p[i].i_visible_pitch == p_pic->p[i].i_pitch)
621         {
622             /* Plane is packed, only one memcpy is needed. */
623             uint32_t plane_size = p_pic->p[i].i_pitch * p_pic->p[i].i_visible_lines;
624             memcpy(p_dst, p_src, plane_size);
625             p_src += plane_size;
626             continue;
627         }
628
629         for (int i_line = 0; i_line < p_pic->p[i].i_visible_lines; i_line++)
630         {
631             memcpy(p_dst, p_src, p_pic->p[i].i_visible_pitch);
632             p_src += p_pic->p[i].i_visible_pitch;
633             p_dst += p_pic->p[i].i_pitch;
634         }
635     }
636 }
637
638 static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, void **result)
639 {
640     decoder_sys_t *p_sys = p_dec->p_sys;
641     HRESULT hr;
642     picture_t *picture = NULL;
643     block_t *aout_buffer = NULL;
644
645     *result = NULL;
646
647     DWORD output_status = 0;
648     MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
649     hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status);
650     if (output_buffer.pEvents)
651         IMFCollection_Release(output_buffer.pEvents);
652     /* Use the returned sample since it can be provided by the MFT. */
653     IMFSample *output_sample = output_buffer.pSample;
654
655     if (hr == S_OK)
656     {
657         if (!output_sample)
658             return VLC_SUCCESS;
659
660         LONGLONG sample_time;
661         hr = IMFSample_GetSampleTime(output_sample, &sample_time);
662         if (FAILED(hr))
663             goto error;
664         /* Convert from 100 nanoseconds unit to microseconds. */
665         sample_time /= 10;
666
667         DWORD total_length = 0;
668         hr = IMFSample_GetTotalLength(output_sample, &total_length);
669         if (FAILED(hr))
670             goto error;
671
672         if (p_dec->fmt_in.i_cat == VIDEO_ES)
673         {
674             picture = decoder_NewPicture(p_dec);
675             if (!picture)
676                 return VLC_SUCCESS;
677
678             UINT32 interlaced = false;
679             hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced);
680             picture->b_progressive = !interlaced;
681
682             picture->date = sample_time;
683         }
684         else
685         {
686             if (p_dec->fmt_out.audio.i_bitspersample == 0 || p_dec->fmt_out.audio.i_channels == 0)
687                 goto error;
688             int samples = total_length / (p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8);
689             aout_buffer = decoder_NewAudioBuffer(p_dec, samples);
690             if (!aout_buffer)
691                 return VLC_SUCCESS;
692             if (aout_buffer->i_buffer < total_length)
693                 goto error;
694
695             aout_buffer->i_pts = sample_time;
696         }
697
698         IMFMediaBuffer *output_media_buffer = NULL;
699         hr = IMFSample_GetBufferByIndex(output_sample, 0, &output_media_buffer);
700
701         BYTE *buffer_start;
702         hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
703         if (FAILED(hr))
704             goto error;
705
706         if (p_dec->fmt_in.i_cat == VIDEO_ES)
707             CopyPackedBufferToPicture(picture, buffer_start);
708         else
709             memcpy(aout_buffer->p_buffer, buffer_start, total_length);
710
711         hr = IMFMediaBuffer_Unlock(output_media_buffer);
712         IMFSample_Release(output_media_buffer);
713         if (FAILED(hr))
714             goto error;
715
716         if (p_sys->output_sample)
717         {
718             /* Sample is not provided by the MFT: clear its content. */
719             hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0);
720             if (FAILED(hr))
721                 goto error;
722         }
723         else
724         {
725             /* Sample is provided by the MFT: decrease refcount. */
726             IMFSample_Release(output_sample);
727         }
728     }
729     else if (hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_TYPE_NOT_SET)
730     {
731         if (p_sys->output_type)
732             IMFMediaType_Release(p_sys->output_type);
733         if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
734             goto error;
735
736         /* Reallocate output sample. */
737         if (p_sys->output_sample)
738             IMFSample_Release(p_sys->output_sample);
739         p_sys->output_sample = NULL;
740         if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
741             goto error;
742         return VLC_SUCCESS;
743     }
744     else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
745     {
746         return VLC_SUCCESS;
747     }
748     else /* An error not listed above occurred */
749     {
750         msg_Err(p_dec, "Unexpected error in IMFTransform::ProcessOutput: %#lx",
751                 hr);
752         goto error;
753     }
754
755     if (p_dec->fmt_in.i_cat == VIDEO_ES)
756         *result = picture;
757     else
758         *result = aout_buffer;
759
760     return VLC_SUCCESS;
761
762 error:
763     msg_Err(p_dec, "Error in ProcessOutputStream()");
764     if (picture)
765         picture_Release(picture);
766     if (aout_buffer)
767         block_Release(aout_buffer);
768     return VLC_EGENERIC;
769 }
770
771 static void *DecodeSync(decoder_t *p_dec, block_t **pp_block)
772 {
773     decoder_sys_t *p_sys = p_dec->p_sys;
774
775     if (!pp_block || !*pp_block)
776         return NULL;
777
778     block_t *p_block = *pp_block;
779     if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED))
780     {
781         block_Release(p_block);
782         return NULL;
783     }
784
785     /* Drain the output stream before sending the input packet. */
786     void *result = NULL;
787     if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
788         goto error;
789     if (result)
790         return result;
791
792     if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
793         goto error;
794
795     block_Release(p_block);
796     *pp_block = NULL;
797
798     return NULL;
799
800 error:
801     msg_Err(p_dec, "Error in DecodeSync()");
802     if (p_block)
803         block_Release(p_block);
804     return NULL;
805 }
806
807 static HRESULT DequeueMediaEvent(decoder_t *p_dec)
808 {
809     decoder_sys_t *p_sys = p_dec->p_sys;
810     HRESULT hr;
811
812     IMFMediaEvent *event = NULL;
813     hr = IMFMediaEventGenerator_GetEvent(p_sys->event_generator, MF_EVENT_FLAG_NO_WAIT, &event);
814     if (FAILED(hr))
815         return hr;
816     MediaEventType event_type;
817     hr = IMFMediaEvent_GetType(event, &event_type);
818     IMFMediaEvent_Release(event);
819     if (FAILED(hr))
820         return hr;
821
822     if (event_type == VLC_METransformNeedInput)
823         p_sys->pending_input_events += 1;
824     else if (event_type == VLC_METransformHaveOutput)
825         p_sys->pending_output_events += 1;
826     else
827         msg_Err(p_dec, "Unsupported asynchronous event.");
828
829     return S_OK;
830 }
831
832 static void *DecodeAsync(decoder_t *p_dec, block_t **pp_block)
833 {
834     decoder_sys_t *p_sys = p_dec->p_sys;
835     HRESULT hr;
836
837     if (!pp_block || !*pp_block)
838         return NULL;
839
840     block_t *p_block = *pp_block;
841     if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED))
842     {
843         block_Release(p_block);
844
845         return NULL;
846     }
847
848     /* Dequeue all pending media events. */
849     while ((hr = DequeueMediaEvent(p_dec)) == S_OK)
850         continue;
851     if (hr != MF_E_NO_EVENTS_AVAILABLE && FAILED(hr))
852         goto error;
853
854     /* Drain the output stream of the MFT before sending the input packet. */
855     if (p_sys->pending_output_events > 0)
856     {
857         p_sys->pending_output_events -= 1;
858         void *result = NULL;
859         if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
860             goto error;
861         return result;
862     }
863
864     /* Poll the MFT and return decoded frames until the input stream is ready. */
865     while (p_sys->pending_input_events == 0)
866     {
867         hr = DequeueMediaEvent(p_dec);
868         if (hr == MF_E_NO_EVENTS_AVAILABLE)
869         {
870             /* Sleep for 1 ms to avoid excessive polling. */
871             Sleep(1);
872             continue;
873         }
874         if (FAILED(hr))
875             goto error;
876
877         if (p_sys->pending_output_events > 0)
878         {
879             p_sys->pending_output_events -= 1;
880             void *result = NULL;
881             if (ProcessOutputStream(p_dec, p_sys->output_stream_id, &result))
882                 goto error;
883             return result;
884         }
885     }
886
887     p_sys->pending_input_events -= 1;
888     if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
889         goto error;
890
891     block_Release(p_block);
892     *pp_block = NULL;
893
894     return NULL;
895
896 error:
897     msg_Err(p_dec, "Error in DecodeAsync()");
898     block_Release(p_block);
899     return NULL;
900 }
901
902 static void DestroyMFT(decoder_t *p_dec);
903
904 static int InitializeMFT(decoder_t *p_dec)
905 {
906     decoder_sys_t *p_sys = p_dec->p_sys;
907     HRESULT hr;
908
909     IMFAttributes *attributes = NULL;
910     hr = IMFTransform_GetAttributes(p_sys->mft, &attributes);
911     if (hr != E_NOTIMPL && FAILED(hr))
912         goto error;
913     if (SUCCEEDED(hr))
914     {
915         UINT32 is_async = false;
916         hr = IMFAttributes_GetUINT32(attributes, &MF_TRANSFORM_ASYNC, &is_async);
917         if (hr != MF_E_ATTRIBUTENOTFOUND && FAILED(hr))
918             goto error;
919         p_sys->is_async = is_async;
920         if (p_sys->is_async)
921         {
922             hr = IMFAttributes_SetUINT32(attributes, &MF_TRANSFORM_ASYNC_UNLOCK, true);
923             if (FAILED(hr))
924                 goto error;
925             hr = IMFTransform_QueryInterface(p_sys->mft, &IID_IMFMediaEventGenerator, (void**)&p_sys->event_generator);
926             if (FAILED(hr))
927                 goto error;
928         }
929     }
930
931     DWORD input_streams_count;
932     DWORD output_streams_count;
933     hr = IMFTransform_GetStreamCount(p_sys->mft, &input_streams_count, &output_streams_count);
934     if (FAILED(hr))
935         goto error;
936     if (input_streams_count != 1 || output_streams_count != 1)
937     {
938         msg_Err(p_dec, "MFT decoder should have 1 input stream and 1 output stream.");
939         goto error;
940     }
941
942     hr = IMFTransform_GetStreamIDs(p_sys->mft, 1, &p_sys->input_stream_id, 1, &p_sys->output_stream_id);
943     if (hr == E_NOTIMPL)
944     {
945         /*
946          * This is not an error, it happens if:
947          * - there is a fixed number of streams.
948          * AND
949          * - streams are numbered consecutively from 0 to N-1.
950          */
951         p_sys->input_stream_id = 0;
952         p_sys->output_stream_id = 0;
953     }
954     else if (FAILED(hr))
955         goto error;
956
957     if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type))
958         goto error;
959
960     if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
961         goto error;
962
963     /*
964      * The input type was not set by the previous call to
965      * SetInputType, try again after setting the output type.
966      */
967     if (!p_sys->input_type)
968         if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type) || !p_sys->input_type)
969             goto error;
970
971     /* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
972     hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, (ULONG_PTR)0);
973     if (FAILED(hr))
974         goto error;
975
976     /* This event is required for asynchronous MFTs, optional otherwise. */
977     hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, (ULONG_PTR)0);
978     if (FAILED(hr))
979         goto error;
980
981     if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
982     {
983         /* It's not an error if the following call fails. */
984         IMFAttributes_SetUINT32(attributes, &CODECAPI_AVLowLatencyMode, true);
985
986         if (p_dec->fmt_in.i_extra)
987         {
988             int buf_size = p_dec->fmt_in.i_extra + 20;
989             uint32_t size = p_dec->fmt_in.i_extra;
990             uint8_t *buf = malloc(buf_size);
991             if (((uint8_t*)p_dec->fmt_in.p_extra)[0] == 1)
992             {
993                 convert_sps_pps(p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra,
994                                 buf, buf_size,
995                                 &size, &p_sys->nal_size);
996             }
997             free(buf);
998         }
999     }
1000     return VLC_SUCCESS;
1001
1002 error:
1003     msg_Err(p_dec, "Error in InitializeMFT()");
1004     DestroyMFT(p_dec);
1005     return VLC_EGENERIC;
1006 }
1007
1008 static void DestroyMFT(decoder_t *p_dec)
1009 {
1010     decoder_sys_t *p_sys = p_dec->p_sys;
1011
1012     if (p_sys->event_generator)
1013         IMFMediaEventGenerator_Release(p_sys->event_generator);
1014     if (p_sys->input_type)
1015         IMFMediaType_Release(p_sys->input_type);
1016     if (p_sys->output_sample)
1017     {
1018         IMFMediaBuffer *output_media_buffer = NULL;
1019         HRESULT hr = IMFSample_GetBufferByIndex(p_sys->output_sample, 0, &output_media_buffer);
1020         if (SUCCEEDED(hr))
1021             IMFSample_Release(output_media_buffer);
1022         IMFSample_Release(p_sys->output_sample);
1023     }
1024     if (p_sys->output_type)
1025         IMFMediaType_Release(p_sys->output_type);
1026     if (p_sys->mft)
1027         IMFTransform_Release(p_sys->mft);
1028
1029     p_sys->event_generator = NULL;
1030     p_sys->input_type = NULL;
1031     p_sys->output_sample = NULL;
1032     p_sys->output_type = NULL;
1033     p_sys->mft = NULL;
1034 }
1035
1036 static int FindMFT(decoder_t *p_dec)
1037 {
1038     decoder_sys_t *p_sys = p_dec->p_sys;
1039     MFHandle *mf = &p_sys->mf_handle;
1040     HRESULT hr;
1041
1042     /* Try to create a MFT using MFTEnumEx. */
1043     GUID category;
1044     if (p_dec->fmt_in.i_cat == VIDEO_ES)
1045     {
1046         category = MFT_CATEGORY_VIDEO_DECODER;
1047         p_sys->major_type = &MFMediaType_Video;
1048         p_sys->subtype = FormatToGUID(video_format_table, p_dec->fmt_in.i_codec);
1049     }
1050     else
1051     {
1052         category = MFT_CATEGORY_AUDIO_DECODER;
1053         p_sys->major_type = &MFMediaType_Audio;
1054         p_sys->subtype = FormatToGUID(audio_format_table, p_dec->fmt_in.i_codec);
1055     }
1056     if (!p_sys->subtype)
1057         return VLC_EGENERIC;
1058
1059     UINT32 flags = MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_LOCALMFT
1060                  | MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT
1061                  | MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_TRANSCODE_ONLY;
1062     MFT_REGISTER_TYPE_INFO input_type = { *p_sys->major_type, *p_sys->subtype };
1063     IMFActivate **activate_objects = NULL;
1064     UINT32 activate_objects_count = 0;
1065     hr = mf->fptr_MFTEnumEx(category, flags, &input_type, NULL, &activate_objects, &activate_objects_count);
1066     if (FAILED(hr))
1067         return VLC_EGENERIC;
1068
1069     msg_Dbg(p_dec, "Found %d available MFT module(s)", activate_objects_count);
1070     if (activate_objects_count == 0)
1071         return VLC_EGENERIC;
1072
1073     for (UINT32 i = 0; i < activate_objects_count; ++i)
1074     {
1075         hr = IMFActivate_ActivateObject(activate_objects[i], &IID_IMFTransform, (void**)&p_sys->mft);
1076         IMFActivate_Release(activate_objects[i]);
1077         if (FAILED(hr))
1078             continue;
1079
1080         if (InitializeMFT(p_dec) == VLC_SUCCESS)
1081         {
1082             CoTaskMemFree(activate_objects);
1083             return VLC_SUCCESS;
1084         }
1085     }
1086     CoTaskMemFree(activate_objects);
1087
1088     return VLC_EGENERIC;
1089 }
1090
1091 static int LoadMFTLibrary(MFHandle *mf)
1092 {
1093 #if _WIN32_WINNT < 0x601
1094     mf->mfplat_dll = LoadLibrary(TEXT("mfplat.dll"));
1095     if (!mf->mfplat_dll)
1096         return VLC_EGENERIC;
1097
1098     mf->fptr_MFTEnumEx = (void*)GetProcAddress(mf->mfplat_dll, "MFTEnumEx");
1099     mf->fptr_MFCreateSample = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateSample");
1100     mf->fptr_MFCreateMemoryBuffer = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateMemoryBuffer");
1101     mf->fptr_MFCreateAlignedMemoryBuffer = (void*)GetProcAddress(mf->mfplat_dll, "MFCreateAlignedMemoryBuffer");
1102     if (!mf->fptr_MFTEnumEx || !mf->fptr_MFCreateSample || !mf->fptr_MFCreateMemoryBuffer || !mf->fptr_MFCreateAlignedMemoryBuffer)
1103         return VLC_EGENERIC;
1104 #else
1105     mf->fptr_MFTEnumEx = &MFTEnumEx;
1106     mf->fptr_MFCreateSample = &MFCreateSample;
1107     mf->fptr_MFCreateMemoryBuffer = &MFCreateMemoryBuffer;
1108     mf->fptr_MFCreateAlignedMemoryBuffer = &MFCreateAlignedMemoryBuffer;
1109 #endif
1110
1111     return VLC_SUCCESS;
1112 }
1113
1114 int Open(vlc_object_t *p_this)
1115 {
1116     decoder_t *p_dec = (decoder_t *)p_this;
1117     decoder_sys_t *p_sys;
1118
1119     if (p_dec->fmt_in.i_cat != VIDEO_ES && p_dec->fmt_in.i_cat != AUDIO_ES)
1120         return VLC_EGENERIC;
1121
1122     p_sys = p_dec->p_sys = calloc(1, sizeof(*p_sys));
1123     if (!p_sys)
1124         return VLC_ENOMEM;
1125
1126     if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
1127         vlc_assert_unreachable();
1128
1129     if (LoadMFTLibrary(&p_sys->mf_handle))
1130     {
1131         msg_Err(p_dec, "Failed to load MFT library.");
1132         goto error;
1133     }
1134
1135     if (FindMFT(p_dec))
1136     {
1137         msg_Err(p_dec, "Could not find suitable MFT decoder");
1138         goto error;
1139     }
1140
1141     /* Only one output sample is needed, we can allocate one and reuse it. */
1142     if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
1143         goto error;
1144
1145     if (p_sys->is_async)
1146     {
1147         p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeAsync;
1148         p_dec->pf_decode_audio = (block_t   *(*)(decoder_t *, block_t **))DecodeAsync;
1149     }
1150     else
1151     {
1152         p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))DecodeSync;
1153         p_dec->pf_decode_audio = (block_t   *(*)(decoder_t *, block_t **))DecodeSync;
1154     }
1155
1156     p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
1157     p_dec->b_need_packetized = true;
1158
1159     return VLC_SUCCESS;
1160
1161 error:
1162     Close(p_this);
1163     return VLC_EGENERIC;
1164 }
1165
1166 void Close(vlc_object_t *p_this)
1167 {
1168     decoder_t *p_dec = (decoder_t *)p_this;
1169     decoder_sys_t *p_sys = p_dec->p_sys;
1170     MFHandle *mf = &p_sys->mf_handle;
1171
1172     DestroyMFT(p_dec);
1173
1174     if (mf->mfplat_dll)
1175         FreeLibrary(mf->mfplat_dll);
1176
1177     free(p_sys);
1178
1179     CoUninitialize();
1180 }