[vlc-devel] [PATCH] Support for loading any MFT in case video format is not found from the hardcoded list
Jean-Baptiste Kempf
jb at videolan.org
Sun Mar 4 16:45:53 CET 2018
Hello,
On Sun, 4 Mar 2018, at 15:11, Teemu Ikonen wrote:
>
> On Sun, Mar 4, 2018 at 2:06 PM, Jean-Baptiste Kempf
> <jb at videolan.org> wrote:>> __
>> Hello,
>>
>>
>> On Sun, 4 Mar 2018, at 11:53, Teemu Ikonen wrote:
>>> Adds support in Media Foundation (MFT) module to use decoders whose
>>> FCC is not found from the hardcoded list. Improves compatibility and
>>> adds support for common uncompressed formats decoders might prefer.>>
>>
>> This looks cool, but how do you have examples of such things?
>
> Typical use case for them is to allow Windows Media Player to play
> videos with custom vendor codecs (camera and instrument manufacturers,
> research, ..).> I've done few decoders to support Windows Media Player to play formats
> (e.g. Y800) and noticed it would be easy to extend VLC mft module to
> use any MFT compatible decoder instead of only ones in the hardcoded
> list. (H264, WM9, ..).
Sure, but I thought maybe you had more precise examples than Y800 (which
is just a pixel format, IIRC).
But ok.
>>> Internal formats (like MFVideoFormat_RGB32) are bottom up (negative
>>> stride). Code just changes the to ORIENT_BOTTOM_LEFT in this case
>>> and it works, but is this the right thing do?>>
>> Did you look at the avi code?
>
> No. I know that the bitmapinfo header member biHeight in AVI stream
> format can define the orientation but not sure how it applies. AFAIK
> it's ignored if payload FCC is anything else than 'DIB '.
In modules/demux/avi/avi.c, we memcpy line by line in those cases (l.
967).
ORIENT should work, though, but not in all cases (transcoding, maybe)
> This is more a problem of mapping raw RGB format of MF decoder to VLC
> RGB format. Microsoft recommends that MFT Decoders support NV12 as
> common format but it's optional and custom decoder probably outputs
> just raw RGB that works fine and all the example code does that.
Seems good to me.
> Thank you for the interest!
Thanks for your work.
Best,
>
>>
>>
>> Best,
>>>
>>> ---
>>> modules/codec/mft.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---->>> 1 file changed, 62 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/modules/codec/mft.c b/modules/codec/mft.c
>>> index 24eaaa55cb..3cf6aa494d 100644
>>> --- a/modules/codec/mft.c
>>> +++ b/modules/codec/mft.c
>>> @@ -92,6 +92,8 @@ struct decoder_sys_t
>>>
>>> const GUID* major_type;
>>> const GUID* subtype;
>>> + /* Container for a dynamically constructed subtype */
>>> + GUID custom_subtype;
>>>
>>> /* For asynchronous MFT */
>>> bool is_async;
>>> @@ -183,6 +185,20 @@ static const pair_format_guid
>>> video_format_table[] =>>> { 0, NULL }
>>> };
>>>
>>> +// 8-bit luminance only
>>> +DEFINE_MEDIATYPE_GUID (MFVideoFormat_L8, 50);
>>> +
>>> +/*
>>> + * Table to map MF Transform raw 3D3 output formats to native VLC
>>> FourCC>>> + */
>>> +static const pair_format_guid d3d_format_table[] = {
>>> + { VLC_CODEC_RGB32, &MFVideoFormat_RGB32 },
>>> + { VLC_CODEC_RGB24, &MFVideoFormat_RGB24 },
>>> + { VLC_CODEC_RGBA, &MFVideoFormat_ARGB32 },
>>> + { VLC_CODEC_GREY, &MFVideoFormat_L8 },
>>> + { 0, NULL }
>>> +};
>>> +
>>> #if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 4>>> DEFINE_GUID(MFAudioFormat_Dolby_AC3, 0xe06d802c, 0xdb46, 0x11cf,
>>> 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);>>> #endif
>>> @@ -210,6 +226,15 @@ static const GUID *FormatToGUID(const
>>> pair_format_guid table[], vlc_fourcc_t fou>>> return NULL;
>>> }
>>>
>>> +static vlc_fourcc_t GUIDToFormat(const pair_format_guid table[],
>>> const GUID* guid)>>> +{
>>> + for (int i = 0; table[i].fourcc; ++i)
>>> + if (IsEqualGUID(table[i].guid, guid))
>>> + return table[i].fourcc;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> /*
>>> * Low latency mode for Windows 8. Without this option, the H264
>>> * decoder will fill *all* its internal buffers before returning a>>> @@ -272,6 +297,16 @@ static int SetInputType(decoder_t *p_dec, DWORD
>>> stream_id, IMFMediaType **result>>> hr = IMFMediaType_SetUINT64(input_media_type,
>>> &MF_MT_FRAME_SIZE, frame_size);>>> if (FAILED(hr))
>>> goto error;
>>> +
>>> + /* Some transforms like to know the frame rate and may
>>> reject the input type otherwise. */>>> + UINT64 frame_ratio_num = p_dec->fmt_in.video.i_frame_rate;>>> + UINT64 frame_ratio_dem = p_dec-
>>> >fmt_in.video.i_frame_rate_base;>>> + if(frame_ratio_num && 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);>>> + if(FAILED(hr))
>>> + goto error;
>>> + }
>>> }
>>> else
>>> {
>>> @@ -356,7 +391,7 @@ static int SetOutputType(decoder_t *p_dec, DWORD
>>> stream_id, IMFMediaType **resul>>> * preference thus we will use the first one unless YV12/I420
>>> is>>> * available for video or float32 for audio.
>>> */
>>> - int output_type_index = 0;
>>> + int output_type_index = -1;
>>> bool found = false;
>>> for (int i = 0; !found; ++i)
>>> {
>>> @@ -380,6 +415,10 @@ static int SetOutputType(decoder_t *p_dec,
>>> DWORD stream_id, IMFMediaType **resul>>> {
>>> if (IsEqualGUID(&subtype, &MFVideoFormat_YV12) ||
>>> IsEqualGUID(&subtype, &MFVideoFormat_I420))>>> found = true;
>>> + /* Transform might offer output in a D3DFMT propietary
>>> FCC. If we can>>> + * 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)>>> + output_type_index = i;
>>> }
>>> else
>>> {
>>> @@ -399,9 +438,12 @@ static int SetOutputType(decoder_t *p_dec,
>>> DWORD stream_id, IMFMediaType **resul>>> }
>>> /*
>>> * It's not an error if we don't find the output type we were
>>> - * looking for, in this case we use the first available type
>>> which>>> - * is the "preferred" output type for this MFT.
>>> + * looking for, in this case we use the first available type.
>>> */
>>> + if(output_type_index < 0)
>>> + /* No output format found we prefer, just pick the first
>>> one preferred>>> + * by the MFT */
>>> + output_type_index = 0;
>>>
>>> hr = IMFTransform_GetOutputAvailableType(p_sys->mft, stream_id,
>>> output_type_index, &output_media_type);>>> if (FAILED(hr))
>>> @@ -419,7 +461,17 @@ static int SetOutputType(decoder_t *p_dec,
>>> DWORD stream_id, IMFMediaType **resul>>> if (p_dec->fmt_in.i_cat == VIDEO_ES)
>>> {
>>> video_format_Copy( &p_dec->fmt_out.video, &p_dec-
>>> >fmt_in.video );>>> - p_dec->fmt_out.i_codec = vlc_fourcc_GetCodec(p_dec-
>>> >fmt_in.i_cat, subtype.Data1);>>> +
>>> + /* Transform might offer output in a D3DFMT propietary FCC
>>> */>>> + vlc_fourcc_t fcc = GUIDToFormat(d3d_format_table,
>>> &subtype);>>> + if(fcc) {
>>> + /* D3D formats are upside down */
>>> + p_dec->fmt_out.video.orientation = ORIENT_BOTTOM_LEFT;>>> + } else {
>>> + fcc = vlc_fourcc_GetCodec(p_dec->fmt_in.i_cat,
>>> subtype.Data1);>>> + }
>>> +
>>> + p_dec->fmt_out.i_codec = fcc;
>>> }
>>> else
>>> {
>>> @@ -1046,6 +1098,12 @@ static int FindMFT(decoder_t *p_dec)
>>> category = MFT_CATEGORY_VIDEO_DECODER;
>>> p_sys->major_type = &MFMediaType_Video;
>>> p_sys->subtype = FormatToGUID(video_format_table, p_dec-
>>> >fmt_in.i_codec);>>> + if(!p_sys->subtype) {
>>> + /* Codec is not well known. Construct a MF transform
>>> subtype from the fourcc */>>> + p_sys->custom_subtype = MFVideoFormat_Base;
>>> + p_sys->custom_subtype.Data1 = p_dec->fmt_in.i_codec;
>>> + p_sys->subtype = &p_sys->custom_subtype;
>>> + }
>>> }
>>> else
>>> {
>>> --
>>> 2.14.1
>>>
>>> _________________________________________________
>>> vlc-devel mailing list
>>> To unsubscribe or modify your subscription options:
>>> https://mailman.videolan.org/listinfo/vlc-devel
>>
>> --
>> Jean-Baptiste Kempf - President
>> +33 672 704 734
>>
>>
>>
--
Jean-Baptiste Kempf - President
+33 672 704 734
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20180304/8b8edc00/attachment.html>
More information about the vlc-devel
mailing list