demux: mp4: avoid audio cuts on seek
[vlc.git] / modules / codec / mft.c
blobf91fc7c00fec762a2c147d95f1c05ad615b25227
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 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #undef WINVER
28 #define WINVER 0x0601
30 /* Needed for many mingw macros. */
31 #define COBJMACROS
33 /* Avoid having GUIDs being defined as "extern". */
34 #define INITGUID
36 #ifndef STDCALL
37 # define STDCALL __stdcall
38 #endif
40 #include <winapifamily.h>
41 #undef WINAPI_FAMILY
42 #define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
44 #include <assert.h>
46 #include <vlc_common.h>
47 #include <vlc_plugin.h>
48 #include <vlc_codec.h>
49 #include "../packetizer/h264_nal.h"
50 #define _VIDEOINFOHEADER_
51 #include <vlc_codecs.h>
53 #include <mfapi.h>
54 #include <mftransform.h>
55 #include <mferror.h>
56 #include <mfobjects.h>
58 static int Open(vlc_object_t *);
59 static void Close(vlc_object_t *);
61 vlc_module_begin()
62 set_description(N_("Media Foundation Transform decoder"))
63 add_shortcut("mft")
64 set_capability("video decoder", 1)
65 set_callbacks(Open, Close)
66 set_category(CAT_INPUT)
67 set_subcategory(SUBCAT_INPUT_VCODEC)
69 add_submodule()
70 add_shortcut("mft")
71 set_capability("audio decoder", 1)
72 set_callbacks(Open, Close)
73 vlc_module_end()
75 typedef struct
77 HINSTANCE mfplat_dll;
78 HRESULT (STDCALL *fptr_MFTEnumEx)(GUID guidCategory, UINT32 Flags,
79 const MFT_REGISTER_TYPE_INFO *pInputType,
80 const MFT_REGISTER_TYPE_INFO *pOutputType,
81 IMFActivate ***pppMFTActivate, UINT32 *pcMFTActivate);
82 HRESULT (STDCALL *fptr_MFCreateSample)(IMFSample **ppIMFSample);
83 HRESULT (STDCALL *fptr_MFCreateMemoryBuffer)(DWORD cbMaxLength, IMFMediaBuffer **ppBuffer);
84 HRESULT (STDCALL *fptr_MFCreateAlignedMemoryBuffer)(DWORD cbMaxLength, DWORD fAlignmentFlags, IMFMediaBuffer **ppBuffer);
85 } MFHandle;
87 struct decoder_sys_t
89 MFHandle mf_handle;
91 IMFTransform *mft;
93 const GUID* major_type;
94 const GUID* subtype;
96 /* For asynchronous MFT */
97 bool is_async;
98 IMFMediaEventGenerator *event_generator;
99 int pending_input_events;
100 int pending_output_events;
102 /* Input stream */
103 DWORD input_stream_id;
104 IMFMediaType *input_type;
106 /* Output stream */
107 DWORD output_stream_id;
108 IMFSample *output_sample;
109 IMFMediaType *output_type;
111 /* H264 only. */
112 uint8_t nal_length_size;
115 static const int pi_channels_maps[9] =
118 AOUT_CHAN_CENTER,
119 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
120 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
121 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
122 | AOUT_CHAN_REARRIGHT,
123 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
124 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
125 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
126 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
127 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
128 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
129 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
130 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
131 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
132 | AOUT_CHAN_LFE,
135 /* Possibly missing from mingw headers */
136 #ifndef MF_E_TRANSFORM_NEED_MORE_INPUT
137 # define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72)
138 #endif
140 #ifndef MF_E_TRANSFORM_STREAM_CHANGE
141 # define MF_E_TRANSFORM_STREAM_CHANGE _HRESULT_TYPEDEF_(0xc00d6d61)
142 #endif
144 #ifndef MF_E_NO_EVENTS_AVAILABLE
145 # define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xC00D3E80L)
146 #endif
148 #ifndef MF_EVENT_FLAG_NO_WAIT
149 # define MF_EVENT_FLAG_NO_WAIT 0x00000001
150 #endif
153 * The MFTransformXXX values might not be defined in mingw headers,
154 * thus we use our own enum with the VLC prefix.
156 enum
158 VLC_METransformUnknown = 600,
159 VLC_METransformNeedInput,
160 VLC_METransformHaveOutput,
161 VLC_METransformDrainComplete,
162 VLC_METransformMarker,
165 typedef struct
167 vlc_fourcc_t fourcc;
168 const GUID *guid;
169 } pair_format_guid;
172 * We need this table since the FOURCC used for GUID is not the same
173 * as the FOURCC used by VLC, for instance h264 vs H264.
175 static const pair_format_guid video_format_table[] =
177 { VLC_CODEC_H264, &MFVideoFormat_H264 },
178 { VLC_CODEC_MJPG, &MFVideoFormat_MJPG },
179 { VLC_CODEC_WMV1, &MFVideoFormat_WMV1 },
180 { VLC_CODEC_WMV2, &MFVideoFormat_WMV2 },
181 { VLC_CODEC_WMV3, &MFVideoFormat_WMV3 },
182 { VLC_CODEC_VC1, &MFVideoFormat_WVC1 },
183 { 0, NULL }
186 #if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 4
187 DEFINE_GUID(MFAudioFormat_Dolby_AC3, 0xe06d802c, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
188 #endif
190 * We cannot use the FOURCC code for audio either since the
191 * WAVE_FORMAT value is used to create the GUID.
193 static const pair_format_guid audio_format_table[] =
195 { VLC_CODEC_MPGA, &MFAudioFormat_MPEG },
196 { VLC_CODEC_MP3, &MFAudioFormat_MP3 },
197 { VLC_CODEC_DTS, &MFAudioFormat_DTS },
198 { VLC_CODEC_MP4A, &MFAudioFormat_AAC },
199 { VLC_CODEC_WMA2, &MFAudioFormat_WMAudioV8 },
200 { VLC_CODEC_A52, &MFAudioFormat_Dolby_AC3 },
201 { 0, NULL }
204 static const GUID *FormatToGUID(const pair_format_guid table[], vlc_fourcc_t fourcc)
206 for (int i = 0; table[i].fourcc; ++i)
207 if (table[i].fourcc == fourcc)
208 return table[i].guid;
210 return NULL;
214 * Low latency mode for Windows 8. Without this option, the H264
215 * decoder will fill *all* its internal buffers before returning a
216 * frame. Because of this behavior, the decoder might return no frame
217 * for more than 500 ms, making it unusable for playback.
219 DEFINE_GUID(CODECAPI_AVLowLatencyMode, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee);
221 static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
223 decoder_sys_t *p_sys = p_dec->p_sys;
224 HRESULT hr;
226 *result = NULL;
228 IMFMediaType *input_media_type = NULL;
230 /* Search a suitable input type for the MFT. */
231 int input_type_index = 0;
232 bool found = false;
233 for (int i = 0; !found; ++i)
235 hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, i, &input_media_type);
236 if (hr == MF_E_NO_MORE_TYPES)
237 break;
238 else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
240 /* The output type must be set before setting the input type for this MFT. */
241 return VLC_SUCCESS;
243 else if (FAILED(hr))
244 goto error;
246 GUID subtype;
247 hr = IMFMediaType_GetGUID(input_media_type, &MF_MT_SUBTYPE, &subtype);
248 if (FAILED(hr))
249 goto error;
251 if (IsEqualGUID(&subtype, p_sys->subtype))
252 found = true;
254 if (found)
255 input_type_index = i;
257 IMFMediaType_Release(input_media_type);
258 input_media_type = NULL;
260 if (!found)
261 goto error;
263 hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, input_type_index, &input_media_type);
264 if (FAILED(hr))
265 goto error;
267 if (p_dec->fmt_in.i_cat == VIDEO_ES)
269 UINT64 width = p_dec->fmt_in.video.i_width;
270 UINT64 height = p_dec->fmt_in.video.i_height;
271 UINT64 frame_size = (width << 32) | height;
272 hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_SIZE, frame_size);
273 if (FAILED(hr))
274 goto error;
276 else
278 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1);
279 if (FAILED(hr))
280 goto error;
281 if (p_dec->fmt_in.audio.i_rate)
283 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate);
284 if (FAILED(hr))
285 goto error;
287 if (p_dec->fmt_in.audio.i_channels)
289 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels);
290 if (FAILED(hr))
291 goto error;
293 if (p_dec->fmt_in.audio.i_bitspersample)
295 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample);
296 if (FAILED(hr))
297 goto error;
299 if (p_dec->fmt_in.audio.i_blockalign)
301 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign);
302 if (FAILED(hr))
303 goto error;
305 if (p_dec->fmt_in.i_bitrate)
307 hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8);
308 if (FAILED(hr))
309 goto error;
313 if (p_dec->fmt_in.i_extra > 0)
315 UINT32 blob_size = 0;
316 hr = IMFMediaType_GetBlobSize(input_media_type, &MF_MT_USER_DATA, &blob_size);
318 * Do not overwrite existing user data in the input type, this
319 * can cause the MFT to reject the type.
321 if (hr == MF_E_ATTRIBUTENOTFOUND)
323 hr = IMFMediaType_SetBlob(input_media_type, &MF_MT_USER_DATA,
324 (const UINT8*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
325 if (FAILED(hr))
326 goto error;
330 hr = IMFTransform_SetInputType(p_sys->mft, stream_id, input_media_type, 0);
331 if (FAILED(hr))
332 goto error;
334 *result = input_media_type;
336 return VLC_SUCCESS;
338 error:
339 msg_Err(p_dec, "Error in SetInputType()");
340 if (input_media_type)
341 IMFMediaType_Release(input_media_type);
342 return VLC_EGENERIC;
345 static int SetOutputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
347 decoder_sys_t *p_sys = p_dec->p_sys;
348 HRESULT hr;
350 *result = NULL;
352 IMFMediaType *output_media_type = NULL;
355 * Enumerate available output types. The list is ordered by
356 * preference thus we will use the first one unless YV12/I420 is
357 * available for video or float32 for audio.
359 int output_type_index = 0;
360 bool found = false;
361 for (int i = 0; !found; ++i)
363 hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, i, &output_media_type);
364 if (hr == MF_E_NO_MORE_TYPES)
365 break;
366 else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
368 /* The input type must be set before setting the output type for this MFT. */
369 return VLC_SUCCESS;
371 else if (FAILED(hr))
372 goto error;
374 GUID subtype;
375 hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
376 if (FAILED(hr))
377 goto error;
379 if (p_dec->fmt_in.i_cat == VIDEO_ES)
381 if (IsEqualGUID(&subtype, &MFVideoFormat_YV12) || IsEqualGUID(&subtype, &MFVideoFormat_I420))
382 found = true;
384 else
386 UINT32 bits_per_sample;
387 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
388 if (FAILED(hr))
389 continue;
390 if (bits_per_sample == 32 && IsEqualGUID(&subtype, &MFAudioFormat_Float))
391 found = true;
394 if (found)
395 output_type_index = i;
397 IMFMediaType_Release(output_media_type);
398 output_media_type = NULL;
401 * It's not an error if we don't find the output type we were
402 * looking for, in this case we use the first available type which
403 * is the "preferred" output type for this MFT.
406 hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, output_type_index, &output_media_type);
407 if (FAILED(hr))
408 goto error;
410 hr = IMFTransform_SetOutputType(p_sys->mft, stream_id, output_media_type, 0);
411 if (FAILED(hr))
412 goto error;
414 GUID subtype;
415 hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
416 if (FAILED(hr))
417 goto error;
419 if (p_dec->fmt_in.i_cat == VIDEO_ES)
421 video_format_Copy( &p_dec->fmt_out.video, &p_dec->fmt_in.video );
422 p_dec->fmt_out.i_codec = vlc_fourcc_GetCodec(p_dec->fmt_in.i_cat, subtype.Data1);
424 else
426 p_dec->fmt_out.audio = p_dec->fmt_in.audio;
428 UINT32 bitspersample = 0;
429 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample);
430 if (SUCCEEDED(hr) && bitspersample)
431 p_dec->fmt_out.audio.i_bitspersample = bitspersample;
433 UINT32 channels = 0;
434 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
435 if (SUCCEEDED(hr) && channels)
436 p_dec->fmt_out.audio.i_channels = channels;
438 UINT32 rate = 0;
439 hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
440 if (SUCCEEDED(hr) && rate)
441 p_dec->fmt_out.audio.i_rate = rate;
443 vlc_fourcc_t fourcc;
444 wf_tag_to_fourcc(subtype.Data1, &fourcc, NULL);
445 p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio(fourcc, p_dec->fmt_out.audio.i_bitspersample);
447 p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels];
450 *result = output_media_type;
452 return VLC_SUCCESS;
454 error:
455 msg_Err(p_dec, "Error in SetOutputType()");
456 if (output_media_type)
457 IMFMediaType_Release(output_media_type);
458 return VLC_EGENERIC;
461 static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** result, DWORD size)
463 decoder_sys_t *p_sys = p_dec->p_sys;
464 MFHandle *mf = &p_sys->mf_handle;
465 HRESULT hr;
467 *result = NULL;
469 IMFSample *input_sample = NULL;
471 MFT_INPUT_STREAM_INFO input_info;
472 hr = IMFTransform_GetInputStreamInfo(p_sys->mft, stream_id, &input_info);
473 if (FAILED(hr))
474 goto error;
476 hr = mf->fptr_MFCreateSample(&input_sample);
477 if (FAILED(hr))
478 goto error;
480 IMFMediaBuffer *input_media_buffer = NULL;
481 DWORD allocation_size = __MAX(input_info.cbSize, size);
482 hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &input_media_buffer);
483 if (FAILED(hr))
484 goto error;
486 hr = IMFSample_AddBuffer(input_sample, input_media_buffer);
487 IMFMediaBuffer_Release(input_media_buffer);
488 if (FAILED(hr))
489 goto error;
491 *result = input_sample;
493 return VLC_SUCCESS;
495 error:
496 msg_Err(p_dec, "Error in AllocateInputSample()");
497 if (input_sample)
498 IMFSample_Release(input_sample);
499 if (input_media_buffer)
500 IMFMediaBuffer_Release(input_media_buffer);
501 return VLC_EGENERIC;
504 static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **result)
506 decoder_sys_t *p_sys = p_dec->p_sys;
507 MFHandle *mf = &p_sys->mf_handle;
508 HRESULT hr;
510 *result = NULL;
512 IMFSample *output_sample = NULL;
514 MFT_OUTPUT_STREAM_INFO output_info;
515 hr = IMFTransform_GetOutputStreamInfo(p_sys->mft, stream_id, &output_info);
516 if (FAILED(hr))
517 goto error;
519 if (output_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES))
521 /* The MFT will provide an allocated sample. */
522 return VLC_SUCCESS;
525 DWORD expected_flags = 0;
526 if (p_dec->fmt_in.i_cat == VIDEO_ES)
527 expected_flags |= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
528 | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
529 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
530 if ((output_info.dwFlags & expected_flags) != expected_flags)
531 goto error;
533 hr = mf->fptr_MFCreateSample(&output_sample);
534 if (FAILED(hr))
535 goto error;
537 IMFMediaBuffer *output_media_buffer = NULL;
538 DWORD allocation_size = output_info.cbSize;
539 DWORD alignment = output_info.cbAlignment;
540 if (alignment > 0)
541 hr = mf->fptr_MFCreateAlignedMemoryBuffer(allocation_size, alignment - 1, &output_media_buffer);
542 else
543 hr = mf->fptr_MFCreateMemoryBuffer(allocation_size, &output_media_buffer);
544 if (FAILED(hr))
545 goto error;
547 hr = IMFSample_AddBuffer(output_sample, output_media_buffer);
548 if (FAILED(hr))
549 goto error;
551 *result = output_sample;
553 return VLC_SUCCESS;
555 error:
556 msg_Err(p_dec, "Error in AllocateOutputSample()");
557 if (output_sample)
558 IMFSample_Release(output_sample);
559 return VLC_EGENERIC;
562 static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_block)
564 decoder_sys_t *p_sys = p_dec->p_sys;
565 HRESULT hr;
566 IMFSample *input_sample = NULL;
568 if (AllocateInputSample(p_dec, stream_id, &input_sample, p_block->i_buffer))
569 goto error;
571 IMFMediaBuffer *input_media_buffer = NULL;
572 hr = IMFSample_GetBufferByIndex(input_sample, 0, &input_media_buffer);
573 if (FAILED(hr))
574 goto error;
576 BYTE *buffer_start;
577 hr = IMFMediaBuffer_Lock(input_media_buffer, &buffer_start, NULL, NULL);
578 if (FAILED(hr))
579 goto error;
581 memcpy(buffer_start, p_block->p_buffer, p_block->i_buffer);
583 if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
585 /* in-place NAL to annex B conversion. */
586 h264_AVC_to_AnnexB(buffer_start, p_block->i_buffer, p_sys->nal_length_size);
589 hr = IMFMediaBuffer_Unlock(input_media_buffer);
590 if (FAILED(hr))
591 goto error;
593 hr = IMFMediaBuffer_SetCurrentLength(input_media_buffer, p_block->i_buffer);
594 if (FAILED(hr))
595 goto error;
597 LONGLONG ts = p_block->i_pts;
598 if (!ts && p_block->i_dts)
599 ts = p_block->i_dts;
601 /* Convert from microseconds to 100 nanoseconds unit. */
602 hr = IMFSample_SetSampleTime(input_sample, ts * 10);
603 if (FAILED(hr))
604 goto error;
606 hr = IMFTransform_ProcessInput(p_sys->mft, stream_id, input_sample, 0);
607 if (FAILED(hr))
608 goto error;
610 IMFMediaBuffer_Release(input_media_buffer);
611 IMFSample_Release(input_sample);
613 return VLC_SUCCESS;
615 error:
616 msg_Err(p_dec, "Error in ProcessInputStream()");
617 if (input_sample)
618 IMFSample_Release(input_sample);
619 return VLC_EGENERIC;
622 /* Copy a packed buffer (no padding) to a picture_t */
623 static void CopyPackedBufferToPicture(picture_t *p_pic, const uint8_t *p_src)
625 for (int i = 0; i < p_pic->i_planes; ++i)
627 uint8_t *p_dst = p_pic->p[i].p_pixels;
629 if (p_pic->p[i].i_visible_pitch == p_pic->p[i].i_pitch)
631 /* Plane is packed, only one memcpy is needed. */
632 uint32_t plane_size = p_pic->p[i].i_pitch * p_pic->p[i].i_visible_lines;
633 memcpy(p_dst, p_src, plane_size);
634 p_src += plane_size;
635 continue;
638 for (int i_line = 0; i_line < p_pic->p[i].i_visible_lines; i_line++)
640 memcpy(p_dst, p_src, p_pic->p[i].i_visible_pitch);
641 p_src += p_pic->p[i].i_visible_pitch;
642 p_dst += p_pic->p[i].i_pitch;
647 static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id)
649 decoder_sys_t *p_sys = p_dec->p_sys;
650 HRESULT hr;
651 picture_t *picture = NULL;
652 block_t *aout_buffer = NULL;
654 DWORD output_status = 0;
655 MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
656 hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status);
657 if (output_buffer.pEvents)
658 IMFCollection_Release(output_buffer.pEvents);
659 /* Use the returned sample since it can be provided by the MFT. */
660 IMFSample *output_sample = output_buffer.pSample;
662 if (hr == S_OK)
664 if (!output_sample)
665 return VLC_SUCCESS;
667 LONGLONG sample_time;
668 hr = IMFSample_GetSampleTime(output_sample, &sample_time);
669 if (FAILED(hr))
670 goto error;
671 /* Convert from 100 nanoseconds unit to microseconds. */
672 sample_time /= 10;
674 DWORD total_length = 0;
675 hr = IMFSample_GetTotalLength(output_sample, &total_length);
676 if (FAILED(hr))
677 goto error;
679 if (p_dec->fmt_in.i_cat == VIDEO_ES)
681 if (decoder_UpdateVideoFormat(p_dec))
682 return VLC_SUCCESS;
683 picture = decoder_NewPicture(p_dec);
684 if (!picture)
685 return VLC_SUCCESS;
687 UINT32 interlaced = false;
688 hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced);
689 picture->b_progressive = !interlaced;
691 picture->date = sample_time;
693 else
695 if (decoder_UpdateAudioFormat(p_dec))
696 goto error;
697 if (p_dec->fmt_out.audio.i_bitspersample == 0 || p_dec->fmt_out.audio.i_channels == 0)
698 goto error;
699 int samples = total_length / (p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8);
700 aout_buffer = decoder_NewAudioBuffer(p_dec, samples);
701 if (!aout_buffer)
702 return VLC_SUCCESS;
703 if (aout_buffer->i_buffer < total_length)
704 goto error;
706 aout_buffer->i_pts = sample_time;
709 IMFMediaBuffer *output_media_buffer = NULL;
710 hr = IMFSample_GetBufferByIndex(output_sample, 0, &output_media_buffer);
712 BYTE *buffer_start;
713 hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
714 if (FAILED(hr))
715 goto error;
717 if (p_dec->fmt_in.i_cat == VIDEO_ES)
718 CopyPackedBufferToPicture(picture, buffer_start);
719 else
720 memcpy(aout_buffer->p_buffer, buffer_start, total_length);
722 hr = IMFMediaBuffer_Unlock(output_media_buffer);
723 IMFSample_Release(output_media_buffer);
724 if (FAILED(hr))
725 goto error;
727 if (p_sys->output_sample)
729 /* Sample is not provided by the MFT: clear its content. */
730 hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0);
731 if (FAILED(hr))
732 goto error;
734 else
736 /* Sample is provided by the MFT: decrease refcount. */
737 IMFSample_Release(output_sample);
740 else if (hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_TYPE_NOT_SET)
742 if (p_sys->output_type)
743 IMFMediaType_Release(p_sys->output_type);
744 if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
745 goto error;
747 /* Reallocate output sample. */
748 if (p_sys->output_sample)
749 IMFSample_Release(p_sys->output_sample);
750 p_sys->output_sample = NULL;
751 if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
752 goto error;
753 return VLC_SUCCESS;
755 else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
757 return VLC_SUCCESS;
759 else /* An error not listed above occurred */
761 msg_Err(p_dec, "Unexpected error in IMFTransform::ProcessOutput: %#lx",
762 hr);
763 goto error;
766 if (p_dec->fmt_in.i_cat == VIDEO_ES)
767 decoder_QueueVideo(p_dec, picture);
768 else
769 decoder_QueueAudio(p_dec, aout_buffer);
771 return VLC_SUCCESS;
773 error:
774 msg_Err(p_dec, "Error in ProcessOutputStream()");
775 if (picture)
776 picture_Release(picture);
777 if (aout_buffer)
778 block_Release(aout_buffer);
779 return VLC_EGENERIC;
782 static int DecodeSync(decoder_t *p_dec, block_t *p_block)
784 decoder_sys_t *p_sys = p_dec->p_sys;
786 if (!p_block) /* No Drain */
787 return VLCDEC_SUCCESS;
789 if (p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
791 block_Release(p_block);
792 return VLCDEC_SUCCESS;
795 /* Drain the output stream before sending the input packet. */
796 if (ProcessOutputStream(p_dec, p_sys->output_stream_id))
797 goto error;
798 if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
799 goto error;
800 block_Release(p_block);
802 return VLCDEC_SUCCESS;
804 error:
805 msg_Err(p_dec, "Error in DecodeSync()");
806 block_Release(p_block);
807 return VLCDEC_SUCCESS;
810 static HRESULT DequeueMediaEvent(decoder_t *p_dec)
812 decoder_sys_t *p_sys = p_dec->p_sys;
813 HRESULT hr;
815 IMFMediaEvent *event = NULL;
816 hr = IMFMediaEventGenerator_GetEvent(p_sys->event_generator, MF_EVENT_FLAG_NO_WAIT, &event);
817 if (FAILED(hr))
818 return hr;
819 MediaEventType event_type;
820 hr = IMFMediaEvent_GetType(event, &event_type);
821 IMFMediaEvent_Release(event);
822 if (FAILED(hr))
823 return hr;
825 if (event_type == VLC_METransformNeedInput)
826 p_sys->pending_input_events += 1;
827 else if (event_type == VLC_METransformHaveOutput)
828 p_sys->pending_output_events += 1;
829 else
830 msg_Err(p_dec, "Unsupported asynchronous event.");
832 return S_OK;
835 static int DecodeAsync(decoder_t *p_dec, block_t *p_block)
837 decoder_sys_t *p_sys = p_dec->p_sys;
838 HRESULT hr;
840 if (!p_block) /* No Drain */
841 return VLCDEC_SUCCESS;
843 if (p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
845 block_Release(p_block);
846 return VLCDEC_SUCCESS;
849 /* Dequeue all pending media events. */
850 while ((hr = DequeueMediaEvent(p_dec)) == S_OK)
851 continue;
852 if (hr != MF_E_NO_EVENTS_AVAILABLE && FAILED(hr))
853 goto error;
855 /* Drain the output stream of the MFT before sending the input packet. */
856 if (p_sys->pending_output_events > 0)
858 p_sys->pending_output_events -= 1;
859 if (ProcessOutputStream(p_dec, p_sys->output_stream_id))
860 goto error;
863 /* Poll the MFT and return decoded frames until the input stream is ready. */
864 while (p_sys->pending_input_events == 0)
866 hr = DequeueMediaEvent(p_dec);
867 if (hr == MF_E_NO_EVENTS_AVAILABLE)
869 /* Sleep for 1 ms to avoid excessive polling. */
870 Sleep(1);
871 continue;
873 if (FAILED(hr))
874 goto error;
876 if (p_sys->pending_output_events > 0)
878 p_sys->pending_output_events -= 1;
879 if (ProcessOutputStream(p_dec, p_sys->output_stream_id))
880 goto error;
881 break;
885 p_sys->pending_input_events -= 1;
886 if (ProcessInputStream(p_dec, p_sys->input_stream_id, p_block))
887 goto error;
889 block_Release(p_block);
891 return VLCDEC_SUCCESS;
893 error:
894 msg_Err(p_dec, "Error in DecodeAsync()");
895 block_Release(p_block);
896 return VLCDEC_SUCCESS;
899 static void DestroyMFT(decoder_t *p_dec);
901 static int InitializeMFT(decoder_t *p_dec)
903 decoder_sys_t *p_sys = p_dec->p_sys;
904 HRESULT hr;
906 IMFAttributes *attributes = NULL;
907 hr = IMFTransform_GetAttributes(p_sys->mft, &attributes);
908 if (hr != E_NOTIMPL && FAILED(hr))
909 goto error;
910 if (SUCCEEDED(hr))
912 UINT32 is_async = false;
913 hr = IMFAttributes_GetUINT32(attributes, &MF_TRANSFORM_ASYNC, &is_async);
914 if (hr != MF_E_ATTRIBUTENOTFOUND && FAILED(hr))
915 goto error;
916 p_sys->is_async = is_async;
917 if (p_sys->is_async)
919 hr = IMFAttributes_SetUINT32(attributes, &MF_TRANSFORM_ASYNC_UNLOCK, true);
920 if (FAILED(hr))
921 goto error;
922 hr = IMFTransform_QueryInterface(p_sys->mft, &IID_IMFMediaEventGenerator, (void**)&p_sys->event_generator);
923 if (FAILED(hr))
924 goto error;
928 DWORD input_streams_count;
929 DWORD output_streams_count;
930 hr = IMFTransform_GetStreamCount(p_sys->mft, &input_streams_count, &output_streams_count);
931 if (FAILED(hr))
932 goto error;
933 if (input_streams_count != 1 || output_streams_count != 1)
935 msg_Err(p_dec, "MFT decoder should have 1 input stream and 1 output stream.");
936 goto error;
939 hr = IMFTransform_GetStreamIDs(p_sys->mft, 1, &p_sys->input_stream_id, 1, &p_sys->output_stream_id);
940 if (hr == E_NOTIMPL)
943 * This is not an error, it happens if:
944 * - there is a fixed number of streams.
945 * AND
946 * - streams are numbered consecutively from 0 to N-1.
948 p_sys->input_stream_id = 0;
949 p_sys->output_stream_id = 0;
951 else if (FAILED(hr))
952 goto error;
954 if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type))
955 goto error;
957 if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
958 goto error;
961 * The input type was not set by the previous call to
962 * SetInputType, try again after setting the output type.
964 if (!p_sys->input_type)
965 if (SetInputType(p_dec, p_sys->input_stream_id, &p_sys->input_type) || !p_sys->input_type)
966 goto error;
968 /* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
969 hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, (ULONG_PTR)0);
970 if (FAILED(hr))
971 goto error;
973 /* This event is required for asynchronous MFTs, optional otherwise. */
974 hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, (ULONG_PTR)0);
975 if (FAILED(hr))
976 goto error;
978 if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
980 /* It's not an error if the following call fails. */
981 IMFAttributes_SetUINT32(attributes, &CODECAPI_AVLowLatencyMode, true);
983 if (p_dec->fmt_in.i_extra)
985 if (h264_isavcC((uint8_t*)p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra))
987 size_t i_buf;
988 uint8_t *buf = h264_avcC_to_AnnexB_NAL(p_dec->fmt_in.p_extra,
989 p_dec->fmt_in.i_extra,
990 &i_buf, &p_sys->nal_length_size);
991 if(buf)
993 free(p_dec->fmt_in.p_extra);
994 p_dec->fmt_in.p_extra = buf;
995 p_dec->fmt_in.i_extra = i_buf;
1000 return VLC_SUCCESS;
1002 error:
1003 msg_Err(p_dec, "Error in InitializeMFT()");
1004 DestroyMFT(p_dec);
1005 return VLC_EGENERIC;
1008 static void DestroyMFT(decoder_t *p_dec)
1010 decoder_sys_t *p_sys = p_dec->p_sys;
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)
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);
1024 if (p_sys->output_type)
1025 IMFMediaType_Release(p_sys->output_type);
1026 if (p_sys->mft)
1027 IMFTransform_Release(p_sys->mft);
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;
1036 static int FindMFT(decoder_t *p_dec)
1038 decoder_sys_t *p_sys = p_dec->p_sys;
1039 MFHandle *mf = &p_sys->mf_handle;
1040 HRESULT hr;
1042 /* Try to create a MFT using MFTEnumEx. */
1043 GUID category;
1044 if (p_dec->fmt_in.i_cat == VIDEO_ES)
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);
1050 else
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);
1056 if (!p_sys->subtype)
1057 return VLC_EGENERIC;
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;
1069 msg_Dbg(p_dec, "Found %d available MFT module(s)", activate_objects_count);
1070 if (activate_objects_count == 0)
1071 return VLC_EGENERIC;
1073 for (UINT32 i = 0; i < activate_objects_count; ++i)
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;
1080 if (InitializeMFT(p_dec) == VLC_SUCCESS)
1082 CoTaskMemFree(activate_objects);
1083 return VLC_SUCCESS;
1086 CoTaskMemFree(activate_objects);
1088 return VLC_EGENERIC;
1091 static int LoadMFTLibrary(MFHandle *mf)
1093 #if _WIN32_WINNT < _WIN32_WINNT_WIN7 || VLC_WINSTORE_APP
1094 mf->mfplat_dll = LoadLibrary(TEXT("mfplat.dll"));
1095 if (!mf->mfplat_dll)
1096 return VLC_EGENERIC;
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
1111 return VLC_SUCCESS;
1114 static int Open(vlc_object_t *p_this)
1116 decoder_t *p_dec = (decoder_t *)p_this;
1117 decoder_sys_t *p_sys;
1119 p_sys = p_dec->p_sys = calloc(1, sizeof(*p_sys));
1120 if (!p_sys)
1121 return VLC_ENOMEM;
1123 if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
1124 vlc_assert_unreachable();
1126 if (LoadMFTLibrary(&p_sys->mf_handle))
1128 msg_Err(p_dec, "Failed to load MFT library.");
1129 goto error;
1132 if (FindMFT(p_dec))
1134 msg_Err(p_dec, "Could not find suitable MFT decoder");
1135 goto error;
1138 /* Only one output sample is needed, we can allocate one and reuse it. */
1139 if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
1140 goto error;
1142 p_dec->pf_decode = p_sys->is_async ? DecodeAsync : DecodeSync;
1144 return VLC_SUCCESS;
1146 error:
1147 Close(p_this);
1148 return VLC_EGENERIC;
1151 static void Close(vlc_object_t *p_this)
1153 decoder_t *p_dec = (decoder_t *)p_this;
1154 decoder_sys_t *p_sys = p_dec->p_sys;
1155 MFHandle *mf = &p_sys->mf_handle;
1157 DestroyMFT(p_dec);
1159 if (mf->mfplat_dll)
1160 FreeLibrary(mf->mfplat_dll);
1162 free(p_sys);
1164 CoUninitialize();