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