quartz: Move IMediaSeeking from the parser pin to the parser filter.

This interface really shouldn't be in a pin, but rather in the
implementation of the filter, since any seeking is done on the entire
filtergraph, so implementing it in the filter makes more sense.
This commit is contained in:
Maarten Lankhorst 2008-03-18 16:05:00 -07:00 committed by Alexandre Julliard
parent ebf6bbd50f
commit 796bb92333
8 changed files with 89 additions and 73 deletions

View File

@ -44,6 +44,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz); WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct StreamData
{
DWORD dwSampleSize;
FLOAT fSamplesPerSec;
DWORD dwLength;
} StreamData;
typedef struct AVISplitterImpl typedef struct AVISplitterImpl
{ {
ParserImpl Parser; ParserImpl Parser;
@ -52,6 +59,7 @@ typedef struct AVISplitterImpl
LONGLONG CurrentChunkOffset; /* in media time */ LONGLONG CurrentChunkOffset; /* in media time */
LONGLONG EndOfFile; LONGLONG EndOfFile;
AVIMAINHEADER AviHeader; AVIMAINHEADER AviHeader;
StreamData *streams;
} AVISplitterImpl; } AVISplitterImpl;
static HRESULT AVISplitter_NextChunk(LONGLONG * pllCurrentChunkOffset, RIFFCHUNK * pCurrentChunk, const REFERENCE_TIME * tStart, const REFERENCE_TIME * tStop, const BYTE * pbSrcStream, int inner) static HRESULT AVISplitter_NextChunk(LONGLONG * pllCurrentChunkOffset, RIFFCHUNK * pCurrentChunk, const REFERENCE_TIME * tStart, const REFERENCE_TIME * tStop, const BYTE * pbSrcStream, int inner)
@ -241,6 +249,7 @@ static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
REFERENCE_TIME tAviStart, tAviStop; REFERENCE_TIME tAviStart, tAviStop;
StreamData *stream = This->streams + streamId;
/* FIXME: hack */ /* FIXME: hack */
if (pOutputPin->dwSamplesProcessed == 0) if (pOutputPin->dwSamplesProcessed == 0)
@ -250,14 +259,14 @@ static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample)
pOutputPin->dwSamplesProcessed++; pOutputPin->dwSamplesProcessed++;
if (pOutputPin->dwSampleSize) if (stream->dwSampleSize)
tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)pOutputPin->dwSampleSize * pOutputPin->fSamplesPerSec)); tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)stream->dwSampleSize * stream->fSamplesPerSec));
else else
tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) / (float)pOutputPin->fSamplesPerSec); tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) / (float)stream->fSamplesPerSec);
if (pOutputPin->dwSampleSize) if (stream->dwSampleSize)
tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)pOutputPin->dwSampleSize * pOutputPin->fSamplesPerSec)); tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)stream->dwSampleSize * stream->fSamplesPerSec));
else else
tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed / (float)pOutputPin->fSamplesPerSec); tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed / (float)stream->fSamplesPerSec);
IMediaSample_SetTime(This->pCurrentSample, &tAviStart, &tAviStop); IMediaSample_SetTime(This->pCurrentSample, &tAviStart, &tAviStop);
@ -337,6 +346,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE
DWORD dwLength = 0; DWORD dwLength = 0;
ALLOCATOR_PROPERTIES props; ALLOCATOR_PROPERTIES props;
static const WCHAR wszStreamTemplate[] = {'S','t','r','e','a','m',' ','%','0','2','d',0}; static const WCHAR wszStreamTemplate[] = {'S','t','r','e','a','m',' ','%','0','2','d',0};
StreamData *stream;
props.cbAlign = 1; props.cbAlign = 1;
props.cbPrefix = 0; props.cbPrefix = 0;
@ -456,8 +466,13 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE
TRACE("fSamplesPerSec = %f\n", (double)fSamplesPerSec); TRACE("fSamplesPerSec = %f\n", (double)fSamplesPerSec);
TRACE("dwSampleSize = %x\n", dwSampleSize); TRACE("dwSampleSize = %x\n", dwSampleSize);
TRACE("dwLength = %x\n", dwLength); TRACE("dwLength = %x\n", dwLength);
This->streams = CoTaskMemRealloc(This->streams, sizeof(StreamData) * (This->Parser.cStreams+1));
stream = This->streams + This->Parser.cStreams;
stream->fSamplesPerSec = fSamplesPerSec;
stream->dwSampleSize = dwSampleSize;
stream->dwLength = dwLength; /* TODO: Use this for mediaseeking */
hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt, fSamplesPerSec, dwSampleSize, dwLength); hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt);
return hr; return hr;
} }
@ -605,6 +620,7 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
This = CoTaskMemAlloc(sizeof(AVISplitterImpl)); This = CoTaskMemAlloc(sizeof(AVISplitterImpl));
This->pCurrentSample = NULL; This->pCurrentSample = NULL;
This->streams = NULL;
hr = Parser_Create(&(This->Parser), &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup); hr = Parser_Create(&(This->Parser), &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup);

View File

@ -29,7 +29,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz); WINE_DEFAULT_DEBUG_CHANNEL(quartz);
HRESULT MediaSeekingImpl_Init(LPVOID pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking) HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking)
{ {
assert(fnChangeStop && fnChangeStart && fnChangeRate); assert(fnChangeStop && fnChangeStart && fnChangeRate);
@ -242,9 +242,8 @@ HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
BOOL bChangeRate = (dRate != This->dRate); BOOL bChangeRate = (dRate != This->dRate);
TRACE("(%e)\n", dRate); TRACE("(%e)\n", dRate);
This->dRate = dRate; This->dRate = dRate;
if (bChangeRate) if (bChangeRate)
return This->fnChangeRate(This->pUserData); return This->fnChangeRate(This->pUserData);
else else

View File

@ -18,14 +18,14 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
typedef HRESULT (* CHANGEPROC)(LPVOID pUserData); typedef HRESULT (* CHANGEPROC)(IBaseFilter *pUserData);
typedef struct MediaSeekingImpl typedef struct MediaSeekingImpl
{ {
const IMediaSeekingVtbl * lpVtbl; const IMediaSeekingVtbl * lpVtbl;
ULONG refCount; ULONG refCount;
LPVOID pUserData; IBaseFilter *pUserData;
CHANGEPROC fnChangeStop; CHANGEPROC fnChangeStop;
CHANGEPROC fnChangeStart; CHANGEPROC fnChangeStart;
CHANGEPROC fnChangeRate; CHANGEPROC fnChangeRate;
@ -36,7 +36,7 @@ typedef struct MediaSeekingImpl
LONGLONG llDuration; /* FIXME: needed? */ LONGLONG llDuration; /* FIXME: needed? */
} MediaSeekingImpl; } MediaSeekingImpl;
HRESULT MediaSeekingImpl_Init(LPVOID pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking); HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking);
HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);

View File

@ -1582,7 +1582,7 @@ static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
SendFilterMessage(iface, SendStop); SendFilterMessage(iface, SendStop);
This->state = State_Stopped; This->state = State_Stopped;
LeaveCriticalSection(&This->cs); LeaveCriticalSection(&This->cs);
return S_FALSE; return S_OK;
} }
static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,

View File

@ -52,12 +52,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#define MPEG_AUDIO_HEADER 1 #define MPEG_AUDIO_HEADER 1
#define MPEG_NO_HEADER 0 #define MPEG_NO_HEADER 0
typedef struct MPEGSplitterImpl typedef struct MPEGSplitterImpl
{ {
ParserImpl Parser; ParserImpl Parser;
IMediaSample *pCurrentSample; IMediaSample *pCurrentSample;
LONGLONG EndOfFile; LONGLONG EndOfFile;
DWORD dwSampleSize, dwLength;
FLOAT fSamplesPerSec;
} MPEGSplitterImpl; } MPEGSplitterImpl;
static int MPEGSplitter_head_check(const BYTE *header) static int MPEGSplitter_head_check(const BYTE *header)
@ -169,12 +170,12 @@ static HRESULT MPEGSplitter_process_sample(LPVOID iface, IMediaSample * pSample)
{ {
REFERENCE_TIME tMPEGStart, tMPEGStop; REFERENCE_TIME tMPEGStart, tMPEGStop;
pOutputPin->dwSamplesProcessed = (BYTES_FROM_MEDIATIME(tStart)+used_bytes) / pOutputPin->dwSampleSize; pOutputPin->dwSamplesProcessed = (BYTES_FROM_MEDIATIME(tStart)+used_bytes) / This->dwSampleSize;
tMPEGStart = (tStart + MEDIATIME_FROM_BYTES(used_bytes-bytes_written)) / tMPEGStart = (tStart + MEDIATIME_FROM_BYTES(used_bytes-bytes_written)) /
(pOutputPin->fSamplesPerSec*pOutputPin->dwSampleSize); (This->fSamplesPerSec*This->dwSampleSize);
tMPEGStop = (tStart + MEDIATIME_FROM_BYTES(used_bytes)) / tMPEGStop = (tStart + MEDIATIME_FROM_BYTES(used_bytes)) /
(pOutputPin->fSamplesPerSec*pOutputPin->dwSampleSize); (This->fSamplesPerSec*This->dwSampleSize);
/* If the start of the sample has a valid MPEG header, it's a /* If the start of the sample has a valid MPEG header, it's a
* sync point */ * sync point */
@ -219,12 +220,12 @@ static HRESULT MPEGSplitter_process_sample(LPVOID iface, IMediaSample * pSample)
{ {
REFERENCE_TIME tMPEGStart, tMPEGStop; REFERENCE_TIME tMPEGStart, tMPEGStop;
pOutputPin->dwSamplesProcessed = (BYTES_FROM_MEDIATIME(tStart)+used_bytes) / pOutputPin->dwSampleSize; pOutputPin->dwSamplesProcessed = (BYTES_FROM_MEDIATIME(tStart)+used_bytes) / This->dwSampleSize;
tMPEGStart = (tStart + MEDIATIME_FROM_BYTES(used_bytes-bytes_written)) / tMPEGStart = (tStart + MEDIATIME_FROM_BYTES(used_bytes-bytes_written)) /
(pOutputPin->fSamplesPerSec*pOutputPin->dwSampleSize); (This->fSamplesPerSec*This->dwSampleSize);
tMPEGStop = (tStart + MEDIATIME_FROM_BYTES(used_bytes)) / tMPEGStop = (tStart + MEDIATIME_FROM_BYTES(used_bytes)) /
(pOutputPin->fSamplesPerSec*pOutputPin->dwSampleSize); (This->fSamplesPerSec*This->dwSampleSize);
if (MPEGSplitter_head_check(pbDstStream) == MPEG_AUDIO_HEADER) if (MPEGSplitter_head_check(pbDstStream) == MPEG_AUDIO_HEADER)
IMediaSample_SetSyncPoint(This->pCurrentSample, TRUE); IMediaSample_SetSyncPoint(This->pCurrentSample, TRUE);
@ -490,12 +491,10 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin)
props.cbBuffer = 0x4000 / format->nBlockAlign * props.cbBuffer = 0x4000 / format->nBlockAlign *
format->nBlockAlign; format->nBlockAlign;
props.cBuffers = 1; props.cBuffers = 1;
This->fSamplesPerSec = (float)format->nAvgBytesPerSec / (float)format->nBlockAlign;
hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt, This->dwSampleSize = format->nBlockAlign;
(float)format->nAvgBytesPerSec / This->dwLength = total;
(float)format->nBlockAlign, hr = Parser_AddPin(&(This->Parser), &piOutput, &props, &amt);
format->nBlockAlign,
total);
} }
if (FAILED(hr)) if (FAILED(hr))

View File

@ -43,15 +43,15 @@ static const IPinVtbl Parser_OutputPin_Vtbl;
static const IPinVtbl Parser_InputPin_Vtbl; static const IPinVtbl Parser_InputPin_Vtbl;
static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt); static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
static HRESULT Parser_ChangeStart(LPVOID iface); static HRESULT Parser_ChangeStart(IBaseFilter *iface);
static HRESULT Parser_ChangeStop(LPVOID iface); static HRESULT Parser_ChangeStop(IBaseFilter *iface);
static HRESULT Parser_ChangeRate(LPVOID iface); static HRESULT Parser_ChangeRate(IBaseFilter *iface);
static HRESULT Parser_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); static HRESULT Parser_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
static inline Parser_OutputPin *impl_from_IMediaSeeking( IMediaSeeking *iface ) static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{ {
return (Parser_OutputPin *)((char*)iface - FIELD_OFFSET(Parser_OutputPin, mediaSeeking.lpVtbl)); return (ParserImpl *)((char*)iface - FIELD_OFFSET(ParserImpl, mediaSeeking.lpVtbl));
} }
@ -80,6 +80,9 @@ HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMP
piInput.pFilter = (IBaseFilter *)pParser; piInput.pFilter = (IBaseFilter *)pParser;
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
MediaSeekingImpl_Init((IBaseFilter*)pParser, Parser_ChangeStop, Parser_ChangeStart, Parser_ChangeRate, &pParser->mediaSeeking);
pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
hr = Parser_InputPin_Construct(&piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, &pParser->csFilter, (IPin **)&pParser->pInputPin); hr = Parser_InputPin_Construct(&piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, &pParser->csFilter, (IPin **)&pParser->pInputPin);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -98,21 +101,16 @@ HRESULT Parser_Create(ParserImpl* pParser, const CLSID* pClsid, PFN_PROCESS_SAMP
return hr; 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) static HRESULT Parser_OutputPin_Init(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, LPCRITICAL_SECTION pCritSec, Parser_OutputPin * pPinImpl)
{ {
pPinImpl->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); pPinImpl->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
CopyMediaType(pPinImpl->pmt, pmt); CopyMediaType(pPinImpl->pmt, pmt);
pPinImpl->dwSamplesProcessed = 0; 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); 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) static HRESULT Parser_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES * props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, const AM_MEDIA_TYPE * pmt, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
{ {
Parser_OutputPin * pPinImpl; Parser_OutputPin * pPinImpl;
@ -125,7 +123,7 @@ static HRESULT Parser_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR_P
if (!pPinImpl) if (!pPinImpl)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (SUCCEEDED(Parser_OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pmt, fSamplesPerSec, pCritSec, pPinImpl))) if (SUCCEEDED(Parser_OutputPin_Init(pPinInfo, props, pUserData, pQueryAccept, pmt, pCritSec, pPinImpl)))
{ {
pPinImpl->pin.pin.lpVtbl = &Parser_OutputPin_Vtbl; pPinImpl->pin.pin.lpVtbl = &Parser_OutputPin_Vtbl;
@ -152,6 +150,8 @@ static HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LP
*ppv = (LPVOID)This; *ppv = (LPVOID)This;
else if (IsEqualIID(riid, &IID_IBaseFilter)) else if (IsEqualIID(riid, &IID_IBaseFilter))
*ppv = (LPVOID)This; *ppv = (LPVOID)This;
else if (IsEqualIID(riid, &IID_IMediaSeeking))
*ppv = (LPVOID)&This->mediaSeeking;
if (*ppv) if (*ppv)
{ {
@ -290,10 +290,12 @@ static HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
{ {
for (i = 1; i < This->cStreams + 1; i++) for (i = 1; i < This->cStreams + 1; i++)
{ {
Parser_OutputPin* StreamPin = (Parser_OutputPin *)This->ppPins[i]; LONGLONG duration;
OutputPin_DeliverNewSegment((OutputPin *)This->ppPins[i], 0, (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec), 1.0); DOUBLE speed;
StreamPin->mediaSeeking.llDuration = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec);
StreamPin->mediaSeeking.llStop = (LONGLONG)ceil(10000000.0 * (float)StreamPin->dwLength / StreamPin->fSamplesPerSec); IMediaSeeking_GetDuration((IMediaSeeking *)&This->mediaSeeking, &duration);
IMediaSeeking_GetRate((IMediaSeeking *)&This->mediaSeeking, &speed);
OutputPin_DeliverNewSegment((OutputPin *)This->ppPins[i], 0, duration, speed);
OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]); OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
} }
@ -497,8 +499,7 @@ static const IBaseFilterVtbl Parser_Vtbl =
Parser_QueryVendorInfo Parser_QueryVendorInfo
}; };
HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt)
const AM_MEDIA_TYPE * amt, float fSamplesPerSec, DWORD dwSampleSize, DWORD dwLength)
{ {
IPin ** ppOldPins; IPin ** ppOldPins;
HRESULT hr; HRESULT hr;
@ -508,12 +509,10 @@ HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PR
This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *)); This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * 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); hr = Parser_OutputPin_Construct(piOutput, props, NULL, Parser_OutputPin_QueryAccept, amt, &This->csFilter, This->ppPins + This->cStreams + 1);
if (SUCCEEDED(hr)) 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]; ((Parser_OutputPin *)(This->ppPins[This->cStreams + 1]))->pin.pin.pUserData = (LPVOID)This->ppPins[This->cStreams + 1];
This->cStreams++; This->cStreams++;
CoTaskMemFree(ppOldPins); CoTaskMemFree(ppOldPins);
@ -551,19 +550,19 @@ static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
return S_OK; return S_OK;
} }
static HRESULT Parser_ChangeStart(LPVOID iface) static HRESULT Parser_ChangeStart(IBaseFilter *iface)
{ {
FIXME("(%p)\n", iface); FIXME("(%p)\n", iface);
return S_OK; return S_OK;
} }
static HRESULT Parser_ChangeStop(LPVOID iface) static HRESULT Parser_ChangeStop(IBaseFilter *iface)
{ {
FIXME("(%p)\n", iface); FIXME("(%p)\n", iface);
return S_OK; return S_OK;
} }
static HRESULT Parser_ChangeRate(LPVOID iface) static HRESULT Parser_ChangeRate(IBaseFilter *iface)
{ {
FIXME("(%p)\n", iface); FIXME("(%p)\n", iface);
return S_OK; return S_OK;
@ -572,21 +571,21 @@ static HRESULT Parser_ChangeRate(LPVOID iface)
static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
{ {
Parser_OutputPin *This = impl_from_IMediaSeeking(iface); ParserImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
} }
static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface) static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface)
{ {
Parser_OutputPin *This = impl_from_IMediaSeeking(iface); ParserImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_AddRef((IUnknown *)This); return IUnknown_AddRef((IUnknown *)This);
} }
static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface) static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface)
{ {
Parser_OutputPin *This = impl_from_IMediaSeeking(iface); ParserImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_Release((IUnknown *)This); return IUnknown_Release((IUnknown *)This);
} }
@ -628,7 +627,9 @@ static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid,
else if (IsEqualIID(riid, &IID_IPin)) else if (IsEqualIID(riid, &IID_IPin))
*ppv = (LPVOID)iface; *ppv = (LPVOID)iface;
else if (IsEqualIID(riid, &IID_IMediaSeeking)) else if (IsEqualIID(riid, &IID_IMediaSeeking))
*ppv = (LPVOID)&This->mediaSeeking; {
return IBaseFilter_QueryInterface((IBaseFilter*)&This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
}
if (*ppv) if (*ppv)
{ {

View File

@ -41,6 +41,7 @@ struct ParserImpl
PullPin * pInputPin; PullPin * pInputPin;
IPin ** ppPins; IPin ** ppPins;
ULONG cStreams; ULONG cStreams;
MediaSeekingImpl mediaSeeking;
}; };
typedef struct Parser_OutputPin typedef struct Parser_OutputPin
@ -48,13 +49,9 @@ typedef struct Parser_OutputPin
OutputPin pin; OutputPin pin;
AM_MEDIA_TYPE * pmt; AM_MEDIA_TYPE * pmt;
float fSamplesPerSec;
DWORD dwSamplesProcessed; DWORD dwSamplesProcessed;
DWORD dwSampleSize;
DWORD dwLength;
MediaSeekingImpl mediaSeeking;
} Parser_OutputPin; } Parser_OutputPin;
HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt);
const 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, PFN_CLEANUP); HRESULT Parser_Create(ParserImpl*, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT, PFN_CLEANUP);

View File

@ -47,6 +47,9 @@ typedef struct WAVEParserImpl
IMediaSample * pCurrentSample; IMediaSample * pCurrentSample;
LONGLONG StartOfFile; /* in media time */ LONGLONG StartOfFile; /* in media time */
LONGLONG EndOfFile; LONGLONG EndOfFile;
DWORD dwSampleSize;
FLOAT fSamplesPerSec;
DWORD dwLength;
} WAVEParserImpl; } WAVEParserImpl;
static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample) static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample)
@ -133,14 +136,14 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample)
pOutputPin->dwSamplesProcessed++; pOutputPin->dwSamplesProcessed++;
if (pOutputPin->dwSampleSize) if (This->dwSampleSize)
tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)pOutputPin->dwSampleSize * pOutputPin->fSamplesPerSec)); tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)This->dwSampleSize * This->fSamplesPerSec));
else else
tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) / (float)pOutputPin->fSamplesPerSec); tAviStart = (LONGLONG)ceil(10000000.0 * (float)(pOutputPin->dwSamplesProcessed - 1) / (float)This->fSamplesPerSec);
if (pOutputPin->dwSampleSize) if (This->dwSampleSize)
tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)pOutputPin->dwSampleSize * pOutputPin->fSamplesPerSec)); tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed * (float)IMediaSample_GetActualDataLength(This->pCurrentSample) / ((float)This->dwSampleSize * This->fSamplesPerSec));
else else
tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed / (float)pOutputPin->fSamplesPerSec); tAviStop = (LONGLONG)ceil(10000000.0 * (float)pOutputPin->dwSamplesProcessed / (float)This->fSamplesPerSec);
IMediaSample_SetTime(This->pCurrentSample, &tAviStart, &tAviStop); IMediaSample_SetTime(This->pCurrentSample, &tAviStart, &tAviStop);
@ -220,10 +223,8 @@ static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin)
PIN_INFO piOutput; PIN_INFO piOutput;
ALLOCATOR_PROPERTIES props; ALLOCATOR_PROPERTIES props;
AM_MEDIA_TYPE amt; AM_MEDIA_TYPE amt;
float fSamplesPerSec = 0.0f;
DWORD dwSampleSize = 0;
DWORD dwLength = 0;
WAVEParserImpl * pWAVEParser = (WAVEParserImpl *)This->pin.pinInfo.pFilter; WAVEParserImpl * pWAVEParser = (WAVEParserImpl *)This->pin.pinInfo.pFilter;
LONGLONG length, avail;
piOutput.dir = PINDIR_OUTPUT; piOutput.dir = PINDIR_OUTPUT;
piOutput.pFilter = (IBaseFilter *)This; piOutput.pFilter = (IBaseFilter *)This;
@ -292,8 +293,11 @@ static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin)
props.cbPrefix = 0; props.cbPrefix = 0;
props.cbBuffer = 4096; props.cbBuffer = 4096;
props.cBuffers = 2; props.cBuffers = 2;
pWAVEParser->dwSampleSize = ((WAVEFORMATEX*)amt.pbFormat)->nBlockAlign;
hr = Parser_AddPin(&(pWAVEParser->Parser), &piOutput, &props, &amt, fSamplesPerSec, dwSampleSize, dwLength); IAsyncReader_Length(This->pReader, &length, &avail);
pWAVEParser->dwLength = length / (ULONGLONG)pWAVEParser->dwSampleSize;
pWAVEParser->fSamplesPerSec = ((WAVEFORMATEX*)amt.pbFormat)->nAvgBytesPerSec / ((WAVEFORMATEX*)amt.pbFormat)->nBlockAlign;
hr = Parser_AddPin(&(pWAVEParser->Parser), &piOutput, &props, &amt);
TRACE("WAVE File ok\n"); TRACE("WAVE File ok\n");