diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h index 444557832b..092c4f6ca6 100644 --- a/dlls/winegstreamer/gst_guids.h +++ b/dlls/winegstreamer/gst_guids.h @@ -22,6 +22,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +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); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index a11e8aeb3f..a83817901b 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_Mp3_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr); diff --git a/dlls/winegstreamer/gsttffilter.c b/dlls/winegstreamer/gsttffilter.c index 7a13e6f824..6237fac878 100644 --- a/dlls/winegstreamer/gsttffilter.c +++ b/dlls/winegstreamer/gsttffilter.c @@ -47,6 +47,7 @@ #include "wine/debug.h" #include "initguid.h" +DEFINE_GUID(WMMEDIASUBTYPE_MP3, 0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); WINE_DEFAULT_DEBUG_CHANNEL(gstreamer); @@ -441,6 +442,130 @@ static HRESULT Gstreamer_transform_create(IUnknown *punkout, const CLSID *clsid, return S_OK; } +static HRESULT WINAPI Gstreamer_Mp3_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_Audio) && + !IsEqualGUID(&amt->majortype, &MEDIATYPE_Stream)) || + (!IsEqualGUID(&amt->subtype, &MEDIASUBTYPE_MPEG1AudioPayload) && + !IsEqualGUID(&amt->subtype, &WMMEDIASUBTYPE_MP3)) + || !IsEqualGUID(&amt->formattype, &FORMAT_WaveFormatEx)) + return S_FALSE; + + return S_OK; +} + +static HRESULT WINAPI Gstreamer_Mp3_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; + WAVEFORMATEX *wfx, *wfxin; + HRESULT hr; + int layer; + + if (dir != PINDIR_INPUT) + return S_OK; + + if (Gstreamer_Mp3_QueryConnect(&This->tf, amt) == S_FALSE || !amt->pbFormat) + return VFW_E_TYPE_NOT_ACCEPTED; + + wfxin = (WAVEFORMATEX*)amt->pbFormat; + switch (wfxin->wFormatTag) { + case WAVE_FORMAT_MPEGLAYER3: + layer = 3; + break; + case WAVE_FORMAT_MPEG: { + MPEG1WAVEFORMAT *mpgformat = (MPEG1WAVEFORMAT*)wfxin; + layer = mpgformat->fwHeadLayer; + break; + } + default: + FIXME("Unhandled tag %x\n", wfxin->wFormatTag); + return E_FAIL; + } + + FreeMediaType(outpmt); + CopyMediaType(outpmt, amt); + + outpmt->subtype = MEDIASUBTYPE_PCM; + outpmt->formattype = FORMAT_WaveFormatEx; + outpmt->cbFormat = sizeof(*wfx); + CoTaskMemFree(outpmt->pbFormat); + wfx = CoTaskMemAlloc(outpmt->cbFormat); + outpmt->pbFormat = (BYTE*)wfx; + wfx->wFormatTag = WAVE_FORMAT_PCM; + wfx->wBitsPerSample = 16; + wfx->nSamplesPerSec = wfxin->nSamplesPerSec; + wfx->nChannels = wfxin->nChannels; + wfx->nBlockAlign = wfx->wBitsPerSample * wfx->nChannels / 8; + wfx->cbSize = 0; + wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign; + + capsin = gst_caps_new_simple("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, + "layer", G_TYPE_INT, layer, + "rate", G_TYPE_INT, wfx->nSamplesPerSec, + "channels", G_TYPE_INT, wfx->nChannels, + NULL); + capsout = gst_caps_new_simple("audio/x-raw-int", + "endianness", G_TYPE_INT, 1234, + "signed", G_TYPE_BOOLEAN, 1, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", G_TYPE_INT, wfx->nSamplesPerSec, + "channels", G_TYPE_INT, wfx->nChannels, + NULL); + + hr = Gstreamer_transform_ConnectInput(This, amt, capsin, capsout); + gst_caps_unref(capsin); + gst_caps_unref(capsout); + + This->cbBuffer = wfx->nAvgBytesPerSec / 4; + + return hr; +} + +static HRESULT WINAPI Gstreamer_Mp3_ConnectInput(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin) +{ + return S_OK; +} + +static const TransformFilterFuncTable Gstreamer_Mp3_vtbl = { + Gstreamer_transform_DecideBufferSize, + Gstreamer_transform_ProcessBegin, + Gstreamer_transform_ProcessData, + Gstreamer_transform_ProcessEnd, + Gstreamer_Mp3_QueryConnect, + Gstreamer_Mp3_SetMediaType, + Gstreamer_Mp3_ConnectInput, + Gstreamer_transform_Cleanup, + Gstreamer_transform_EndOfStream, + Gstreamer_transform_BeginFlush, + Gstreamer_transform_EndFlush, + Gstreamer_transform_NewSegment +}; + +IUnknown * CALLBACK Gstreamer_Mp3_create(IUnknown *punkout, HRESULT *phr) +{ + const char *plugin; + IUnknown *obj = NULL; + if (!Gstreamer_init()) + { + *phr = E_FAIL; + return NULL; + } + plugin = Gstreamer_FindMatch("audio/mpeg, mpegversion=(int) 1"); + if (!plugin) + { + *phr = E_FAIL; + return NULL; + } + *phr = Gstreamer_transform_create(punkout, &CLSID_Gstreamer_Mp3, plugin, &Gstreamer_Mp3_vtbl, (LPVOID*)&obj); + return obj; +} + static HRESULT WINAPI Gstreamer_YUV_QueryConnect(TransformFilter *iface, const AM_MEDIA_TYPE *amt) { GstTfImpl *This = (GstTfImpl*)iface; TRACE("%p %p\n", This, amt); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index dba15c52c4..6007ac7710 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -47,6 +47,8 @@ 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_Mp3[] = +{'G','S','t','r','e','a','m','e','r',' ','M','p','3',' ','f','i','l','t','e','r',0}; static WCHAR wNull[] = {'\0'}; @@ -121,6 +123,32 @@ static const AMOVIESETUP_FILTER amfYUV = amfYUVPin }; +AMOVIESETUP_PIN amfMp3Pin[] = +{ { wNull, + FALSE, FALSE, FALSE, FALSE, + &GUID_NULL, + NULL, + 1, + amfMTaudio + }, + { + wNull, + FALSE, TRUE, FALSE, FALSE, + &GUID_NULL, + NULL, + 1, + amfMTaudio + }, +}; + +AMOVIESETUP_FILTER const amfMp3 = +{ &CLSID_Gstreamer_Mp3, + wGstreamer_Mp3, + MERIT_NORMAL, + 2, + amfMp3Pin +}; + FactoryTemplate const g_Templates[] = { { wGstreamer_Splitter, @@ -136,6 +164,13 @@ FactoryTemplate const g_Templates[] = { NULL, &amfYUV, }, + { + wGstreamer_Mp3, + &CLSID_Gstreamer_Mp3, + Gstreamer_Mp3_create, + NULL, + &amfMp3, + }, }; const int g_cTemplates = sizeof(g_Templates) / sizeof (g_Templates[0]);