diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h index 092c4f6ca69..089cd9d3534 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_AudioConvert, 0x334b2ec9, 0xf2b5, 0x40b9, 0x84, 0x32, 0x4a, 0x00, 0xe0, 0x03, 0x86, 0xa8); 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); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index a83817901bf..741fdf49634 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_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_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr); diff --git a/dlls/winegstreamer/gsttffilter.c b/dlls/winegstreamer/gsttffilter.c index 6237fac878f..933929962c2 100644 --- a/dlls/winegstreamer/gsttffilter.c +++ b/dlls/winegstreamer/gsttffilter.c @@ -690,6 +690,119 @@ IUnknown * CALLBACK Gstreamer_YUV_create(IUnknown *punkout, HRESULT *phr) return obj; } +static HRESULT WINAPI Gstreamer_AudioConvert_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->subtype, &MEDIASUBTYPE_PCM) || + !IsEqualGUID(&amt->formattype, &FORMAT_WaveFormatEx)) + return S_FALSE; + return S_OK; +} + +static HRESULT WINAPI Gstreamer_AudioConvert_ConnectInput(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin) +{ + return S_OK; +} + +static HRESULT WINAPI Gstreamer_AudioConvert_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 *inwfe; + WAVEFORMATEX *outwfe; + WAVEFORMATEXTENSIBLE *outwfx; + HRESULT hr; + int inisfloat = 0, indepth; + + if (dir != PINDIR_INPUT) + return S_OK; + + if (Gstreamer_AudioConvert_QueryConnect(&This->tf, amt) == S_FALSE || !amt->pbFormat) + return E_FAIL; + + FreeMediaType(outpmt); + *outpmt = *amt; + outpmt->pUnk = NULL; + outpmt->cbFormat = sizeof(WAVEFORMATEXTENSIBLE); + outpmt->pbFormat = CoTaskMemAlloc(outpmt->cbFormat); + + inwfe = (WAVEFORMATEX*)amt->pbFormat; + indepth = inwfe->wBitsPerSample; + if (inwfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { + WAVEFORMATEXTENSIBLE *inwfx = (WAVEFORMATEXTENSIBLE*)inwfe; + inisfloat = IsEqualGUID(&inwfx->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT); + if (inwfx->Samples.wValidBitsPerSample) + indepth = inwfx->Samples.wValidBitsPerSample; + } + + capsin = gst_caps_new_simple(inisfloat ? "audio/x-raw-float" : "audio/x-raw-int", + "endianness", G_TYPE_INT, 1234, + "width", G_TYPE_INT, inwfe->wBitsPerSample, + "depth", G_TYPE_INT, indepth, + "channels", G_TYPE_INT, inwfe->nChannels, + "rate", G_TYPE_INT, inwfe->nSamplesPerSec, + NULL); + + outwfe = (WAVEFORMATEX*)outpmt->pbFormat; + outwfx = (WAVEFORMATEXTENSIBLE*)outwfe; + outwfe->wFormatTag = WAVE_FORMAT_EXTENSIBLE; + outwfe->nChannels = 2; + outwfe->nSamplesPerSec = inwfe->nSamplesPerSec; + outwfe->wBitsPerSample = 16; + outwfe->nBlockAlign = outwfe->nChannels * outwfe->wBitsPerSample / 8; + outwfe->nAvgBytesPerSec = outwfe->nBlockAlign * outwfe->nSamplesPerSec; + outwfe->cbSize = sizeof(*outwfx) - sizeof(*outwfe); + outwfx->Samples.wValidBitsPerSample = outwfe->wBitsPerSample; + outwfx->dwChannelMask = SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT; + outwfx->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + capsout = gst_caps_new_simple("audio/x-raw-int", + "endianness", G_TYPE_INT, 1234, + "width", G_TYPE_INT, outwfe->wBitsPerSample, + "depth", G_TYPE_INT, outwfx->Samples.wValidBitsPerSample, + "channels", G_TYPE_INT, outwfe->nChannels, + "rate", G_TYPE_INT, outwfe->nSamplesPerSec, + NULL); + + hr = Gstreamer_transform_ConnectInput(This, amt, capsin, capsout); + FIXME("%08x\n", hr); + gst_caps_unref(capsin); + gst_caps_unref(capsout); + + This->cbBuffer = inwfe->nAvgBytesPerSec; + return hr; +} + +static const TransformFilterFuncTable Gstreamer_AudioConvert_vtbl = { + Gstreamer_transform_DecideBufferSize, + Gstreamer_transform_ProcessBegin, + Gstreamer_transform_ProcessData, + Gstreamer_transform_ProcessEnd, + Gstreamer_AudioConvert_QueryConnect, + Gstreamer_AudioConvert_SetMediaType, + Gstreamer_AudioConvert_ConnectInput, + Gstreamer_transform_Cleanup, + Gstreamer_transform_EndOfStream, + Gstreamer_transform_BeginFlush, + Gstreamer_transform_EndFlush, + Gstreamer_transform_NewSegment +}; + +IUnknown * CALLBACK Gstreamer_AudioConvert_create(IUnknown *punkout, HRESULT *phr) +{ + IUnknown *obj = NULL; + if (!Gstreamer_init()) + { + *phr = E_FAIL; + return NULL; + } + *phr = Gstreamer_transform_create(punkout, &CLSID_Gstreamer_AudioConvert, "audioconvert", &Gstreamer_AudioConvert_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 6007ac7710a..ac9e97b03dc 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -49,6 +49,8 @@ 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 const WCHAR wGstreamer_AudioConvert[] = +{'G','S','t','r','e','a','m','e','r',' ','A','u','d','i','o','C','o','n','v','e','r','t',' ','f','i','l','t','e','r',0}; static WCHAR wNull[] = {'\0'}; @@ -149,6 +151,32 @@ AMOVIESETUP_FILTER const amfMp3 = amfMp3Pin }; +AMOVIESETUP_PIN amfAudioConvertPin[] = +{ { wNull, + FALSE, FALSE, FALSE, FALSE, + &GUID_NULL, + NULL, + 1, + amfMTaudio + }, + { + wNull, + FALSE, TRUE, FALSE, FALSE, + &GUID_NULL, + NULL, + 1, + amfMTaudio + }, +}; + +AMOVIESETUP_FILTER const amfAudioConvert = +{ &CLSID_Gstreamer_AudioConvert, + wGstreamer_AudioConvert, + MERIT_UNLIKELY, + 2, + amfAudioConvertPin +}; + FactoryTemplate const g_Templates[] = { { wGstreamer_Splitter, @@ -171,6 +199,13 @@ FactoryTemplate const g_Templates[] = { NULL, &amfMp3, }, + { + wGstreamer_AudioConvert, + &CLSID_Gstreamer_AudioConvert, + Gstreamer_AudioConvert_create, + NULL, + &amfAudioConvert, + }, }; const int g_cTemplates = sizeof(g_Templates) / sizeof (g_Templates[0]);