mirror of
https://github.com/reactos/wine.git
synced 2024-11-26 13:10:28 +00:00
winegstreamer: Add gstreamer mp3 transform filter.
This commit is contained in:
parent
7135ac7641
commit
5e79508fe9
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
Loading…
Reference in New Issue
Block a user