Aric Stewart : winegstreamer: Add gstreamer audio convert transform filter.
Alexandre Julliard
julliard at winehq.org
Fri Oct 29 10:58:20 CDT 2010
Module: wine
Branch: master
Commit: 0e55930effbfb5b6e79a77b5da4f4e0e5a52455e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0e55930effbfb5b6e79a77b5da4f4e0e5a52455e
Author: Aric Stewart <aric at codeweavers.com>
Date: Thu Oct 28 14:42:33 2010 -0500
winegstreamer: Add gstreamer audio convert transform filter.
---
dlls/winegstreamer/gst_guids.h | 1 +
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/gsttffilter.c | 113 ++++++++++++++++++++++++++++++++++++++
dlls/winegstreamer/main.c | 35 ++++++++++++
4 files changed, 150 insertions(+), 0 deletions(-)
diff --git a/dlls/winegstreamer/gst_guids.h b/dlls/winegstreamer/gst_guids.h
index 092c4f6..089cd9d 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 a838179..741fdf4 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 6237fac..9339299 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 6007ac7..ac9e97b 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]);
More information about the wine-cvs
mailing list