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