Aric Stewart : winegstreamer: Add gstreamer YUV->RGB transform filter.

Alexandre Julliard julliard at winehq.org
Thu Oct 28 12:19:53 CDT 2010


Module: wine
Branch: master
Commit: 82a232d1544eb71e3db3e94d0f88a63e7968fe4d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=82a232d1544eb71e3db3e94d0f88a63e7968fe4d

Author: Aric Stewart <aric at codeweavers.com>
Date:   Wed Oct 27 13:14:15 2010 -0500

winegstreamer: Add gstreamer YUV->RGB transform filter.

---

 dlls/winegstreamer/gst_guids.h   |    1 +
 dlls/winegstreamer/gst_private.h |    1 +
 dlls/winegstreamer/gsttffilter.c |  124 ++++++++++++++++++++++++++++++++++++++
 dlls/winegstreamer/main.c        |   35 +++++++++++
 4 files changed, 161 insertions(+), 0 deletions(-)

diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h
index 8997d94..4445578 100644
--- a/dlls/winegstreamer/gst_guids.h
+++ b/dlls/winegstreamer/gst_guids.h
@@ -24,3 +24,4 @@
 
 DEFINE_GUID(CLSID_Gstreamer_Splitter, 0xf9d8d64e, 0xa144, 0x47dc, 0x8e, 0xe0, 0xf5, 0x34, 0x98, 0x37, 0x2c, 0x29);
 DEFINE_GUID(WINESUBTYPE_Gstreamer, 0xffffffff, 0x128f, 0x4dd1, 0xad, 0x22, 0xbe, 0xcf, 0xa6, 0x6c, 0xe7, 0xaa);
+DEFINE_GUID(CLSID_Gstreamer_YUV, 0x2d5507df, 0x5ac9, 0x4bb9, 0x9c, 0x09, 0xb2, 0x80, 0xfc, 0x0b, 0xce, 0x01);
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 6838419..a11e8ae 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -40,6 +40,7 @@
 /* enum media */
 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
 
+IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *pUnkOuter, HRESULT *phr);
 IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr);
 
 void g_thread_impl_init(void);
diff --git a/dlls/winegstreamer/gsttffilter.c b/dlls/winegstreamer/gsttffilter.c
index f5093b4..7a13e6f 100644
--- a/dlls/winegstreamer/gsttffilter.c
+++ b/dlls/winegstreamer/gsttffilter.c
@@ -441,6 +441,130 @@ static HRESULT Gstreamer_transform_create(IUnknown *punkout, const CLSID *clsid,
     return S_OK;
 }
 
+static HRESULT WINAPI Gstreamer_YUV_QueryConnect(TransformFilter *iface, const AM_MEDIA_TYPE *amt) {
+    GstTfImpl *This = (GstTfImpl*)iface;
+    TRACE("%p %p\n", This, amt);
+    dump_AM_MEDIA_TYPE(amt);
+
+    if (!IsEqualGUID(&amt->majortype, &MEDIATYPE_Video) ||
+        (!IsEqualGUID(&amt->formattype, &FORMAT_VideoInfo) &&
+         !IsEqualGUID(&amt->formattype, &FORMAT_VideoInfo2)))
+        return S_FALSE;
+    if (memcmp(&amt->subtype.Data2, &MEDIATYPE_Video.Data2, sizeof(GUID) - sizeof(amt->subtype.Data1)))
+        return S_FALSE;
+    switch (amt->subtype.Data1) {
+        case mmioFOURCC('I','4','2','0'):
+        case mmioFOURCC('Y','V','1','2'):
+        case mmioFOURCC('N','V','1','2'):
+        case mmioFOURCC('N','V','2','1'):
+        case mmioFOURCC('Y','U','Y','2'):
+        case mmioFOURCC('Y','V','Y','U'):
+            return S_OK;
+        default:
+            WARN("Unhandled fourcc %s\n", debugstr_an((char*)&amt->subtype.Data1, 4));
+            return S_FALSE;
+    }
+}
+
+static HRESULT WINAPI Gstreamer_YUV_ConnectInput(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI Gstreamer_YUV_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir,  const AM_MEDIA_TYPE *amt) {
+    GstTfImpl *This = (GstTfImpl*)tf;
+    GstCaps *capsin, *capsout;
+    AM_MEDIA_TYPE *outpmt = &This->tf.pmt;
+    HRESULT hr;
+    int avgtime;
+    DWORD width, height;
+
+    if (dir != PINDIR_INPUT)
+        return S_OK;
+
+    if (Gstreamer_YUV_QueryConnect(&This->tf, amt) == S_FALSE || !amt->pbFormat)
+        return E_FAIL;
+
+    FreeMediaType(outpmt);
+    CopyMediaType(outpmt, amt);
+
+    if (IsEqualGUID(&amt->formattype, &FORMAT_VideoInfo)) {
+        VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)outpmt->pbFormat;
+        avgtime = vih->AvgTimePerFrame;
+        width = vih->bmiHeader.biWidth;
+        height = vih->bmiHeader.biHeight;
+        if ((LONG)vih->bmiHeader.biHeight > 0)
+            vih->bmiHeader.biHeight = -vih->bmiHeader.biHeight;
+        vih->bmiHeader.biBitCount = 24;
+        vih->bmiHeader.biCompression = BI_RGB;
+    } else {
+        VIDEOINFOHEADER2 *vih = (VIDEOINFOHEADER2*)outpmt->pbFormat;
+        avgtime = vih->AvgTimePerFrame;
+        width = vih->bmiHeader.biWidth;
+        height = vih->bmiHeader.biHeight;
+        if ((LONG)vih->bmiHeader.biHeight > 0)
+            vih->bmiHeader.biHeight = -vih->bmiHeader.biHeight;
+        vih->bmiHeader.biBitCount = 24;
+        vih->bmiHeader.biCompression = BI_RGB;
+    }
+    if (!avgtime)
+        avgtime = 10000000 / 30;
+
+    outpmt->subtype = MEDIASUBTYPE_RGB24;
+
+    capsin = gst_caps_new_simple("video/x-raw-yuv",
+                                 "format", GST_TYPE_FOURCC, amt->subtype.Data1,
+                                 "width", G_TYPE_INT, width,
+                                 "height", G_TYPE_INT, height,
+                                 "framerate", GST_TYPE_FRACTION, 10000000, avgtime,
+                                 NULL);
+    capsout = gst_caps_new_simple("video/x-raw-rgb",
+                                  "endianness", G_TYPE_INT, 4321,
+                                  "width", G_TYPE_INT, width,
+                                  "height", G_TYPE_INT, height,
+                                  "framerate", GST_TYPE_FRACTION, 10000000, avgtime,
+                                  "bpp", G_TYPE_INT, 24,
+                                  "depth", G_TYPE_INT, 24,
+                                  "red_mask", G_TYPE_INT, 0xff,
+                                  "green_mask", G_TYPE_INT, 0xff00,
+                                  "blue_mask", G_TYPE_INT, 0xff0000,
+                                   NULL);
+
+    hr = Gstreamer_transform_ConnectInput(This, amt, capsin, capsout);
+    gst_caps_unref(capsin);
+    gst_caps_unref(capsout);
+
+    This->cbBuffer = width * height * 4;
+    return hr;
+}
+
+static const TransformFilterFuncTable Gstreamer_YUV_vtbl = {
+    Gstreamer_transform_DecideBufferSize,
+    Gstreamer_transform_ProcessBegin,
+    Gstreamer_transform_ProcessData,
+    Gstreamer_transform_ProcessEnd,
+    Gstreamer_YUV_QueryConnect,
+    Gstreamer_YUV_SetMediaType,
+    Gstreamer_YUV_ConnectInput,
+    Gstreamer_transform_Cleanup,
+    Gstreamer_transform_EndOfStream,
+    Gstreamer_transform_BeginFlush,
+    Gstreamer_transform_EndFlush,
+    Gstreamer_transform_NewSegment
+};
+
+IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *punkout, HRESULT *phr)
+{
+    IUnknown *obj = NULL;
+    if (!Gstreamer_init())
+    {
+        *phr = E_FAIL;
+        return NULL;
+    }
+    *phr = Gstreamer_transform_create(punkout, &CLSID_Gstreamer_YUV, "ffmpegcolorspace", &Gstreamer_YUV_vtbl, (LPVOID*)&obj);
+    return obj;
+}
+
 HRESULT WINAPI GSTTf_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
 {
     HRESULT hr;
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 1fafc35..dba15c5 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -45,6 +45,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(gstreamer);
 
 static const WCHAR wGstreamer_Splitter[] =
 {'G','S','t','r','e','a','m','e','r',' ','s','p','l','i','t','t','e','r',' ','f','i','l','t','e','r',0};
+static const WCHAR wGstreamer_YUV[] =
+{'G','S','t','r','e','a','m','e','r',' ','Y','U','V',' ','f','i','l','t','e','r',0};
 
 static WCHAR wNull[] = {'\0'};
 
@@ -93,6 +95,32 @@ static const AMOVIESETUP_FILTER amfSplitter =
     amfSplitPin
 };
 
+static const AMOVIESETUP_PIN amfYUVPin[] =
+{   {   wNull,
+        FALSE, FALSE, FALSE, FALSE,
+        &GUID_NULL,
+        NULL,
+        1,
+        amfMTvideo
+    },
+    {
+        wNull,
+        FALSE, TRUE, FALSE, FALSE,
+        &GUID_NULL,
+        NULL,
+        1,
+        amfMTvideo
+    },
+};
+
+static const AMOVIESETUP_FILTER amfYUV =
+{   &CLSID_Gstreamer_YUV,
+    wGstreamer_YUV,
+    MERIT_UNLIKELY,
+    2,
+    amfYUVPin
+};
+
 FactoryTemplate const g_Templates[] = {
     {
         wGstreamer_Splitter,
@@ -101,6 +129,13 @@ FactoryTemplate const g_Templates[] = {
         NULL,
         &amfSplitter,
     },
+    {
+        wGstreamer_YUV,
+        &CLSID_Gstreamer_YUV,
+        Gstreamer_YUV_create,
+        NULL,
+        &amfYUV,
+    },
 };
 
 const int g_cTemplates = sizeof(g_Templates) / sizeof (g_Templates[0]);




More information about the wine-cvs mailing list