[PATCH] winegstreamer: Don't store DirectShow caps.

Zebediah Figura z.figura12 at gmail.com
Mon Jun 29 20:14:06 CDT 2020


Primarily so that we can connect using video caps that can't be translated into
DirectShow caps. They will later be converted into translatable caps once the
DirectShow source pin is connected.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47642
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/winegstreamer/gstdemux.c | 162 ++++++++++++++++++++--------------
 1 file changed, 94 insertions(+), 68 deletions(-)

diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 8f89935b82..5697d2c0e0 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -78,7 +78,6 @@ struct gstdemux_source
 
     GstPad *their_src, *post_sink, *post_src, *my_sink;
     GstElement *flip;
-    AM_MEDIA_TYPE mt;
     HANDLE caps_event, eos_event;
     GstSegment *segment;
     SourceSeeking seek;
@@ -99,15 +98,11 @@ static HRESULT WINAPI GST_ChangeCurrent(IMediaSeeking *iface);
 static HRESULT WINAPI GST_ChangeStop(IMediaSeeking *iface);
 static HRESULT WINAPI GST_ChangeRate(IMediaSeeking *iface);
 
-static gboolean amt_from_gst_caps_audio_raw(const GstCaps *caps, AM_MEDIA_TYPE *amt)
+static gboolean amt_from_gst_audio_info(const GstAudioInfo *info, AM_MEDIA_TYPE *amt)
 {
     WAVEFORMATEXTENSIBLE *wfe;
     WAVEFORMATEX *wfx;
     gint32 depth, bpp;
-    GstAudioInfo ainfo;
-
-    if (!gst_audio_info_from_caps (&ainfo, caps))
-        return FALSE;
 
     wfe = CoTaskMemAlloc(sizeof(*wfe));
     wfx = (WAVEFORMATEX*)wfe;
@@ -122,10 +117,10 @@ static gboolean amt_from_gst_caps_audio_raw(const GstCaps *caps, AM_MEDIA_TYPE *
 
     wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
 
-    wfx->nChannels = ainfo.channels;
-    wfx->nSamplesPerSec = ainfo.rate;
-    depth = GST_AUDIO_INFO_WIDTH(&ainfo);
-    bpp = GST_AUDIO_INFO_DEPTH(&ainfo);
+    wfx->nChannels = info->channels;
+    wfx->nSamplesPerSec = info->rate;
+    depth = GST_AUDIO_INFO_WIDTH(info);
+    bpp = GST_AUDIO_INFO_DEPTH(info);
 
     if (!depth || depth > 32 || depth % 8)
         depth = bpp;
@@ -144,7 +139,8 @@ static gboolean amt_from_gst_caps_audio_raw(const GstCaps *caps, AM_MEDIA_TYPE *
         default:
         wfe->dwChannelMask = 0;
     }
-    if (GST_AUDIO_INFO_IS_FLOAT(&ainfo)) {
+    if (GST_AUDIO_INFO_IS_FLOAT(info))
+    {
         amt->subtype = MEDIASUBTYPE_IEEE_FLOAT;
         wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
     } else {
@@ -207,7 +203,7 @@ static gboolean amt_from_gst_video_info(const GstVideoInfo *info, AM_MEDIA_TYPE
             bih->biBitCount = 16;
             break;
         default:
-            FIXME("Unhandled type %s.\n", GST_VIDEO_INFO_NAME(info));
+            WARN("Cannot convert %s to a DirectShow type.\n", GST_VIDEO_INFO_NAME(info));
             CoTaskMemFree(vih);
             return FALSE;
         }
@@ -314,8 +310,16 @@ static gboolean amt_from_gst_caps(const GstCaps *caps, AM_MEDIA_TYPE *mt)
     const char *type = gst_structure_get_name(gst_caps_get_structure(caps, 0));
     GstStructure *structure = gst_caps_get_structure(caps, 0);
 
+    memset(mt, 0, sizeof(AM_MEDIA_TYPE));
+
     if (!strcmp(type, "audio/x-raw"))
-        return amt_from_gst_caps_audio_raw(caps, mt);
+    {
+        GstAudioInfo info;
+
+        if (!(gst_audio_info_from_caps(&info, caps)))
+            return FALSE;
+        return amt_from_gst_audio_info(&info, mt);
+    }
     else if (!strcmp(type, "video/x-raw"))
     {
         GstVideoInfo info;
@@ -331,7 +335,6 @@ static gboolean amt_from_gst_caps(const GstCaps *caps, AM_MEDIA_TYPE *mt)
         VIDEOINFOHEADER *vih;
         gint i;
 
-        memset(mt, 0, sizeof(AM_MEDIA_TYPE));
         mt->majortype = MEDIATYPE_Video;
         mt->subtype = MEDIASUBTYPE_CVID;
         mt->bTemporalCompression = TRUE;
@@ -466,24 +469,6 @@ static GstCaps *amt_to_gst_caps(const AM_MEDIA_TYPE *mt)
     return NULL;
 }
 
-static gboolean setcaps_sink(GstPad *pad, GstCaps *caps)
-{
-    struct gstdemux_source *pin = gst_pad_get_element_private(pad);
-    struct gstdemux *filter = impl_from_strmbase_filter(pin->pin.pin.filter);
-    gchar *caps_str = gst_caps_to_string(caps);
-
-    TRACE("filter %p, caps %s.\n", filter, debugstr_a(caps_str));
-    g_free(caps_str);
-
-    FreeMediaType(&pin->mt);
-
-    if (!amt_from_gst_caps(caps, &pin->mt))
-        return FALSE;
-
-    SetEvent(pin->caps_event);
-    return TRUE;
-}
-
 static gboolean query_sink(GstPad *pad, GstObject *parent, GstQuery *query)
 {
     struct gstdemux_source *pin = gst_pad_get_element_private(pad);
@@ -662,6 +647,7 @@ static gboolean event_src(GstPad *pad, GstObject *parent, GstEvent *event)
 static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event)
 {
     struct gstdemux_source *pin = gst_pad_get_element_private(pad);
+    gboolean ret;
 
     TRACE("pin %p, type \"%s\".\n", pin, GST_EVENT_TYPE_NAME(event));
 
@@ -722,11 +708,10 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event)
             if (pin->pin.pin.peer)
                 IPin_EndFlush(pin->pin.pin.peer);
             return TRUE;
-        case GST_EVENT_CAPS: {
-            GstCaps *caps;
-            gst_event_parse_caps(event, &caps);
-            return setcaps_sink(pad, caps);
-        }
+        case GST_EVENT_CAPS:
+            ret = gst_pad_event_default(pad, parent, event);
+            SetEvent(pin->caps_event);
+            return ret;
         default:
             WARN("Ignoring \"%s\" event.\n", GST_EVENT_TYPE_NAME(event));
             return gst_pad_event_default(pad, parent, event);
@@ -1678,6 +1663,10 @@ static HRESULT gstdecoder_source_query_accept(struct gstdemux_source *pin, const
 static HRESULT gstdecoder_source_get_media_type(struct gstdemux_source *pin,
         unsigned int index, AM_MEDIA_TYPE *mt)
 {
+    GstCaps *caps = gst_pad_get_current_caps(pin->my_sink);
+    const GstStructure *structure;
+    const char *type;
+
     static const GstVideoFormat video_formats[] =
     {
         /* Try to prefer YUV formats over RGB ones. Most decoders output in the
@@ -1695,42 +1684,48 @@ static HRESULT gstdecoder_source_get_media_type(struct gstdemux_source *pin,
         GST_VIDEO_FORMAT_BGR,
     };
 
-    if (!index)
+    assert(caps); /* We shouldn't be able to get here if caps haven't been set. */
+    structure = gst_caps_get_structure(caps, 0);
+    type = gst_structure_get_name(structure);
+
+    memset(mt, 0, sizeof(AM_MEDIA_TYPE));
+
+    if (amt_from_gst_caps(caps, mt))
     {
-        CopyMediaType(mt, &pin->mt);
-        return S_OK;
+        if (!index--)
+        {
+            gst_caps_unref(caps);
+            return S_OK;
+        }
     }
-    else if (IsEqualGUID(&pin->mt.majortype, &MEDIATYPE_Video)
-            && index - 1 < ARRAY_SIZE(video_formats))
+
+    if (!strcmp(type, "video/x-raw") && index < ARRAY_SIZE(video_formats))
     {
-        const VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pin->mt.pbFormat;
+        gint width, height;
         GstVideoInfo info;
 
-        gst_video_info_set_format(&info, video_formats[index - 1],
-                vih->bmiHeader.biWidth, vih->bmiHeader.biHeight);
+        gst_caps_unref(caps);
+        gst_structure_get_int(structure, "width", &width);
+        gst_structure_get_int(structure, "height", &height);
+        gst_video_info_set_format(&info, video_formats[index], width, height);
         if (!amt_from_gst_video_info(&info, mt))
             return E_OUTOFMEMORY;
         return S_OK;
     }
-    else if (IsEqualGUID(&pin->mt.majortype, &MEDIATYPE_Audio) && index == 1)
-    {
-        const WAVEFORMATEX *our_format = (WAVEFORMATEX *)pin->mt.pbFormat;
-        WAVEFORMATEX *format;
-
-        *mt = pin->mt;
-        mt->subtype = MEDIASUBTYPE_PCM;
-        mt->pbFormat = CoTaskMemAlloc(sizeof(WAVEFORMATEX));
-        format = (WAVEFORMATEX *)mt->pbFormat;
-        format->wFormatTag = WAVE_FORMAT_PCM;
-        format->nChannels = 2;
-        format->nSamplesPerSec = our_format->nSamplesPerSec;
-        format->wBitsPerSample = 16;
-        format->nBlockAlign = 4;
-        format->nAvgBytesPerSec = format->nSamplesPerSec * 4;
-        format->cbSize = 0;
+    else if (!strcmp(type, "audio/x-raw") && !index)
+    {
+        GstAudioInfo info;
+        gint rate;
+
+        gst_caps_unref(caps);
+        gst_structure_get_int(structure, "rate", &rate);
+        gst_audio_info_set_format(&info, GST_AUDIO_FORMAT_S16LE, rate, 2, NULL);
+        if (!amt_from_gst_audio_info(&info, mt))
+            return E_OUTOFMEMORY;
         return S_OK;
     }
 
+    gst_caps_unref(caps);
     return VFW_S_NO_MORE_ITEMS;
 }
 
@@ -2137,7 +2132,6 @@ static void free_source_pin(struct gstdemux_source *pin)
     gst_object_unref(pin->my_sink);
     CloseHandle(pin->caps_event);
     CloseHandle(pin->eos_event);
-    FreeMediaType(&pin->mt);
     gst_segment_free(pin->segment);
 
     strmbase_seeking_cleanup(&pin->seek);
@@ -2394,9 +2388,24 @@ static BOOL wave_parser_init_gst(struct gstdemux *filter)
     return TRUE;
 }
 
+static gboolean get_source_amt(const struct gstdemux_source *pin, AM_MEDIA_TYPE *mt)
+{
+    GstCaps *caps = gst_pad_get_current_caps(pin->my_sink);
+    gboolean ret = amt_from_gst_caps(caps, mt);
+    gst_caps_unref(caps);
+    return ret;
+}
+
 static HRESULT wave_parser_source_query_accept(struct gstdemux_source *pin, const AM_MEDIA_TYPE *mt)
 {
-    return compare_media_types(mt, &pin->mt) ? S_OK : S_FALSE;
+    AM_MEDIA_TYPE pad_mt;
+    HRESULT hr;
+
+    if (!get_source_amt(pin, &pad_mt))
+        return E_OUTOFMEMORY;
+    hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE;
+    FreeMediaType(&pad_mt);
+    return hr;
 }
 
 static HRESULT wave_parser_source_get_media_type(struct gstdemux_source *pin,
@@ -2404,7 +2413,8 @@ static HRESULT wave_parser_source_get_media_type(struct gstdemux_source *pin,
 {
     if (index > 0)
         return VFW_S_NO_MORE_ITEMS;
-    CopyMediaType(mt, &pin->mt);
+    if (!get_source_amt(pin, mt))
+        return E_OUTOFMEMORY;
     return S_OK;
 }
 
@@ -2507,7 +2517,14 @@ static BOOL avi_splitter_init_gst(struct gstdemux *filter)
 
 static HRESULT avi_splitter_source_query_accept(struct gstdemux_source *pin, const AM_MEDIA_TYPE *mt)
 {
-    return compare_media_types(mt, &pin->mt) ? S_OK : S_FALSE;
+    AM_MEDIA_TYPE pad_mt;
+    HRESULT hr;
+
+    if (!get_source_amt(pin, &pad_mt))
+        return E_OUTOFMEMORY;
+    hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE;
+    FreeMediaType(&pad_mt);
+    return hr;
 }
 
 static HRESULT avi_splitter_source_get_media_type(struct gstdemux_source *pin,
@@ -2515,7 +2532,8 @@ static HRESULT avi_splitter_source_get_media_type(struct gstdemux_source *pin,
 {
     if (index > 0)
         return VFW_S_NO_MORE_ITEMS;
-    CopyMediaType(mt, &pin->mt);
+    if (!get_source_amt(pin, mt))
+        return E_OUTOFMEMORY;
     return S_OK;
 }
 
@@ -2632,7 +2650,14 @@ static BOOL mpeg_splitter_init_gst(struct gstdemux *filter)
 
 static HRESULT mpeg_splitter_source_query_accept(struct gstdemux_source *pin, const AM_MEDIA_TYPE *mt)
 {
-    return compare_media_types(mt, &pin->mt) ? S_OK : S_FALSE;
+    AM_MEDIA_TYPE pad_mt;
+    HRESULT hr;
+
+    if (!get_source_amt(pin, &pad_mt))
+        return E_OUTOFMEMORY;
+    hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE;
+    FreeMediaType(&pad_mt);
+    return hr;
 }
 
 static HRESULT mpeg_splitter_source_get_media_type(struct gstdemux_source *pin,
@@ -2640,7 +2665,8 @@ static HRESULT mpeg_splitter_source_get_media_type(struct gstdemux_source *pin,
 {
     if (index > 0)
         return VFW_S_NO_MORE_ITEMS;
-    CopyMediaType(mt, &pin->mt);
+    if (!get_source_amt(pin, mt))
+        return E_OUTOFMEMORY;
     return S_OK;
 }
 
-- 
2.27.0




More information about the wine-devel mailing list