winegstreamer: Add gstreamer YUV->RGB transform filter.

This commit is contained in:
Aric Stewart 2010-10-27 13:14:15 -05:00 committed by Alexandre Julliard
parent aeb19307c7
commit 82a232d154
4 changed files with 161 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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]);