[QUARTZ] Added parser template and made AVISplitter use it.
Christian Costa
titan.costa at wanadoo.fr
Mon Feb 7 15:09:43 CST 2005
Hi,
Changelog:
Added parser template and made AVISplitter use it.
Christian Costa titan.costa at wanadoo.fr
-------------- next part --------------
Index: dlls/quartz/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/quartz/Makefile.in,v
retrieving revision 1.42
diff -u -r1.42 Makefile.in
--- dlls/quartz/Makefile.in 1 Feb 2005 14:22:00 -0000 1.42
+++ dlls/quartz/Makefile.in 7 Feb 2005 19:54:35 -0000
@@ -22,6 +22,7 @@
filtermapper.c \
main.c \
memallocator.c \
+ parser.c \
pin.c \
regsvr.c \
systemclock.c \
Index: dlls/quartz/avisplit.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/avisplit.c,v
retrieving revision 1.12
diff -u -r1.12 avisplit.c
--- dlls/quartz/avisplit.c 6 Jan 2005 19:36:47 -0000 1.12
+++ dlls/quartz/avisplit.c 7 Feb 2005 19:54:39 -0000
@@ -2,6 +2,7 @@
* AVI Splitter Filter
*
* Copyright 2003 Robert Shearman
+ * Copyright 2004-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
@@ -40,460 +41,19 @@
#include <math.h>
#include <assert.h>
-WINE_DEFAULT_DEBUG_CHANNEL(quartz);
-
-static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
-static const struct IBaseFilterVtbl AVISplitter_Vtbl;
-static const struct IMediaSeekingVtbl AVISplitter_Seeking_Vtbl;
-static const struct IPinVtbl AVISplitter_OutputPin_Vtbl;
-static const struct IPinVtbl AVISplitter_InputPin_Vtbl;
-
-static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample);
-static HRESULT AVISplitter_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
-static HRESULT AVISplitter_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
-static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin);
-static HRESULT AVISplitter_ChangeStart(LPVOID iface);
-static HRESULT AVISplitter_ChangeStop(LPVOID iface);
-static HRESULT AVISplitter_ChangeRate(LPVOID iface);
+#include "parser.h"
-static HRESULT AVISplitter_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
-typedef struct AVISplitter
+typedef struct AVISplitterImpl
{
- const IBaseFilterVtbl * lpVtbl;
-
- ULONG refCount;
- CRITICAL_SECTION csFilter;
- FILTER_STATE state;
- REFERENCE_TIME rtStreamStart;
- IReferenceClock * pClock;
- FILTER_INFO filterInfo;
-
- PullPin * pInputPin;
- ULONG cStreams;
- IPin ** ppPins;
+ ParserImpl Parser;
IMediaSample * pCurrentSample;
RIFFCHUNK CurrentChunk;
LONGLONG CurrentChunkOffset; /* in media time */
LONGLONG EndOfFile;
AVIMAINHEADER AviHeader;
-} AVISplitter;
-
-typedef struct AVISplitter_OutputPin
-{
- OutputPin pin;
-
- AM_MEDIA_TYPE * pmt;
- float fSamplesPerSec;
- DWORD dwSamplesProcessed;
- DWORD dwSampleSize;
- DWORD dwLength;
- MediaSeekingImpl mediaSeeking;
-} AVISplitter_OutputPin;
-
-
-#define _IMediaSeeking_Offset ((int)(&(((AVISplitter_OutputPin*)0)->mediaSeeking)))
-#define ICOM_THIS_From_IMediaSeeking(impl, iface) impl* This = (impl*)(((char*)iface)-_IMediaSeeking_Offset);
-
-HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
-{
- HRESULT hr;
- PIN_INFO piInput;
- AVISplitter * pAviSplit;
-
- TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
- *ppv = NULL;
-
- if (pUnkOuter)
- return CLASS_E_NOAGGREGATION;
-
- pAviSplit = CoTaskMemAlloc(sizeof(AVISplitter));
-
- pAviSplit->lpVtbl = &AVISplitter_Vtbl;
- pAviSplit->refCount = 1;
- InitializeCriticalSection(&pAviSplit->csFilter);
- pAviSplit->state = State_Stopped;
- pAviSplit->pClock = NULL;
- pAviSplit->pCurrentSample = NULL;
- ZeroMemory(&pAviSplit->filterInfo, sizeof(FILTER_INFO));
-
- pAviSplit->cStreams = 0;
- pAviSplit->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
-
- /* construct input pin */
- piInput.dir = PINDIR_INPUT;
- piInput.pFilter = (IBaseFilter *)pAviSplit;
- strncpyW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
-
- hr = AVISplitter_InputPin_Construct(&piInput, AVISplitter_Sample, (LPVOID)pAviSplit, AVISplitter_QueryAccept, &pAviSplit->csFilter, (IPin **)&pAviSplit->pInputPin);
-
- if (SUCCEEDED(hr))
- {
- pAviSplit->ppPins[0] = (IPin *)pAviSplit->pInputPin;
- pAviSplit->pInputPin->fnPreConnect = AVISplitter_InputPin_PreConnect;
- *ppv = (LPVOID)pAviSplit;
- }
- else
- {
- CoTaskMemFree(pAviSplit->ppPins);
- DeleteCriticalSection(&pAviSplit->csFilter);
- CoTaskMemFree(pAviSplit);
- }
-
- return hr;
-}
-
-static HRESULT AVISplitter_OutputPin_Init(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, float fSamplesPerSec, LPCRITICAL_SECTION pCritSec, AVISplitter_OutputPin * pPinImpl)
-{
- pPinImpl->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
- CopyMediaType(pPinImpl->pmt, pmt);
- pPinImpl->dwSamplesProcessed = 0;
- pPinImpl->dwSampleSize = 0;
- pPinImpl->fSamplesPerSec = fSamplesPerSec;
-
- MediaSeekingImpl_Init((LPVOID)pPinInfo->pFilter, AVISplitter_ChangeStop, AVISplitter_ChangeStart, AVISplitter_ChangeRate, &pPinImpl->mediaSeeking);
- pPinImpl->mediaSeeking.lpVtbl = &AVISplitter_Seeking_Vtbl;
-
- return OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pCritSec, &pPinImpl->pin);
-}
-
-static HRESULT AVISplitter_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, float fSamplesPerSec, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
-{
- AVISplitter_OutputPin * pPinImpl;
-
- *ppPin = NULL;
-
- assert(pPinInfo->dir == PINDIR_OUTPUT);
-
- pPinImpl = CoTaskMemAlloc(sizeof(AVISplitter_OutputPin));
-
- if (!pPinImpl)
- return E_OUTOFMEMORY;
-
- if (SUCCEEDED(AVISplitter_OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pmt, fSamplesPerSec, pCritSec, pPinImpl)))
- {
- pPinImpl->pin.pin.lpVtbl = &AVISplitter_OutputPin_Vtbl;
-
- *ppPin = (IPin *)pPinImpl;
- return S_OK;
- }
- return E_FAIL;
-}
-
-static HRESULT WINAPI AVISplitter_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
-{
- AVISplitter *This = (AVISplitter *)iface;
- TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
-
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = (LPVOID)This;
- else if (IsEqualIID(riid, &IID_IPersist))
- *ppv = (LPVOID)This;
- else if (IsEqualIID(riid, &IID_IMediaFilter))
- *ppv = (LPVOID)This;
- else if (IsEqualIID(riid, &IID_IBaseFilter))
- *ppv = (LPVOID)This;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
-
- FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
-
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AVISplitter_AddRef(IBaseFilter * iface)
-{
- AVISplitter *This = (AVISplitter *)iface;
- ULONG refCount = InterlockedIncrement(&This->refCount);
-
- TRACE("(%p/%p)->() AddRef from %ld\n", This, iface, refCount - 1);
-
- return refCount;
-}
-
-static ULONG WINAPI AVISplitter_Release(IBaseFilter * iface)
-{
- AVISplitter *This = (AVISplitter *)iface;
- ULONG refCount = InterlockedDecrement(&This->refCount);
-
- TRACE("(%p/%p)->() Release from %ld\n", This, iface, refCount + 1);
-
- if (!refCount)
- {
- ULONG i;
-
- DeleteCriticalSection(&This->csFilter);
- if (This->pClock)
- IReferenceClock_Release(This->pClock);
-
- for (i = 0; i < This->cStreams + 1; i++)
- IPin_Release(This->ppPins[i]);
-
- HeapFree(GetProcessHeap(), 0, This->ppPins);
- This->lpVtbl = NULL;
-
- TRACE("Destroying AVI splitter\n");
- CoTaskMemFree(This);
-
- return 0;
- }
- else
- return refCount;
-}
-
-/** IPersist methods **/
-
-static HRESULT WINAPI AVISplitter_GetClassID(IBaseFilter * iface, CLSID * pClsid)
-{
- TRACE("(%p)\n", pClsid);
-
- *pClsid = CLSID_AviSplitter;
-
- return S_OK;
-}
-
-/** IMediaFilter methods **/
-
-static HRESULT WINAPI AVISplitter_Stop(IBaseFilter * iface)
-{
- HRESULT hr;
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("()\n");
-
- EnterCriticalSection(&This->csFilter);
- {
- hr = PullPin_StopProcessing(This->pInputPin);
- This->state = State_Stopped;
- }
- LeaveCriticalSection(&This->csFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI AVISplitter_Pause(IBaseFilter * iface)
-{
- HRESULT hr = S_OK;
- BOOL bInit;
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("()\n");
-
- EnterCriticalSection(&This->csFilter);
- {
- bInit = (This->state == State_Stopped);
- This->state = State_Paused;
- }
- LeaveCriticalSection(&This->csFilter);
-
- if (bInit)
- {
- unsigned int i;
-
- hr = PullPin_Seek(This->pInputPin, This->CurrentChunkOffset, This->EndOfFile);
-
- if (SUCCEEDED(hr))
- hr = PullPin_InitProcessing(This->pInputPin);
-
- if (SUCCEEDED(hr))
- {
- for (i = 1; i < This->cStreams + 1; i++)
- {
- AVISplitter_OutputPin* StreamPin = (AVISplitter_OutputPin *)This->ppPins[i];
- OutputPin_DeliverNewSegment((OutputPin *)This->ppPins[i], 0, (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec), 1.0);
- StreamPin->mediaSeeking.llDuration = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec);
- StreamPin->mediaSeeking.llStop = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec);
- OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
- }
-
- /* FIXME: this is a little hacky: we have to deliver (at least?) one sample
- * to each renderer before they will complete their transitions. We should probably
- * seek through the stream for the first of each, rather than do it this way which is
- * probably a bit prone to deadlocking */
- hr = PullPin_StartProcessing(This->pInputPin);
- }
- }
- /* FIXME: else pause thread */
-
- return hr;
-}
-
-static HRESULT WINAPI AVISplitter_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
-{
- HRESULT hr = S_OK;
- AVISplitter *This = (AVISplitter *)iface;
- int i;
-
- TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
-
- EnterCriticalSection(&This->csFilter);
- {
- This->rtStreamStart = tStart;
- This->state = State_Running;
-
- hr = PullPin_InitProcessing(This->pInputPin);
-
- if (SUCCEEDED(hr))
- {
- for (i = 1; i < This->cStreams + 1; i++)
- {
- OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
- }
- hr = PullPin_StartProcessing(This->pInputPin);
- }
- }
- LeaveCriticalSection(&This->csFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI AVISplitter_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
-{
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%ld, %p)\n", dwMilliSecsTimeout, pState);
-
- EnterCriticalSection(&This->csFilter);
- {
- *pState = This->state;
- }
- LeaveCriticalSection(&This->csFilter);
-
- /* FIXME: this is a little bit unsafe, but I don't see that we can do this
- * while in the critical section. Maybe we could copy the pointer and addref in the
- * critical section and then release after this.
- */
- if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE))
- return VFW_S_STATE_INTERMEDIATE;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AVISplitter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
-{
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%p)\n", pClock);
-
- EnterCriticalSection(&This->csFilter);
- {
- if (This->pClock)
- IReferenceClock_Release(This->pClock);
- This->pClock = pClock;
- if (This->pClock)
- IReferenceClock_AddRef(This->pClock);
- }
- LeaveCriticalSection(&This->csFilter);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AVISplitter_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
-{
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%p)\n", ppClock);
-
- EnterCriticalSection(&This->csFilter);
- {
- *ppClock = This->pClock;
- if (This->pClock)
- IReferenceClock_AddRef(This->pClock);
- }
- LeaveCriticalSection(&This->csFilter);
-
- return S_OK;
-}
-
-/** IBaseFilter implementation **/
-
-static HRESULT WINAPI AVISplitter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
-{
- ENUMPINDETAILS epd;
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%p)\n", ppEnum);
-
- epd.cPins = This->cStreams + 1; /* +1 for input pin */
- epd.ppPins = This->ppPins;
- return IEnumPinsImpl_Construct(&epd, ppEnum);
-}
-
-static HRESULT WINAPI AVISplitter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
-{
- FIXME("AVISplitter::FindPin(...)\n");
-
- /* FIXME: critical section */
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AVISplitter_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
-{
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%p)\n", pInfo);
-
- strcpyW(pInfo->achName, This->filterInfo.achName);
- pInfo->pGraph = This->filterInfo.pGraph;
-
- if (pInfo->pGraph)
- IFilterGraph_AddRef(pInfo->pGraph);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AVISplitter_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
-{
- HRESULT hr = S_OK;
- AVISplitter *This = (AVISplitter *)iface;
-
- TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
-
- EnterCriticalSection(&This->csFilter);
- {
- if (pName)
- strcpyW(This->filterInfo.achName, pName);
- else
- *This->filterInfo.achName = '\0';
- This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
- }
- LeaveCriticalSection(&This->csFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI AVISplitter_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
-{
- TRACE("(%p)\n", pVendorInfo);
- return E_NOTIMPL;
-}
-
-static const IBaseFilterVtbl AVISplitter_Vtbl =
-{
- AVISplitter_QueryInterface,
- AVISplitter_AddRef,
- AVISplitter_Release,
- AVISplitter_GetClassID,
- AVISplitter_Stop,
- AVISplitter_Pause,
- AVISplitter_Run,
- AVISplitter_GetState,
- AVISplitter_SetSyncSource,
- AVISplitter_GetSyncSource,
- AVISplitter_EnumPins,
- AVISplitter_FindPin,
- AVISplitter_QueryFilterInfo,
- AVISplitter_JoinFilterGraph,
- AVISplitter_QueryVendorInfo
-};
+} AVISplitterImpl;
static HRESULT AVISplitter_NextChunk(LONGLONG * pllCurrentChunkOffset, RIFFCHUNK * pCurrentChunk, const REFERENCE_TIME * tStart, const REFERENCE_TIME * tStop, const BYTE * pbSrcStream)
{
@@ -514,7 +74,7 @@
static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample)
{
- AVISplitter *This = (AVISplitter *)iface;
+ AVISplitterImpl *This = (AVISplitterImpl *)iface;
LPBYTE pbSrcStream = NULL;
long cbSrcStream = 0;
REFERENCE_TIME tStart, tStop;
@@ -559,7 +119,7 @@
long chunk_remaining_bytes = 0;
long offset_src;
WORD streamId;
- AVISplitter_OutputPin * pOutputPin;
+ Parser_OutputPin * pOutputPin;
BOOL bSyncPoint = TRUE;
if (This->CurrentChunkOffset >= tStart)
@@ -617,13 +177,13 @@
streamId = StreamFromFOURCC(This->CurrentChunk.fcc);
- if (streamId > This->cStreams)
+ if (streamId > This->Parser.cStreams)
{
- ERR("Corrupted AVI file (contains stream id %d, but supposed to only have %ld streams)\n", streamId, This->cStreams);
+ ERR("Corrupted AVI file (contains stream id %d, but supposed to only have %ld streams)\n", streamId, This->Parser.cStreams);
return E_FAIL;
}
- pOutputPin = (AVISplitter_OutputPin *)This->ppPins[streamId + 1];
+ pOutputPin = (Parser_OutputPin *)This->Parser.ppPins[streamId + 1];
if (!This->pCurrentSample)
{
@@ -726,11 +286,10 @@
return S_FALSE;
}
-static HRESULT AVISplitter_ProcessStreamList(AVISplitter * This, const BYTE * pData, DWORD cb)
+static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE * pData, DWORD cb)
{
PIN_INFO piOutput;
const RIFFCHUNK * pChunk;
- IPin ** ppOldPins;
HRESULT hr;
AM_MEDIA_TYPE amt;
float fSamplesPerSec = 0.0f;
@@ -747,7 +306,7 @@
ZeroMemory(&amt, sizeof(amt));
piOutput.dir = PINDIR_OUTPUT;
piOutput.pFilter = (IBaseFilter *)This;
- wsprintfW(piOutput.achName, wszStreamTemplate, This->cStreams);
+ wsprintfW(piOutput.achName, wszStreamTemplate, This->Parser.cStreams);
for (pChunk = (const RIFFCHUNK *)pData;
((const BYTE *)pChunk >= pData) && ((const BYTE *)pChunk + sizeof(RIFFCHUNK) < pData + cb) && (pChunk->cb > 0);
@@ -858,54 +417,11 @@
TRACE("dwSampleSize = %lx\n", dwSampleSize);
TRACE("dwLength = %lx\n", dwLength);
- ppOldPins = This->ppPins;
-
- This->ppPins = HeapAlloc(GetProcessHeap(), 0, (This->cStreams + 2) * sizeof(IPin *));
- memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
-
- hr = AVISplitter_OutputPin_Construct(&piOutput, &props, NULL, AVISplitter_OutputPin_QueryAccept, &amt, fSamplesPerSec, &This->csFilter, This->ppPins + This->cStreams + 1);
-
- if (SUCCEEDED(hr))
- {
- ((AVISplitter_OutputPin *)(This->ppPins[This->cStreams + 1]))->dwSampleSize = dwSampleSize;
- ((AVISplitter_OutputPin *)(This->ppPins[This->cStreams + 1]))->dwLength = dwLength;
- ((AVISplitter_OutputPin *)(This->ppPins[This->cStreams + 1]))->pin.pin.pUserData = (LPVOID)This->ppPins[This->cStreams + 1];
- This->cStreams++;
- HeapFree(GetProcessHeap(), 0, ppOldPins);
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, This->ppPins);
- This->ppPins = ppOldPins;
- ERR("Failed with error %lx\n", hr);
- }
+ hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt, fSamplesPerSec, dwSampleSize, dwLength);
return hr;
}
-static HRESULT AVISplitter_RemoveOutputPins(AVISplitter * This)
-{
- /* NOTE: should be in critical section when calling this function */
-
- ULONG i;
- IPin ** ppOldPins = This->ppPins;
-
- /* reduce the pin array down to 1 (just our input pin) */
- This->ppPins = HeapAlloc(GetProcessHeap(), 0, sizeof(IPin *) * 1);
- memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1);
-
- for (i = 0; i < This->cStreams; i++)
- {
- OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
- IPin_Release(ppOldPins[i + 1]);
- }
-
- This->cStreams = 0;
- HeapFree(GetProcessHeap(), 0, ppOldPins);
-
- return S_OK;
-}
-
/* FIXME: fix leaks on failure here */
static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin)
{
@@ -915,7 +431,7 @@
LONGLONG pos = 0; /* in bytes */
BYTE * pBuffer;
RIFFCHUNK * pCurrentChunk;
- AVISplitter * pAviSplit = (AVISplitter *)This->pin.pinInfo.pFilter;
+ AVISplitterImpl * pAviSplit = (AVISplitterImpl *)This->pin.pinInfo.pFilter;
hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
pos += sizeof(list);
@@ -1025,237 +541,29 @@
return hr;
}
-static HRESULT AVISplitter_ChangeStart(LPVOID iface)
-{
- FIXME("(%p)\n", iface);
- return S_OK;
-}
-
-static HRESULT AVISplitter_ChangeStop(LPVOID iface)
-{
- FIXME("(%p)\n", iface);
- return S_OK;
-}
-
-static HRESULT AVISplitter_ChangeRate(LPVOID iface)
-{
- FIXME("(%p)\n", iface);
- return S_OK;
-}
-
-
-static HRESULT WINAPI AVISplitter_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
-{
- ICOM_THIS_From_IMediaSeeking(AVISplitter_OutputPin, iface);
-
- return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
-}
-
-static ULONG WINAPI AVISplitter_Seeking_AddRef(IMediaSeeking * iface)
-{
- ICOM_THIS_From_IMediaSeeking(AVISplitter_OutputPin, iface);
-
- return IUnknown_AddRef((IUnknown *)This);
-}
-
-static ULONG WINAPI AVISplitter_Seeking_Release(IMediaSeeking * iface)
-{
- ICOM_THIS_From_IMediaSeeking(AVISplitter_OutputPin, iface);
-
- return IUnknown_Release((IUnknown *)This);
-}
-
-static const IMediaSeekingVtbl AVISplitter_Seeking_Vtbl =
-{
- AVISplitter_Seeking_QueryInterface,
- AVISplitter_Seeking_AddRef,
- AVISplitter_Seeking_Release,
- MediaSeekingImpl_GetCapabilities,
- MediaSeekingImpl_CheckCapabilities,
- MediaSeekingImpl_IsFormatSupported,
- MediaSeekingImpl_QueryPreferredFormat,
- MediaSeekingImpl_GetTimeFormat,
- MediaSeekingImpl_IsUsingTimeFormat,
- MediaSeekingImpl_SetTimeFormat,
- MediaSeekingImpl_GetDuration,
- MediaSeekingImpl_GetStopPosition,
- MediaSeekingImpl_GetCurrentPosition,
- MediaSeekingImpl_ConvertTimeFormat,
- MediaSeekingImpl_SetPositions,
- MediaSeekingImpl_GetPositions,
- MediaSeekingImpl_GetAvailable,
- MediaSeekingImpl_SetRate,
- MediaSeekingImpl_GetRate,
- MediaSeekingImpl_GetPreroll
-};
-
-HRESULT WINAPI AVISplitter_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
+HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
- AVISplitter_OutputPin *This = (AVISplitter_OutputPin *)iface;
+ HRESULT hr;
+ AVISplitterImpl * This;
- TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
*ppv = NULL;
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = (LPVOID)iface;
- else if (IsEqualIID(riid, &IID_IPin))
- *ppv = (LPVOID)iface;
- else if (IsEqualIID(riid, &IID_IMediaSeeking))
- *ppv = (LPVOID)&This->mediaSeeking;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
-
- FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
-
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AVISplitter_OutputPin_Release(IPin * iface)
-{
- AVISplitter_OutputPin *This = (AVISplitter_OutputPin *)iface;
- ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
-
- TRACE("()\n");
-
- if (!refCount)
- {
- DeleteMediaType(This->pmt);
- CoTaskMemFree(This->pmt);
- DeleteMediaType(&This->pin.pin.mtCurrent);
- CoTaskMemFree(This);
- return 0;
- }
- return refCount;
-}
-
-static HRESULT WINAPI AVISplitter_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
-{
- ENUMMEDIADETAILS emd;
- AVISplitter_OutputPin *This = (AVISplitter_OutputPin *)iface;
-
- TRACE("(%p)\n", ppEnum);
-
- /* override this method to allow enumeration of your types */
- emd.cMediaTypes = 1;
- emd.pMediaTypes = This->pmt;
-
- return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
-}
-
-static HRESULT AVISplitter_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
-{
- AVISplitter_OutputPin *This = (AVISplitter_OutputPin *)iface;
-
- TRACE("()\n");
- dump_AM_MEDIA_TYPE(pmt);
-
- return (memcmp(This->pmt, pmt, sizeof(AM_MEDIA_TYPE)) == 0);
-}
-
-static const IPinVtbl AVISplitter_OutputPin_Vtbl =
-{
- AVISplitter_OutputPin_QueryInterface,
- IPinImpl_AddRef,
- AVISplitter_OutputPin_Release,
- OutputPin_Connect,
- OutputPin_ReceiveConnection,
- OutputPin_Disconnect,
- IPinImpl_ConnectedTo,
- IPinImpl_ConnectionMediaType,
- IPinImpl_QueryPinInfo,
- IPinImpl_QueryDirection,
- IPinImpl_QueryId,
- IPinImpl_QueryAccept,
- AVISplitter_OutputPin_EnumMediaTypes,
- IPinImpl_QueryInternalConnections,
- OutputPin_EndOfStream,
- OutputPin_BeginFlush,
- OutputPin_EndFlush,
- OutputPin_NewSegment
-};
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
-static HRESULT AVISplitter_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
-{
- PullPin * pPinImpl;
+ /* Note: This memory is managed by the transform filter once created */
+ This = CoTaskMemAlloc(sizeof(AVISplitterImpl));
- *ppPin = NULL;
+ This->pCurrentSample = NULL;
- if (pPinInfo->dir != PINDIR_INPUT)
- {
- ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
- return E_INVALIDARG;
- }
+ hr = Parser_Create(&(This->Parser), &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect);
- pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+ if (FAILED(hr))
+ return hr;
- if (!pPinImpl)
- return E_OUTOFMEMORY;
+ *ppv = (LPVOID)This;
- if (SUCCEEDED(PullPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
- {
- pPinImpl->pin.lpVtbl = &AVISplitter_InputPin_Vtbl;
-
- *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
- return S_OK;
- }
- return E_FAIL;
-}
-
-static HRESULT WINAPI AVISplitter_InputPin_Disconnect(IPin * iface)
-{
- HRESULT hr;
- IPinImpl *This = (IPinImpl *)iface;
-
- TRACE("()\n");
-
- EnterCriticalSection(This->pCritSec);
- {
- if (This->pConnectedTo)
- {
- FILTER_STATE state;
-
- hr = IBaseFilter_GetState(This->pinInfo.pFilter, 0, &state);
-
- if (SUCCEEDED(hr) && (state == State_Stopped))
- {
- IPin_Release(This->pConnectedTo);
- This->pConnectedTo = NULL;
- hr = AVISplitter_RemoveOutputPins((AVISplitter *)This->pinInfo.pFilter);
- }
- else
- hr = VFW_E_NOT_STOPPED;
- }
- else
- hr = S_FALSE;
- }
- LeaveCriticalSection(This->pCritSec);
-
return hr;
}
-
-static const IPinVtbl AVISplitter_InputPin_Vtbl =
-{
- PullPin_QueryInterface,
- IPinImpl_AddRef,
- PullPin_Release,
- OutputPin_Connect,
- PullPin_ReceiveConnection,
- AVISplitter_InputPin_Disconnect,
- IPinImpl_ConnectedTo,
- IPinImpl_ConnectionMediaType,
- IPinImpl_QueryPinInfo,
- IPinImpl_QueryDirection,
- IPinImpl_QueryId,
- IPinImpl_QueryAccept,
- IPinImpl_EnumMediaTypes,
- IPinImpl_QueryInternalConnections,
- PullPin_EndOfStream,
- PullPin_BeginFlush,
- PullPin_EndFlush,
- PullPin_NewSegment
-};
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/parser.h 2005-02-05 19:39:54.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ * Parser declarations
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+typedef struct ParserImpl ParserImpl;
+
+typedef HRESULT (*PFN_PROCESS_SAMPLE) (LPVOID iface, IMediaSample * pSample);
+typedef HRESULT (*PFN_QUERY_ACCEPT) (LPVOID iface, const AM_MEDIA_TYPE * pmt);
+typedef HRESULT (*PFN_PRE_CONNECT) (IPin * iface, IPin * pConnectPin);
+
+struct ParserImpl
+{
+ const IBaseFilterVtbl * lpVtbl;
+
+ ULONG refCount;
+ CRITICAL_SECTION csFilter;
+ FILTER_STATE state;
+ REFERENCE_TIME rtStreamStart;
+ IReferenceClock * pClock;
+ FILTER_INFO filterInfo;
+ CLSID clsid;
+
+ PullPin * pInputPin;
+ IPin ** ppPins;
+ ULONG cStreams;
+};
+
+typedef struct Parser_OutputPin
+{
+ OutputPin pin;
+
+ AM_MEDIA_TYPE * pmt;
+ float fSamplesPerSec;
+ DWORD dwSamplesProcessed;
+ DWORD dwSampleSize;
+ DWORD dwLength;
+ MediaSeekingImpl mediaSeeking;
+} Parser_OutputPin;
+
+HRESULT Parser_AddPin(ParserImpl * This, PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, AM_MEDIA_TYPE * amt, float fSamplesPerSec, DWORD dwSampleSize, DWORD dwLength);
+HRESULT Parser_Create(ParserImpl*, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT);
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/quartz/parser.c 2005-02-05 19:02:30.000000000 +0000
@@ -0,0 +1,737 @@
+/*
+ * Parser (Base for parsers and splitters)
+ *
+ * Copyright 2003 Robert Shearman
+ * Copyright 2004-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "quartz_private.h"
+#include "control_private.h"
+#include "pin.h"
+
+#include "uuids.h"
+#include "aviriff.h"
+#include "mmreg.h"
+#include "vfwmsgs.h"
+#include "amvideo.h"
+
+#include "fourcc.h"
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include <math.h>
+#include <assert.h>
+
+#include "parser.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+
+static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
+static const struct IBaseFilterVtbl Parser_Vtbl;
+static const struct IMediaSeekingVtbl Parser_Seeking_Vtbl;
+static const struct IPinVtbl Parser_OutputPin_Vtbl;
+static const struct IPinVtbl Parser_InputPin_Vtbl;
+
+static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
+static HRESULT Parser_ChangeStart(LPVOID iface);
+static HRESULT Parser_ChangeStop(LPVOID iface);
+static HRESULT Parser_ChangeRate(LPVOID iface);
+
+static HRESULT Parser_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
+
+#define _IMediaSeeking_Offset ((int)(&(((Parser_OutputPin*)0)->mediaSeeking)))
+#define ICOM_THIS_From_IMediaSeeking(impl, iface) impl* This = (impl*)(((char*)iface)-_IMediaSeeking_Offset);
+
+HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect)
+{
+ HRESULT hr;
+ PIN_INFO piInput;
+
+ /* pTransformFilter is already allocated */
+ pParser->clsid = *pClsid;
+
+ pParser->lpVtbl = &Parser_Vtbl;
+ pParser->refCount = 1;
+ InitializeCriticalSection(&pParser->csFilter);
+ pParser->state = State_Stopped;
+ pParser->pClock = NULL;
+ ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
+
+ pParser->cStreams = 0;
+ pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
+
+ /* construct input pin */
+ piInput.dir = PINDIR_INPUT;
+ piInput.pFilter = (IBaseFilter *)pParser;
+ strncpyW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
+
+ hr = Parser_InputPin_Construct(&piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, &pParser->csFilter, (IPin **)&pParser->pInputPin);
+
+ if (SUCCEEDED(hr))
+ {
+ pParser->ppPins[0] = (IPin *)pParser->pInputPin;
+ pParser->pInputPin->fnPreConnect = fnPreConnect;
+ }
+ else
+ {
+ CoTaskMemFree(pParser->ppPins);
+ DeleteCriticalSection(&pParser->csFilter);
+ CoTaskMemFree(pParser);
+ }
+
+ return hr;
+}
+
+static HRESULT Parser_OutputPin_Init(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, float fSamplesPerSec, LPCRITICAL_SECTION pCritSec, Parser_OutputPin * pPinImpl)
+{
+ pPinImpl->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+ CopyMediaType(pPinImpl->pmt, pmt);
+ pPinImpl->dwSamplesProcessed = 0;
+ pPinImpl->dwSampleSize = 0;
+ pPinImpl->fSamplesPerSec = fSamplesPerSec;
+
+ MediaSeekingImpl_Init((LPVOID)pPinInfo->pFilter, Parser_ChangeStop, Parser_ChangeStart, Parser_ChangeRate, &pPinImpl->mediaSeeking);
+ pPinImpl->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
+
+ return OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pCritSec, &pPinImpl->pin);
+}
+
+static HRESULT Parser_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, float fSamplesPerSec, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ Parser_OutputPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ assert(pPinInfo->dir == PINDIR_OUTPUT);
+
+ pPinImpl = CoTaskMemAlloc(sizeof(Parser_OutputPin));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+
+ if (SUCCEEDED(Parser_OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pmt, fSamplesPerSec, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.pin.lpVtbl = &Parser_OutputPin_Vtbl;
+
+ *ppPin = (IPin *)pPinImpl;
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+static HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+ TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IPersist))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IMediaFilter))
+ *ppv = (LPVOID)This;
+ else if (IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = (LPVOID)This;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Parser_AddRef(IBaseFilter * iface)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+
+ TRACE("(%p/%p)->() AddRef from %ld\n", This, iface, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI Parser_Release(IBaseFilter * iface)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ TRACE("(%p/%p)->() Release from %ld\n", This, iface, refCount + 1);
+
+ if (!refCount)
+ {
+ ULONG i;
+
+ DeleteCriticalSection(&This->csFilter);
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+
+ for (i = 0; i < This->cStreams + 1; i++)
+ IPin_Release(This->ppPins[i]);
+
+ HeapFree(GetProcessHeap(), 0, This->ppPins);
+ This->lpVtbl = NULL;
+
+ TRACE("Destroying AVI splitter\n");
+ CoTaskMemFree(This);
+
+ return 0;
+ }
+ else
+ return refCount;
+}
+
+/** IPersist methods **/
+
+static HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+{
+ TRACE("(%p)\n", pClsid);
+
+ *pClsid = CLSID_AviSplitter;
+
+ return S_OK;
+}
+
+/** IMediaFilter methods **/
+
+static HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
+{
+ HRESULT hr;
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("()\n");
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ hr = PullPin_StopProcessing(This->pInputPin);
+ This->state = State_Stopped;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
+{
+ HRESULT hr = S_OK;
+ BOOL bInit;
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("()\n");
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ bInit = (This->state == State_Stopped);
+ This->state = State_Paused;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ if (bInit)
+ {
+ unsigned int i;
+
+ //hr = PullPin_Seek(This->pInputPin, This->CurrentChunkOffset, This->EndOfFile);
+
+ if (SUCCEEDED(hr))
+ hr = PullPin_InitProcessing(This->pInputPin);
+
+ if (SUCCEEDED(hr))
+ {
+ for (i = 1; i < This->cStreams + 1; i++)
+ {
+ Parser_OutputPin* StreamPin = (Parser_OutputPin *)This->ppPins[i];
+ OutputPin_DeliverNewSegment((OutputPin *)This->ppPins[i], 0, (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec), 1.0);
+ StreamPin->mediaSeeking.llDuration = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec);
+ StreamPin->mediaSeeking.llStop = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec);
+ OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
+ }
+
+ /* FIXME: this is a little hacky: we have to deliver (at least?) one sample
+ * to each renderer before they will complete their transitions. We should probably
+ * seek through the stream for the first of each, rather than do it this way which is
+ * probably a bit prone to deadlocking */
+ hr = PullPin_StartProcessing(This->pInputPin);
+ }
+ }
+ /* FIXME: else pause thread */
+
+ return hr;
+}
+
+static HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+{
+ HRESULT hr = S_OK;
+ ParserImpl *This = (ParserImpl *)iface;
+ int i;
+
+ TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ This->rtStreamStart = tStart;
+ This->state = State_Running;
+
+ hr = PullPin_InitProcessing(This->pInputPin);
+
+ if (SUCCEEDED(hr))
+ {
+ for (i = 1; i < This->cStreams + 1; i++)
+ {
+ OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
+ }
+ hr = PullPin_StartProcessing(This->pInputPin);
+ }
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%ld, %p)\n", dwMilliSecsTimeout, pState);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *pState = This->state;
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ /* FIXME: this is a little bit unsafe, but I don't see that we can do this
+ * while in the critical section. Maybe we could copy the pointer and addref in the
+ * critical section and then release after this.
+ */
+ if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE))
+ return VFW_S_STATE_INTERMEDIATE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%p)\n", pClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (This->pClock)
+ IReferenceClock_Release(This->pClock);
+ This->pClock = pClock;
+ if (This->pClock)
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%p)\n", ppClock);
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ *ppClock = This->pClock;
+ if (This->pClock)
+ IReferenceClock_AddRef(This->pClock);
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return S_OK;
+}
+
+/** IBaseFilter implementation **/
+
+static HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+ ENUMPINDETAILS epd;
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%p)\n", ppEnum);
+
+ epd.cPins = This->cStreams + 1; /* +1 for input pin */
+ epd.ppPins = This->ppPins;
+ return IEnumPinsImpl_Construct(&epd, ppEnum);
+}
+
+static HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
+{
+ FIXME("(%p)->(%s,%p)\n", iface, debugstr_w(Id), ppPin);
+
+ /* FIXME: critical section */
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+{
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%p)\n", pInfo);
+
+ strcpyW(pInfo->achName, This->filterInfo.achName);
+ pInfo->pGraph = This->filterInfo.pGraph;
+
+ if (pInfo->pGraph)
+ IFilterGraph_AddRef(pInfo->pGraph);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+{
+ HRESULT hr = S_OK;
+ ParserImpl *This = (ParserImpl *)iface;
+
+ TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
+
+ EnterCriticalSection(&This->csFilter);
+ {
+ if (pName)
+ strcpyW(This->filterInfo.achName, pName);
+ else
+ *This->filterInfo.achName = '\0';
+ This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ }
+ LeaveCriticalSection(&This->csFilter);
+
+ return hr;
+}
+
+static HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+{
+ TRACE("(%p)\n", pVendorInfo);
+ return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl Parser_Vtbl =
+{
+ Parser_QueryInterface,
+ Parser_AddRef,
+ Parser_Release,
+ Parser_GetClassID,
+ Parser_Stop,
+ Parser_Pause,
+ Parser_Run,
+ Parser_GetState,
+ Parser_SetSyncSource,
+ Parser_GetSyncSource,
+ Parser_EnumPins,
+ Parser_FindPin,
+ Parser_QueryFilterInfo,
+ Parser_JoinFilterGraph,
+ Parser_QueryVendorInfo
+};
+
+HRESULT Parser_AddPin(ParserImpl * This, PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, AM_MEDIA_TYPE * amt, float fSamplesPerSec, DWORD dwSampleSize, DWORD dwLength)
+{
+ IPin ** ppOldPins;
+ HRESULT hr;
+
+ ppOldPins = This->ppPins;
+
+ This->ppPins = HeapAlloc(GetProcessHeap(), 0, (This->cStreams + 2) * sizeof(IPin *));
+ memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
+
+ hr = Parser_OutputPin_Construct(piOutput, props, NULL, Parser_OutputPin_QueryAccept, amt, fSamplesPerSec, &This->csFilter, This->ppPins + This->cStreams + 1);
+
+ if (SUCCEEDED(hr))
+ {
+ ((Parser_OutputPin *)(This->ppPins[This->cStreams + 1]))->dwSampleSize = dwSampleSize;
+ ((Parser_OutputPin *)(This->ppPins[This->cStreams + 1]))->dwLength = dwLength;
+ ((Parser_OutputPin *)(This->ppPins[This->cStreams + 1]))->pin.pin.pUserData = (LPVOID)This->ppPins[This->cStreams + 1];
+ This->cStreams++;
+ HeapFree(GetProcessHeap(), 0, ppOldPins);
+ }
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, This->ppPins);
+ This->ppPins = ppOldPins;
+ ERR("Failed with error %lx\n", hr);
+ }
+
+ return hr;
+}
+
+static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
+{
+ /* NOTE: should be in critical section when calling this function */
+
+ ULONG i;
+ IPin ** ppOldPins = This->ppPins;
+
+ /* reduce the pin array down to 1 (just our input pin) */
+ This->ppPins = HeapAlloc(GetProcessHeap(), 0, sizeof(IPin *) * 1);
+ memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1);
+
+ for (i = 0; i < This->cStreams; i++)
+ {
+ OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
+ IPin_Release(ppOldPins[i + 1]);
+ }
+
+ This->cStreams = 0;
+ HeapFree(GetProcessHeap(), 0, ppOldPins);
+
+ return S_OK;
+}
+
+static HRESULT Parser_ChangeStart(LPVOID iface)
+{
+ FIXME("(%p)\n", iface);
+ return S_OK;
+}
+
+static HRESULT Parser_ChangeStop(LPVOID iface)
+{
+ FIXME("(%p)\n", iface);
+ return S_OK;
+}
+
+static HRESULT Parser_ChangeRate(LPVOID iface)
+{
+ FIXME("(%p)\n", iface);
+ return S_OK;
+}
+
+
+static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
+{
+ ICOM_THIS_From_IMediaSeeking(Parser_OutputPin, iface);
+
+ return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
+}
+
+static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface)
+{
+ ICOM_THIS_From_IMediaSeeking(Parser_OutputPin, iface);
+
+ return IUnknown_AddRef((IUnknown *)This);
+}
+
+static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface)
+{
+ ICOM_THIS_From_IMediaSeeking(Parser_OutputPin, iface);
+
+ return IUnknown_Release((IUnknown *)This);
+}
+
+static const IMediaSeekingVtbl Parser_Seeking_Vtbl =
+{
+ Parser_Seeking_QueryInterface,
+ Parser_Seeking_AddRef,
+ Parser_Seeking_Release,
+ MediaSeekingImpl_GetCapabilities,
+ MediaSeekingImpl_CheckCapabilities,
+ MediaSeekingImpl_IsFormatSupported,
+ MediaSeekingImpl_QueryPreferredFormat,
+ MediaSeekingImpl_GetTimeFormat,
+ MediaSeekingImpl_IsUsingTimeFormat,
+ MediaSeekingImpl_SetTimeFormat,
+ MediaSeekingImpl_GetDuration,
+ MediaSeekingImpl_GetStopPosition,
+ MediaSeekingImpl_GetCurrentPosition,
+ MediaSeekingImpl_ConvertTimeFormat,
+ MediaSeekingImpl_SetPositions,
+ MediaSeekingImpl_GetPositions,
+ MediaSeekingImpl_GetAvailable,
+ MediaSeekingImpl_SetRate,
+ MediaSeekingImpl_GetRate,
+ MediaSeekingImpl_GetPreroll
+};
+
+HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
+{
+ Parser_OutputPin *This = (Parser_OutputPin *)iface;
+
+ TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (LPVOID)iface;
+ else if (IsEqualIID(riid, &IID_IPin))
+ *ppv = (LPVOID)iface;
+ else if (IsEqualIID(riid, &IID_IMediaSeeking))
+ *ppv = (LPVOID)&This->mediaSeeking;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Parser_OutputPin_Release(IPin * iface)
+{
+ Parser_OutputPin *This = (Parser_OutputPin *)iface;
+ ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
+
+ TRACE("()\n");
+
+ if (!refCount)
+ {
+ DeleteMediaType(This->pmt);
+ CoTaskMemFree(This->pmt);
+ DeleteMediaType(&This->pin.pin.mtCurrent);
+ CoTaskMemFree(This);
+ return 0;
+ }
+ return refCount;
+}
+
+static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+{
+ ENUMMEDIADETAILS emd;
+ Parser_OutputPin *This = (Parser_OutputPin *)iface;
+
+ TRACE("(%p)\n", ppEnum);
+
+ /* override this method to allow enumeration of your types */
+ emd.cMediaTypes = 1;
+ emd.pMediaTypes = This->pmt;
+
+ return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+}
+
+static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
+{
+ Parser_OutputPin *This = (Parser_OutputPin *)iface;
+
+ TRACE("()\n");
+ dump_AM_MEDIA_TYPE(pmt);
+
+ return (memcmp(This->pmt, pmt, sizeof(AM_MEDIA_TYPE)) == 0);
+}
+
+static const IPinVtbl Parser_OutputPin_Vtbl =
+{
+ Parser_OutputPin_QueryInterface,
+ IPinImpl_AddRef,
+ Parser_OutputPin_Release,
+ OutputPin_Connect,
+ OutputPin_ReceiveConnection,
+ OutputPin_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ Parser_OutputPin_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ OutputPin_EndOfStream,
+ OutputPin_BeginFlush,
+ OutputPin_EndFlush,
+ OutputPin_NewSegment
+};
+
+static HRESULT Parser_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+ PullPin * pPinImpl;
+
+ *ppPin = NULL;
+
+ if (pPinInfo->dir != PINDIR_INPUT)
+ {
+ ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
+ return E_INVALIDARG;
+ }
+
+ pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+
+ if (!pPinImpl)
+ return E_OUTOFMEMORY;
+
+ if (SUCCEEDED(PullPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
+ {
+ pPinImpl->pin.lpVtbl = &Parser_InputPin_Vtbl;
+
+ *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+static HRESULT WINAPI Parser_InputPin_Disconnect(IPin * iface)
+{
+ HRESULT hr;
+ IPinImpl *This = (IPinImpl *)iface;
+
+ TRACE("()\n");
+
+ EnterCriticalSection(This->pCritSec);
+ {
+ if (This->pConnectedTo)
+ {
+ FILTER_STATE state;
+
+ hr = IBaseFilter_GetState(This->pinInfo.pFilter, 0, &state);
+
+ if (SUCCEEDED(hr) && (state == State_Stopped))
+ {
+ IPin_Release(This->pConnectedTo);
+ This->pConnectedTo = NULL;
+ hr = Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
+ }
+ else
+ hr = VFW_E_NOT_STOPPED;
+ }
+ else
+ hr = S_FALSE;
+ }
+ LeaveCriticalSection(This->pCritSec);
+
+ return hr;
+}
+
+static const IPinVtbl Parser_InputPin_Vtbl =
+{
+ PullPin_QueryInterface,
+ IPinImpl_AddRef,
+ PullPin_Release,
+ OutputPin_Connect,
+ PullPin_ReceiveConnection,
+ Parser_InputPin_Disconnect,
+ IPinImpl_ConnectedTo,
+ IPinImpl_ConnectionMediaType,
+ IPinImpl_QueryPinInfo,
+ IPinImpl_QueryDirection,
+ IPinImpl_QueryId,
+ IPinImpl_QueryAccept,
+ IPinImpl_EnumMediaTypes,
+ IPinImpl_QueryInternalConnections,
+ PullPin_EndOfStream,
+ PullPin_BeginFlush,
+ PullPin_EndFlush,
+ PullPin_NewSegment
+};
More information about the wine-patches
mailing list