[PATCH v3 1/5] winegstreamer: Insert videoconvert into decoded-video streams.

Zebediah Figura zfigura at codeweavers.com
Tue Oct 13 10:21:02 CDT 2020


On 10/12/20 11:08 PM, Zebediah Figura wrote:
> On 10/8/20 4:49 PM, Derek Lesho wrote:
>> Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
>> ---
>>  dlls/winegstreamer/media_source.c | 124 ++++++++++++++++++++++++++----
>>  1 file changed, 110 insertions(+), 14 deletions(-)
>>
>> diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
>> index 5f3c43a0204..cbee412030d 100644
>> --- a/dlls/winegstreamer/media_source.c
>> +++ b/dlls/winegstreamer/media_source.c
>> @@ -384,6 +384,43 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
>>      media_stream_RequestSample
>>  };
>>  
>> +/* Setup a chain of elements which should hopefully allow transformations to any IMFMediaType
>> +   the user throws at us through gstreamer's caps negotiation. */
>> +static HRESULT media_stream_connect_to_sink(struct media_stream *stream)
>> +{
>> +    GstCaps *source_caps = gst_pad_query_caps(stream->their_src, NULL);
> 
> If you're only using the stream type, I think gst_pad_get_current_caps()
> has less overhead.

Sorry, I just realized this isn't valid after all; I don't think the
caps would be fixed yet.

> 
>> +    const gchar *stream_type;
>> +
>> +    if (!source_caps)
>> +        return E_FAIL;
>> +
>> +    stream_type = gst_structure_get_name(gst_caps_get_structure(source_caps, 0));
>> +    gst_caps_unref(source_caps);
>> +
>> +    if (!strcmp(stream_type, "video/x-raw"))
>> +    {
>> +        GstElement *videoconvert = gst_element_factory_make("videoconvert", NULL);
>> +
>> +        gst_bin_add(GST_BIN(stream->parent_source->container), videoconvert);
>> +
>> +        stream->my_sink = gst_element_get_static_pad(videoconvert, "sink");
>> +
>> +        if (!gst_element_link(videoconvert, stream->appsink))
>> +            return E_FAIL;
>> +
>> +        gst_element_sync_state_with_parent(videoconvert);
>> +    }
>> +    else
>> +    {
>> +        stream->my_sink = gst_element_get_static_pad(stream->appsink, "sink");
>> +    }
>> +
>> +    if (gst_pad_link(stream->their_src, stream->my_sink) != GST_PAD_LINK_OK)
>> +        return E_FAIL;
>> +
>> +    return S_OK;
>> +}
>> +
>>  static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
>>  {
>>      struct media_stream *object = heap_alloc_zero(sizeof(*object));
>> @@ -414,8 +451,8 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
>>      g_object_set(object->appsink, "sync", FALSE, NULL);
>>      g_object_set(object->appsink, "max-buffers", 5, NULL);
>>  
>> -    object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
>> -    gst_pad_link(object->their_src, object->my_sink);
>> +    if (FAILED(hr = media_stream_connect_to_sink(object)))
>> +        goto fail;
>>  
>>      gst_element_sync_state_with_parent(object->appsink);
>>  
>> @@ -435,28 +472,87 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
>>  {
>>      GstCaps *current_caps = gst_pad_get_current_caps(stream->their_src);
>>      IMFMediaTypeHandler *type_handler;
>> +    IMFMediaType **stream_types = NULL;
>>      IMFMediaType *stream_type = NULL;
>> +    DWORD type_count = 0;
>> +    const gchar *major_type;
>> +    unsigned int i;
>>      HRESULT hr;
>>  
>> -    stream_type = mf_media_type_from_caps(current_caps);
>> -    gst_caps_unref(current_caps);
>> -    if (!stream_type)
>> -        return E_FAIL;
>> +    major_type = gst_structure_get_name(gst_caps_get_structure(current_caps, 0));
>> +
>> +    if (!strcmp(major_type, "video/x-raw"))
>> +    {
>> +        /* These are the most common native output types of decoders: https://docs.microsoft.com/en-us/windows/win32/medfound/mft-decoder-expose-output-types-in-native-order */
> 
> This line is very long.
> 
>> +        static const GUID * video_types[] =
> 
> "static const GUID *const video_types[]"
> 
>> +        {
>> +            &MFVideoFormat_NV12,
>> +            &MFVideoFormat_YV12,
>> +            &MFVideoFormat_YUY2,
>> +            &MFVideoFormat_IYUV,
>> +            &MFVideoFormat_I420,
>> +        };
>>  
>> -    hr = MFCreateStreamDescriptor(stream->stream_id, 1, &stream_type, &stream->descriptor);
>> +        IMFMediaType *base_type = mf_media_type_from_caps(current_caps);
>> +        GUID base_subtype;
>>  
>> -    IMFMediaType_Release(stream_type);
>> +        IMFMediaType_GetGUID(base_type, &MF_MT_SUBTYPE, &base_subtype);
>>  
>> -    if (FAILED(hr))
>> -        return hr;
>> +        stream_types = heap_alloc( sizeof(IMFMediaType *) * ARRAY_SIZE(video_types) + 1);
>>  
>> -    if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
>> -        return hr;
>> +        stream_types[0] = base_type;
>> +        type_count = 1;
>>  
>> -    hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_type);
>> +        for (i = 0; i < ARRAY_SIZE(video_types); i++)
>> +        {
>> +            IMFMediaType *new_type;
>>  
>> -    IMFMediaTypeHandler_Release(type_handler);
>> +            if (IsEqualGUID(&base_subtype, video_types[i]))
>> +                continue;
>>  
>> +            if (FAILED(hr = MFCreateMediaType(&new_type)))
>> +                goto done;
>> +            stream_types[type_count++] = new_type;
>> +
>> +            if (FAILED(hr = IMFMediaType_CopyAllItems(base_type, (IMFAttributes *) new_type)))
>> +                goto done;
>> +            if (FAILED(hr = IMFMediaType_SetGUID(new_type, &MF_MT_SUBTYPE, video_types[i])))
>> +                goto done;
>> +        }
>> +    }
>> +    else
>> +    {
>> +        stream_type = mf_media_type_from_caps(current_caps);
>> +        if (stream_type)
>> +        {
>> +            stream_types = &stream_type;
>> +            type_count = 1;
>> +        }
>> +    }
>> +
>> +    if (!type_count)
>> +    {
>> +        ERR("Failed to establish an IMFMediaType from any of the possible stream caps!\n");
>> +        return E_FAIL;
>> +    }
>> +
>> +    if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, type_count, stream_types, &stream->descriptor)))
>> +        goto done;
>> +
>> +    if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
>> +        goto done;
>> +
>> +    if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0])))
>> +        goto done;
>> +
>> +done:
>> +    gst_caps_unref(current_caps);
>> +    if (type_handler)
>> +        IMFMediaTypeHandler_Release(type_handler);
>> +    for (i = 0; i < type_count; i++)
>> +        IMFMediaType_Release(stream_types[i]);
>> +    if (stream_types != &stream_type)
>> +        heap_free(stream_types);
>>      return hr;
>>  }
>>  
>>
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20201013/ad1b2e69/attachment-0001.sig>


More information about the wine-devel mailing list