mirror of
https://code.videolan.org/videolan/vlc
synced 2024-09-12 13:44:56 +02:00
mft: compile as C++ so we can use some more headers
Using COM interfaces is better in C++ anyway. It also makes it usable with the GDK (Xbox).
This commit is contained in:
parent
37e7fa05c8
commit
7bd3788c2e
@ -590,7 +590,7 @@ codec_LTLIBRARIES += libdmo_plugin.la
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libmft_plugin_la_SOURCES = codec/mft.c
|
libmft_plugin_la_SOURCES = codec/mft.cpp
|
||||||
if HAVE_WIN32
|
if HAVE_WIN32
|
||||||
libmft_plugin_la_LIBADD = $(LIBCOM) -luuid -lmfuuid -lmfplat libvlc_hxxxhelper.la
|
libmft_plugin_la_LIBADD = $(LIBCOM) -luuid -lmfuuid -lmfplat libvlc_hxxxhelper.la
|
||||||
codec_LTLIBRARIES += libmft_plugin.la
|
codec_LTLIBRARIES += libmft_plugin.la
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* mft.c : Media Foundation Transform audio/video decoder
|
* mft.cpp : Media Foundation Transform audio/video decoder
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* Copyright (C) 2014 VLC authors and VideoLAN
|
* Copyright (C) 2014 VLC authors and VideoLAN
|
||||||
*
|
*
|
||||||
@ -33,9 +33,10 @@
|
|||||||
#include <vlc_common.h>
|
#include <vlc_common.h>
|
||||||
#include <vlc_plugin.h>
|
#include <vlc_plugin.h>
|
||||||
#include <vlc_codec.h>
|
#include <vlc_codec.h>
|
||||||
|
extern "C" {
|
||||||
#include "hxxx_helper.h"
|
#include "hxxx_helper.h"
|
||||||
|
}
|
||||||
|
|
||||||
#define COBJMACROS
|
|
||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
#include <mfapi.h>
|
#include <mfapi.h>
|
||||||
#include <mftransform.h>
|
#include <mftransform.h>
|
||||||
@ -46,6 +47,8 @@
|
|||||||
#define _VIDEOINFOHEADER_
|
#define _VIDEOINFOHEADER_
|
||||||
#include <vlc_codecs.h>
|
#include <vlc_codecs.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
static int Open(vlc_object_t *);
|
static int Open(vlc_object_t *);
|
||||||
static void Close(vlc_object_t *);
|
static void Close(vlc_object_t *);
|
||||||
|
|
||||||
@ -196,10 +199,10 @@ static const GUID *FormatToGUID(const pair_format_guid table[], vlc_fourcc_t fou
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static vlc_fourcc_t GUIDToFormat(const pair_format_guid table[], const GUID* guid)
|
static vlc_fourcc_t GUIDToFormat(const pair_format_guid table[], const GUID & guid)
|
||||||
{
|
{
|
||||||
for (int i = 0; table[i].fourcc; ++i)
|
for (int i = 0; table[i].fourcc; ++i)
|
||||||
if (IsEqualGUID(table[i].guid, guid))
|
if (IsEqualGUID(*table[i].guid, guid))
|
||||||
return table[i].fourcc;
|
return table[i].fourcc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -215,7 +218,7 @@ DEFINE_GUID(CODECAPI_AVLowLatencyMode, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0
|
|||||||
|
|
||||||
static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
|
static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
@ -227,7 +230,7 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; !found; ++i)
|
for (int i = 0; !found; ++i)
|
||||||
{
|
{
|
||||||
hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, i, &input_media_type);
|
hr = p_sys->mft->GetInputAvailableType(stream_id, i, &input_media_type);
|
||||||
if (hr == MF_E_NO_MORE_TYPES)
|
if (hr == MF_E_NO_MORE_TYPES)
|
||||||
break;
|
break;
|
||||||
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
|
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
|
||||||
@ -239,23 +242,23 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
GUID subtype;
|
GUID subtype;
|
||||||
hr = IMFMediaType_GetGUID(input_media_type, &MF_MT_SUBTYPE, &subtype);
|
hr = input_media_type->GetGUID(MF_MT_SUBTYPE, &subtype);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (IsEqualGUID(&subtype, p_sys->subtype))
|
if (IsEqualGUID(subtype, *p_sys->subtype))
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
input_type_index = i;
|
input_type_index = i;
|
||||||
|
|
||||||
IMFMediaType_Release(input_media_type);
|
input_media_type->Release();
|
||||||
input_media_type = NULL;
|
input_media_type = NULL;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFTransform_GetInputAvailableType(p_sys->mft, stream_id, input_type_index, &input_media_type);
|
hr = p_sys->mft->GetInputAvailableType(stream_id, input_type_index, &input_media_type);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -264,7 +267,7 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
UINT64 width = p_dec->fmt_in.video.i_width;
|
UINT64 width = p_dec->fmt_in.video.i_width;
|
||||||
UINT64 height = p_dec->fmt_in.video.i_height;
|
UINT64 height = p_dec->fmt_in.video.i_height;
|
||||||
UINT64 frame_size = (width << 32) | height;
|
UINT64 frame_size = (width << 32) | height;
|
||||||
hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_SIZE, frame_size);
|
hr = input_media_type->SetUINT64(MF_MT_FRAME_SIZE, frame_size);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -273,43 +276,43 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
UINT64 frame_ratio_dem = p_dec->fmt_in.video.i_frame_rate_base;
|
UINT64 frame_ratio_dem = p_dec->fmt_in.video.i_frame_rate_base;
|
||||||
if(frame_ratio_num && frame_ratio_dem) {
|
if(frame_ratio_num && frame_ratio_dem) {
|
||||||
UINT64 frame_rate = (frame_ratio_num << 32) | frame_ratio_dem;
|
UINT64 frame_rate = (frame_ratio_num << 32) | frame_ratio_dem;
|
||||||
hr = IMFMediaType_SetUINT64(input_media_type, &MF_MT_FRAME_RATE, frame_rate);
|
hr = input_media_type->SetUINT64(MF_MT_FRAME_RATE, frame_rate);
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1);
|
hr = input_media_type->SetUINT32(MF_MT_ORIGINAL_WAVE_FORMAT_TAG, p_sys->subtype->Data1);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
if (p_dec->fmt_in.audio.i_rate)
|
if (p_dec->fmt_in.audio.i_rate)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate);
|
hr = input_media_type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, p_dec->fmt_in.audio.i_rate);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (p_dec->fmt_in.audio.i_channels)
|
if (p_dec->fmt_in.audio.i_channels)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels);
|
hr = input_media_type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, p_dec->fmt_in.audio.i_channels);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (p_dec->fmt_in.audio.i_bitspersample)
|
if (p_dec->fmt_in.audio.i_bitspersample)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample);
|
hr = input_media_type->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, p_dec->fmt_in.audio.i_bitspersample);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (p_dec->fmt_in.audio.i_blockalign)
|
if (p_dec->fmt_in.audio.i_blockalign)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign);
|
hr = input_media_type->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, p_dec->fmt_in.audio.i_blockalign);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (p_dec->fmt_in.i_bitrate)
|
if (p_dec->fmt_in.i_bitrate)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetUINT32(input_media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8);
|
hr = input_media_type->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, p_dec->fmt_in.i_bitrate / 8);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -318,21 +321,21 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
if (p_dec->fmt_in.i_extra > 0)
|
if (p_dec->fmt_in.i_extra > 0)
|
||||||
{
|
{
|
||||||
UINT32 blob_size = 0;
|
UINT32 blob_size = 0;
|
||||||
hr = IMFMediaType_GetBlobSize(input_media_type, &MF_MT_USER_DATA, &blob_size);
|
hr = input_media_type->GetBlobSize(MF_MT_USER_DATA, &blob_size);
|
||||||
/*
|
/*
|
||||||
* Do not overwrite existing user data in the input type, this
|
* Do not overwrite existing user data in the input type, this
|
||||||
* can cause the MFT to reject the type.
|
* can cause the MFT to reject the type.
|
||||||
*/
|
*/
|
||||||
if (hr == MF_E_ATTRIBUTENOTFOUND)
|
if (hr == MF_E_ATTRIBUTENOTFOUND)
|
||||||
{
|
{
|
||||||
hr = IMFMediaType_SetBlob(input_media_type, &MF_MT_USER_DATA,
|
hr = input_media_type->SetBlob(MF_MT_USER_DATA,
|
||||||
p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
|
static_cast<const UINT8*>(p_dec->fmt_in.p_extra), p_dec->fmt_in.i_extra);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IMFTransform_SetInputType(p_sys->mft, stream_id, input_media_type, 0);
|
hr = p_sys->mft->SetInputType(stream_id, input_media_type, 0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -343,13 +346,13 @@ static int SetInputType(decoder_t *p_dec, DWORD stream_id, IMFMediaType **result
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in SetInputType()");
|
msg_Err(p_dec, "Error in SetInputType()");
|
||||||
if (input_media_type)
|
if (input_media_type)
|
||||||
IMFMediaType_Release(input_media_type);
|
input_media_type->Release();
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
IMFMediaType *output_media_type = NULL;
|
IMFMediaType *output_media_type = NULL;
|
||||||
@ -363,7 +366,7 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; !found; ++i)
|
for (int i = 0; !found; ++i)
|
||||||
{
|
{
|
||||||
hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, i, &output_media_type);
|
hr = p_sys->mft->GetOutputAvailableType(stream_id, i, &output_media_type);
|
||||||
if (hr == MF_E_NO_MORE_TYPES)
|
if (hr == MF_E_NO_MORE_TYPES)
|
||||||
break;
|
break;
|
||||||
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
|
else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET)
|
||||||
@ -375,33 +378,33 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
GUID subtype;
|
GUID subtype;
|
||||||
hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
|
hr = output_media_type->GetGUID(MF_MT_SUBTYPE, &subtype);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (p_dec->fmt_in.i_cat == VIDEO_ES)
|
if (p_dec->fmt_in.i_cat == VIDEO_ES)
|
||||||
{
|
{
|
||||||
if (IsEqualGUID(&subtype, &MFVideoFormat_NV12) || IsEqualGUID(&subtype, &MFVideoFormat_YV12) || IsEqualGUID(&subtype, &MFVideoFormat_I420))
|
if (IsEqualGUID(subtype, MFVideoFormat_NV12) || IsEqualGUID(subtype, MFVideoFormat_YV12) || IsEqualGUID(subtype, MFVideoFormat_I420))
|
||||||
found = true;
|
found = true;
|
||||||
/* Transform might offer output in a D3DFMT proprietary FCC. If we can
|
/* Transform might offer output in a D3DFMT proprietary FCC. If we can
|
||||||
* use it, fall back to it in case we do not find YV12 or I420 */
|
* use it, fall back to it in case we do not find YV12 or I420 */
|
||||||
else if(output_type_index < 0 && GUIDToFormat(d3d_format_table, &subtype) > 0)
|
else if(output_type_index < 0 && GUIDToFormat(d3d_format_table, subtype) > 0)
|
||||||
output_type_index = i;
|
output_type_index = i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UINT32 bits_per_sample;
|
UINT32 bits_per_sample;
|
||||||
hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
|
hr = output_media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
continue;
|
continue;
|
||||||
if (bits_per_sample == 32 && IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
if (bits_per_sample == 32 && IsEqualGUID(subtype, MFAudioFormat_Float))
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
output_type_index = i;
|
output_type_index = i;
|
||||||
|
|
||||||
IMFMediaType_Release(output_media_type);
|
output_media_type->Release();
|
||||||
output_media_type = NULL;
|
output_media_type = NULL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -413,16 +416,16 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
* by the MFT */
|
* by the MFT */
|
||||||
output_type_index = 0;
|
output_type_index = 0;
|
||||||
|
|
||||||
hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id, output_type_index, &output_media_type);
|
hr = p_sys->mft->GetOutputAvailableType(stream_id, output_type_index, &output_media_type);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFTransform_SetOutputType(p_sys->mft, stream_id, output_media_type, 0);
|
hr = p_sys->mft->SetOutputType(stream_id, output_media_type, 0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
GUID subtype;
|
GUID subtype;
|
||||||
hr = IMFMediaType_GetGUID(output_media_type, &MF_MT_SUBTYPE, &subtype);
|
hr = output_media_type->GetGUID(MF_MT_SUBTYPE, &subtype);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -431,7 +434,7 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
video_format_Copy( &p_dec->fmt_out.video, &p_dec->fmt_in.video );
|
video_format_Copy( &p_dec->fmt_out.video, &p_dec->fmt_in.video );
|
||||||
|
|
||||||
/* Transform might offer output in a D3DFMT proprietary FCC */
|
/* Transform might offer output in a D3DFMT proprietary FCC */
|
||||||
vlc_fourcc_t fcc = GUIDToFormat(d3d_format_table, &subtype);
|
vlc_fourcc_t fcc = GUIDToFormat(d3d_format_table, subtype);
|
||||||
if(fcc) {
|
if(fcc) {
|
||||||
/* D3D formats are upside down */
|
/* D3D formats are upside down */
|
||||||
p_dec->fmt_out.video.orientation = ORIENT_BOTTOM_LEFT;
|
p_dec->fmt_out.video.orientation = ORIENT_BOTTOM_LEFT;
|
||||||
@ -446,17 +449,17 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
p_dec->fmt_out.audio = p_dec->fmt_in.audio;
|
p_dec->fmt_out.audio = p_dec->fmt_in.audio;
|
||||||
|
|
||||||
UINT32 bitspersample = 0;
|
UINT32 bitspersample = 0;
|
||||||
hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample);
|
hr = output_media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bitspersample);
|
||||||
if (SUCCEEDED(hr) && bitspersample)
|
if (SUCCEEDED(hr) && bitspersample)
|
||||||
p_dec->fmt_out.audio.i_bitspersample = bitspersample;
|
p_dec->fmt_out.audio.i_bitspersample = bitspersample;
|
||||||
|
|
||||||
UINT32 channels = 0;
|
UINT32 channels = 0;
|
||||||
hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
|
hr = output_media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channels);
|
||||||
if (SUCCEEDED(hr) && channels)
|
if (SUCCEEDED(hr) && channels)
|
||||||
p_dec->fmt_out.audio.i_channels = channels;
|
p_dec->fmt_out.audio.i_channels = channels;
|
||||||
|
|
||||||
UINT32 rate = 0;
|
UINT32 rate = 0;
|
||||||
hr = IMFMediaType_GetUINT32(output_media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
|
hr = output_media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
|
||||||
if (SUCCEEDED(hr) && rate)
|
if (SUCCEEDED(hr) && rate)
|
||||||
p_dec->fmt_out.audio.i_rate = rate;
|
p_dec->fmt_out.audio.i_rate = rate;
|
||||||
|
|
||||||
@ -472,22 +475,23 @@ static int SetOutputType(decoder_t *p_dec, DWORD stream_id)
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in SetOutputType()");
|
msg_Err(p_dec, "Error in SetOutputType()");
|
||||||
if (output_media_type)
|
if (output_media_type)
|
||||||
IMFMediaType_Release(output_media_type);
|
output_media_type->Release();
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** result, DWORD size)
|
static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** result, DWORD size)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
|
|
||||||
IMFSample *input_sample = NULL;
|
IMFSample *input_sample = NULL;
|
||||||
IMFMediaBuffer *input_media_buffer = NULL;
|
IMFMediaBuffer *input_media_buffer = NULL;
|
||||||
|
DWORD allocation_size;
|
||||||
|
|
||||||
MFT_INPUT_STREAM_INFO input_info;
|
MFT_INPUT_STREAM_INFO input_info;
|
||||||
hr = IMFTransform_GetInputStreamInfo(p_sys->mft, stream_id, &input_info);
|
hr = p_sys->mft->GetInputStreamInfo(stream_id, &input_info);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -495,13 +499,13 @@ static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** re
|
|||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
DWORD allocation_size = __MAX(input_info.cbSize, size);
|
allocation_size = __MAX(input_info.cbSize, size);
|
||||||
hr = MFCreateMemoryBuffer(allocation_size, &input_media_buffer);
|
hr = MFCreateMemoryBuffer(allocation_size, &input_media_buffer);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFSample_AddBuffer(input_sample, input_media_buffer);
|
hr = input_sample->AddBuffer(input_media_buffer);
|
||||||
IMFMediaBuffer_Release(input_media_buffer);
|
input_media_buffer->Release();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -512,15 +516,15 @@ static int AllocateInputSample(decoder_t *p_dec, DWORD stream_id, IMFSample** re
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in AllocateInputSample()");
|
msg_Err(p_dec, "Error in AllocateInputSample()");
|
||||||
if (input_sample)
|
if (input_sample)
|
||||||
IMFSample_Release(input_sample);
|
input_sample->Release();
|
||||||
if (input_media_buffer)
|
if (input_media_buffer)
|
||||||
IMFMediaBuffer_Release(input_media_buffer);
|
input_media_buffer->Release();
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **result)
|
static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **result)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
@ -528,7 +532,11 @@ static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **r
|
|||||||
IMFSample *output_sample = NULL;
|
IMFSample *output_sample = NULL;
|
||||||
|
|
||||||
MFT_OUTPUT_STREAM_INFO output_info;
|
MFT_OUTPUT_STREAM_INFO output_info;
|
||||||
hr = IMFTransform_GetOutputStreamInfo(p_sys->mft, stream_id, &output_info);
|
IMFMediaBuffer *output_media_buffer = NULL;
|
||||||
|
DWORD allocation_size;
|
||||||
|
DWORD alignment;
|
||||||
|
|
||||||
|
hr = p_sys->mft->GetOutputStreamInfo(stream_id, &output_info);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -552,9 +560,8 @@ static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **r
|
|||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
IMFMediaBuffer *output_media_buffer = NULL;
|
allocation_size = output_info.cbSize;
|
||||||
DWORD allocation_size = output_info.cbSize;
|
alignment = output_info.cbAlignment;
|
||||||
DWORD alignment = output_info.cbAlignment;
|
|
||||||
if (alignment > 0)
|
if (alignment > 0)
|
||||||
hr = MFCreateAlignedMemoryBuffer(allocation_size, alignment - 1, &output_media_buffer);
|
hr = MFCreateAlignedMemoryBuffer(allocation_size, alignment - 1, &output_media_buffer);
|
||||||
else
|
else
|
||||||
@ -562,7 +569,7 @@ static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **r
|
|||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFSample_AddBuffer(output_sample, output_media_buffer);
|
hr = output_sample->AddBuffer(output_media_buffer);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -573,18 +580,20 @@ static int AllocateOutputSample(decoder_t *p_dec, DWORD stream_id, IMFSample **r
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in AllocateOutputSample()");
|
msg_Err(p_dec, "Error in AllocateOutputSample()");
|
||||||
if (output_sample)
|
if (output_sample)
|
||||||
IMFSample_Release(output_sample);
|
output_sample->Release();
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_block)
|
static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_block)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
IMFSample *input_sample = NULL;
|
IMFSample *input_sample = NULL;
|
||||||
|
|
||||||
block_t *p_xps_blocks = NULL;
|
block_t *p_xps_blocks = NULL;
|
||||||
DWORD alloc_size = p_block->i_buffer;
|
DWORD alloc_size = p_block->i_buffer;
|
||||||
|
vlc_tick_t ts;
|
||||||
|
IMFMediaBuffer *input_media_buffer = NULL;
|
||||||
|
|
||||||
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
||||||
{
|
{
|
||||||
@ -606,13 +615,12 @@ static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_bloc
|
|||||||
if (AllocateInputSample(p_dec, stream_id, &input_sample, alloc_size))
|
if (AllocateInputSample(p_dec, stream_id, &input_sample, alloc_size))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
IMFMediaBuffer *input_media_buffer = NULL;
|
hr = input_sample->GetBufferByIndex(0, &input_media_buffer);
|
||||||
hr = IMFSample_GetBufferByIndex(input_sample, 0, &input_media_buffer);
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
BYTE *buffer_start;
|
BYTE *buffer_start;
|
||||||
hr = IMFMediaBuffer_Lock(input_media_buffer, &buffer_start, NULL, NULL);
|
hr = input_media_buffer->Lock(&buffer_start, NULL, NULL);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -622,30 +630,30 @@ static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_bloc
|
|||||||
}
|
}
|
||||||
memcpy(buffer_start, p_block->p_buffer, p_block->i_buffer);
|
memcpy(buffer_start, p_block->p_buffer, p_block->i_buffer);
|
||||||
|
|
||||||
hr = IMFMediaBuffer_Unlock(input_media_buffer);
|
hr = input_media_buffer->Unlock();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFMediaBuffer_SetCurrentLength(input_media_buffer, p_block->i_buffer);
|
hr = input_media_buffer->SetCurrentLength(p_block->i_buffer);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
vlc_tick_t ts = p_block->i_pts == VLC_TICK_INVALID ? p_block->i_dts : p_block->i_pts;
|
ts = p_block->i_pts == VLC_TICK_INVALID ? p_block->i_dts : p_block->i_pts;
|
||||||
|
|
||||||
/* Convert from microseconds to 100 nanoseconds unit. */
|
/* Convert from microseconds to 100 nanoseconds unit. */
|
||||||
hr = IMFSample_SetSampleTime(input_sample, MSFTIME_FROM_VLC_TICK(ts));
|
hr = input_sample->SetSampleTime(MSFTIME_FROM_VLC_TICK(ts));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
hr = IMFTransform_ProcessInput(p_sys->mft, stream_id, input_sample, 0);
|
hr = p_sys->mft->ProcessInput(stream_id, input_sample, 0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
msg_Dbg(p_dec, "Failed to process input stream %lu (error 0x%lX)", stream_id, hr);
|
msg_Dbg(p_dec, "Failed to process input stream %lu (error 0x%lX)", stream_id, hr);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMFMediaBuffer_Release(input_media_buffer);
|
input_media_buffer->Release();
|
||||||
IMFSample_Release(input_sample);
|
input_sample->Release();
|
||||||
block_ChainRelease(p_xps_blocks);
|
block_ChainRelease(p_xps_blocks);
|
||||||
|
|
||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
@ -653,7 +661,7 @@ static int ProcessInputStream(decoder_t *p_dec, DWORD stream_id, block_t *p_bloc
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in ProcessInputStream(). (hr=0x%lX)\n", hr);
|
msg_Err(p_dec, "Error in ProcessInputStream(). (hr=0x%lX)\n", hr);
|
||||||
if (input_sample)
|
if (input_sample)
|
||||||
IMFSample_Release(input_sample);
|
input_sample->Release();
|
||||||
block_ChainRelease(p_xps_blocks);
|
block_ChainRelease(p_xps_blocks);
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
@ -683,23 +691,23 @@ static void CopyPackedBufferToPicture(picture_t *p_pic, const uint8_t *p_src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_reading)
|
static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool & keep_reading)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
picture_t *picture = NULL;
|
picture_t *picture = NULL;
|
||||||
block_t *aout_buffer = NULL;
|
block_t *aout_buffer = NULL;
|
||||||
|
|
||||||
DWORD output_status = 0;
|
DWORD output_status = 0;
|
||||||
MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
|
MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
|
||||||
hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status);
|
hr = p_sys->mft->ProcessOutput(0, 1, &output_buffer, &output_status);
|
||||||
if (output_buffer.pEvents)
|
if (output_buffer.pEvents)
|
||||||
IMFCollection_Release(output_buffer.pEvents);
|
output_buffer.pEvents->Release();
|
||||||
/* Use the returned sample since it can be provided by the MFT. */
|
/* Use the returned sample since it can be provided by the MFT. */
|
||||||
IMFSample *output_sample = output_buffer.pSample;
|
IMFSample *output_sample = output_buffer.pSample;
|
||||||
IMFMediaBuffer *output_media_buffer = NULL;
|
IMFMediaBuffer *output_media_buffer = NULL;
|
||||||
|
|
||||||
*keep_reading = false;
|
keep_reading = false;
|
||||||
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
|
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
|
||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
|
|
||||||
@ -709,20 +717,20 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
|
|
||||||
LONGLONG sample_time;
|
LONGLONG sample_time;
|
||||||
hr = IMFSample_GetSampleTime(output_sample, &sample_time);
|
hr = output_sample->GetSampleTime(&sample_time);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
/* Convert from 100 nanoseconds unit to microseconds. */
|
/* Convert from 100 nanoseconds unit to microseconds. */
|
||||||
vlc_tick_t samp_time = VLC_TICK_FROM_MSFTIME(sample_time);
|
vlc_tick_t samp_time = VLC_TICK_FROM_MSFTIME(sample_time);
|
||||||
|
|
||||||
DWORD output_count = 0;
|
DWORD output_count = 0;
|
||||||
hr = IMFSample_GetBufferCount(output_sample, &output_count);
|
hr = output_sample->GetBufferCount(&output_count);
|
||||||
if (unlikely(FAILED(hr)))
|
if (unlikely(FAILED(hr)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
for (DWORD buf_index = 0; buf_index < output_count; buf_index++)
|
for (DWORD buf_index = 0; buf_index < output_count; buf_index++)
|
||||||
{
|
{
|
||||||
hr = IMFSample_GetBufferByIndex(output_sample, buf_index, &output_media_buffer);
|
hr = output_sample->GetBufferByIndex(buf_index, &output_media_buffer);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -735,7 +743,7 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
|
|
||||||
UINT32 interlaced = false;
|
UINT32 interlaced = false;
|
||||||
hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced);
|
hr = output_sample->GetUINT32(MFSampleExtension_Interlaced, &interlaced);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
picture->b_progressive = true;
|
picture->b_progressive = true;
|
||||||
else
|
else
|
||||||
@ -744,13 +752,13 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
picture->date = samp_time;
|
picture->date = samp_time;
|
||||||
|
|
||||||
BYTE *buffer_start;
|
BYTE *buffer_start;
|
||||||
hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
|
hr = output_media_buffer->Lock(&buffer_start, NULL, NULL);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
CopyPackedBufferToPicture(picture, buffer_start);
|
CopyPackedBufferToPicture(picture, buffer_start);
|
||||||
|
|
||||||
hr = IMFMediaBuffer_Unlock(output_media_buffer);
|
hr = output_media_buffer->Unlock();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -764,7 +772,7 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
DWORD total_length = 0;
|
DWORD total_length = 0;
|
||||||
hr = IMFSample_GetTotalLength(output_sample, &total_length);
|
hr = output_sample->GetTotalLength(&total_length);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -778,13 +786,13 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
aout_buffer->i_pts = samp_time;
|
aout_buffer->i_pts = samp_time;
|
||||||
|
|
||||||
BYTE *buffer_start;
|
BYTE *buffer_start;
|
||||||
hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
|
hr = output_media_buffer->Lock(&buffer_start, NULL, NULL);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
memcpy(aout_buffer->p_buffer, buffer_start, total_length);
|
memcpy(aout_buffer->p_buffer, buffer_start, total_length);
|
||||||
|
|
||||||
hr = IMFMediaBuffer_Unlock(output_media_buffer);
|
hr = output_media_buffer->Unlock();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -794,22 +802,22 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
if (p_sys->output_sample)
|
if (p_sys->output_sample)
|
||||||
{
|
{
|
||||||
/* Sample is not provided by the MFT: clear its content. */
|
/* Sample is not provided by the MFT: clear its content. */
|
||||||
hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0);
|
hr = output_media_buffer->SetCurrentLength(0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMFMediaBuffer_Release(output_media_buffer);
|
output_media_buffer->Release();
|
||||||
output_media_buffer = NULL;
|
output_media_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_sys->output_sample)
|
if (!p_sys->output_sample)
|
||||||
{
|
{
|
||||||
/* Sample is provided by the MFT: decrease refcount. */
|
/* Sample is provided by the MFT: decrease refcount. */
|
||||||
IMFSample_Release(output_sample);
|
output_sample->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
*keep_reading = true;
|
keep_reading = true;
|
||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,13 +829,13 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
/* Reallocate output sample. */
|
/* Reallocate output sample. */
|
||||||
if (p_sys->output_sample)
|
if (p_sys->output_sample)
|
||||||
{
|
{
|
||||||
IMFSample_Release(p_sys->output_sample);
|
p_sys->output_sample->Release();
|
||||||
p_sys->output_sample = NULL;
|
p_sys->output_sample = NULL;
|
||||||
}
|
}
|
||||||
if (AllocateOutputSample(p_dec, p_sys->output_stream_id, &p_sys->output_sample))
|
if (AllocateOutputSample(p_dec, p_sys->output_stream_id, &p_sys->output_sample))
|
||||||
goto error;
|
goto error;
|
||||||
// there's an output ready, keep trying
|
// there's an output ready, keep trying
|
||||||
*keep_reading = hr == MF_E_TRANSFORM_STREAM_CHANGE;
|
keep_reading = hr == MF_E_TRANSFORM_STREAM_CHANGE;
|
||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,7 +845,7 @@ static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id, bool *keep_rea
|
|||||||
error:
|
error:
|
||||||
msg_Err(p_dec, "Error in ProcessOutputStream()");
|
msg_Err(p_dec, "Error in ProcessOutputStream()");
|
||||||
if (output_media_buffer)
|
if (output_media_buffer)
|
||||||
IMFMediaBuffer_Release(output_media_buffer);
|
output_media_buffer->Release();
|
||||||
if (picture)
|
if (picture)
|
||||||
picture_Release(picture);
|
picture_Release(picture);
|
||||||
if (aout_buffer)
|
if (aout_buffer)
|
||||||
@ -847,15 +855,15 @@ error:
|
|||||||
|
|
||||||
static void Flush(decoder_t *p_dec)
|
static void Flush(decoder_t *p_dec)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_COMMAND_FLUSH, 0);
|
hr = p_sys->mft->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeSync(decoder_t *p_dec, block_t *p_block)
|
static int DecodeSync(decoder_t *p_dec, block_t *p_block)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
|
|
||||||
if (p_block && p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
|
if (p_block && p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
|
||||||
{
|
{
|
||||||
@ -866,7 +874,7 @@ static int DecodeSync(decoder_t *p_dec, block_t *p_block)
|
|||||||
if (p_block == NULL)
|
if (p_block == NULL)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_COMMAND_DRAIN, 0);
|
hr = p_sys->mft->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return VLC_EGENERIC;
|
return VLC_EGENERIC;
|
||||||
}
|
}
|
||||||
@ -875,7 +883,7 @@ static int DecodeSync(decoder_t *p_dec, block_t *p_block)
|
|||||||
bool keep_reading;
|
bool keep_reading;
|
||||||
int err;
|
int err;
|
||||||
do {
|
do {
|
||||||
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, &keep_reading);
|
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, keep_reading);
|
||||||
} while (err == VLC_SUCCESS && keep_reading);
|
} while (err == VLC_SUCCESS && keep_reading);
|
||||||
if (err != VLC_SUCCESS)
|
if (err != VLC_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
@ -897,16 +905,16 @@ error:
|
|||||||
|
|
||||||
static HRESULT DequeueMediaEvent(decoder_t *p_dec)
|
static HRESULT DequeueMediaEvent(decoder_t *p_dec)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
IMFMediaEvent *event = NULL;
|
IMFMediaEvent *event = NULL;
|
||||||
hr = IMFMediaEventGenerator_GetEvent(p_sys->event_generator, MF_EVENT_FLAG_NO_WAIT, &event);
|
hr = p_sys->event_generator->GetEvent(MF_EVENT_FLAG_NO_WAIT, &event);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
MediaEventType event_type;
|
MediaEventType event_type;
|
||||||
hr = IMFMediaEvent_GetType(event, &event_type);
|
hr = event->GetType(&event_type);
|
||||||
IMFMediaEvent_Release(event);
|
event->Release();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -922,7 +930,7 @@ static HRESULT DequeueMediaEvent(decoder_t *p_dec)
|
|||||||
|
|
||||||
static int DecodeAsync(decoder_t *p_dec, block_t *p_block)
|
static int DecodeAsync(decoder_t *p_dec, block_t *p_block)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (!p_block) /* No Drain */
|
if (!p_block) /* No Drain */
|
||||||
@ -947,7 +955,7 @@ static int DecodeAsync(decoder_t *p_dec, block_t *p_block)
|
|||||||
bool keep_reading;
|
bool keep_reading;
|
||||||
int err;
|
int err;
|
||||||
do {
|
do {
|
||||||
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, &keep_reading);
|
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, keep_reading);
|
||||||
} while (err == VLC_SUCCESS && keep_reading);
|
} while (err == VLC_SUCCESS && keep_reading);
|
||||||
if (err != VLC_SUCCESS)
|
if (err != VLC_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
@ -972,7 +980,7 @@ static int DecodeAsync(decoder_t *p_dec, block_t *p_block)
|
|||||||
bool keep_reading;
|
bool keep_reading;
|
||||||
int err;
|
int err;
|
||||||
do {
|
do {
|
||||||
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, &keep_reading);
|
err = ProcessOutputStream(p_dec, p_sys->output_stream_id, keep_reading);
|
||||||
} while (err == VLC_SUCCESS && keep_reading);
|
} while (err == VLC_SUCCESS && keep_reading);
|
||||||
if (err != VLC_SUCCESS)
|
if (err != VLC_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
@ -998,36 +1006,36 @@ static void DestroyMFT(decoder_t *p_dec);
|
|||||||
|
|
||||||
static int InitializeMFT(decoder_t *p_dec)
|
static int InitializeMFT(decoder_t *p_dec)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
IMFAttributes *attributes = NULL;
|
IMFAttributes *attributes = NULL;
|
||||||
hr = IMFTransform_GetAttributes(p_sys->mft, &attributes);
|
hr = p_sys->mft->GetAttributes(&attributes);
|
||||||
if (hr != E_NOTIMPL && FAILED(hr))
|
if (hr != E_NOTIMPL && FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
UINT32 is_async = false;
|
UINT32 is_async = false;
|
||||||
hr = IMFAttributes_GetUINT32(attributes, &MF_TRANSFORM_ASYNC, &is_async);
|
hr = attributes->GetUINT32(MF_TRANSFORM_ASYNC, &is_async);
|
||||||
if (hr != MF_E_ATTRIBUTENOTFOUND && FAILED(hr))
|
if (hr != MF_E_ATTRIBUTENOTFOUND && FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
p_sys->is_async = is_async;
|
p_sys->is_async = is_async;
|
||||||
if (p_sys->is_async)
|
if (p_sys->is_async)
|
||||||
{
|
{
|
||||||
hr = IMFAttributes_SetUINT32(attributes, &MF_TRANSFORM_ASYNC_UNLOCK, true);
|
hr = attributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, true);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
void *pv;
|
void *pv;
|
||||||
hr = IMFTransform_QueryInterface(p_sys->mft, &IID_IMFMediaEventGenerator, &pv);
|
hr = p_sys->mft->QueryInterface(IID_IMFMediaEventGenerator, &pv);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
p_sys->event_generator = pv;
|
p_sys->event_generator = static_cast<IMFMediaEventGenerator *>(pv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD input_streams_count;
|
DWORD input_streams_count;
|
||||||
DWORD output_streams_count;
|
DWORD output_streams_count;
|
||||||
hr = IMFTransform_GetStreamCount(p_sys->mft, &input_streams_count, &output_streams_count);
|
hr = p_sys->mft->GetStreamCount(&input_streams_count, &output_streams_count);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
if (input_streams_count != 1 || output_streams_count != 1)
|
if (input_streams_count != 1 || output_streams_count != 1)
|
||||||
@ -1036,7 +1044,7 @@ static int InitializeMFT(decoder_t *p_dec)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IMFTransform_GetStreamIDs(p_sys->mft, 1, &p_sys->input_stream_id, 1, &p_sys->output_stream_id);
|
hr = p_sys->mft->GetStreamIDs(1, &p_sys->input_stream_id, 1, &p_sys->output_stream_id);
|
||||||
if (hr == E_NOTIMPL)
|
if (hr == E_NOTIMPL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1066,19 +1074,19 @@ static int InitializeMFT(decoder_t *p_dec)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
|
/* This call can be a no-op for some MFT decoders, but it can potentially reduce starting time. */
|
||||||
hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, (ULONG_PTR)0);
|
hr = p_sys->mft->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, (ULONG_PTR)0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* This event is required for asynchronous MFTs, optional otherwise. */
|
/* This event is required for asynchronous MFTs, optional otherwise. */
|
||||||
hr = IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, (ULONG_PTR)0);
|
hr = p_sys->mft->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, (ULONG_PTR)0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
||||||
{
|
{
|
||||||
/* It's not an error if the following call fails. */
|
/* It's not an error if the following call fails. */
|
||||||
IMFAttributes_SetUINT32(attributes, &CODECAPI_AVLowLatencyMode, true);
|
attributes->SetUINT32(CODECAPI_AVLowLatencyMode, true);
|
||||||
|
|
||||||
hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec), p_dec->fmt_in.i_codec, 0, 0);
|
hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec), p_dec->fmt_in.i_codec, 0, 0);
|
||||||
hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
|
hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
|
||||||
@ -1093,22 +1101,22 @@ error:
|
|||||||
|
|
||||||
static void DestroyMFT(decoder_t *p_dec)
|
static void DestroyMFT(decoder_t *p_dec)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
|
|
||||||
if (p_sys->event_generator)
|
if (p_sys->event_generator)
|
||||||
IMFMediaEventGenerator_Release(p_sys->event_generator);
|
p_sys->event_generator->Release();
|
||||||
if (p_sys->input_type)
|
if (p_sys->input_type)
|
||||||
IMFMediaType_Release(p_sys->input_type);
|
p_sys->input_type->Release();
|
||||||
if (p_sys->output_sample)
|
if (p_sys->output_sample)
|
||||||
{
|
{
|
||||||
IMFSample_RemoveAllBuffers(p_sys->output_sample);
|
p_sys->output_sample->RemoveAllBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_sys->mft)
|
if (p_sys->mft)
|
||||||
{
|
{
|
||||||
IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_END_OF_STREAM, (ULONG_PTR)0);
|
p_sys->mft->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, (ULONG_PTR)0);
|
||||||
IMFTransform_ProcessMessage(p_sys->mft, MFT_MESSAGE_NOTIFY_END_STREAMING, (ULONG_PTR)0);
|
p_sys->mft->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, (ULONG_PTR)0);
|
||||||
IMFTransform_Release(p_sys->mft);
|
p_sys->mft->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
|
||||||
@ -1123,7 +1131,7 @@ static void DestroyMFT(decoder_t *p_dec)
|
|||||||
|
|
||||||
static int FindMFT(decoder_t *p_dec)
|
static int FindMFT(decoder_t *p_dec)
|
||||||
{
|
{
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
/* Try to create a MFT using MFTEnumEx. */
|
/* Try to create a MFT using MFTEnumEx. */
|
||||||
@ -1166,16 +1174,16 @@ static int FindMFT(decoder_t *p_dec)
|
|||||||
void *pv;
|
void *pv;
|
||||||
for (UINT32 i = 0; i < activate_objects_count; ++i)
|
for (UINT32 i = 0; i < activate_objects_count; ++i)
|
||||||
{
|
{
|
||||||
hr = IMFActivate_ActivateObject(activate_objects[i], &IID_IMFTransform, &pv);
|
hr = activate_objects[i]->ActivateObject(IID_IMFTransform, &pv);
|
||||||
IMFActivate_Release(activate_objects[i]);
|
activate_objects[i]->Release();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
continue;
|
continue;
|
||||||
p_sys->mft = pv;
|
p_sys->mft = static_cast<IMFTransform *>(pv);
|
||||||
|
|
||||||
if (InitializeMFT(p_dec) == VLC_SUCCESS)
|
if (InitializeMFT(p_dec) == VLC_SUCCESS)
|
||||||
{
|
{
|
||||||
for (++i; i < activate_objects_count; ++i)
|
for (++i; i < activate_objects_count; ++i)
|
||||||
IMFActivate_Release(activate_objects[i]);
|
activate_objects[i]->Release();
|
||||||
CoTaskMemFree(activate_objects);
|
CoTaskMemFree(activate_objects);
|
||||||
return VLC_SUCCESS;
|
return VLC_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1200,9 +1208,10 @@ static int Open(vlc_object_t *p_this)
|
|||||||
decoder_t *p_dec = (decoder_t *)p_this;
|
decoder_t *p_dec = (decoder_t *)p_this;
|
||||||
decoder_sys_t *p_sys;
|
decoder_sys_t *p_sys;
|
||||||
|
|
||||||
p_sys = p_dec->p_sys = calloc(1, sizeof(*p_sys));
|
p_sys = static_cast<decoder_sys_t*>(calloc(1, sizeof(*p_sys)));
|
||||||
if (!p_sys)
|
if (!p_sys)
|
||||||
return VLC_ENOMEM;
|
return VLC_ENOMEM;
|
||||||
|
p_dec->p_sys = p_sys;
|
||||||
|
|
||||||
if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
|
if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
|
||||||
{
|
{
|
||||||
@ -1213,8 +1222,7 @@ static int Open(vlc_object_t *p_this)
|
|||||||
if (LoadMFTLibrary())
|
if (LoadMFTLibrary())
|
||||||
{
|
{
|
||||||
msg_Err(p_dec, "Failed to load MFT library.");
|
msg_Err(p_dec, "Failed to load MFT library.");
|
||||||
free(p_sys);
|
goto error;
|
||||||
return VLC_EGENERIC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FindMFT(p_dec))
|
if (FindMFT(p_dec))
|
||||||
@ -1240,7 +1248,7 @@ error:
|
|||||||
static void Close(vlc_object_t *p_this)
|
static void Close(vlc_object_t *p_this)
|
||||||
{
|
{
|
||||||
decoder_t *p_dec = (decoder_t *)p_this;
|
decoder_t *p_dec = (decoder_t *)p_this;
|
||||||
decoder_sys_t *p_sys = p_dec->p_sys;
|
decoder_sys_t *p_sys = static_cast<decoder_sys_t*>(p_dec->p_sys);
|
||||||
|
|
||||||
DestroyMFT(p_dec);
|
DestroyMFT(p_dec);
|
||||||
|
|
@ -315,7 +315,7 @@ modules/codec/libass.c
|
|||||||
modules/codec/libmpeg2.c
|
modules/codec/libmpeg2.c
|
||||||
modules/codec/lpcm.c
|
modules/codec/lpcm.c
|
||||||
modules/codec/mad.c
|
modules/codec/mad.c
|
||||||
modules/codec/mft.c
|
modules/codec/mft.cpp
|
||||||
modules/codec/mpg123.c
|
modules/codec/mpg123.c
|
||||||
modules/codec/oggspots.c
|
modules/codec/oggspots.c
|
||||||
modules/codec/omxil/mediacodec.c
|
modules/codec/omxil/mediacodec.c
|
||||||
|
Loading…
Reference in New Issue
Block a user