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:
parent
ebf6bbd50f
commit
796bb92333
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue