Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 397af6ef555..9160d12a5a5 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -140,7 +140,6 @@ static gboolean amt_from_gst_caps_audio(const GstCaps *caps, AM_MEDIA_TYPE *amt) amt->cbFormat = sizeof(*wfe); amt->bFixedSizeSamples = 0; amt->bTemporalCompression = 1; - amt->lSampleSize = 0; amt->pUnk = NULL;
wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE; @@ -177,7 +176,7 @@ static gboolean amt_from_gst_caps_audio(const GstCaps *caps, AM_MEDIA_TYPE *amt) wfx->cbSize = 0; } } - wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample/8; + amt->lSampleSize = wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample/8; wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign; return TRUE; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 9160d12a5a5..9abb7bd2894 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -138,7 +138,7 @@ static gboolean amt_from_gst_caps_audio(const GstCaps *caps, AM_MEDIA_TYPE *amt) amt->formattype = FORMAT_WaveFormatEx; amt->pbFormat = (BYTE*)wfe; amt->cbFormat = sizeof(*wfe); - amt->bFixedSizeSamples = 0; + amt->bFixedSizeSamples = TRUE; amt->bTemporalCompression = 1; amt->pUnk = NULL;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 9abb7bd2894..60136abaac9 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -139,7 +139,7 @@ static gboolean amt_from_gst_caps_audio(const GstCaps *caps, AM_MEDIA_TYPE *amt) amt->pbFormat = (BYTE*)wfe; amt->cbFormat = sizeof(*wfe); amt->bFixedSizeSamples = TRUE; - amt->bTemporalCompression = 1; + amt->bTemporalCompression = FALSE; amt->pUnk = NULL;
wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 60136abaac9..2ad4b08a13b 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -174,6 +174,7 @@ static gboolean amt_from_gst_caps_audio(const GstCaps *caps, AM_MEDIA_TYPE *amt) if (wfx->nChannels <= 2 && bpp <= 16 && depth == bpp) { wfx->wFormatTag = WAVE_FORMAT_PCM; wfx->cbSize = 0; + amt->cbFormat = sizeof(WAVEFORMATEX); } } amt->lSampleSize = wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample/8;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
dlls/quartz/Makefile.in | 3 +- dlls/quartz/main.c | 1 - dlls/quartz/quartz_private.h | 1 - dlls/quartz/quartz_strmif.idl | 7 - dlls/quartz/regsvr.c | 19 -- dlls/quartz/tests/waveparser.c | 13 +- dlls/quartz/waveparser.c | 440 ------------------------------- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/gstdemux.c | 268 +++++++++++++------ dlls/winegstreamer/main.c | 50 ++++ 10 files changed, 257 insertions(+), 546 deletions(-) delete mode 100644 dlls/quartz/waveparser.c
diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in index 3824efbfa98..7963e212fc5 100644 --- a/dlls/quartz/Makefile.in +++ b/dlls/quartz/Makefile.in @@ -23,8 +23,7 @@ C_SRCS = \ regsvr.c \ systemclock.c \ videorenderer.c \ - vmr9.c \ - waveparser.c + vmr9.c
RC_SRCS = quartz.rc
diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c index 2c7284de13b..115fc806fc7 100644 --- a/dlls/quartz/main.c +++ b/dlls/quartz/main.c @@ -80,7 +80,6 @@ static const struct object_creation_info object_creation[] = { &CLSID_AVIDec, AVIDec_create }, { &CLSID_SystemClock, QUARTZ_CreateSystemClock }, { &CLSID_ACMWrapper, ACMWrapper_create }, - { &CLSID_WAVEParser, WAVEParser_create } };
static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h index 874b29f2b12..d43e445bd04 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -63,7 +63,6 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; -HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; HRESULT VMR7Impl_create(IUnknown *pUnkOuter, LPVOID *ppv) DECLSPEC_HIDDEN; HRESULT VMR9Impl_create(IUnknown *pUnkOuter, LPVOID *ppv) DECLSPEC_HIDDEN;
diff --git a/dlls/quartz/quartz_strmif.idl b/dlls/quartz/quartz_strmif.idl index ab1af89ac42..c84e3aea5cb 100644 --- a/dlls/quartz/quartz_strmif.idl +++ b/dlls/quartz/quartz_strmif.idl @@ -140,13 +140,6 @@ coclass VideoRendererDefault { interface IBaseFilter; } ] coclass ACMWrapper { interface IBaseFilter; }
-[ - helpstring("Wave Parser"), - threading(both), - uuid(d51bd5a1-7548-11cf-a520-0080c77ef58a) -] -coclass WAVEParser { interface IBaseFilter; } - [ helpstring("Video Mixing Renderer"), threading(both), diff --git a/dlls/quartz/regsvr.c b/dlls/quartz/regsvr.c index 44b2f60d138..eebca1c00a6 100644 --- a/dlls/quartz/regsvr.c +++ b/dlls/quartz/regsvr.c @@ -354,25 +354,6 @@ static struct regsvr_filter const filter_list[] = { { 0xFFFFFFFF }, } }, - { &CLSID_WAVEParser, - &CLSID_LegacyAmFilterCategory, - {'W','a','v','e',' ','P','a','r','s','e','r',0}, - 0x400000, - { { 0, - { { &MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE }, - { &MEDIATYPE_Stream, &MEDIASUBTYPE_AU }, - { &MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF }, - { NULL } - }, - }, - { REG_PINFLAG_B_OUTPUT, - { { &MEDIATYPE_Audio, &GUID_NULL }, - { NULL } - }, - }, - { 0xFFFFFFFF }, - } - }, { NULL } /* list terminator */ };
diff --git a/dlls/quartz/tests/waveparser.c b/dlls/quartz/tests/waveparser.c index 4bfa17a9e5f..2e4cc914618 100644 --- a/dlls/quartz/tests/waveparser.c +++ b/dlls/quartz/tests/waveparser.c @@ -148,7 +148,7 @@ static void test_interfaces(void) check_interface(pin, &IID_IKsPropertySet, FALSE); check_interface(pin, &IID_IMemInputPin, FALSE); check_interface(pin, &IID_IMediaPosition, FALSE); - todo_wine check_interface(pin, &IID_IMediaSeeking, FALSE); + check_interface(pin, &IID_IMediaSeeking, FALSE);
IPin_Release(pin);
@@ -157,6 +157,7 @@ static void test_interfaces(void) todo_wine check_interface(pin, &IID_IMediaPosition, TRUE); check_interface(pin, &IID_IMediaSeeking, TRUE); check_interface(pin, &IID_IPin, TRUE); + check_interface(pin, &IID_IQualityControl, TRUE); check_interface(pin, &IID_IUnknown, TRUE);
check_interface(pin, &IID_IAsyncReader, FALSE); @@ -762,8 +763,18 @@ static void test_enum_media_types(void)
START_TEST(waveparser) { + IBaseFilter *filter; + CoInitialize(NULL);
+ if (FAILED(CoCreateInstance(&CLSID_WAVEParser, NULL, CLSCTX_INPROC_SERVER, + &IID_IBaseFilter, (void **)&filter))) + { + skip("Failed to create WAVE parser.\n"); + return; + } + IBaseFilter_Release(filter); + test_interfaces(); test_aggregation(); test_enum_pins(); diff --git a/dlls/quartz/waveparser.c b/dlls/quartz/waveparser.c deleted file mode 100644 index 43bfff060b5..00000000000 --- a/dlls/quartz/waveparser.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * WAVE Parser Filter - * - * Copyright 2005 Christian Costa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "quartz_private.h" -#include "pin.h" - -#include "uuids.h" -#include "aviriff.h" -#include "vfwmsgs.h" -#include "mmsystem.h" - -#include "wine/debug.h" - -#include <math.h> -#include <assert.h> - -#include "parser.h" - -WINE_DEFAULT_DEBUG_CHANNEL(quartz); - -static const WCHAR outputW[] = {'o','u','t','p','u','t',0}; - -typedef struct WAVEParserImpl -{ - ParserImpl Parser; - LONGLONG StartOfFile; /* in media time */ - LONGLONG EndOfFile; - DWORD nAvgBytesPerSec; - DWORD nBlockAlign; -} WAVEParserImpl; - -static inline WAVEParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) -{ - return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.sourceSeeking.IMediaSeeking_iface); -} - -static inline WAVEParserImpl *impl_from_strmbase_filter(struct strmbase_filter *iface) -{ - return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.filter); -} - -static LONGLONG bytepos_to_duration(WAVEParserImpl *This, LONGLONG bytepos) -{ - LONGLONG duration = BYTES_FROM_MEDIATIME(bytepos - This->StartOfFile); - duration *= 10000000; - duration /= This->nAvgBytesPerSec; - - return duration; -} - -static LONGLONG duration_to_bytepos(WAVEParserImpl *This, LONGLONG duration) -{ - LONGLONG bytepos; - - bytepos = This->nAvgBytesPerSec; - bytepos *= duration; - bytepos /= 10000000; - bytepos -= bytepos % This->nBlockAlign; - bytepos += BYTES_FROM_MEDIATIME(This->StartOfFile); - - return MEDIATIME_FROM_BYTES(bytepos); -} - -static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR cookie) -{ - WAVEParserImpl *This = iface; - LPBYTE pbSrcStream = NULL; - ULONG cbSrcStream = 0; - REFERENCE_TIME tStart, tStop; - HRESULT hr; - IMediaSample *newsample = NULL; - Parser_OutputPin *pOutputPin; - PullPin *pin = This->Parser.pInputPin; - - IMediaSample_GetPointer(pSample, &pbSrcStream); - hr = IMediaSample_GetTime(pSample, &tStart, &tStop); - - cbSrcStream = IMediaSample_GetActualDataLength(pSample); - - /* Flush occurring */ - if (cbSrcStream == 0) - { - TRACE(".. Why do I need you?\n"); - return S_OK; - } - - pOutputPin = This->Parser.sources[0]; - - if (SUCCEEDED(hr)) - hr = IMemAllocator_GetBuffer(pin->pAlloc, &newsample, NULL, NULL, 0); - - if (SUCCEEDED(hr)) - { - LONGLONG rtSampleStart = pin->rtNext; - /* Add 4 for the next header, which should hopefully work */ - LONGLONG rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(IMediaSample_GetSize(newsample)); - - if (rtSampleStop > pin->rtStop) - rtSampleStop = MEDIATIME_FROM_BYTES(ALIGNUP(BYTES_FROM_MEDIATIME(pin->rtStop), pin->cbAlign)); - - IMediaSample_SetTime(newsample, &rtSampleStart, &rtSampleStop); - - pin->rtCurrent = pin->rtNext; - pin->rtNext = rtSampleStop; - - IMediaSample_SetPreroll(newsample, FALSE); - IMediaSample_SetDiscontinuity(newsample, FALSE); - IMediaSample_SetSyncPoint(newsample, TRUE); - - hr = IAsyncReader_Request(pin->pReader, newsample, 0); - } - - if (SUCCEEDED(hr)) - { - REFERENCE_TIME tAviStart, tAviStop; - - IMediaSample_SetSyncPoint(pSample, TRUE); - pOutputPin->dwSamplesProcessed++; - - tAviStart = bytepos_to_duration(This, tStart); - tAviStop = bytepos_to_duration(This, tStart + MEDIATIME_FROM_BYTES(IMediaSample_GetActualDataLength(pSample))); - - IMediaSample_SetTime(pSample, &tAviStart, &tAviStop); - - hr = BaseOutputPinImpl_Deliver(&pOutputPin->pin, pSample); - if (hr != S_OK && hr != S_FALSE && hr != VFW_E_WRONG_STATE) - ERR("Error sending sample (%x)\n", hr); - else if (hr != S_OK) - /* Unset progression if denied! */ - This->Parser.pInputPin->rtCurrent = tStart; - } - - if (tStop >= This->EndOfFile || (bytepos_to_duration(This, tStop) >= This->Parser.sourceSeeking.llStop) || hr == VFW_E_NOT_CONNECTED) - { - unsigned int i; - - TRACE("End of file reached\n"); - - for (i = 0; i < This->Parser.cStreams; i++) - { - IPin* ppin; - HRESULT hr; - - TRACE("Send End Of Stream to output pin %u\n", i); - - hr = IPin_ConnectedTo(&This->Parser.sources[i]->pin.pin.IPin_iface, &ppin); - if (SUCCEEDED(hr)) - { - hr = IPin_EndOfStream(ppin); - IPin_Release(ppin); - } - if (FAILED(hr)) - { - ERR("%x\n", hr); - break; - } - } - - /* Force the pullpin thread to stop */ - hr = S_FALSE; - } - - return hr; -} - -static HRESULT WAVEParser_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) -{ - if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Stream)) - return S_FALSE; - if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_WAVE)) - return S_OK; - if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_AU) || IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_AIFF)) - FIXME("AU and AIFF files not supported yet!\n"); - return S_FALSE; -} - -static HRESULT WINAPI WAVEParserImpl_seek(IMediaSeeking *iface) -{ - WAVEParserImpl *This = impl_from_IMediaSeeking(iface); - PullPin *pPin = This->Parser.pInputPin; - LONGLONG newpos, curpos, endpos, bytepos; - IPin *peer; - - newpos = This->Parser.sourceSeeking.llCurrent; - curpos = bytepos_to_duration(This, pPin->rtCurrent); - endpos = bytepos_to_duration(This, This->EndOfFile); - bytepos = duration_to_bytepos(This, newpos); - - if (newpos > endpos) - { - WARN("Requesting position %s beyond end of stream %s\n", - wine_dbgstr_longlong(newpos), wine_dbgstr_longlong(endpos)); - return E_INVALIDARG; - } - - if (curpos/1000000 == newpos/1000000) - { - TRACE("Requesting position %s same as current position %s\n", - wine_dbgstr_longlong(newpos), wine_dbgstr_longlong(curpos)); - return S_OK; - } - - TRACE("Moving sound to %08u bytes!\n", (DWORD)BYTES_FROM_MEDIATIME(bytepos)); - - EnterCriticalSection(&pPin->thread_lock); - IPin_BeginFlush(&pPin->pin.IPin_iface); - - /* Make sure this is done while stopped, BeginFlush takes care of this */ - EnterCriticalSection(&This->Parser.filter.csFilter); - - if ((peer = This->Parser.sources[0]->pin.pin.pConnectedTo)) - IPin_NewSegment(peer, newpos, endpos, pPin->dRate); - - pPin->rtStart = pPin->rtCurrent = bytepos; - This->Parser.sources[0]->dwSamplesProcessed = 0; - LeaveCriticalSection(&This->Parser.filter.csFilter); - - TRACE("Done flushing\n"); - IPin_EndFlush(&pPin->pin.IPin_iface); - LeaveCriticalSection(&pPin->thread_lock); - - return S_OK; -} - -static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, ALLOCATOR_PROPERTIES *props) -{ - PullPin *This = impl_PullPin_from_IPin(iface); - HRESULT hr; - RIFFLIST list; - RIFFCHUNK chunk; - LONGLONG pos = 0; /* in bytes */ - AM_MEDIA_TYPE amt; - WAVEParserImpl *pWAVEParser = impl_from_strmbase_filter(This->pin.filter); - - hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list); - pos += sizeof(list); - - if (list.fcc != FOURCC_RIFF) - { - ERR("Input stream not a RIFF file\n"); - return E_FAIL; - } - if (list.cb > 1 * 1024 * 1024 * 1024) /* cannot be more than 1Gb in size */ - { - ERR("Input stream violates RIFF spec\n"); - return E_FAIL; - } - if (list.fccListType != mmioFOURCC('W','A','V','E')) - { - ERR("Input stream not an WAVE RIFF file\n"); - return E_FAIL; - } - - hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(chunk), (BYTE *)&chunk); - pos += sizeof(chunk); - if (chunk.fcc != mmioFOURCC('f','m','t',' ')) - { - ERR("Expected 'fmt ' chunk, but got %.04s\n", (LPSTR)&chunk.fcc); - return E_FAIL; - } - - amt.majortype = MEDIATYPE_Audio; - amt.formattype = FORMAT_WaveFormatEx; - amt.bFixedSizeSamples = TRUE; - amt.bTemporalCompression = FALSE; - amt.lSampleSize = 1; - amt.pUnk = NULL; - amt.cbFormat = max(chunk.cb, sizeof(WAVEFORMATEX)); - amt.pbFormat = CoTaskMemAlloc(amt.cbFormat); - memset(amt.pbFormat, 0, amt.cbFormat); - IAsyncReader_SyncRead(This->pReader, pos, chunk.cb, amt.pbFormat); - amt.subtype = MEDIATYPE_Audio; - amt.subtype.Data1 = ((WAVEFORMATEX*)amt.pbFormat)->wFormatTag; - - pos += chunk.cb; - hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(chunk), (BYTE *)&chunk); - while (chunk.fcc != mmioFOURCC('d','a','t','a')) - { - FIXME("Ignoring %s chunk.\n", debugstr_fourcc(chunk.fcc)); - pos += sizeof(chunk) + chunk.cb; - hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(chunk), (BYTE *)&chunk); - if (hr != S_OK) - return E_FAIL; - } - - pWAVEParser->StartOfFile = MEDIATIME_FROM_BYTES(pos + sizeof(RIFFCHUNK)); - pWAVEParser->EndOfFile = MEDIATIME_FROM_BYTES(pos + chunk.cb + sizeof(RIFFCHUNK)); - - props->cbAlign = ((WAVEFORMATEX*)amt.pbFormat)->nBlockAlign; - props->cbPrefix = 0; - props->cbBuffer = 4096; - props->cBuffers = 3; - pWAVEParser->nBlockAlign = ((WAVEFORMATEX*)amt.pbFormat)->nBlockAlign; - pWAVEParser->nAvgBytesPerSec = ((WAVEFORMATEX*)amt.pbFormat)->nAvgBytesPerSec; - hr = Parser_AddPin(&pWAVEParser->Parser, outputW, props, &amt); - CoTaskMemFree(amt.pbFormat); - - pWAVEParser->Parser.sourceSeeking.llCurrent = 0; - pWAVEParser->Parser.sourceSeeking.llStop = pWAVEParser->Parser.sourceSeeking.llDuration = bytepos_to_duration(pWAVEParser, pWAVEParser->EndOfFile); - TRACE("Duration: %u seconds\n", (DWORD)(pWAVEParser->Parser.sourceSeeking.llDuration / (LONGLONG)10000000)); - - This->rtStop = pWAVEParser->EndOfFile; - This->rtStart = pWAVEParser->StartOfFile; - - TRACE("WAVE File ok\n"); - - return hr; -} - -static HRESULT WAVEParser_Cleanup(LPVOID iface) -{ - WAVEParserImpl *This = iface; - - TRACE("(%p)->()\n", This); - - return S_OK; -} - -static HRESULT WAVEParser_first_request(LPVOID iface) -{ - WAVEParserImpl *This = iface; - PullPin *pin = This->Parser.pInputPin; - HRESULT hr; - IMediaSample *sample; - - if (pin->rtCurrent >= pin->rtStop) - { - /* Last sample has already been queued, request nothing more */ - TRACE("Done!\n"); - return S_OK; - } - - hr = IMemAllocator_GetBuffer(pin->pAlloc, &sample, NULL, NULL, 0); - - pin->rtNext = pin->rtCurrent; - if (SUCCEEDED(hr)) - { - LONGLONG rtSampleStart = pin->rtNext; - /* Add 4 for the next header, which should hopefully work */ - LONGLONG rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(IMediaSample_GetSize(sample)); - - if (rtSampleStop > pin->rtStop) - rtSampleStop = MEDIATIME_FROM_BYTES(ALIGNUP(BYTES_FROM_MEDIATIME(pin->rtStop), pin->cbAlign)); - - IMediaSample_SetTime(sample, &rtSampleStart, &rtSampleStop); - - pin->rtCurrent = pin->rtNext; - pin->rtNext = rtSampleStop; - - IMediaSample_SetPreroll(sample, FALSE); - if (!This->Parser.sources[0]->dwSamplesProcessed++) - IMediaSample_SetDiscontinuity(sample, TRUE); - else - IMediaSample_SetDiscontinuity(sample, FALSE); - - hr = IAsyncReader_Request(pin->pReader, sample, 0); - } - if (FAILED(hr)) - ERR("Horsemen of the apocalypse came to bring error 0x%08x %p\n", hr, sample); - - return hr; -} - -static HRESULT WAVEParser_disconnect(LPVOID iface) -{ - /* TODO: Find and plug memory leaks */ - return S_OK; -} - -static const IBaseFilterVtbl WAVEParser_Vtbl = -{ - BaseFilterImpl_QueryInterface, - BaseFilterImpl_AddRef, - BaseFilterImpl_Release, - BaseFilterImpl_GetClassID, - Parser_Stop, - Parser_Pause, - Parser_Run, - Parser_GetState, - Parser_SetSyncSource, - BaseFilterImpl_GetSyncSource, - BaseFilterImpl_EnumPins, - BaseFilterImpl_FindPin, - BaseFilterImpl_QueryFilterInfo, - BaseFilterImpl_JoinFilterGraph, - BaseFilterImpl_QueryVendorInfo, -}; - -static void wave_parser_destroy(struct strmbase_filter *iface) -{ - WAVEParserImpl *filter = impl_from_strmbase_filter(iface); - Parser_Destroy(&filter->Parser); -} - -static const struct strmbase_filter_ops filter_ops = -{ - .filter_get_pin = parser_get_pin, - .filter_destroy = wave_parser_destroy, -}; - -HRESULT WAVEParser_create(IUnknown *outer, void **out) -{ - static const WCHAR sink_name[] = {'i','n','p','u','t',' ','p','i','n',0}; - HRESULT hr; - WAVEParserImpl * This; - - *out = NULL; - - /* Note: This memory is managed by the transform filter once created */ - This = CoTaskMemAlloc(sizeof(WAVEParserImpl)); - - hr = Parser_Create(&This->Parser, &WAVEParser_Vtbl, outer, &CLSID_WAVEParser, - &filter_ops, sink_name, WAVEParser_Sample, WAVEParser_QueryAccept, - WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, WAVEParser_disconnect, - WAVEParser_first_request, NULL, NULL, WAVEParserImpl_seek, NULL); - - if (FAILED(hr)) - return hr; - - *out = &This->Parser.filter.IUnknown_inner; - - return hr; -} diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 18d6eb8a8e8..392cfa849d3 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -43,6 +43,7 @@ IUnknown * CALLBACK Gstreamer_Mp3_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_YUV2RGB_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_YUV2ARGB_create(IUnknown *pUnkOuter, HRESULT *phr); IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr); +IUnknown * CALLBACK wave_parser_create(IUnknown *outer, HRESULT *phr) DECLSPEC_HIDDEN;
BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 2ad4b08a13b..1b4857a2a18 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -68,6 +68,8 @@ struct gstdemux HANDLE no_more_pads_event;
HANDLE push_thread; + + BOOL (*init_gst)(struct gstdemux *filter); };
struct gstdemux_source @@ -104,7 +106,7 @@ static const IPinVtbl GST_InputPin_Vtbl; static const IBaseFilterVtbl GST_Vtbl; static const IQualityControlVtbl GSTOutPin_QualityControl_Vtbl;
-static BOOL create_pin(struct gstdemux *filter, const WCHAR *name); +static struct gstdemux_source *create_pin(struct gstdemux *filter, const WCHAR *name); static HRESULT GST_RemoveOutputPins(struct gstdemux *This); static HRESULT WINAPI GST_ChangeCurrent(IMediaSeeking *iface); static HRESULT WINAPI GST_ChangeStop(IMediaSeeking *iface); @@ -775,10 +777,8 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, struct gstdemux * char *name; GstCaps *caps; GstStructure *arg; - GstPad *mypad; struct gstdemux_source *pin; int ret; - gchar my_name[1024]; WCHAR nameW[128];
TRACE("%p %p %p\n", This, bin, pad); @@ -787,8 +787,6 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, struct gstdemux * MultiByteToWideChar(CP_UNIXCP, 0, name, -1, nameW, ARRAY_SIZE(nameW) - 1); nameW[ARRAY_SIZE(nameW) - 1] = 0; TRACE("Name: %s\n", name); - strcpy(my_name, "qz_sink_"); - strcat(my_name, name); g_free(name);
caps = gst_pad_query_caps(pad, NULL); @@ -796,29 +794,18 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, struct gstdemux * arg = gst_caps_get_structure(caps, 0); typename = gst_structure_get_name(arg);
- mypad = gst_pad_new(my_name, GST_PAD_SINK); - gst_pad_set_chain_function(mypad, got_data_sink_wrapper); - gst_pad_set_event_function(mypad, event_sink_wrapper); - gst_pad_set_query_function(mypad, query_sink_wrapper); - if (strcmp(typename, "audio/x-raw") && strcmp(typename, "video/x-raw")) { FIXME("Unknown type '%s'\n", typename); return; }
- if (!create_pin(This, nameW)) + if (!(pin = create_pin(This, nameW))) { ERR("Failed to allocate memory.\n"); return; }
- pin = This->ppPins[This->cStreams - 1]; - gst_pad_set_element_private(mypad, pin); - pin->my_sink = mypad; - - gst_segment_init(pin->segment, GST_FORMAT_TIME); - if (!strcmp(typename, "video/x-raw")) { GstElement *vconv; @@ -889,9 +876,9 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, struct gstdemux * goto exit; } } else - ret = gst_pad_link(pad, mypad); + ret = gst_pad_link(pad, pin->my_sink);
- gst_pad_set_active(mypad, 1); + gst_pad_set_active(pin->my_sink, 1);
exit: TRACE("Linking: %i\n", ret); @@ -1083,14 +1070,12 @@ static void unknown_type(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer u
static HRESULT GST_Connect(struct gstdemux *This, IPin *pConnectPin, ALLOCATOR_PROPERTIES *props) { - int ret, i; - LONGLONG avail, duration; + LONGLONG avail; GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE( "quartz_src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); - GstElement *gstfilter;
This->props = *props; IAsyncReader_Length(This->reader, &This->filesize, &avail); @@ -1103,68 +1088,21 @@ static HRESULT GST_Connect(struct gstdemux *This, IPin *pConnectPin, ALLOCATOR_P This->container = gst_bin_new(NULL); gst_element_set_bus(This->container, This->bus);
- gstfilter = gst_element_factory_make("decodebin", NULL); - if (!gstfilter) { - ERR("Could not make source filter, are gstreamer-plugins-* installed for %u bits?\n", - 8 * (int)sizeof(void*)); - return E_FAIL; - } - - gst_bin_add(GST_BIN(This->container), gstfilter); - - g_signal_connect(gstfilter, "pad-added", G_CALLBACK(existing_new_pad_wrapper), This); - g_signal_connect(gstfilter, "pad-removed", G_CALLBACK(removed_decoded_pad_wrapper), This); - g_signal_connect(gstfilter, "autoplug-select", G_CALLBACK(autoplug_blacklist_wrapper), This); - g_signal_connect(gstfilter, "unknown-type", G_CALLBACK(unknown_type_wrapper), This); - This->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src"); gst_pad_set_getrange_function(This->my_src, request_buffer_src_wrapper); gst_pad_set_query_function(This->my_src, query_function_wrapper); gst_pad_set_activatemode_function(This->my_src, activate_mode_wrapper); gst_pad_set_event_function(This->my_src, event_src_wrapper); gst_pad_set_element_private (This->my_src, This); - This->their_sink = gst_element_get_static_pad(gstfilter, "sink");
- g_signal_connect(gstfilter, "no-more-pads", G_CALLBACK(no_more_pads_wrapper), This); - ret = gst_pad_link(This->my_src, This->their_sink); - if (ret < 0) { - ERR("Returns: %i\n", ret); - return E_FAIL; - } This->start = This->nextofs = This->nextpullofs = This->stop = 0;
- /* Add initial pins */ This->initial = TRUE; - ResetEvent(This->no_more_pads_event); - gst_element_set_state(This->container, GST_STATE_PLAYING); - ret = gst_element_get_state(This->container, NULL, NULL, -1); - - if (ret == GST_STATE_CHANGE_FAILURE) - { - ERR("GStreamer failed to play stream\n"); + if (!This->init_gst(This)) return E_FAIL; - } - - WaitForSingleObject(This->no_more_pads_event, INFINITE); - - gst_pad_query_duration(This->ppPins[0]->their_src, GST_FORMAT_TIME, &duration); - for (i = 0; i < This->cStreams; ++i) - { - This->ppPins[i]->seek.llDuration = This->ppPins[i]->seek.llStop = duration / 100; - This->ppPins[i]->seek.llCurrent = 0; - if (!This->ppPins[i]->seek.llDuration) - This->ppPins[i]->seek.dwCapabilities = 0; - WaitForSingleObject(This->ppPins[i]->caps_event, INFINITE); - } - *props = This->props; - - This->ignore_flush = TRUE; - gst_element_set_state(This->container, GST_STATE_READY); - gst_element_get_state(This->container, NULL, NULL, -1); - This->ignore_flush = FALSE; - This->initial = FALSE;
+ *props = This->props; This->nextofs = This->nextpullofs = 0; return S_OK; } @@ -1238,6 +1176,67 @@ static const BasePinFuncTable sink_ops = .pfnGetMediaType = BasePinImpl_GetMediaType, };
+static BOOL gstdecoder_init_gst(struct gstdemux *filter) +{ + GstElement *element = gst_element_factory_make("decodebin", NULL); + LONGLONG duration; + unsigned int i; + int ret; + + if (!element) + { + ERR("Failed to create decodebin; are %u-bit GStreamer "base" plugins installed?\n", + 8 * (int)sizeof(void*)); + return FALSE; + } + + gst_bin_add(GST_BIN(filter->container), element); + + g_signal_connect(element, "pad-added", G_CALLBACK(existing_new_pad_wrapper), filter); + g_signal_connect(element, "pad-removed", G_CALLBACK(removed_decoded_pad_wrapper), filter); + g_signal_connect(element, "autoplug-select", G_CALLBACK(autoplug_blacklist_wrapper), filter); + g_signal_connect(element, "unknown-type", G_CALLBACK(unknown_type_wrapper), filter); + g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_wrapper), filter); + + filter->their_sink = gst_element_get_static_pad(element, "sink"); + ResetEvent(filter->no_more_pads_event); + + if ((ret = gst_pad_link(filter->my_src, filter->their_sink)) < 0) + { + ERR("Failed to link pads, error %d.\n", ret); + return FALSE; + } + + gst_element_set_state(filter->container, GST_STATE_PLAYING); + ret = gst_element_get_state(filter->container, NULL, NULL, -1); + if (ret == GST_STATE_CHANGE_FAILURE) + { + ERR("Failed to play stream.\n"); + return FALSE; + } + + WaitForSingleObject(filter->no_more_pads_event, INFINITE); + + gst_pad_query_duration(filter->ppPins[0]->their_src, GST_FORMAT_TIME, &duration); + for (i = 0; i < filter->cStreams; ++i) + { + struct gstdemux_source *pin = filter->ppPins[i]; + + pin->seek.llDuration = pin->seek.llStop = duration / 100; + pin->seek.llCurrent = 0; + if (!pin->seek.llDuration) + pin->seek.dwCapabilities = 0; + WaitForSingleObject(pin->caps_event, INFINITE); + } + + filter->ignore_flush = TRUE; + gst_element_set_state(filter->container, GST_STATE_READY); + gst_element_get_state(filter->container, NULL, NULL, -1); + filter->ignore_flush = FALSE; + + return TRUE; +} + IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr) { struct gstdemux *object; @@ -1264,6 +1263,7 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr) lstrcpynW(object->sink.name, wcsInputPinName, ARRAY_SIZE(object->sink.name)); object->sink.IPin_iface.lpVtbl = &GST_InputPin_Vtbl; object->sink.pFuncsTable = &sink_ops; + object->init_gst = gstdecoder_init_gst; *phr = S_OK;
TRACE("Created GStreamer demuxer %p.\n", object); @@ -1784,28 +1784,37 @@ static const struct strmbase_source_ops source_ops = GSTOutPin_DecideAllocator, };
-static BOOL create_pin(struct gstdemux *filter, const WCHAR *name) +static struct gstdemux_source *create_pin(struct gstdemux *filter, const WCHAR *name) { struct gstdemux_source *pin, **new_array; + char pad_name[19];
if (!(new_array = heap_realloc(filter->ppPins, (filter->cStreams + 1) * sizeof(*new_array)))) - return FALSE; + return NULL; filter->ppPins = new_array;
if (!(pin = heap_alloc_zero(sizeof(*pin)))) - return FALSE; + return NULL;
strmbase_source_init(&pin->pin, &GST_OutputPin_Vtbl, &filter->filter, name, &source_ops); pin->caps_event = CreateEventW(NULL, FALSE, FALSE, NULL); pin->segment = gst_segment_new(); + gst_segment_init(pin->segment, GST_FORMAT_TIME); pin->IQualityControl_iface.lpVtbl = &GSTOutPin_QualityControl_Vtbl; SourceSeeking_Init(&pin->seek, &GST_Seeking_Vtbl, GST_ChangeStop, GST_ChangeCurrent, GST_ChangeRate, &filter->filter.csFilter); BaseFilterImpl_IncrementPinVersion(&filter->filter);
+ sprintf(pad_name, "qz_sink_%u", filter->cStreams); + pin->my_sink = gst_pad_new(pad_name, GST_PAD_SINK); + gst_pad_set_element_private(pin->my_sink, pin); + gst_pad_set_chain_function(pin->my_sink, got_data_sink_wrapper); + gst_pad_set_event_function(pin->my_sink, event_sink_wrapper); + gst_pad_set_query_function(pin->my_sink, query_sink_wrapper); + filter->ppPins[filter->cStreams++] = pin; - return TRUE; + return pin; }
static HRESULT GST_RemoveOutputPins(struct gstdemux *This) @@ -2163,3 +2172,112 @@ void start_dispatch_thread(void) pthread_key_create(&wine_gst_key, NULL); CloseHandle(CreateThread(NULL, 0, &dispatch_thread, NULL, 0, NULL)); } + +static HRESULT WINAPI wave_parser_sink_CheckMediaType(BasePin *iface, const AM_MEDIA_TYPE *mt) +{ + if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Stream)) + return S_FALSE; + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WAVE)) + return S_OK; + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_AU) || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_AIFF)) + FIXME("AU and AIFF files are not yet supported.\n"); + return S_FALSE; +} + +static const BasePinFuncTable wave_parser_sink_ops = +{ + .pfnCheckMediaType = wave_parser_sink_CheckMediaType, + .pfnGetMediaType = BasePinImpl_GetMediaType, +}; + +static BOOL wave_parser_init_gst(struct gstdemux *filter) +{ + static const WCHAR source_name[] = {'o','u','t','p','u','t',0}; + struct gstdemux_source *pin; + GstElement *element; + LONGLONG duration; + int ret; + + if (!(element = gst_element_factory_make("wavparse", NULL))) + { + ERR("Failed to create wavparse; are %u-bit GStreamer "good" plugins installed?\n", + 8 * (int)sizeof(void*)); + return FALSE; + } + + gst_bin_add(GST_BIN(filter->container), element); + + filter->their_sink = gst_element_get_static_pad(element, "sink"); + if ((ret = gst_pad_link(filter->my_src, filter->their_sink)) < 0) + { + ERR("Failed to link sink pads, error %d.\n", ret); + return FALSE; + } + + if (!(pin = create_pin(filter, source_name))) + return FALSE; + pin->their_src = gst_element_get_static_pad(element, "src"); + gst_object_ref(pin->their_src); + if ((ret = gst_pad_link(pin->their_src, pin->my_sink)) < 0) + { + ERR("Failed to link source pads, error %d.\n", ret); + return FALSE; + } + + gst_pad_set_active(pin->my_sink, 1); + gst_element_set_state(filter->container, GST_STATE_PAUSED); + ret = gst_element_get_state(filter->container, NULL, NULL, -1); + if (ret == GST_STATE_CHANGE_FAILURE) + { + ERR("Failed to play stream.\n"); + return FALSE; + } + + gst_pad_query_duration(pin->their_src, GST_FORMAT_TIME, &duration); + pin->seek.llDuration = pin->seek.llStop = duration / 100; + pin->seek.llCurrent = 0; + if (!pin->seek.llDuration) + pin->seek.dwCapabilities = 0; + + WaitForSingleObject(pin->caps_event, INFINITE); + + filter->ignore_flush = TRUE; + gst_element_set_state(filter->container, GST_STATE_READY); + gst_element_get_state(filter->container, NULL, NULL, -1); + filter->ignore_flush = FALSE; + + return TRUE; +} + +IUnknown * CALLBACK wave_parser_create(IUnknown *outer, HRESULT *phr) +{ + static const WCHAR sink_name[] = {'i','n','p','u','t',' ','p','i','n',0}; + struct gstdemux *object; + + if (!init_gstreamer()) + { + *phr = E_FAIL; + return NULL; + } + + mark_wine_thread(); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + { + *phr = E_OUTOFMEMORY; + return NULL; + } + + strmbase_filter_init(&object->filter, &GST_Vtbl, outer, &CLSID_WAVEParser, &filter_ops); + + object->sink.dir = PINDIR_INPUT; + object->sink.filter = &object->filter; + lstrcpynW(object->sink.name, sink_name, ARRAY_SIZE(object->sink.name)); + object->sink.IPin_iface.lpVtbl = &GST_InputPin_Vtbl; + object->sink.pFuncsTable = &wave_parser_sink_ops; + object->init_gst = wave_parser_init_gst; + *phr = S_OK; + + TRACE("Created WAVE parser %p.\n", object); + return &object->filter.IUnknown_inner; +} diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 4419a6fde54..8503f9c7aba 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -46,6 +46,8 @@ 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 const WCHAR wave_parserW[] = +{'W','a','v','e',' ','P','a','r','s','e','r',0};
static WCHAR wNull[] = {'\0'};
@@ -180,6 +182,47 @@ AMOVIESETUP_FILTER const amfAudioConvert = amfAudioConvertPin };
+static const AMOVIESETUP_MEDIATYPE wave_parser_sink_type_data[] = +{ + {&MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE}, + {&MEDIATYPE_Stream, &MEDIASUBTYPE_AU}, + {&MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF}, +}; + +static const AMOVIESETUP_MEDIATYPE wave_parser_source_type_data[] = +{ + {&MEDIATYPE_Audio, &GUID_NULL}, +}; + +static const AMOVIESETUP_PIN wave_parser_pin_data[] = +{ + { + NULL, + FALSE, FALSE, FALSE, FALSE, + &GUID_NULL, + NULL, + ARRAY_SIZE(wave_parser_sink_type_data), + wave_parser_sink_type_data, + }, + { + NULL, + FALSE, FALSE, FALSE, FALSE, + &GUID_NULL, + NULL, + ARRAY_SIZE(wave_parser_source_type_data), + wave_parser_source_type_data, + }, +}; + +static const AMOVIESETUP_FILTER wave_parser_filter_data = +{ + &CLSID_WAVEParser, + wave_parserW, + MERIT_UNLIKELY, + ARRAY_SIZE(wave_parser_pin_data), + wave_parser_pin_data, +}; + FactoryTemplate const g_Templates[] = { { wGstreamer_Splitter, @@ -216,6 +259,13 @@ FactoryTemplate const g_Templates[] = { NULL, &amfAudioConvert, }, + { + wave_parserW, + &CLSID_WAVEParser, + wave_parser_create, + NULL, + &wave_parser_filter_data, + }, };
const int g_cTemplates = ARRAY_SIZE(g_Templates);
On Mon, 16 Sep 2019 19:29:47 -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
I'm so exciting to hear this idea. This might be outside the scope of your improvements, but what do you think about decoding MPEG-1 video streams? GStreamer's mpegpsdemux and mpegvideoparse are in the "bad" set and have multi-arch issue in Ubuntu 18.04 LTS[1]. [1] gstreamer1.0-plugins-bad package depends on liblilv-0-0 0.24.2~dfsg0-1 package which doesn't support multi-arch. (Debian bug #904099)
Regarding the patch, it's very long. You might want to split into two parts, e.g. i) introducing init_gst member and make gstdecoder_init_gst, ii) move WAVE parser function to winegstreamer and add wave_parser_init_gst.
Akihiro Sagawa
On 9/17/19 9:04 AM, Akihiro Sagawa wrote:
On Mon, 16 Sep 2019 19:29:47 -0500, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
I'm so exciting to hear this idea. This might be outside the scope of your improvements, but what do you think about decoding MPEG-1 video streams? GStreamer's mpegpsdemux and mpegvideoparse are in the "bad" set and have multi-arch issue in Ubuntu 18.04 LTS[1].
Well, that's essentially the problem we have already; this patch doesn't really change anything. But yes, implementing either PS or video parsing would be pretty easy to plug in in this manner.
(Side note: I'm not actually sure whether PS demuxing is still covered under patents. If it is, we don't have much of a choice anyway; we'd have to delegate to some library or another...)
Note also that it's extremely rare for applications to manually create decoders. Bug 9127 [2] has a lot of applications attached to it, but almost all of them use one of the autoplugging APIs (RenderFile(), Connect(), etc.) The only one I found that actually depends on the MPEG-1 stream splitter being able to split program streams is LEGO Drome Racers.
[2] https://bugs.winehq.org/show_bug.cgi?id=9127
Regarding the patch, it's very long. You might want to split into two parts, e.g. i) introducing init_gst member and make gstdecoder_init_gst, ii) move WAVE parser function to winegstreamer and add wave_parser_init_gst.
Yeah, that's probably a good idea.
Akihiro Sagawa
September 16, 2019 7:30 PM, "Zebediah Figura" z.figura12@gmail.com wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
This will break on Mac when wineqtdecoder is used instead of winegstreamer.
Chip
On Sep 17, 2019, at 9:26 AM, Chip Davis cdavis@codeweavers.com wrote:
September 16, 2019 7:30 PM, "Zebediah Figura" z.figura12@gmail.com wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
This will break on Mac when wineqtdecoder is used instead of winegstreamer.
Of course, wineqtdecoder is not long for this world. But I would prefer leaving open the possibility of replacing it with an AVFoundation-based replacement, rather than requiring GStreamer.
-Ken
On 9/17/19 9:26 AM, Chip Davis wrote:
September 16, 2019 7:30 PM, "Zebediah Figura" z.figura12@gmail.com wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
As might be implied by this patch, I also have patches to replace the AVI splitter and the MPEG-1 splitter with avidemux and mpegaudioparse, respectively.
This of course means requiring GStreamer to decode all media files. I'm not particularly inclined to see this as a blocking problem, especially since the required plugins are all in the "good" set, which as far as I'm aware has full multiarch handling in all major distributions.
This will break on Mac when wineqtdecoder is used instead of winegstreamer.
Well, yes, except not really. Autoplugging will still work, and it's very rare for applications to manually create specific filters to decode (see my reply to Akihiro Sagawa in this same thread).
Chip