From 82a232d1544eb71e3db3e94d0f88a63e7968fe4d Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Wed, 27 Oct 2010 13:14:15 -0500 Subject: [PATCH] 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(+) diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h index 8997d947d2..444557832b 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 6838419e44..a11e8aeb3f 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 f5093b4e55..7a13e6f824 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 1fafc35e2e..dba15c52c4 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]); -- 2.32.0.93.g670b81a890