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