[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