From 008e4d3e86073c77c173fdaa339cbb6fa06cfd85 Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Thu, 12 May 2016 14:27:00 -0500 Subject: [PATCH] winegstreamer: Add YUV to ARGB32 transformation filter. Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/winegstreamer/gst_guids.h | 3 +- dlls/winegstreamer/gst_private.h | 3 +- dlls/winegstreamer/gsttffilter.c | 116 +++++++++++++++++++++++++++++-- dlls/winegstreamer/main.c | 35 +++++++--- 4 files changed, 141 insertions(+), 16 deletions(-) diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h index 6b45bc4c43d..b445dc59625 100644 --- a/dlls/winegstreamer/gst_guids.h +++ b/dlls/winegstreamer/gst_guids.h @@ -23,4 +23,5 @@ DEFINE_GUID(CLSID_Gstreamer_AudioConvert, 0x334b2ec9, 0xf2b5, 0x40b9, 0x84, 0x32 DEFINE_GUID(CLSID_Gstreamer_Mp3, 0x728dcf55, 0x128f, 0x4dd1, 0xad, 0x22, 0xbe, 0xcf, 0xa6, 0x6c, 0xe7, 0xaa); 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); +DEFINE_GUID(CLSID_Gstreamer_YUV2RGB, 0x2d5507df, 0x5ac9, 0x4bb9, 0x9c, 0x09, 0xb2, 0x80, 0xfc, 0x0b, 0xce, 0x01); +DEFINE_GUID(CLSID_Gstreamer_YUV2ARGB, 0x2d5507df, 0x5ac9, 0x4bb9, 0x9c, 0x09, 0xb2, 0x80, 0xfc, 0x0b, 0xce, 0x02); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 4b29f21a298..a1f201c6f4e 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -39,7 +39,8 @@ void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt); IUnknown * CALLBACK Gstreamer_AudioConvert_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_Mp3_create(IUnknown *pUnkOuter, HRESULT *phr); -IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *pUnkOuter, HRESULT *phr); +IUnknown * CALLBACK Gstreamer_YUV2RGB_create(IUnknown *pUnkOuter, HRESULT *phr); +IUnknown * CALLBACK Gstreamer_YUV2ARGB_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr); DWORD Gstreamer_init(void); diff --git a/dlls/winegstreamer/gsttffilter.c b/dlls/winegstreamer/gsttffilter.c index 2209c5e2318..52aa2679464 100644 --- a/dlls/winegstreamer/gsttffilter.c +++ b/dlls/winegstreamer/gsttffilter.c @@ -677,7 +677,7 @@ static HRESULT WINAPI Gstreamer_YUV_ConnectInput(TransformFilter *tf, PIN_DIRECT return S_OK; } -static HRESULT WINAPI Gstreamer_YUV_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE *amt) +static HRESULT WINAPI Gstreamer_YUV2RGB_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE *amt) { GstTfImpl *This = (GstTfImpl*)tf; GstCaps *capsin, *capsout; @@ -748,13 +748,13 @@ static HRESULT WINAPI Gstreamer_YUV_SetMediaType(TransformFilter *tf, PIN_DIRECT return hr; } -static const TransformFilterFuncTable Gstreamer_YUV_vtbl = { +static const TransformFilterFuncTable Gstreamer_YUV2RGB_vtbl = { Gstreamer_transform_DecideBufferSize, Gstreamer_transform_ProcessBegin, Gstreamer_transform_ProcessData, Gstreamer_transform_ProcessEnd, Gstreamer_YUV_QueryConnect, - Gstreamer_YUV_SetMediaType, + Gstreamer_YUV2RGB_SetMediaType, Gstreamer_YUV_ConnectInput, Gstreamer_transform_Cleanup, Gstreamer_transform_EndOfStream, @@ -764,7 +764,7 @@ static const TransformFilterFuncTable Gstreamer_YUV_vtbl = { Gstreamer_transform_QOS }; -IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *punkouter, HRESULT *phr) +IUnknown * CALLBACK Gstreamer_YUV2RGB_create(IUnknown *punkouter, HRESULT *phr) { IUnknown *obj = NULL; @@ -776,7 +776,113 @@ IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *punkouter, HRESULT *phr) return NULL; } - *phr = Gstreamer_transform_create(punkouter, &CLSID_Gstreamer_YUV, "videoconvert", &Gstreamer_YUV_vtbl, (LPVOID*)&obj); + *phr = Gstreamer_transform_create(punkouter, &CLSID_Gstreamer_YUV2RGB, "videoconvert", &Gstreamer_YUV2RGB_vtbl, (LPVOID*)&obj); + + TRACE("returning %p\n", obj); + + return obj; +} + +static HRESULT WINAPI Gstreamer_YUV2ARGB_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; + LONG width, height; + + TRACE("%p 0x%x %p\n", This, dir, amt); + + mark_wine_thread(); + + 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 (vih->bmiHeader.biHeight > 0) + vih->bmiHeader.biHeight = -vih->bmiHeader.biHeight; + vih->bmiHeader.biBitCount = 32; + vih->bmiHeader.biCompression = BI_RGB; + vih->bmiHeader.biSizeImage = width * abs(height) * 3; + } else { + VIDEOINFOHEADER2 *vih = (VIDEOINFOHEADER2*)outpmt->pbFormat; + avgtime = vih->AvgTimePerFrame; + width = vih->bmiHeader.biWidth; + height = vih->bmiHeader.biHeight; + if (vih->bmiHeader.biHeight > 0) + vih->bmiHeader.biHeight = -vih->bmiHeader.biHeight; + vih->bmiHeader.biBitCount = 32; + vih->bmiHeader.biCompression = BI_RGB; + vih->bmiHeader.biSizeImage = width * abs(height) * 3; + } + if (!avgtime) + avgtime = 10000000 / 30; + + outpmt->subtype = MEDIASUBTYPE_ARGB32; + + capsin = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, + gst_video_format_to_string( + gst_video_format_from_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", + "format", G_TYPE_STRING, "BGRA", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, 10000000, avgtime, + 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_YUV2ARGB_vtbl = { + Gstreamer_transform_DecideBufferSize, + Gstreamer_transform_ProcessBegin, + Gstreamer_transform_ProcessData, + Gstreamer_transform_ProcessEnd, + Gstreamer_YUV_QueryConnect, + Gstreamer_YUV2ARGB_SetMediaType, + Gstreamer_YUV_ConnectInput, + Gstreamer_transform_Cleanup, + Gstreamer_transform_EndOfStream, + Gstreamer_transform_BeginFlush, + Gstreamer_transform_EndFlush, + Gstreamer_transform_NewSegment, + Gstreamer_transform_QOS +}; + +IUnknown * CALLBACK Gstreamer_YUV2ARGB_create(IUnknown *punkouter, HRESULT *phr) +{ + IUnknown *obj = NULL; + + TRACE("%p %p\n", punkouter, phr); + + if (!Gstreamer_init()) + { + *phr = E_FAIL; + return NULL; + } + + *phr = Gstreamer_transform_create(punkouter, &CLSID_Gstreamer_YUV2ARGB, "videoconvert", &Gstreamer_YUV2ARGB_vtbl, (LPVOID*)&obj); TRACE("returning %p\n", obj); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 7b9cd319596..2bb69f403fa 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -43,8 +43,10 @@ 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 const WCHAR wGstreamer_YUV2RGB[] = +{'G','S','t','r','e','a','m','e','r',' ','Y','U','V',' ','t','o',' ','R','G','B',' ','f','i','l','t','e','r',0}; +static const WCHAR wGstreamer_YUV2ARGB[] = +{'G','S','t','r','e','a','m','e','r',' ','Y','U','V',' ','t','o',' ','A','R','G','B',' ','f','i','l','t','e','r',0}; static const WCHAR wGstreamer_Mp3[] = {'G','S','t','r','e','a','m','e','r',' ','M','p','3',' ','f','i','l','t','e','r',0}; static const WCHAR wGstreamer_AudioConvert[] = @@ -115,9 +117,17 @@ static const AMOVIESETUP_PIN amfYUVPin[] = }, }; -static const AMOVIESETUP_FILTER amfYUV = -{ &CLSID_Gstreamer_YUV, - wGstreamer_YUV, +static const AMOVIESETUP_FILTER amfYUV2RGB = +{ &CLSID_Gstreamer_YUV2RGB, + wGstreamer_YUV2RGB, + MERIT_UNLIKELY, + 2, + amfYUVPin +}; + +static const AMOVIESETUP_FILTER amfYUV2ARGB = +{ &CLSID_Gstreamer_YUV2ARGB, + wGstreamer_YUV2ARGB, MERIT_UNLIKELY, 2, amfYUVPin @@ -184,11 +194,18 @@ FactoryTemplate const g_Templates[] = { &amfSplitter, }, { - wGstreamer_YUV, - &CLSID_Gstreamer_YUV, - Gstreamer_YUV_create, + wGstreamer_YUV2RGB, + &CLSID_Gstreamer_YUV2RGB, + Gstreamer_YUV2RGB_create, NULL, - &amfYUV, + &amfYUV2RGB, + }, + { + wGstreamer_YUV2ARGB, + &CLSID_Gstreamer_YUV2ARGB, + Gstreamer_YUV2ARGB_create, + NULL, + &amfYUV2ARGB, }, { wGstreamer_Mp3,