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