Sweden-Number/dlls/quartz/parser.c

1006 lines
23 KiB
C
Raw Normal View History

/*
* Implements IBaseFilter for parsers. (internal)
*
* hidenori@a2.ctktv.ne.jp
*
* FIXME - save the array of pSample and handle errors/flushing correctly.
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "winerror.h"
#include "strmif.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "parser.h"
#include "mtype.h"
#include "memalloc.h"
#define QUARTZ_MSG_BEGINFLUSH (WM_APP+1)
#define QUARTZ_MSG_ENDFLUSH (WM_APP+2)
#define QUARTZ_MSG_EXITTHREAD (WM_APP+3)
#define QUARTZ_MSG_SEEK (WM_APP+0)
/***************************************************************************
*
* CParserImpl internal methods
*
*/
static
void CParserImpl_SetAsyncReader( CParserImpl* This, IAsyncReader* pReader )
{
if ( This->m_pReader != NULL )
{
IAsyncReader_Release( This->m_pReader );
This->m_pReader = NULL;
}
if ( pReader != NULL )
{
This->m_pReader = pReader;
IAsyncReader_AddRef(This->m_pReader);
}
}
static
void CParserImpl_ReleaseOutPins( CParserImpl* This )
{
ULONG nIndex;
if ( This->m_ppOutPins != NULL )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
if ( This->m_ppOutPins[nIndex] != NULL )
{
IUnknown_Release(This->m_ppOutPins[nIndex]->unk.punkControl);
This->m_ppOutPins[nIndex] = NULL;
}
}
QUARTZ_FreeMem(This->m_ppOutPins);
This->m_ppOutPins = NULL;
}
This->m_cOutStreams = 0;
}
static
void CParserImpl_ClearAllRequests( CParserImpl* This )
{
ULONG nIndex;
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
}
static
HRESULT CParserImpl_ReleaseAllPendingSamples( CParserImpl* This )
{
HRESULT hr;
IMediaSample* pSample;
DWORD_PTR dwContext;
IAsyncReader_BeginFlush(This->m_pReader);
while ( 1 )
{
hr = IAsyncReader_WaitForNext(This->m_pReader,0,&pSample,&dwContext);
if ( hr != S_OK )
break;
IMediaSample_Release(pSample);
}
IAsyncReader_EndFlush(This->m_pReader);
if ( hr == VFW_E_TIMEOUT )
hr = NOERROR;
return hr;
}
static
HRESULT CParserImpl_ProcessNextSample( CParserImpl* This )
{
IMediaSample* pSample;
DWORD_PTR dwContext;
ULONG nIndex;
HRESULT hr;
CParserOutPinImpl* pOutPin;
MSG msg;
while ( 1 )
{
if ( PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_REMOVE ) )
{
hr = NOERROR;
switch ( msg.message )
{
case QUARTZ_MSG_BEGINFLUSH:
FIXME("BeginFlush\n");
hr = IAsyncReader_BeginFlush(This->m_pReader);
/* send to all output pins */
break;
case QUARTZ_MSG_ENDFLUSH:
FIXME("EndFlush\n");
hr = IAsyncReader_EndFlush(This->m_pReader);
/* send to all output pins */
break;
case QUARTZ_MSG_EXITTHREAD:
FIXME("EndThread\n");
CParserImpl_ReleaseAllPendingSamples(This);
CParserImpl_ClearAllRequests(This);
return S_FALSE;
case QUARTZ_MSG_SEEK:
FIXME("Seek\n");
break;
default:
FIXME( "invalid message %04u\n", (unsigned)msg.message );
/* Notify (ABORT) */
hr = E_FAIL;
}
return hr;
}
hr = IAsyncReader_WaitForNext(This->m_pReader,PARSER_POLL_INTERVAL,&pSample,&dwContext);
nIndex = (ULONG)dwContext;
if ( hr != VFW_E_TIMEOUT )
break;
}
if ( FAILED(hr) )
return hr;
pOutPin = This->m_ppOutPins[nIndex];
if ( pOutPin != NULL && pOutPin->m_bReqUsed )
{
if ( This->m_pHandler->pProcessSample != NULL )
hr = This->m_pHandler->pProcessSample(This,nIndex,pOutPin->m_llReqStart,pOutPin->m_lReqLength,pSample);
if ( FAILED(hr) )
{
/* Notify (ABORT) */
}
else
{
/* FIXME - if pin has its own allocator, sample must be copied */
hr = CPinBaseImpl_SendSample(&pOutPin->pin,pSample);
}
pOutPin->m_bReqUsed = FALSE;
}
if ( SUCCEEDED(hr) )
hr = NOERROR;
IMediaSample_Release(pSample);
TRACE("return %08lx\n",hr);
return hr;
}
static
DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
{
CParserImpl* This = (CParserImpl*)pv;
BOOL bReqNext;
ULONG nIndex = 0;
HRESULT hr;
REFERENCE_TIME rtSampleTimeStart, rtSampleTimeEnd;
LONGLONG llReqStart;
LONG lReqLength;
REFERENCE_TIME rtReqStart, rtReqStop;
IMediaSample* pSample;
MSG msg;
/* initialize the message queue. */
PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE );
CParserImpl_ClearAllRequests(This);
/* resume the owner thread. */
SetEvent( This->m_hEventInit );
TRACE( "Enter message loop.\n" );
bReqNext = TRUE;
while ( 1 )
{
if ( bReqNext )
{
/* Get the next request. */
hr = This->m_pHandler->pGetNextRequest( This, &nIndex, &llReqStart, &lReqLength, &rtReqStart, &rtReqStop );
if ( FAILED(hr) )
{
/* Notify (ABORT) */
break;
}
if ( hr != S_OK )
{
/* Flush */
/* Notify (COMPLETE) */
/* Waiting... */
hr = CParserImpl_ProcessNextSample(This);
if ( hr != S_OK )
{
/* notification is already sent */
break;
}
continue;
}
if ( This->m_ppOutPins[nIndex]->pin.pPinConnectedTo == NULL )
continue;
rtSampleTimeStart = llReqStart * QUARTZ_TIMEUNITS;
rtSampleTimeEnd = (llReqStart + lReqLength) * QUARTZ_TIMEUNITS;
bReqNext = FALSE;
}
if ( !This->m_ppOutPins[nIndex]->m_bReqUsed )
{
hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
if ( FAILED(hr) )
{
/* Notify (ABORT) */
break;
}
hr = IMediaSample_SetTime(pSample,&rtSampleTimeStart,&rtSampleTimeEnd);
if ( SUCCEEDED(hr) )
hr = IAsyncReader_Request(This->m_pReader,pSample,nIndex);
if ( FAILED(hr) )
{
/* Notify (ABORT) */
break;
}
This->m_ppOutPins[nIndex]->m_bReqUsed = TRUE;
This->m_ppOutPins[nIndex]->m_llReqStart = llReqStart;
This->m_ppOutPins[nIndex]->m_lReqLength = lReqLength;
This->m_ppOutPins[nIndex]->m_rtReqStart = rtSampleTimeStart;
This->m_ppOutPins[nIndex]->m_rtReqStop = rtSampleTimeEnd;
bReqNext = TRUE;
continue;
}
hr = CParserImpl_ProcessNextSample(This);
if ( hr != S_OK )
{
/* notification is already sent */
break;
}
}
return 0;
}
static
HRESULT CParserImpl_BeginThread( CParserImpl* This )
{
DWORD dwRes;
HANDLE hEvents[2];
if ( This->m_hEventInit != (HANDLE)NULL ||
This->m_hThread != (HANDLE)NULL )
return E_UNEXPECTED;
This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
if ( This->m_hEventInit == (HANDLE)NULL )
return E_OUTOFMEMORY;
/* create the processing thread. */
This->m_hThread = CreateThread(
NULL, 0,
CParserImpl_ThreadEntry,
(LPVOID)This,
0, &This->m_dwThreadId );
if ( This->m_hThread == (HANDLE)NULL )
return E_FAIL;
hEvents[0] = This->m_hEventInit;
hEvents[1] = This->m_hThread;
dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
if ( dwRes != WAIT_OBJECT_0 )
return E_FAIL;
return NOERROR;
}
static
void CParserImpl_EndThread( CParserImpl* This )
{
if ( This->m_hThread != (HANDLE)NULL )
{
if ( PostThreadMessageA(
This->m_dwThreadId, QUARTZ_MSG_EXITTHREAD, 0, 0 ) )
{
WaitForSingleObject( This->m_hThread, INFINITE );
}
CloseHandle( This->m_hThread );
This->m_hThread = (HANDLE)NULL;
This->m_dwThreadId = 0;
}
if ( This->m_hEventInit != (HANDLE)NULL )
{
CloseHandle( This->m_hEventInit );
This->m_hEventInit = (HANDLE)NULL;
}
}
static
HRESULT CParserImpl_MemCommit( CParserImpl* This )
{
HRESULT hr;
ULONG nIndex;
IMemAllocator* pAlloc;
if ( This->m_pAllocator == NULL )
return E_UNEXPECTED;
hr = IMemAllocator_Commit( This->m_pAllocator );
if ( FAILED(hr) )
return hr;
if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
if ( pAlloc != NULL && pAlloc != This->m_pAllocator )
{
hr = IMemAllocator_Commit( pAlloc );
if ( FAILED(hr) )
return hr;
}
}
}
return NOERROR;
}
static
void CParserImpl_MemDecommit( CParserImpl* This )
{
ULONG nIndex;
IMemAllocator* pAlloc;
if ( This->m_pAllocator != NULL )
IMemAllocator_Decommit( This->m_pAllocator );
if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
{
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
if ( pAlloc != NULL )
IMemAllocator_Decommit( pAlloc );
}
}
}
/***************************************************************************
*
* CParserImpl methods
*
*/
static HRESULT CParserImpl_OnActive( CBaseFilterImpl* pImpl )
{
CParserImpl_THIS(pImpl,basefilter);
HRESULT hr;
TRACE( "(%p)\n", This );
hr = CParserImpl_MemCommit(This);
if ( FAILED(hr) )
return hr;
hr = CParserImpl_BeginThread(This);
if ( FAILED(hr) )
return hr;
return NOERROR;
}
static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
{
CParserImpl_THIS(pImpl,basefilter);
TRACE( "(%p)\n", This );
CParserImpl_EndThread(This);
CParserImpl_MemDecommit(This);
return NOERROR;
}
static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
{
CParserImpl_THIS(pImpl,basefilter);
FIXME( "(%p)\n", This );
/* FIXME - reset streams. */
return NOERROR;
}
static const CBaseFilterHandlers filterhandlers =
{
CParserImpl_OnActive, /* pOnActive */
CParserImpl_OnInactive, /* pOnInactive */
CParserImpl_OnStop, /* pOnStop */
};
/***************************************************************************
*
* CParserInPinImpl methods
*
*/
static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CParserInPinImpl_THIS(pImpl,pin);
HRESULT hr;
ULONG nIndex;
IUnknown* punk;
IAsyncReader* pReader = NULL;
LPCWSTR pwszOutPinName;
IMemAllocator* pAllocActual;
AM_MEDIA_TYPE* pmt;
TRACE("(%p,%p)\n",This,pPin);
if ( This->pParser->m_pHandler->pInitParser == NULL ||
This->pParser->m_pHandler->pUninitParser == NULL ||
This->pParser->m_pHandler->pGetOutPinName == NULL ||
This->pParser->m_pHandler->pGetStreamType == NULL ||
This->pParser->m_pHandler->pCheckStreamType == NULL ||
This->pParser->m_pHandler->pGetAllocProp == NULL ||
This->pParser->m_pHandler->pGetNextRequest == NULL )
{
FIXME("this parser is not implemented.\n");
return E_NOTIMPL;
}
CParserImpl_SetAsyncReader( This->pParser, NULL );
hr = IPin_QueryInterface( pPin, &IID_IAsyncReader, (void**)&pReader );
if ( FAILED(hr) )
return hr;
CParserImpl_SetAsyncReader( This->pParser, pReader );
IAsyncReader_Release(pReader);
/* initialize parser. */
hr = This->pParser->m_pHandler->pInitParser(This->pParser,&This->pParser->m_cOutStreams);
if ( FAILED(hr) )
return hr;
This->pParser->m_ppOutPins = (CParserOutPinImpl**)QUARTZ_AllocMem(
sizeof(CParserOutPinImpl*) * This->pParser->m_cOutStreams );
if ( This->pParser->m_ppOutPins == NULL )
return E_OUTOFMEMORY;
for ( nIndex = 0; nIndex < This->pParser->m_cOutStreams; nIndex++ )
This->pParser->m_ppOutPins[nIndex] = NULL;
/* create and initialize an allocator. */
hr = This->pParser->m_pHandler->pGetAllocProp(This->pParser,&This->pParser->m_propAlloc);
if ( FAILED(hr) )
return hr;
if ( This->pParser->m_pAllocator == NULL )
{
hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
if ( FAILED(hr) )
return hr;
hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&This->pParser->m_pAllocator );
IUnknown_Release(punk);
if ( FAILED(hr) )
return hr;
}
pAllocActual = NULL;
hr = IAsyncReader_RequestAllocator(pReader,This->pParser->m_pAllocator,&This->pParser->m_propAlloc,&pAllocActual);
if ( FAILED(hr) )
return hr;
IMemAllocator_Release(This->pParser->m_pAllocator);
This->pParser->m_pAllocator = pAllocActual;
/* create output pins. */
for ( nIndex = 0; nIndex < This->pParser->m_cOutStreams; nIndex++ )
{
pwszOutPinName = This->pParser->m_pHandler->pGetOutPinName(This->pParser,nIndex);
if ( pwszOutPinName == NULL )
return E_FAIL;
hr = QUARTZ_CreateParserOutPin(
This->pParser,
&This->pParser->m_csParser,
&This->pParser->m_ppOutPins[nIndex],
nIndex, pwszOutPinName );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
This->pParser->basefilter.pOutPins,
(IUnknown*)&(This->pParser->m_ppOutPins[nIndex]->pin),
NULL, 0 );
if ( FAILED(hr) )
return hr;
pmt = &This->pParser->m_ppOutPins[nIndex]->m_mtOut;
QUARTZ_MediaType_Free( pmt );
ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
hr = This->pParser->m_pHandler->pGetStreamType(This->pParser,nIndex,pmt);
if ( FAILED(hr) )
{
ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
return hr;
}
This->pParser->m_ppOutPins[nIndex]->pin.cAcceptTypes = 1;
This->pParser->m_ppOutPins[nIndex]->pin.pmtAcceptTypes = pmt;
}
return NOERROR;
}
static HRESULT CParserInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CParserInPinImpl_THIS(pImpl,pin);
CParserImpl_OnInactive(&This->pParser->basefilter);
CParserImpl_OnStop(&This->pParser->basefilter);
if ( This->pParser->m_pHandler->pUninitParser != NULL )
This->pParser->m_pHandler->pUninitParser(This->pParser);
CParserImpl_SetAsyncReader( This->pParser, NULL );
if ( This->pParser->m_pAllocator != NULL )
{
IMemAllocator_Release(This->pParser->m_pAllocator);
This->pParser->m_pAllocator = NULL;
}
return NOERROR;
}
static HRESULT CParserInPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CParserInPinImpl_THIS(pImpl,pin);
TRACE("(%p,%p)\n",This,pmt);
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
return E_FAIL;
return NOERROR;
}
static const CBasePinHandlers inputpinhandlers =
{
CParserInPinImpl_OnPreConnect, /* pOnPreConnect */
NULL, /* pOnPostConnect */
CParserInPinImpl_OnDisconnect, /* pOnDisconnect */
CParserInPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
NULL, /* pReceive */
NULL, /* pReceiveCanBlock */
NULL, /* pEndOfStream */
NULL, /* pBeginFlush */
NULL, /* pEndFlush */
NULL, /* pNewSegment */
};
/***************************************************************************
*
* CParserOutPinImpl methods
*
*/
static HRESULT CParserOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CParserOutPinImpl_THIS(pImpl,pin);
ALLOCATOR_PROPERTIES propReq;
IMemAllocator* pAllocator;
HRESULT hr;
BOOL bNewAllocator = FALSE;
TRACE("(%p,%p)\n",This,pPin);
if ( This->pin.pMemInputPinConnectedTo == NULL )
return E_UNEXPECTED;
if ( This->m_pOutPinAllocator != NULL )
{
IMemAllocator_Release(This->m_pOutPinAllocator);
This->m_pOutPinAllocator = NULL;
}
/* try to use This->pParser->m_pAllocator. */
ZeroMemory( &propReq, sizeof(ALLOCATOR_PROPERTIES) );
hr = IMemInputPin_GetAllocatorRequirements(
This->pin.pMemInputPinConnectedTo, &propReq );
if ( propReq.cbAlign != 0 )
{
if ( This->pParser->m_propAlloc.cbAlign != ( This->pParser->m_propAlloc.cbAlign / propReq.cbAlign * propReq.cbAlign ) )
bNewAllocator = TRUE;
}
if ( propReq.cbPrefix != 0 )
bNewAllocator = TRUE;
if ( !bNewAllocator )
{
hr = IMemInputPin_NotifyAllocator(
This->pin.pMemInputPinConnectedTo,
This->pParser->m_pAllocator, FALSE );
if ( hr == NOERROR )
{
This->m_pOutPinAllocator = This->pParser->m_pAllocator;
IMemAllocator_AddRef(This->m_pOutPinAllocator);
return NOERROR;
}
}
hr = IMemInputPin_GetAllocator(
This->pin.pMemInputPinConnectedTo, &pAllocator );
if ( FAILED(hr) )
return hr;
hr = IMemInputPin_NotifyAllocator(
This->pin.pMemInputPinConnectedTo, pAllocator, FALSE );
if ( FAILED(hr) )
{
IMemAllocator_Release(pAllocator);
return hr;
}
This->m_pOutPinAllocator = pAllocator;
return NOERROR;
}
static HRESULT CParserOutPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CParserOutPinImpl_THIS(pImpl,pin);
if ( This->m_pOutPinAllocator != NULL )
{
IMemAllocator_Release(This->m_pOutPinAllocator);
This->m_pOutPinAllocator = NULL;
}
return NOERROR;
}
static HRESULT CParserOutPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CParserOutPinImpl_THIS(pImpl,pin);
HRESULT hr;
TRACE("(%p,%p)\n",This,pmt);
if ( pmt == NULL )
return E_POINTER;
if ( This->pParser->m_pHandler->pCheckStreamType == NULL )
return E_NOTIMPL;
hr = This->pParser->m_pHandler->pCheckStreamType( This->pParser, This->nStreamIndex, pmt );
if ( FAILED(hr) )
return hr;
return NOERROR;
}
static const CBasePinHandlers outputpinhandlers =
{
NULL, /* pOnPreConnect */
CParserOutPinImpl_OnPostConnect, /* pOnPostConnect */
CParserOutPinImpl_OnDisconnect, /* pOnDisconnect */
CParserOutPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
OutputPinSync_Receive, /* pReceive */
OutputPinSync_ReceiveCanBlock, /* pReceiveCanBlock */
OutputPinSync_EndOfStream, /* pEndOfStream */
OutputPinSync_BeginFlush, /* pBeginFlush */
OutputPinSync_EndFlush, /* pEndFlush */
OutputPinSync_NewSegment, /* pNewSegment */
};
/***************************************************************************
*
* new/delete CParserImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry FilterIFEntries[] =
{
{ &IID_IPersist, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
{ &IID_IMediaFilter, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
{ &IID_IBaseFilter, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
};
static void QUARTZ_DestroyParser(IUnknown* punk)
{
CParserImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
if ( This->m_pInPin != NULL )
CParserInPinImpl_OnDisconnect(&This->m_pInPin->pin);
CParserImpl_SetAsyncReader( This, NULL );
if ( This->m_pAllocator != NULL )
{
IMemAllocator_Release(This->m_pAllocator);
This->m_pAllocator = NULL;
}
if ( This->m_pInPin != NULL )
{
IUnknown_Release(This->m_pInPin->unk.punkControl);
This->m_pInPin = NULL;
}
CParserImpl_ReleaseOutPins( This );
DeleteCriticalSection( &This->m_csParser );
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
}
HRESULT QUARTZ_CreateParser(
IUnknown* punkOuter,void** ppobj,
const CLSID* pclsidParser,
LPCWSTR pwszParserName,
LPCWSTR pwszInPinName,
const ParserHandlers* pHandler )
{
CParserImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p)\n",punkOuter,ppobj);
This = (CParserImpl*)
QUARTZ_AllocObj( sizeof(CParserImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
This->m_pInPin = NULL;
This->m_cOutStreams = 0;
This->m_ppOutPins = NULL;
This->m_pReader = NULL;
This->m_pAllocator = NULL;
ZeroMemory( &This->m_propAlloc, sizeof(ALLOCATOR_PROPERTIES) );
This->m_hEventInit = (HANDLE)NULL;
This->m_hThread = (HANDLE)NULL;
This->m_dwThreadId = 0;
This->m_pHandler = pHandler;
This->m_pUserData = NULL;
QUARTZ_IUnkInit( &This->unk, punkOuter );
hr = CBaseFilterImpl_InitIBaseFilter(
&This->basefilter,
This->unk.punkControl,
pclsidParser,
pwszParserName,
&filterhandlers );
if ( SUCCEEDED(hr) )
{
/* construct this class. */
hr = S_OK;
if ( FAILED(hr) )
{
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
}
}
if ( FAILED(hr) )
{
QUARTZ_FreeObj(This);
return hr;
}
This->unk.pEntries = FilterIFEntries;
This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroyParser;
InitializeCriticalSection( &This->m_csParser );
/* create the input pin. */
hr = QUARTZ_CreateParserInPin(
This,
&This->m_csParser,
&This->m_pInPin,
pwszInPinName );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
This->basefilter.pInPins,
(IUnknown*)&(This->m_pInPin->pin),
NULL, 0 );
if ( FAILED(hr) )
{
IUnknown_Release( This->unk.punkControl );
return hr;
}
*ppobj = (void*)&(This->unk);
return S_OK;
}
/***************************************************************************
*
* new/delete CParserInPinImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry InPinIFEntries[] =
{
{ &IID_IPin, offsetof(CParserInPinImpl,pin)-offsetof(CParserInPinImpl,unk) },
{ &IID_IMemInputPin, offsetof(CParserInPinImpl,meminput)-offsetof(CParserInPinImpl,unk) },
};
static void QUARTZ_DestroyParserInPin(IUnknown* punk)
{
CParserInPinImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
CPinBaseImpl_UninitIPin( &This->pin );
CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
}
HRESULT QUARTZ_CreateParserInPin(
CParserImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CParserInPinImpl** ppPin,
LPCWSTR pwszPinName )
{
CParserInPinImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
This = (CParserInPinImpl*)
QUARTZ_AllocObj( sizeof(CParserInPinImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, NULL );
This->pParser = pFilter;
hr = CPinBaseImpl_InitIPin(
&This->pin,
This->unk.punkControl,
pcsPin,
&pFilter->basefilter,
pwszPinName,
FALSE,
&inputpinhandlers );
if ( SUCCEEDED(hr) )
{
hr = CMemInputPinBaseImpl_InitIMemInputPin(
&This->meminput,
This->unk.punkControl,
&This->pin );
if ( FAILED(hr) )
{
CPinBaseImpl_UninitIPin( &This->pin );
}
}
if ( FAILED(hr) )
{
QUARTZ_FreeObj(This);
return hr;
}
This->unk.pEntries = InPinIFEntries;
This->unk.dwEntries = sizeof(InPinIFEntries)/sizeof(InPinIFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroyParserInPin;
*ppPin = This;
TRACE("returned successfully.\n");
return S_OK;
}
/***************************************************************************
*
* new/delete CParserOutPinImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry OutPinIFEntries[] =
{
{ &IID_IPin, offsetof(CParserOutPinImpl,pin)-offsetof(CParserOutPinImpl,unk) },
{ &IID_IQualityControl, offsetof(CParserOutPinImpl,qcontrol)-offsetof(CParserOutPinImpl,unk) },
};
static void QUARTZ_DestroyParserOutPin(IUnknown* punk)
{
CParserOutPinImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
QUARTZ_MediaType_Free( &This->m_mtOut );
if ( This->m_pOutPinAllocator != NULL )
IMemAllocator_Release(This->m_pOutPinAllocator);
CPinBaseImpl_UninitIPin( &This->pin );
CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
}
HRESULT QUARTZ_CreateParserOutPin(
CParserImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CParserOutPinImpl** ppPin,
ULONG nStreamIndex,
LPCWSTR pwszPinName )
{
CParserOutPinImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
This = (CParserOutPinImpl*)
QUARTZ_AllocObj( sizeof(CParserOutPinImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, NULL );
This->pParser = pFilter;
This->nStreamIndex = nStreamIndex;
ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
This->m_pOutPinAllocator = NULL;
This->m_pUserData = NULL;
This->m_bReqUsed = FALSE;
This->m_llReqStart = 0;
This->m_lReqLength = 0;
This->m_rtReqStart = 0;
This->m_rtReqStop = 0;
hr = CPinBaseImpl_InitIPin(
&This->pin,
This->unk.punkControl,
pcsPin,
&pFilter->basefilter,
pwszPinName,
TRUE,
&outputpinhandlers );
if ( SUCCEEDED(hr) )
{
hr = CQualityControlPassThruImpl_InitIQualityControl(
&This->qcontrol,
This->unk.punkControl,
&This->pin );
if ( FAILED(hr) )
{
CPinBaseImpl_UninitIPin( &This->pin );
}
}
if ( FAILED(hr) )
{
QUARTZ_FreeObj(This);
return hr;
}
This->unk.pEntries = OutPinIFEntries;
This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroyParserOutPin;
*ppPin = This;
TRACE("returned successfully.\n");
return S_OK;
}