Started Implementing Video Renderer.
Started Implementing WAVE/AU/AIFF Parser. Started Implementing file source. Fixed some bugs.
This commit is contained in:
parent
90d4b11b3a
commit
bd3be7a905
|
@ -10,6 +10,7 @@ SYMBOLFILE = $(MODULE).tmp.o
|
|||
|
||||
C_SRCS = \
|
||||
amundoc.c \
|
||||
asyncsrc.c \
|
||||
audren.c \
|
||||
basefilt.c \
|
||||
basepin.c \
|
||||
|
@ -34,10 +35,13 @@ C_SRCS = \
|
|||
main.c \
|
||||
memalloc.c \
|
||||
mtype.c \
|
||||
parser.c \
|
||||
regsvr.c \
|
||||
sample.c \
|
||||
seekpass.c \
|
||||
sysclock.c
|
||||
sysclock.c \
|
||||
vidren.c \
|
||||
wavparse.c
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
||||
|
|
|
@ -0,0 +1,840 @@
|
|||
/*
|
||||
* Implements Asynchronous File/URL Source.
|
||||
*
|
||||
* FIXME - not work yet.
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/obj_base.h"
|
||||
#include "strmif.h"
|
||||
#include "vfwmsgs.h"
|
||||
#include "uuids.h"
|
||||
|
||||
#include "debugtools.h"
|
||||
DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
||||
#include "quartz_private.h"
|
||||
#include "asyncsrc.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CAsyncReaderImpl internal methods
|
||||
*
|
||||
*/
|
||||
|
||||
static DWORD WINAPI
|
||||
CAsyncReaderImpl_ThreadEntry( LPVOID pv )
|
||||
{
|
||||
CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
|
||||
HANDLE hWaitEvents[2];
|
||||
HANDLE hReadEvents[2];
|
||||
DWORD dwRes;
|
||||
|
||||
SetEvent( This->m_hEventInit );
|
||||
|
||||
hWaitEvents[0] = This->m_hEventReqQueued;
|
||||
hWaitEvents[1] = This->m_hEventAbort;
|
||||
|
||||
hReadEvents[0] = This->m_hEventSampQueued;
|
||||
hReadEvents[1] = This->m_hEventAbort;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
|
||||
if ( dwRes != WAIT_OBJECT_0 )
|
||||
break;
|
||||
|
||||
/* FIXME - process a queued request */
|
||||
|
||||
dwRes = WaitForMultipleObjects(2,hReadEvents,FALSE,INFINITE);
|
||||
if ( dwRes != WAIT_OBJECT_0 )
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
|
||||
{
|
||||
DWORD dwRes;
|
||||
DWORD dwThreadId;
|
||||
HANDLE hEvents[2];
|
||||
|
||||
if ( This->m_hEventInit != (HANDLE)NULL ||
|
||||
This->m_hEventAbort != (HANDLE)NULL ||
|
||||
This->m_hEventReqQueued != (HANDLE)NULL ||
|
||||
This->m_hEventSampQueued != (HANDLE)NULL ||
|
||||
This->m_hEventCompletion != (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;
|
||||
This->m_hEventAbort = CreateEventA(NULL,TRUE,FALSE,NULL);
|
||||
if ( This->m_hEventAbort == (HANDLE)NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
This->m_hEventReqQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
|
||||
if ( This->m_hEventReqQueued == (HANDLE)NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
This->m_hEventSampQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
|
||||
if ( This->m_hEventSampQueued == (HANDLE)NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
This->m_hEventCompletion = CreateEventA(NULL,TRUE,FALSE,NULL);
|
||||
if ( This->m_hEventCompletion == (HANDLE)NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
/* create the processing thread. */
|
||||
This->m_hThread = CreateThread(
|
||||
NULL, 0,
|
||||
CAsyncReaderImpl_ThreadEntry,
|
||||
(LPVOID)This,
|
||||
0, &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
|
||||
CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
|
||||
{
|
||||
if ( This->m_hThread != (HANDLE)NULL )
|
||||
{
|
||||
SetEvent( This->m_hEventAbort );
|
||||
|
||||
WaitForSingleObject( This->m_hThread, INFINITE );
|
||||
CloseHandle( This->m_hThread );
|
||||
This->m_hThread = (HANDLE)NULL;
|
||||
}
|
||||
if ( This->m_hEventInit != (HANDLE)NULL )
|
||||
{
|
||||
CloseHandle( This->m_hEventInit );
|
||||
This->m_hEventInit = (HANDLE)NULL;
|
||||
}
|
||||
if ( This->m_hEventAbort != (HANDLE)NULL )
|
||||
{
|
||||
CloseHandle( This->m_hEventAbort );
|
||||
This->m_hEventAbort = (HANDLE)NULL;
|
||||
}
|
||||
if ( This->m_hEventReqQueued != (HANDLE)NULL )
|
||||
{
|
||||
CloseHandle( This->m_hEventReqQueued );
|
||||
This->m_hEventReqQueued = (HANDLE)NULL;
|
||||
}
|
||||
if ( This->m_hEventSampQueued != (HANDLE)NULL )
|
||||
{
|
||||
CloseHandle( This->m_hEventSampQueued );
|
||||
This->m_hEventSampQueued = (HANDLE)NULL;
|
||||
}
|
||||
if ( This->m_hEventCompletion != (HANDLE)NULL )
|
||||
{
|
||||
CloseHandle( This->m_hEventCompletion );
|
||||
This->m_hEventCompletion = (HANDLE)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CAsyncReaderImpl methods
|
||||
*
|
||||
*/
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnQueryInterface(IAsyncReader* iface,REFIID riid,void** ppobj)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_AddRef(This->punkControl);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
CAsyncReaderImpl_fnRelease(IAsyncReader* iface)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_Release(This->punkControl);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnRequestAllocator(IAsyncReader* iface,IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES* pProp,IMemAllocator** ppAllocActual)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
HRESULT hr;
|
||||
ALLOCATOR_PROPERTIES propActual;
|
||||
IUnknown* punk = NULL;
|
||||
|
||||
TRACE("(%p)->(%p,%p,%p)\n",This,pAlloc,pProp,ppAllocActual);
|
||||
|
||||
if ( pAlloc == NULL || pProp == NULL || ppAllocActual == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
IMemAllocator_AddRef(pAlloc);
|
||||
hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
*ppAllocActual = pAlloc;
|
||||
return S_OK;
|
||||
}
|
||||
IMemAllocator_Release(pAlloc);
|
||||
|
||||
hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
|
||||
IUnknown_Release(punk);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
*ppAllocActual = pAlloc;
|
||||
return S_OK;
|
||||
}
|
||||
IMemAllocator_Release(pAlloc);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnRequest(IAsyncReader* iface,IMediaSample* pSample,DWORD_PTR dwContext)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnWaitForNext(IAsyncReader* iface,DWORD dwTimeout,IMediaSample** pSample,DWORD_PTR* pdwContext)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CAsyncReaderImpl_fnEndFlush(IAsyncReader* iface)
|
||||
{
|
||||
ICOM_THIS(CAsyncReaderImpl,iface);
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
|
||||
EnterCriticalSection( This->pcsReader );
|
||||
LeaveCriticalSection( This->pcsReader );
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
static ICOM_VTABLE(IAsyncReader) iasyncreader =
|
||||
{
|
||||
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
||||
/* IUnknown fields */
|
||||
CAsyncReaderImpl_fnQueryInterface,
|
||||
CAsyncReaderImpl_fnAddRef,
|
||||
CAsyncReaderImpl_fnRelease,
|
||||
|
||||
/* IAsyncReader fields */
|
||||
CAsyncReaderImpl_fnRequestAllocator,
|
||||
CAsyncReaderImpl_fnRequest,
|
||||
CAsyncReaderImpl_fnWaitForNext,
|
||||
CAsyncReaderImpl_fnSyncReadAligned,
|
||||
CAsyncReaderImpl_fnSyncRead,
|
||||
CAsyncReaderImpl_fnLength,
|
||||
CAsyncReaderImpl_fnBeginFlush,
|
||||
CAsyncReaderImpl_fnEndFlush,
|
||||
};
|
||||
|
||||
HRESULT CAsyncReaderImpl_InitIAsyncReader(
|
||||
CAsyncReaderImpl* This, IUnknown* punkControl,
|
||||
CAsyncSourceImpl* pSource,
|
||||
CRITICAL_SECTION* pcsReader )
|
||||
{
|
||||
TRACE("(%p,%p)\n",This,punkControl);
|
||||
|
||||
if ( punkControl == NULL )
|
||||
{
|
||||
ERR( "punkControl must not be NULL\n" );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
ICOM_VTBL(This) = &iasyncreader;
|
||||
This->punkControl = punkControl;
|
||||
This->pSource = pSource;
|
||||
This->pcsReader = pcsReader;
|
||||
This->m_hEventInit = (HANDLE)NULL;
|
||||
This->m_hEventAbort = (HANDLE)NULL;
|
||||
This->m_hEventReqQueued = (HANDLE)NULL;
|
||||
This->m_hEventSampQueued = (HANDLE)NULL;
|
||||
This->m_hEventCompletion = (HANDLE)NULL;
|
||||
This->m_hThread = (HANDLE)NULL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
void CAsyncReaderImpl_UninitIAsyncReader(
|
||||
CAsyncReaderImpl* This )
|
||||
{
|
||||
TRACE("(%p)\n",This);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CFileSourceFilterImpl
|
||||
*
|
||||
*/
|
||||
|
||||
static HRESULT WINAPI
|
||||
CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter* iface,REFIID riid,void** ppobj)
|
||||
{
|
||||
ICOM_THIS(CFileSourceFilterImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
|
||||
{
|
||||
ICOM_THIS(CFileSourceFilterImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_AddRef(This->punkControl);
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
CFileSourceFilterImpl_fnRelease(IFileSourceFilter* iface)
|
||||
{
|
||||
ICOM_THIS(CFileSourceFilterImpl,iface);
|
||||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
return IUnknown_Release(This->punkControl);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CFileSourceFilterImpl_fnLoad(IFileSourceFilter* iface,LPCOLESTR pFileName,const AM_MEDIA_TYPE* pmt)
|
||||
{
|
||||
ICOM_THIS(CFileSourceFilterImpl,iface);
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
|
||||
|
||||
if ( pFileName == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
if ( This->m_pwszFileName != NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pFileName)+1);
|
||||
This->m_pwszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
|
||||
if ( This->m_pwszFileName == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy( This->m_pwszFileName, pFileName, This->m_cbFileName );
|
||||
|
||||
if ( pmt != NULL )
|
||||
{
|
||||
hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
|
||||
memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
|
||||
memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
|
||||
This->m_mt.lSampleSize = 1;
|
||||
memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
|
||||
}
|
||||
|
||||
hr = This->pSource->m_pHandler->pLoad( This->pSource, pFileName );
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
|
||||
return NOERROR;
|
||||
err:;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter* iface,LPOLESTR* ppFileName,AM_MEDIA_TYPE* pmt)
|
||||
{
|
||||
ICOM_THIS(CFileSourceFilterImpl,iface);
|
||||
HRESULT hr = E_NOTIMPL;
|
||||
|
||||
TRACE("(%p)->(%p,%p)\n",This,ppFileName,pmt);
|
||||
|
||||
if ( ppFileName == NULL || pmt == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
if ( This->m_pwszFileName == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
*ppFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
|
||||
if ( *ppFileName == NULL )
|
||||
{
|
||||
QUARTZ_MediaType_Free(pmt);
|
||||
ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
memcpy( *ppFileName, This->m_pwszFileName, This->m_cbFileName );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static ICOM_VTABLE(IFileSourceFilter) ifilesource =
|
||||
{
|
||||
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
||||
/* IUnknown fields */
|
||||
CFileSourceFilterImpl_fnQueryInterface,
|
||||
CFileSourceFilterImpl_fnAddRef,
|
||||
CFileSourceFilterImpl_fnRelease,
|
||||
/* IFileSourceFilter fields */
|
||||
CFileSourceFilterImpl_fnLoad,
|
||||
CFileSourceFilterImpl_fnGetCurFile,
|
||||
};
|
||||
|
||||
HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
|
||||
CFileSourceFilterImpl* This, IUnknown* punkControl,
|
||||
CAsyncSourceImpl* pSource,
|
||||
CRITICAL_SECTION* pcsFileSource )
|
||||
{
|
||||
TRACE("(%p,%p)\n",This,punkControl);
|
||||
|
||||
if ( punkControl == NULL )
|
||||
{
|
||||
ERR( "punkControl must not be NULL\n" );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
ICOM_VTBL(This) = &ifilesource;
|
||||
This->punkControl = punkControl;
|
||||
This->pSource = pSource;
|
||||
This->pcsFileSource = pcsFileSource;
|
||||
This->m_pwszFileName = NULL;
|
||||
This->m_cbFileName = 0;
|
||||
ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
void CFileSourceFilterImpl_UninitIFileSourceFilter(
|
||||
CFileSourceFilterImpl* This )
|
||||
{
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
This->pSource->m_pHandler->pCleanup( This->pSource );
|
||||
if ( This->m_pwszFileName != NULL )
|
||||
QUARTZ_FreeMem( This->m_pwszFileName );
|
||||
QUARTZ_MediaType_Free( &This->m_mt );
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CAsyncSourcePinImpl methods
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static HRESULT CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(pImpl,pin);
|
||||
|
||||
This->bAsyncReaderQueried = FALSE;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(pImpl,pin);
|
||||
|
||||
if ( !This->bAsyncReaderQueried )
|
||||
return E_FAIL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(pImpl,pin);
|
||||
|
||||
This->bAsyncReaderQueried = FALSE;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(pImpl,pin);
|
||||
|
||||
TRACE("(%p,%p)\n",This,pmt);
|
||||
if ( pmt == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
|
||||
return E_FAIL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static const CBasePinHandlers outputpinhandlers =
|
||||
{
|
||||
CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
|
||||
CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
|
||||
CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
|
||||
CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
|
||||
NULL, /* pQualityNotify */
|
||||
NULL, /* pReceive */
|
||||
NULL, /* pReceiveCanBlock */
|
||||
NULL, /* pEndOfStream */
|
||||
NULL, /* pBeginFlush */
|
||||
NULL, /* pEndFlush */
|
||||
NULL, /* pNewSegment */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CAsyncSourceImpl methods
|
||||
*
|
||||
*/
|
||||
|
||||
static HRESULT CAsyncSourceImpl_OnActive( CBaseFilterImpl* pImpl )
|
||||
{
|
||||
CAsyncSourceImpl_THIS(pImpl,basefilter);
|
||||
HRESULT hr;
|
||||
|
||||
TRACE( "(%p)\n", This );
|
||||
|
||||
hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
|
||||
{
|
||||
CAsyncSourceImpl_THIS(pImpl,basefilter);
|
||||
|
||||
TRACE( "(%p)\n", This );
|
||||
|
||||
CAsyncReaderImpl_EndThread(&This->pPin->async);
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static const CBaseFilterHandlers filterhandlers =
|
||||
{
|
||||
CAsyncSourceImpl_OnActive, /* pOnActive */
|
||||
CAsyncSourceImpl_OnInactive, /* pOnInactive */
|
||||
NULL, /* pOnStop */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* new/delete CAsyncSourceImpl
|
||||
*
|
||||
*/
|
||||
|
||||
/* can I use offsetof safely? - FIXME? */
|
||||
static QUARTZ_IFEntry FilterIFEntries[] =
|
||||
{
|
||||
{ &IID_IPersist, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
|
||||
{ &IID_IMediaFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
|
||||
{ &IID_IBaseFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
|
||||
{ &IID_IFileSourceFilter, offsetof(CAsyncSourceImpl,filesrc)-offsetof(CAsyncSourceImpl,unk) },
|
||||
};
|
||||
|
||||
static void QUARTZ_DestroyAsyncSource(IUnknown* punk)
|
||||
{
|
||||
CAsyncSourceImpl_THIS(punk,unk);
|
||||
|
||||
TRACE( "(%p)\n", This );
|
||||
|
||||
if ( This->pPin != NULL )
|
||||
{
|
||||
IUnknown_Release(This->pPin->unk.punkControl);
|
||||
This->pPin = NULL;
|
||||
}
|
||||
|
||||
This->m_pHandler->pCleanup( This );
|
||||
|
||||
CFileSourceFilterImpl_UninitIFileSourceFilter(&This->filesrc);
|
||||
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
|
||||
|
||||
DeleteCriticalSection( &This->csFilter );
|
||||
}
|
||||
|
||||
HRESULT QUARTZ_CreateAsyncSource(
|
||||
IUnknown* punkOuter,void** ppobj,
|
||||
const CLSID* pclsidAsyncSource,
|
||||
LPCWSTR pwszAsyncSourceName,
|
||||
LPCWSTR pwszOutPinName,
|
||||
const AsyncSourceHandlers* pHandler )
|
||||
{
|
||||
CAsyncSourceImpl* This = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p)\n",punkOuter,ppobj);
|
||||
|
||||
This = (CAsyncSourceImpl*)
|
||||
QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
|
||||
if ( This == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
This->pPin = NULL;
|
||||
This->m_pHandler = pHandler;
|
||||
This->m_pUserData = NULL;
|
||||
|
||||
QUARTZ_IUnkInit( &This->unk, punkOuter );
|
||||
|
||||
hr = CBaseFilterImpl_InitIBaseFilter(
|
||||
&This->basefilter,
|
||||
This->unk.punkControl,
|
||||
pclsidAsyncSource,
|
||||
pwszAsyncSourceName,
|
||||
&filterhandlers );
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
/* construct this class. */
|
||||
hr = CFileSourceFilterImpl_InitIFileSourceFilter(
|
||||
&This->filesrc, This->unk.punkControl,
|
||||
This, &This->csFilter );
|
||||
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_DestroyAsyncSource;
|
||||
InitializeCriticalSection( &This->csFilter );
|
||||
|
||||
/* create the output pin. */
|
||||
hr = S_OK;
|
||||
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
IUnknown_Release( This->unk.punkControl );
|
||||
return hr;
|
||||
}
|
||||
|
||||
*ppobj = (void*)&(This->unk);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* new/delete CAsyncSourcePinImpl
|
||||
*
|
||||
*/
|
||||
|
||||
/* can I use offsetof safely? - FIXME? */
|
||||
static QUARTZ_IFEntry OutPinIFEntries[] =
|
||||
{
|
||||
{ &IID_IPin, offsetof(CAsyncSourcePinImpl,pin)-offsetof(CAsyncSourcePinImpl,unk) },
|
||||
/***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
|
||||
};
|
||||
|
||||
static HRESULT CAsyncSourceImpl_OnQueryInterface(
|
||||
IUnknown* punk, const IID* piid, void** ppobj )
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(punk,unk);
|
||||
|
||||
if ( IsEqualGUID( &IID_IAsyncReader, piid ) )
|
||||
{
|
||||
*ppobj = (void*)&This->async;
|
||||
IUnknown_AddRef(punk);
|
||||
This->bAsyncReaderQueried = TRUE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static void QUARTZ_DestroyAsyncSourcePin(IUnknown* punk)
|
||||
{
|
||||
CAsyncSourcePinImpl_THIS(punk,unk);
|
||||
|
||||
TRACE( "(%p)\n", This );
|
||||
|
||||
CAsyncReaderImpl_UninitIAsyncReader( &This->async );
|
||||
CPinBaseImpl_UninitIPin( &This->pin );
|
||||
}
|
||||
|
||||
HRESULT QUARTZ_CreateAsyncSourcePin(
|
||||
CAsyncSourceImpl* pFilter,
|
||||
CRITICAL_SECTION* pcsPin,
|
||||
CAsyncSourcePinImpl** ppPin,
|
||||
LPCWSTR pwszPinName )
|
||||
{
|
||||
CAsyncSourcePinImpl* This = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
|
||||
|
||||
This = (CAsyncSourcePinImpl*)
|
||||
QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
|
||||
if ( This == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
QUARTZ_IUnkInit( &This->unk, NULL );
|
||||
This->qiext.pNext = NULL;
|
||||
This->qiext.pOnQueryInterface = &CAsyncSourceImpl_OnQueryInterface;
|
||||
QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
|
||||
|
||||
This->bAsyncReaderQueried = FALSE;
|
||||
This->pSource = pFilter;
|
||||
|
||||
hr = CPinBaseImpl_InitIPin(
|
||||
&This->pin,
|
||||
This->unk.punkControl,
|
||||
pcsPin,
|
||||
&pFilter->basefilter,
|
||||
pwszPinName,
|
||||
TRUE,
|
||||
&outputpinhandlers );
|
||||
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
hr = CAsyncReaderImpl_InitIAsyncReader(
|
||||
&This->async,
|
||||
This->unk.punkControl,
|
||||
pFilter,
|
||||
pcsPin );
|
||||
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_DestroyAsyncSourcePin;
|
||||
|
||||
*ppPin = This;
|
||||
|
||||
TRACE("returned successfully.\n");
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Implements Asynchronous File/URL Source.
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#ifndef WINE_DSHOW_ASYNCSRC_H
|
||||
#define WINE_DSHOW_ASYNCSRC_H
|
||||
|
||||
#include "iunk.h"
|
||||
#include "basefilt.h"
|
||||
|
||||
typedef struct CAsyncSourceImpl CAsyncSourceImpl;
|
||||
typedef struct CAsyncSourcePinImpl CAsyncSourcePinImpl;
|
||||
typedef struct AsyncSourceHandlers AsyncSourceHandlers;
|
||||
|
||||
typedef struct CAsyncReaderImpl
|
||||
{
|
||||
ICOM_VFIELD(IAsyncReader);
|
||||
|
||||
/* IUnknown fields */
|
||||
IUnknown* punkControl;
|
||||
/* IAsyncReader fields */
|
||||
CAsyncSourceImpl* pSource;
|
||||
|
||||
CRITICAL_SECTION* pcsReader;
|
||||
HANDLE m_hEventInit;
|
||||
HANDLE m_hEventAbort;
|
||||
HANDLE m_hEventReqQueued;
|
||||
HANDLE m_hEventSampQueued;
|
||||
HANDLE m_hEventCompletion;
|
||||
HANDLE m_hThread;
|
||||
} CAsyncReaderImpl;
|
||||
|
||||
typedef struct CFileSourceFilterImpl
|
||||
{
|
||||
ICOM_VFIELD(IFileSourceFilter);
|
||||
|
||||
/* IUnknown fields */
|
||||
IUnknown* punkControl;
|
||||
/* IFileSourceFilter fields */
|
||||
CAsyncSourceImpl* pSource;
|
||||
|
||||
CRITICAL_SECTION* pcsFileSource;
|
||||
WCHAR* m_pwszFileName;
|
||||
DWORD m_cbFileName;
|
||||
AM_MEDIA_TYPE m_mt;
|
||||
} CFileSourceFilterImpl;
|
||||
|
||||
struct CAsyncSourceImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CBaseFilterImpl basefilter;
|
||||
CFileSourceFilterImpl filesrc;
|
||||
|
||||
CRITICAL_SECTION csFilter;
|
||||
CAsyncSourcePinImpl* pPin;
|
||||
const AsyncSourceHandlers* m_pHandler;
|
||||
void* m_pUserData;
|
||||
};
|
||||
|
||||
struct CAsyncSourcePinImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CPinBaseImpl pin;
|
||||
CAsyncReaderImpl async;
|
||||
QUARTZ_IFDelegation qiext;
|
||||
|
||||
BOOL bAsyncReaderQueried;
|
||||
CAsyncSourceImpl* pSource;
|
||||
};
|
||||
|
||||
struct AsyncSourceHandlers
|
||||
{
|
||||
/* all handlers MUST be implemented. */
|
||||
HRESULT (*pLoad)( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName );
|
||||
HRESULT (*pCleanup)( CAsyncSourceImpl* pImpl );
|
||||
HRESULT (*pGetLength)( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable );
|
||||
HRESULT (*pReadAsync)( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, HANDLE hEventCompletion );
|
||||
HRESULT (*pGetResult)( CAsyncSourceImpl* pImpl, LONG* plReturned );
|
||||
HRESULT (*pCancelAsync)( CAsyncSourceImpl* pImpl );
|
||||
};
|
||||
|
||||
#define CAsyncSourceImpl_THIS(iface,member) CAsyncSourceImpl* This = ((CAsyncSourceImpl*)(((char*)iface)-offsetof(CAsyncSourceImpl,member)))
|
||||
#define CAsyncSourcePinImpl_THIS(iface,member) CAsyncSourcePinImpl* This = ((CAsyncSourcePinImpl*)(((char*)iface)-offsetof(CAsyncSourcePinImpl,member)))
|
||||
|
||||
|
||||
HRESULT CAsyncReaderImpl_InitIAsyncReader(
|
||||
CAsyncReaderImpl* This, IUnknown* punkControl,
|
||||
CAsyncSourceImpl* pSource,
|
||||
CRITICAL_SECTION* pcsReader );
|
||||
void CAsyncReaderImpl_UninitIAsyncReader(
|
||||
CAsyncReaderImpl* This );
|
||||
HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
|
||||
CFileSourceFilterImpl* This, IUnknown* punkControl,
|
||||
CAsyncSourceImpl* pSource,
|
||||
CRITICAL_SECTION* pcsFileSource );
|
||||
void CFileSourceFilterImpl_UninitIFileSourceFilter(
|
||||
CFileSourceFilterImpl* This );
|
||||
|
||||
|
||||
HRESULT QUARTZ_CreateAsyncSource(
|
||||
IUnknown* punkOuter,void** ppobj,
|
||||
const CLSID* pclsidAsyncSource,
|
||||
LPCWSTR pwszAsyncSourceName,
|
||||
LPCWSTR pwszOutPinName,
|
||||
const AsyncSourceHandlers* pHandler );
|
||||
HRESULT QUARTZ_CreateAsyncSourcePin(
|
||||
CAsyncSourceImpl* pFilter,
|
||||
CRITICAL_SECTION* pcsPin,
|
||||
CAsyncSourcePinImpl** ppPin,
|
||||
LPCWSTR pwszPinName );
|
||||
|
||||
|
||||
#endif /* WINE_DSHOW_ASYNCSRC_H */
|
|
@ -22,6 +22,7 @@
|
|||
#include "control.h"
|
||||
#include "vfwmsgs.h"
|
||||
#include "uuids.h"
|
||||
#include "evcode.h"
|
||||
|
||||
#include "debugtools.h"
|
||||
DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
@ -365,6 +366,7 @@ static const CBaseFilterHandlers filterhandlers =
|
|||
{
|
||||
CAudioRendererImpl_OnActive, /* pOnActive */
|
||||
CAudioRendererImpl_OnInactive, /* pOnInactive */
|
||||
NULL, /* pOnStop */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -463,9 +465,11 @@ static HRESULT CAudioRendererPinImpl_EndOfStream( CPinBaseImpl* pImpl )
|
|||
FIXME( "(%p)\n", This );
|
||||
|
||||
This->pRender->m_fInFlush = FALSE;
|
||||
/* IMediaEventSink::Notify(EC_COMPLETE) */
|
||||
|
||||
return NOERROR;
|
||||
/* FIXME - don't notify twice until stopped or seeked. */
|
||||
return CBaseFilterImpl_MediaEventNotify(
|
||||
&This->pRender->basefilter, EC_COMPLETE,
|
||||
(LONG_PTR)S_OK, (LONG_PTR)(IBaseFilter*)(This->pRender) );
|
||||
}
|
||||
|
||||
static HRESULT CAudioRendererPinImpl_BeginFlush( CPinBaseImpl* pImpl )
|
||||
|
@ -497,11 +501,16 @@ static HRESULT CAudioRendererPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_
|
|||
|
||||
FIXME( "(%p)\n", This );
|
||||
|
||||
This->pRender->m_fInFlush = FALSE;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static const CBasePinHandlers pinhandlers =
|
||||
{
|
||||
NULL, /* pOnPreConnect */
|
||||
NULL, /* pOnPostConnect */
|
||||
NULL, /* pOnDisconnect */
|
||||
CAudioRendererPinImpl_CheckMediaType, /* pCheckMediaType */
|
||||
NULL, /* pQualityNotify */
|
||||
CAudioRendererPinImpl_Receive, /* pReceive */
|
||||
|
|
|
@ -23,6 +23,13 @@ DEFAULT_DEBUG_CHANNEL(quartz);
|
|||
#include "basefilt.h"
|
||||
#include "enumunk.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CBaseFilterImpl::IBaseFilter
|
||||
*
|
||||
*/
|
||||
|
||||
static HRESULT WINAPI
|
||||
CBaseFilterImpl_fnQueryInterface(IBaseFilter* iface,REFIID riid,void** ppobj)
|
||||
{
|
||||
|
@ -85,10 +92,17 @@ CBaseFilterImpl_fnStop(IBaseFilter* iface)
|
|||
{
|
||||
if ( This->pHandlers->pOnInactive != NULL )
|
||||
hr = This->pHandlers->pOnInactive( This );
|
||||
if ( SUCCEEDED(hr) )
|
||||
This->fstate = State_Paused;
|
||||
}
|
||||
|
||||
if ( This->fstate == State_Paused )
|
||||
{
|
||||
if ( This->pHandlers->pOnStop != NULL )
|
||||
hr = This->pHandlers->pOnStop( This );
|
||||
if ( SUCCEEDED(hr) )
|
||||
This->fstate = State_Stopped;
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->csFilter );
|
||||
|
||||
return hr;
|
||||
|
@ -105,16 +119,13 @@ CBaseFilterImpl_fnPause(IBaseFilter* iface)
|
|||
hr = NOERROR;
|
||||
|
||||
EnterCriticalSection( &This->csFilter );
|
||||
|
||||
if ( This->fstate == State_Running )
|
||||
if ( This->fstate != State_Paused )
|
||||
{
|
||||
if ( This->pHandlers->pOnInactive != NULL )
|
||||
hr = This->pHandlers->pOnInactive( This );
|
||||
}
|
||||
|
||||
if ( SUCCEEDED(hr) )
|
||||
This->fstate = State_Paused;
|
||||
|
||||
}
|
||||
LeaveCriticalSection( &This->csFilter );
|
||||
|
||||
TRACE("hr = %08lx\n",hr);
|
||||
|
@ -136,14 +147,20 @@ CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart)
|
|||
|
||||
This->rtStart = rtStart;
|
||||
|
||||
if ( This->fstate != State_Running )
|
||||
if ( This->fstate == State_Stopped )
|
||||
{
|
||||
if ( This->pHandlers->pOnInactive != NULL )
|
||||
hr = This->pHandlers->pOnInactive( This );
|
||||
if ( SUCCEEDED(hr) )
|
||||
This->fstate = State_Paused;
|
||||
}
|
||||
if ( This->fstate == State_Paused )
|
||||
{
|
||||
if ( This->pHandlers->pOnActive != NULL )
|
||||
hr = This->pHandlers->pOnActive( This );
|
||||
}
|
||||
|
||||
if ( SUCCEEDED(hr) )
|
||||
This->fstate = State_Running;
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->csFilter );
|
||||
|
||||
|
@ -366,6 +383,11 @@ CBaseFilterImpl_fnQueryVendorInfo(IBaseFilter* iface,LPWSTR* lpwszVendor)
|
|||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* construct/destruct CBaseFilterImpl
|
||||
*
|
||||
*/
|
||||
|
||||
static ICOM_VTABLE(IBaseFilter) ibasefilter =
|
||||
{
|
||||
|
@ -491,3 +513,41 @@ void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This )
|
|||
|
||||
DeleteCriticalSection( &This->csFilter );
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CBaseFilterImpl methods
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT CBaseFilterImpl_MediaEventNotify(
|
||||
CBaseFilterImpl* This, long lEvent,LONG_PTR lParam1,LONG_PTR lParam2)
|
||||
{
|
||||
IMediaEventSink* pSink = NULL;
|
||||
HRESULT hr = E_NOTIMPL;
|
||||
|
||||
EnterCriticalSection( &This->csFilter );
|
||||
|
||||
if ( This->pfg == NULL )
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = IFilterGraph_QueryInterface( This->pfg, &IID_IMediaEventSink, (void**)&pSink );
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
if ( pSink == NULL )
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = IMediaEventSink_Notify(pSink,lEvent,lParam1,lParam2);
|
||||
IMediaEventSink_Release(pSink);
|
||||
err:
|
||||
LeaveCriticalSection( &This->csFilter );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ struct CBaseFilterHandlers
|
|||
{
|
||||
HRESULT (*pOnActive)( CBaseFilterImpl* pImpl );
|
||||
HRESULT (*pOnInactive)( CBaseFilterImpl* pImpl );
|
||||
HRESULT (*pOnStop)( CBaseFilterImpl* pImpl );
|
||||
};
|
||||
|
||||
|
||||
|
@ -54,12 +55,18 @@ HRESULT CBaseFilterImpl_InitIBaseFilter(
|
|||
void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This );
|
||||
|
||||
|
||||
HRESULT CBaseFilterImpl_MediaEventNotify(
|
||||
CBaseFilterImpl* This, long lEvent,LONG_PTR lParam1,LONG_PTR lParam2);
|
||||
|
||||
|
||||
/*
|
||||
* Implements IPin, IMemInputPin, and IQualityControl. (internal)
|
||||
*
|
||||
* a base class for implementing IPin.
|
||||
*/
|
||||
|
||||
typedef struct OutputPinAsyncImpl OutputPinAsyncImpl;
|
||||
|
||||
typedef struct CPinBaseImpl
|
||||
{
|
||||
/* IPin */
|
||||
|
@ -80,7 +87,9 @@ typedef struct CPinBaseImpl
|
|||
CRITICAL_SECTION* pcsPin;
|
||||
CBaseFilterImpl* pFilter;
|
||||
IPin* pPinConnectedTo;
|
||||
IMemInputPin* pMemInputPinConnectedTo;
|
||||
AM_MEDIA_TYPE* pmtConn;
|
||||
OutputPinAsyncImpl* pAsyncOut; /* for asynchronous output */
|
||||
} CPinBaseImpl;
|
||||
|
||||
typedef struct CMemInputPinBaseImpl
|
||||
|
@ -111,6 +120,9 @@ typedef struct CQualityControlPassThruImpl
|
|||
|
||||
struct CBasePinHandlers
|
||||
{
|
||||
HRESULT (*pOnPreConnect)( CPinBaseImpl* pImpl, IPin* pPin );
|
||||
HRESULT (*pOnPostConnect)( CPinBaseImpl* pImpl, IPin* pPin );
|
||||
HRESULT (*pOnDisconnect)( CPinBaseImpl* pImpl );
|
||||
HRESULT (*pCheckMediaType)( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt );
|
||||
HRESULT (*pQualityNotify)( CPinBaseImpl* pImpl, IBaseFilter* pFilter, Quality q );
|
||||
HRESULT (*pReceive)( CPinBaseImpl* pImpl, IMediaSample* pSample );
|
||||
|
@ -146,5 +158,41 @@ void CQualityControlPassThruImpl_UninitIQualityControl(
|
|||
CQualityControlPassThruImpl* This );
|
||||
|
||||
|
||||
HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample );
|
||||
HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This );
|
||||
HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This );
|
||||
HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This );
|
||||
HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate );
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* handlers for output pins.
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample );
|
||||
HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate );
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* handlers for output pins (async).
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample );
|
||||
HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl );
|
||||
HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate );
|
||||
|
||||
|
||||
|
||||
#endif /* WINE_DSHOW_BASEFILT_H */
|
||||
|
|
|
@ -71,9 +71,11 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
|
|||
|
||||
if ( !This->bOutput )
|
||||
return E_UNEXPECTED;
|
||||
if ( pPin == NULL || pmt == NULL )
|
||||
if ( pPin == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
TRACE("try to connect to %p\n",pPin);
|
||||
|
||||
EnterCriticalSection( This->pcsPin );
|
||||
|
||||
if ( This->pPinConnectedTo != NULL )
|
||||
|
@ -84,6 +86,13 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
|
|||
|
||||
/* FIXME - return fail if running */
|
||||
|
||||
if ( This->pHandlers->pOnPreConnect != NULL )
|
||||
{
|
||||
hr = This->pHandlers->pOnPreConnect(This,pPin);
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ( pmt != NULL )
|
||||
{
|
||||
hr = IPin_QueryAccept(iface,pmt);
|
||||
|
@ -113,9 +122,6 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
|
||||
connected:;
|
||||
This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
|
||||
if ( This->pmtConn == NULL )
|
||||
|
@ -124,11 +130,32 @@ connected:;
|
|||
IPin_Disconnect(pPin);
|
||||
goto err;
|
||||
}
|
||||
hr = S_OK;
|
||||
|
||||
This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
|
||||
hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
IPin_Disconnect(pPin);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ( This->pHandlers->pOnPostConnect != NULL )
|
||||
{
|
||||
hr = This->pHandlers->pOnPostConnect(This,pPin);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
IPin_Disconnect(pPin);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
hr = S_OK;
|
||||
|
||||
err:
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
IPin_Disconnect(iface);
|
||||
}
|
||||
LeaveCriticalSection( This->pcsPin );
|
||||
|
||||
return hr;
|
||||
|
@ -157,6 +184,12 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt
|
|||
|
||||
/* FIXME - return fail if running */
|
||||
|
||||
if ( This->pHandlers->pOnPreConnect != NULL )
|
||||
{
|
||||
hr = This->pHandlers->pOnPreConnect(This,pPin);
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = IPin_QueryAccept(iface,pmt);
|
||||
if ( FAILED(hr) )
|
||||
|
@ -168,10 +201,20 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt
|
|||
hr = E_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
hr = S_OK;
|
||||
|
||||
if ( This->pHandlers->pOnPostConnect != NULL )
|
||||
{
|
||||
hr = This->pHandlers->pOnPostConnect(This,pPin);
|
||||
if ( FAILED(hr) )
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = S_OK;
|
||||
This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
|
||||
|
||||
err:
|
||||
if ( FAILED(hr) )
|
||||
IPin_Disconnect(iface);
|
||||
LeaveCriticalSection( This->pcsPin );
|
||||
|
||||
return hr;
|
||||
|
@ -189,15 +232,22 @@ CPinBaseImpl_fnDisconnect(IPin* iface)
|
|||
|
||||
/* FIXME - return fail if running */
|
||||
|
||||
if ( This->pPinConnectedTo != NULL )
|
||||
{
|
||||
/* FIXME - cleanup */
|
||||
if ( This->pHandlers->pOnDisconnect != NULL )
|
||||
hr = This->pHandlers->pOnDisconnect(This);
|
||||
|
||||
if ( This->pmtConn != NULL )
|
||||
{
|
||||
QUARTZ_MediaType_Destroy( This->pmtConn );
|
||||
This->pmtConn = NULL;
|
||||
}
|
||||
if ( This->pMemInputPinConnectedTo != NULL )
|
||||
{
|
||||
IMemInputPin_Release(This->pMemInputPinConnectedTo);
|
||||
This->pMemInputPinConnectedTo = NULL;
|
||||
}
|
||||
if ( This->pPinConnectedTo != NULL )
|
||||
{
|
||||
/* FIXME - cleanup */
|
||||
|
||||
IPin_Release(This->pPinConnectedTo);
|
||||
This->pPinConnectedTo = NULL;
|
||||
|
@ -517,7 +567,9 @@ HRESULT CPinBaseImpl_InitIPin(
|
|||
This->pcsPin = pcsPin;
|
||||
This->pFilter = pFilter;
|
||||
This->pPinConnectedTo = NULL;
|
||||
This->pMemInputPinConnectedTo = NULL;
|
||||
This->pmtConn = NULL;
|
||||
This->pAsyncOut = NULL;
|
||||
|
||||
This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
|
||||
if ( This->pwszId == NULL )
|
||||
|
@ -877,3 +929,463 @@ void CQualityControlPassThruImpl_UninitIQualityControl(
|
|||
{
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* helper methods for output pins.
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
|
||||
{
|
||||
if ( This->pHandlers->pReceive == NULL )
|
||||
return E_NOTIMPL;
|
||||
|
||||
return This->pHandlers->pReceive( This, pSample );
|
||||
}
|
||||
|
||||
HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
|
||||
{
|
||||
if ( This->pHandlers->pEndOfStream == NULL )
|
||||
return E_NOTIMPL;
|
||||
|
||||
return This->pHandlers->pEndOfStream( This );
|
||||
}
|
||||
|
||||
HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
|
||||
{
|
||||
if ( This->pHandlers->pBeginFlush == NULL )
|
||||
return E_NOTIMPL;
|
||||
|
||||
return This->pHandlers->pBeginFlush( This );
|
||||
}
|
||||
|
||||
HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
|
||||
{
|
||||
if ( This->pHandlers->pEndFlush == NULL )
|
||||
return E_NOTIMPL;
|
||||
|
||||
return This->pHandlers->pEndFlush( This );
|
||||
}
|
||||
|
||||
HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
|
||||
{
|
||||
if ( This->pHandlers->pNewSegment == NULL )
|
||||
return E_NOTIMPL;
|
||||
|
||||
return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* handlers for output pins.
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
|
||||
{
|
||||
if ( pImpl->pMemInputPinConnectedTo == NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
|
||||
}
|
||||
|
||||
HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
|
||||
{
|
||||
if ( pImpl->pMemInputPinConnectedTo == NULL )
|
||||
return S_FALSE;
|
||||
|
||||
return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
|
||||
}
|
||||
|
||||
HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
|
||||
{
|
||||
if ( pImpl->pPinConnectedTo == NULL )
|
||||
return NOERROR;
|
||||
|
||||
return IPin_EndOfStream(pImpl->pPinConnectedTo);
|
||||
}
|
||||
|
||||
HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
|
||||
{
|
||||
if ( pImpl->pPinConnectedTo == NULL )
|
||||
return NOERROR;
|
||||
|
||||
return IPin_BeginFlush(pImpl->pPinConnectedTo);
|
||||
}
|
||||
|
||||
HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
|
||||
{
|
||||
if ( pImpl->pPinConnectedTo == NULL )
|
||||
return NOERROR;
|
||||
|
||||
return IPin_EndFlush(pImpl->pPinConnectedTo);
|
||||
}
|
||||
|
||||
HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
|
||||
{
|
||||
if ( pImpl->pPinConnectedTo == NULL )
|
||||
return NOERROR;
|
||||
|
||||
return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* handlers for output pins (async).
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct OutputPinTask OutputPinTask;
|
||||
|
||||
enum OutputPinTaskType
|
||||
{
|
||||
OutTask_ExitThread,
|
||||
OutTask_Receive,
|
||||
OutTask_EndOfStream,
|
||||
OutTask_BeginFlush,
|
||||
OutTask_EndFlush,
|
||||
OutTask_NewSegment,
|
||||
};
|
||||
|
||||
struct OutputPinTask
|
||||
{
|
||||
OutputPinTask* pNext;
|
||||
enum OutputPinTaskType tasktype;
|
||||
IMediaSample* pSample;
|
||||
REFERENCE_TIME rtStart;
|
||||
REFERENCE_TIME rtStop;
|
||||
double rate;
|
||||
};
|
||||
|
||||
struct OutputPinAsyncImpl
|
||||
{
|
||||
HANDLE m_hTaskThread;
|
||||
HANDLE m_hTaskEvent;
|
||||
IPin* m_pPin; /* connected pin */
|
||||
IMemInputPin* m_pMemInputPin; /* connected pin */
|
||||
CRITICAL_SECTION m_csTasks;
|
||||
OutputPinTask* m_pFirst;
|
||||
OutputPinTask* m_pLast;
|
||||
OutputPinTask* m_pTaskExitThread;
|
||||
};
|
||||
|
||||
static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
|
||||
{
|
||||
OutputPinTask* pTask;
|
||||
|
||||
pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
|
||||
pTask->pNext = NULL;
|
||||
pTask->tasktype = tasktype;
|
||||
pTask->pSample = NULL;
|
||||
|
||||
return pTask;
|
||||
}
|
||||
|
||||
static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
|
||||
{
|
||||
if ( pTask->pSample != NULL )
|
||||
IMediaSample_Release( pTask->pSample );
|
||||
QUARTZ_FreeMem( pTask );
|
||||
}
|
||||
|
||||
static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
|
||||
{
|
||||
EnterCriticalSection( &This->m_csTasks );
|
||||
|
||||
if ( bFirst )
|
||||
{
|
||||
pTask->pNext = This->m_pFirst;
|
||||
This->m_pFirst = pTask;
|
||||
if ( This->m_pLast == NULL )
|
||||
This->m_pLast = pTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( This->m_pLast != NULL )
|
||||
This->m_pLast->pNext = pTask;
|
||||
else
|
||||
This->m_pFirst = pTask;
|
||||
This->m_pLast = pTask;
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->m_csTasks );
|
||||
|
||||
SetEvent( This->m_hTaskEvent );
|
||||
}
|
||||
|
||||
static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
|
||||
{
|
||||
OutputPinTask* pTask;
|
||||
|
||||
EnterCriticalSection( &This->m_csTasks );
|
||||
pTask = This->m_pFirst;
|
||||
if ( pTask != NULL )
|
||||
{
|
||||
This->m_pFirst = pTask->pNext;
|
||||
if ( This->m_pFirst == NULL )
|
||||
This->m_pLast = NULL;
|
||||
else
|
||||
SetEvent( This->m_hTaskEvent );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &This->m_csTasks );
|
||||
|
||||
return pTask;
|
||||
}
|
||||
|
||||
static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
|
||||
{
|
||||
OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
BOOL bLoop = TRUE;
|
||||
BOOL bInFlush = FALSE;
|
||||
HRESULT hr;
|
||||
|
||||
while ( bLoop )
|
||||
{
|
||||
WaitForSingleObject( This->m_hTaskEvent, INFINITE );
|
||||
ResetEvent( This->m_hTaskEvent );
|
||||
|
||||
pTask = OutputPinAsync_GetNextTask( This );
|
||||
if ( pTask == NULL )
|
||||
continue;
|
||||
|
||||
hr = S_OK;
|
||||
switch ( pTask->tasktype )
|
||||
{
|
||||
case OutTask_ExitThread:
|
||||
bLoop = FALSE;
|
||||
break;
|
||||
case OutTask_Receive:
|
||||
if ( !bInFlush )
|
||||
hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
|
||||
break;
|
||||
case OutTask_EndOfStream:
|
||||
hr = IPin_EndOfStream( This->m_pPin );
|
||||
break;
|
||||
case OutTask_BeginFlush:
|
||||
bInFlush = TRUE;
|
||||
hr = IPin_BeginFlush( This->m_pPin );
|
||||
break;
|
||||
case OutTask_EndFlush:
|
||||
bInFlush = FALSE;
|
||||
hr = IPin_EndFlush( This->m_pPin );
|
||||
break;
|
||||
case OutTask_NewSegment:
|
||||
hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
|
||||
break;
|
||||
default:
|
||||
ERR( "unexpected task type %d.\n", pTask->tasktype );
|
||||
bLoop = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
OutputPinAsync_FreeTask( pTask );
|
||||
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
ERR( "hresult %08lx\n", hr );
|
||||
bLoop = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD dwThreadId;
|
||||
|
||||
FIXME("(%p)\n",pImpl);
|
||||
|
||||
if ( pImpl->pMemInputPinConnectedTo == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pImpl->pAsyncOut = (OutputPinAsyncImpl*)
|
||||
QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
|
||||
if ( pImpl->pAsyncOut == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
|
||||
pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
|
||||
pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
|
||||
pImpl->pAsyncOut->m_pFirst = NULL;
|
||||
pImpl->pAsyncOut->m_pLast = NULL;
|
||||
pImpl->pAsyncOut->m_pTaskExitThread = NULL;
|
||||
pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
|
||||
pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
|
||||
|
||||
pImpl->pAsyncOut->m_hTaskEvent =
|
||||
CreateEventA( NULL, TRUE, FALSE, NULL );
|
||||
if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pImpl->pAsyncOut->m_pTaskExitThread =
|
||||
OutputPinAsync_AllocTask( OutTask_ExitThread );
|
||||
if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pImpl->pAsyncOut->m_hTaskThread = CreateThread(
|
||||
NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
|
||||
0, &dwThreadId );
|
||||
if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return NOERROR;
|
||||
err:
|
||||
OutputPinAsync_OnInactive( pImpl );
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
|
||||
{
|
||||
OutputPinTask* pTask;
|
||||
|
||||
FIXME("(%p)\n",pImpl);
|
||||
|
||||
if ( pImpl->pAsyncOut == NULL )
|
||||
return NOERROR;
|
||||
|
||||
if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
|
||||
{
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
|
||||
pImpl->pAsyncOut->m_pTaskExitThread = NULL;
|
||||
}
|
||||
|
||||
if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
|
||||
{
|
||||
WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
|
||||
CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
|
||||
}
|
||||
if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
|
||||
CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
|
||||
|
||||
/* release all tasks. */
|
||||
while ( 1 )
|
||||
{
|
||||
pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
|
||||
if ( pTask == NULL )
|
||||
break;
|
||||
OutputPinAsync_FreeTask( pTask );
|
||||
}
|
||||
|
||||
DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
|
||||
|
||||
QUARTZ_FreeMem( pImpl->pAsyncOut );
|
||||
pImpl->pAsyncOut = NULL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
|
||||
{
|
||||
OutputPinAsyncImpl* This = pImpl->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
|
||||
TRACE("(%p,%p)\n",pImpl,pSample);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pTask = OutputPinAsync_AllocTask( OutTask_Receive );
|
||||
if ( pTask == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
pTask->pSample = pSample; IMediaSample_AddRef( pSample );
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
|
||||
{
|
||||
OutputPinAsyncImpl* This = pImpl->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
|
||||
TRACE("(%p)\n",pImpl);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
|
||||
if ( pTask == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
|
||||
{
|
||||
OutputPinAsyncImpl* This = pImpl->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
|
||||
TRACE("(%p)\n",pImpl);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
|
||||
if ( pTask == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
|
||||
{
|
||||
OutputPinAsyncImpl* This = pImpl->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
|
||||
TRACE("(%p)\n",pImpl);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
|
||||
if ( pTask == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
|
||||
{
|
||||
OutputPinAsyncImpl* This = pImpl->pAsyncOut;
|
||||
OutputPinTask* pTask;
|
||||
|
||||
TRACE("(%p)\n",pImpl);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
|
||||
if ( pTask == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
pTask->rtStart = rtStart;
|
||||
pTask->rtStop = rtStop;
|
||||
pTask->rate = rate;
|
||||
OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -73,10 +73,19 @@ static HRESULT WINAPI
|
|||
IGraphConfig_fnReconfigure(IGraphConfig* iface,IGraphConfigCallback* pCallback,PVOID pvParam,DWORD dwFlags,HANDLE hAbort)
|
||||
{
|
||||
CFilterGraph_THIS(iface,grphconf);
|
||||
HRESULT hr;
|
||||
|
||||
FIXME("(%p)->() stub!\n",This);
|
||||
FIXME("(%p)->(%p,%p,%08lx,%08x) stub!\n",This,pCallback,pvParam,dwFlags,hAbort);
|
||||
|
||||
return E_NOTIMPL;
|
||||
QUARTZ_CompList_Lock( This->m_pFilterList );
|
||||
EnterCriticalSection( &This->m_csGraphState );
|
||||
|
||||
hr = IGraphConfigCallback_Reconfigure(pCallback,pvParam,dwFlags);
|
||||
|
||||
LeaveCriticalSection( &This->m_csGraphState );
|
||||
QUARTZ_CompList_Unlock( This->m_pFilterList );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
|
|
@ -32,7 +32,8 @@ DEFAULT_DEBUG_CHANNEL(quartz);
|
|||
#include "fmap2.h"
|
||||
#include "seekpass.h"
|
||||
#include "audren.h"
|
||||
|
||||
#include "vidren.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef struct QUARTZ_CLASSENTRY
|
||||
{
|
||||
|
@ -77,6 +78,8 @@ static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] =
|
|||
{ &CLSID_FilterMapper2, &QUARTZ_CreateFilterMapper2 },
|
||||
{ &CLSID_SeekingPassThru, &QUARTZ_CreateSeekingPassThru },
|
||||
{ &CLSID_AudioRender, &QUARTZ_CreateAudioRenderer },
|
||||
{ &CLSID_VideoRenderer, &QUARTZ_CreateVideoRenderer },
|
||||
{ &CLSID_quartzWaveParser, &QUARTZ_CreateWaveParser },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
|
|
@ -318,6 +318,8 @@ IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE
|
|||
|
||||
EnterCriticalSection( &This->csMem );
|
||||
|
||||
TRACE("(%p) enter critical section\n",This);
|
||||
|
||||
hr = NOERROR;
|
||||
|
||||
if ( This->pData == NULL || This->ppSamples == NULL ||
|
||||
|
@ -353,6 +355,7 @@ IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE
|
|||
|
||||
end:
|
||||
LeaveCriticalSection( &This->csMem );
|
||||
TRACE("(%p) leave critical section\n",This);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -418,3 +421,4 @@ void CMemoryAllocator_UninitIMemAllocator( CMemoryAllocator* pma )
|
|||
if ( pma->hEventSample != (HANDLE)NULL )
|
||||
CloseHandle( pma->hEventSample );
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "wine/obj_base.h"
|
||||
#include "strmif.h"
|
||||
#include "vfwmsgs.h"
|
||||
#include "uuids.h"
|
||||
|
||||
#include "debugtools.h"
|
||||
DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
@ -101,6 +102,22 @@ void QUARTZ_MediaType_Destroy(
|
|||
CoTaskMemFree( pmt );
|
||||
}
|
||||
|
||||
void QUARTZ_MediaSubType_FromFourCC(
|
||||
GUID* psubtype, DWORD dwFourCC )
|
||||
{
|
||||
memcpy( psubtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
|
||||
psubtype->Data1 = dwFourCC;
|
||||
}
|
||||
|
||||
BOOL QUARTZ_MediaSubType_IsFourCC(
|
||||
const GUID* psubtype )
|
||||
{
|
||||
GUID guidTemp;
|
||||
|
||||
QUARTZ_MediaSubType_FromFourCC(
|
||||
&guidTemp, psubtype->Data1 );
|
||||
return IsEqualGUID( psubtype, &guidTemp );
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@ AM_MEDIA_TYPE* QUARTZ_MediaType_Duplicate(
|
|||
void QUARTZ_MediaType_Destroy(
|
||||
AM_MEDIA_TYPE* pmt );
|
||||
|
||||
void QUARTZ_MediaSubType_FromFourCC(
|
||||
GUID* psubtype, DWORD dwFourCC );
|
||||
BOOL QUARTZ_MediaSubType_IsFourCC(
|
||||
const GUID* psubtype );
|
||||
|
||||
HRESULT QUARTZ_CreateEnumMediaTypes(
|
||||
IEnumMediaTypes** ppobj,
|
||||
|
|
|
@ -0,0 +1,999 @@
|
|||
/*
|
||||
* Implements IBaseFilter for parsers. (internal)
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "mmsystem.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/obj_base.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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Implements Parser.
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#ifndef WINE_DSHOW_PARSER_H
|
||||
#define WINE_DSHOW_PARSER_H
|
||||
|
||||
#include "iunk.h"
|
||||
#include "basefilt.h"
|
||||
|
||||
typedef struct CParserImpl CParserImpl;
|
||||
typedef struct CParserInPinImpl CParserInPinImpl;
|
||||
typedef struct CParserOutPinImpl CParserOutPinImpl;
|
||||
typedef struct ParserHandlers ParserHandlers;
|
||||
|
||||
/* {D51BD5A1-7548-11CF-A520-0080C77EF58A} */
|
||||
DEFINE_GUID(CLSID_quartzWaveParser,
|
||||
0xD51BD5A1,0x7548,0x11CF,0xA5,0x20,0x00,0x80,0xC7,0x7E,0xF5,0x8A);
|
||||
|
||||
struct CParserImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CBaseFilterImpl basefilter;
|
||||
|
||||
CParserInPinImpl* m_pInPin;
|
||||
ULONG m_cOutStreams;
|
||||
CParserOutPinImpl** m_ppOutPins;
|
||||
|
||||
CRITICAL_SECTION m_csParser;
|
||||
IAsyncReader* m_pReader;
|
||||
IMemAllocator* m_pAllocator;
|
||||
ALLOCATOR_PROPERTIES m_propAlloc;
|
||||
HANDLE m_hEventInit;
|
||||
DWORD m_dwThreadId;
|
||||
HANDLE m_hThread;
|
||||
const ParserHandlers* m_pHandler;
|
||||
|
||||
void* m_pUserData;
|
||||
};
|
||||
|
||||
struct CParserInPinImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CPinBaseImpl pin;
|
||||
CMemInputPinBaseImpl meminput;
|
||||
|
||||
CParserImpl* pParser;
|
||||
};
|
||||
|
||||
struct CParserOutPinImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CPinBaseImpl pin;
|
||||
CQualityControlPassThruImpl qcontrol;
|
||||
|
||||
CParserImpl* pParser;
|
||||
ULONG nStreamIndex;
|
||||
|
||||
AM_MEDIA_TYPE m_mtOut;
|
||||
IMemAllocator* m_pOutPinAllocator;
|
||||
void* m_pUserData;
|
||||
|
||||
/* for parser */
|
||||
BOOL m_bReqUsed;
|
||||
LONGLONG m_llReqStart;
|
||||
LONG m_lReqLength;
|
||||
REFERENCE_TIME m_rtReqStart;
|
||||
REFERENCE_TIME m_rtReqStop;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ParserHandlers
|
||||
{
|
||||
HRESULT (*pInitParser)( CParserImpl* pImpl, ULONG* pcStreams );
|
||||
HRESULT (*pUninitParser)( CParserImpl* pImpl );
|
||||
LPCWSTR (*pGetOutPinName)( CParserImpl* pImpl, ULONG nStreamIndex );
|
||||
HRESULT (*pGetStreamType)( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt );
|
||||
HRESULT (*pCheckStreamType)( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt );
|
||||
HRESULT (*pGetAllocProp)( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp );
|
||||
/* S_OK - ok, S_FALSE - end of stream */
|
||||
HRESULT (*pGetNextRequest)( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop );
|
||||
HRESULT (*pProcessSample)( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample );
|
||||
|
||||
/* for IQualityControl */
|
||||
HRESULT (*pQualityNotify)( CParserImpl* pImpl, ULONG nStreamIndex, Quality q );
|
||||
|
||||
/* for seeking */
|
||||
HRESULT (*pGetSeekingCaps)( CParserImpl* pImpl, DWORD* pdwCaps );
|
||||
HRESULT (*pIsTimeFormatSupported)( CParserImpl* pImpl, const GUID* pTimeFormat );
|
||||
HRESULT (*pGetCurPos)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG* pllPos );
|
||||
HRESULT (*pSetCurPos)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG llPos );
|
||||
HRESULT (*pGetDuration)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG* pllDuration );
|
||||
HRESULT (*pSetDuration)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG llDuration );
|
||||
HRESULT (*pGetStopPos)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG* pllPos );
|
||||
HRESULT (*pSetStopPos)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG llPos );
|
||||
HRESULT (*pGetPreroll)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG* pllPreroll );
|
||||
HRESULT (*pSetPreroll)( CParserImpl* pImpl, const GUID* pTimeFormat, DWORD nStreamIndex, LONGLONG llPreroll );
|
||||
};
|
||||
|
||||
#define CParserImpl_THIS(iface,member) CParserImpl* This = ((CParserImpl*)(((char*)iface)-offsetof(CParserImpl,member)))
|
||||
#define CParserInPinImpl_THIS(iface,member) CParserInPinImpl* This = ((CParserInPinImpl*)(((char*)iface)-offsetof(CParserInPinImpl,member)))
|
||||
#define CParserOutPinImpl_THIS(iface,member) CParserOutPinImpl* This = ((CParserOutPinImpl*)(((char*)iface)-offsetof(CParserOutPinImpl,member)))
|
||||
|
||||
|
||||
HRESULT QUARTZ_CreateParser(
|
||||
IUnknown* punkOuter,void** ppobj,
|
||||
const CLSID* pclsidParser,
|
||||
LPCWSTR pwszParserName,
|
||||
LPCWSTR pwszInPinName,
|
||||
const ParserHandlers* pHandler );
|
||||
HRESULT QUARTZ_CreateParserInPin(
|
||||
CParserImpl* pFilter,
|
||||
CRITICAL_SECTION* pcsPin,
|
||||
CParserInPinImpl** ppPin,
|
||||
LPCWSTR pwszPinName );
|
||||
HRESULT QUARTZ_CreateParserOutPin(
|
||||
CParserImpl* pFilter,
|
||||
CRITICAL_SECTION* pcsPin,
|
||||
CParserOutPinImpl** ppPin,
|
||||
ULONG nStreamIndex,
|
||||
LPCWSTR pwszPinName );
|
||||
|
||||
|
||||
#define QUARTZ_TIMEUNITS ((LONGLONG)10000000)
|
||||
#define PARSER_POLL_INTERVAL 100
|
||||
|
||||
#define PARSER_RIFF_OfsFirst 12
|
||||
#define PARSER_WAVE mmioFOURCC('W','A','V','E')
|
||||
#define PARSER_AVI mmioFOURCC('A','V','I',' ')
|
||||
#define PARSER_AVIX mmioFOURCC('A','V','I','X')
|
||||
|
||||
#define PARSER_fmt mmioFOURCC('f','m','t',' ')
|
||||
#define PARSER_fact mmioFOURCC('f','a','c','t')
|
||||
#define PARSER_data mmioFOURCC('d','a','t','a')
|
||||
|
||||
#define PARSER_avih mmioFOURCC('a','v','i','h')
|
||||
#define PARSER_strl mmioFOURCC('s','t','r','l')
|
||||
#define PARSER_strh mmioFOURCC('s','t','r','h')
|
||||
#define PARSER_strf mmioFOURCC('s','t','r','f')
|
||||
#define PARSER_idx1 mmioFOURCC('i','d','x','1')
|
||||
#define PARSER_indx mmioFOURCC('i','n','d','x')
|
||||
#define PARSER_movi mmioFOURCC('m','o','v','i')
|
||||
#define PARSER_JUNK mmioFOURCC('J','U','N','K')
|
||||
|
||||
#define PARSER_vids mmioFOURCC('v','i','d','s')
|
||||
#define PARSER_auds mmioFOURCC('a','u','d','s')
|
||||
#define PARSER_mids mmioFOURCC('m','i','d','s')
|
||||
#define PARSER_txts mmioFOURCC('t','x','t','s')
|
||||
|
||||
#define PARSER_LE_UINT16(ptr) (((DWORD)(ptr)[0])|((DWORD)(ptr)[1]<<8))
|
||||
#define PARSER_LE_UINT32(ptr) (((DWORD)(ptr)[0])|((DWORD)(ptr)[1]<<8)|((DWORD)(ptr)[2]<<16)|((DWORD)(ptr)[3]<<24))
|
||||
#define PARSER_BE_UINT16(ptr) (((DWORD)(ptr)[0]<<8)|((DWORD)(ptr)[1]))
|
||||
#define PARSER_BE_UINT32(ptr) (((DWORD)(ptr)[0]<<24)|((DWORD)(ptr)[1]<<16)|((DWORD)(ptr)[2]<<8)|((DWORD)(ptr)[3]))
|
||||
|
||||
HRESULT QUARTZ_CreateWaveParser(IUnknown* punkOuter,void** ppobj);
|
||||
|
||||
|
||||
|
||||
#endif /* WINE_DSHOW_PARSER_H */
|
|
@ -6,7 +6,7 @@ import oleaut32.dll
|
|||
import ole32.dll
|
||||
import winmm.dll
|
||||
import user32.dll
|
||||
#import gdi32.dll
|
||||
import gdi32.dll
|
||||
import advapi32.dll
|
||||
import kernel32.dll
|
||||
import ntdll.dll
|
||||
|
|
|
@ -23,6 +23,147 @@ DEFAULT_DEBUG_CHANNEL(quartz);
|
|||
#include "mtype.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* Helper functions
|
||||
*
|
||||
*/
|
||||
|
||||
HRESULT QUARTZ_IMediaSample_GetProperties(
|
||||
IMediaSample* pSample,
|
||||
AM_SAMPLE2_PROPERTIES* pProp )
|
||||
{
|
||||
HRESULT hr;
|
||||
AM_SAMPLE2_PROPERTIES prop;
|
||||
IMediaSample2* pSample2 = NULL;
|
||||
|
||||
ZeroMemory( &prop, sizeof(AM_SAMPLE2_PROPERTIES) );
|
||||
|
||||
#if 0 /* not yet */
|
||||
hr = IMediaSample_QueryInterface( pSample, &IID_IMediaSample2, (void**)&pSample2 );
|
||||
if ( hr == S_OK )
|
||||
{
|
||||
hr = IMediaSample2_GetProperties(pSample2,sizeof(AM_SAMPLE2_PROPERTIES),&prop);
|
||||
IMediaSample2_Release(pSample2);
|
||||
if ( hr == S_OK )
|
||||
{
|
||||
memcpy( pProp, &prop, sizeof(AM_SAMPLE2_PROPERTIES) );
|
||||
pProp->pMediaType =
|
||||
QUARTZ_MediaType_Duplicate( &prop.pMediaType );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pProp->cbData = sizeof(AM_SAMPLE2_PROPERTIES);
|
||||
pProp->dwTypeSpecificFlags = 0;
|
||||
pProp->dwSampleFlags = 0;
|
||||
if ( IMediaSample_IsSyncPoint(pSample) == S_OK )
|
||||
pProp->dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
|
||||
if ( IMediaSample_IsPreroll(pSample) == S_OK )
|
||||
pProp->dwSampleFlags |= AM_SAMPLE_PREROLL;
|
||||
if ( IMediaSample_IsDiscontinuity(pSample) == S_OK )
|
||||
pProp->dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
|
||||
pProp->lActual = (LONG)IMediaSample_GetActualDataLength(pSample);
|
||||
if ( IMediaSample_GetTime(pSample,&pProp->tStart,&pProp->tStop) == S_OK )
|
||||
pProp->dwSampleFlags |= AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID;
|
||||
pProp->dwStreamId = 0;
|
||||
if ( IMediaSample_GetMediaType(pSample,&(pProp->pMediaType)) == S_OK )
|
||||
pProp->dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
|
||||
IMediaSample_GetPointer(pSample,&(pProp->pbBuffer));
|
||||
pProp->cbBuffer = (LONG)IMediaSample_GetSize(pSample);
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT QUARTZ_IMediaSample_SetProperties(
|
||||
IMediaSample* pSample,
|
||||
const AM_SAMPLE2_PROPERTIES* pProp )
|
||||
{
|
||||
HRESULT hr;
|
||||
AM_SAMPLE2_PROPERTIES prop;
|
||||
IMediaSample2* pSample2 = NULL;
|
||||
|
||||
memcpy( &prop, pProp, sizeof(AM_SAMPLE2_PROPERTIES) );
|
||||
prop.cbData = sizeof(AM_SAMPLE2_PROPERTIES);
|
||||
prop.pbBuffer = NULL;
|
||||
prop.cbBuffer = 0;
|
||||
|
||||
#if 0 /* not yet */
|
||||
hr = IMediaSample_QueryInterface( pSample, &IID_IMediaSample2, (void**)&pSample2 );
|
||||
if ( hr == S_OK )
|
||||
{
|
||||
hr = IMediaSample2_SetProperties(pSample2,sizeof(AM_SAMPLE2_PROPERTIES),&prop);
|
||||
IMediaSample2_Release(pSample2);
|
||||
if ( hr == S_OK )
|
||||
return NOERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
hr = S_OK;
|
||||
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_SetSyncPoint(pSample,
|
||||
(prop.dwSampleFlags & AM_SAMPLE_SPLICEPOINT) ? TRUE : FALSE);
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_SetPreroll(pSample,
|
||||
(prop.dwSampleFlags & AM_SAMPLE_PREROLL) ? TRUE : FALSE);
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_SetDiscontinuity(pSample,
|
||||
(prop.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) ? TRUE : FALSE);
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_SetActualDataLength(pSample,prop.lActual);
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
if ( ( prop.dwSampleFlags & AM_SAMPLE_TIMEVALID) &&
|
||||
( prop.dwSampleFlags & AM_SAMPLE_STOPVALID) )
|
||||
hr = IMediaSample_SetTime(pSample,&prop.tStart,&prop.tStop);
|
||||
else
|
||||
hr = IMediaSample_SetTime(pSample,NULL,NULL);
|
||||
}
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_SetMediaType(pSample,
|
||||
(prop.dwSampleFlags & AM_SAMPLE_TYPECHANGED) ?
|
||||
prop.pMediaType : NULL);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT QUARTZ_IMediaSample_Copy(
|
||||
IMediaSample* pDstSample,
|
||||
IMediaSample* pSrcSample,
|
||||
BOOL bCopyData )
|
||||
{
|
||||
HRESULT hr;
|
||||
AM_SAMPLE2_PROPERTIES prop;
|
||||
BYTE* pDataSrc = NULL;
|
||||
BYTE* pDataDst = NULL;
|
||||
|
||||
hr = QUARTZ_IMediaSample_GetProperties( pSrcSample, &prop );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
hr = QUARTZ_IMediaSample_SetProperties( pDstSample, &prop );
|
||||
if ( prop.pMediaType != NULL )
|
||||
QUARTZ_MediaType_Destroy( prop.pMediaType );
|
||||
|
||||
if ( SUCCEEDED(hr) && bCopyData )
|
||||
{
|
||||
hr = IMediaSample_GetPointer(pSrcSample,&pDataSrc);
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = IMediaSample_GetPointer(pDstSample,&pDataDst);
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
if ( pDataSrc != NULL && pDataDst != NULL )
|
||||
memcpy( pDataDst, pDataSrc, prop.lActual );
|
||||
else
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* CMemMediaSample::IMediaSample2
|
||||
|
@ -69,6 +210,12 @@ IMediaSample2_fnRelease(IMediaSample2* iface)
|
|||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
if ( This->ref == 0 )
|
||||
{
|
||||
ERR("(%p) - released sample!\n",This);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
|
||||
if ( ref > 0 )
|
||||
return (ULONG)ref;
|
||||
|
@ -97,6 +244,12 @@ IMediaSample2_fnGetPointer(IMediaSample2* iface,BYTE** ppData)
|
|||
|
||||
TRACE("(%p)->()\n",This);
|
||||
|
||||
if ( This->ref == 0 )
|
||||
{
|
||||
ERR("(%p) - released sample!\n",This);
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if ( ppData == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
|
@ -121,6 +274,12 @@ IMediaSample2_fnGetTime(IMediaSample2* iface,REFERENCE_TIME* prtStart,REFERENCE_
|
|||
|
||||
TRACE("(%p)->(%p,%p)\n",This,prtStart,prtEnd);
|
||||
|
||||
if ( This->ref == 0 )
|
||||
{
|
||||
ERR("(%p) - released sample!\n",This);
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if ( prtStart == NULL || prtEnd == NULL )
|
||||
return E_POINTER;
|
||||
|
||||
|
@ -226,7 +385,7 @@ IMediaSample2_fnSetActualDataLength(IMediaSample2* iface,long lLength)
|
|||
|
||||
TRACE("(%p)->(%ld)\n",This,lLength);
|
||||
|
||||
if ( This->prop.cbBuffer > lLength )
|
||||
if ( This->prop.cbBuffer < lLength )
|
||||
return E_INVALIDARG;
|
||||
|
||||
This->prop.lActual = lLength;
|
||||
|
|
|
@ -31,4 +31,18 @@ HRESULT QUARTZ_CreateMemMediaSample(
|
|||
void QUARTZ_DestroyMemMediaSample(
|
||||
CMemMediaSample* pSample );
|
||||
|
||||
|
||||
HRESULT QUARTZ_IMediaSample_GetProperties(
|
||||
IMediaSample* pSample,
|
||||
AM_SAMPLE2_PROPERTIES* pProp );
|
||||
HRESULT QUARTZ_IMediaSample_SetProperties(
|
||||
IMediaSample* pSample,
|
||||
const AM_SAMPLE2_PROPERTIES* pProp );
|
||||
HRESULT QUARTZ_IMediaSample_Copy(
|
||||
IMediaSample* pDstSample,
|
||||
IMediaSample* pSrcSample,
|
||||
BOOL bCopyData );
|
||||
|
||||
|
||||
|
||||
#endif /* WINE_DSHOW_SAMPLE_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Implements CLSID_VideoRenderer.
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#ifndef WINE_DSHOW_VIDREN_H
|
||||
#define WINE_DSHOW_VIDREN_H
|
||||
|
||||
#include "iunk.h"
|
||||
#include "basefilt.h"
|
||||
|
||||
typedef struct CVideoRendererImpl CVideoRendererImpl;
|
||||
typedef struct CVideoRendererPinImpl CVideoRendererPinImpl;
|
||||
|
||||
|
||||
typedef struct VidRen_IBasicVideo
|
||||
{
|
||||
ICOM_VFIELD(IBasicVideo2);
|
||||
} VidRen_IBasicVideo;
|
||||
|
||||
typedef struct VidRen_IVideoWindow
|
||||
{
|
||||
ICOM_VFIELD(IVideoWindow);
|
||||
} VidRen_IVideoWindow;
|
||||
|
||||
struct CVideoRendererImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CBaseFilterImpl basefilter;
|
||||
VidRen_IBasicVideo basvid;
|
||||
VidRen_IVideoWindow vidwin;
|
||||
|
||||
CVideoRendererPinImpl* pPin;
|
||||
|
||||
BOOL m_fInFlush;
|
||||
|
||||
/* for rendering */
|
||||
HANDLE m_hEventInit;
|
||||
HANDLE m_hThread;
|
||||
HWND m_hwnd;
|
||||
CRITICAL_SECTION m_csSample;
|
||||
BOOL m_bSampleIsValid;
|
||||
BYTE* m_pSampleData;
|
||||
DWORD m_cbSampleData;
|
||||
};
|
||||
|
||||
struct CVideoRendererPinImpl
|
||||
{
|
||||
QUARTZ_IUnkImpl unk;
|
||||
CPinBaseImpl pin;
|
||||
CMemInputPinBaseImpl meminput;
|
||||
|
||||
CVideoRendererImpl* pRender;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define CVideoRendererImpl_THIS(iface,member) CVideoRendererImpl* This = ((CVideoRendererImpl*)(((char*)iface)-offsetof(CVideoRendererImpl,member)))
|
||||
#define CVideoRendererPinImpl_THIS(iface,member) CVideoRendererPinImpl* This = ((CVideoRendererPinImpl*)(((char*)iface)-offsetof(CVideoRendererPinImpl,member)))
|
||||
|
||||
HRESULT CVideoRendererImpl_InitIBasicVideo2( CVideoRendererImpl* This );
|
||||
void CVideoRendererImpl_UninitIBasicVideo2( CVideoRendererImpl* This );
|
||||
HRESULT CVideoRendererImpl_InitIVideoWindow( CVideoRendererImpl* This );
|
||||
void CVideoRendererImpl_UninitIVideoWindow( CVideoRendererImpl* This );
|
||||
|
||||
HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj);
|
||||
HRESULT QUARTZ_CreateVideoRendererPin(
|
||||
CVideoRendererImpl* pFilter,
|
||||
CRITICAL_SECTION* pcsPin,
|
||||
CVideoRendererPinImpl** ppPin);
|
||||
|
||||
|
||||
#endif /* WINE_DSHOW_VIDREN_H */
|
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* Implements WAVE/AU/AIFF Parser.
|
||||
*
|
||||
* hidenori@a2.ctktv.ne.jp
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "mmsystem.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/obj_base.h"
|
||||
#include "strmif.h"
|
||||
#include "vfwmsgs.h"
|
||||
#include "uuids.h"
|
||||
|
||||
#include "debugtools.h"
|
||||
DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
||||
#include "quartz_private.h"
|
||||
|
||||
/* for CLSID_quartzWaveParser. */
|
||||
#include "initguid.h"
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
static const WCHAR QUARTZ_WaveParser_Name[] =
|
||||
{ 'W','a','v','e',' ','P','a','r','s','e','r',0 };
|
||||
static const WCHAR QUARTZ_WaveParserInPin_Name[] =
|
||||
{ 'I','n',0 };
|
||||
static const WCHAR QUARTZ_WaveParserOutPin_Name[] =
|
||||
{ 'O','u','t',0 };
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* S_OK = found, S_FALSE = not found */
|
||||
HRESULT RIFF_GetNext(
|
||||
CParserImpl* pImpl, LONGLONG llOfs,
|
||||
DWORD* pdwCode, DWORD* pdwLength )
|
||||
{
|
||||
BYTE bTemp[8];
|
||||
HRESULT hr;
|
||||
|
||||
hr = IAsyncReader_SyncRead( pImpl->m_pReader, llOfs, 8, bTemp );
|
||||
if ( hr == S_OK )
|
||||
{
|
||||
*pdwCode = mmioFOURCC(bTemp[0],bTemp[1],bTemp[2],bTemp[3]);
|
||||
*pdwLength = PARSER_LE_UINT32(&bTemp[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwCode = 0;
|
||||
*pdwLength = 0;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* S_OK = found, S_FALSE = not found */
|
||||
HRESULT RIFF_SearchChunk(
|
||||
CParserImpl* pImpl,
|
||||
LONGLONG llOfs, DWORD dwChunk,
|
||||
LONGLONG* pllOfs, DWORD* pdwChunkLength )
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD dwCurCode;
|
||||
DWORD dwCurLen;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
hr = RIFF_GetNext( pImpl, llOfs, &dwCurCode, &dwCurLen );
|
||||
if ( hr != S_OK )
|
||||
break;
|
||||
if ( dwChunk == dwCurCode )
|
||||
break;
|
||||
llOfs += 8 + (LONGLONG)((dwCurLen+1)&(~1));
|
||||
}
|
||||
|
||||
*pllOfs = llOfs;
|
||||
*pdwChunkLength = dwCurLen;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* CWavParseImpl
|
||||
*/
|
||||
|
||||
typedef enum WavParseFmtType
|
||||
{
|
||||
WaveParse_Native,
|
||||
WaveParse_Signed8,
|
||||
WaveParse_Signed16BE,
|
||||
WaveParse_Unsigned16LE,
|
||||
WaveParse_Unsigned16BE,
|
||||
} WavParseFmtType;
|
||||
|
||||
typedef struct CWavParseImpl
|
||||
{
|
||||
DWORD cbFmt;
|
||||
WAVEFORMATEX* pFmt;
|
||||
DWORD dwBlockSize;
|
||||
LONGLONG llDataStart;
|
||||
LONGLONG llBytesTotal;
|
||||
LONGLONG llBytesProcessed;
|
||||
WavParseFmtType iFmtType;
|
||||
} CWavParseImpl;
|
||||
|
||||
|
||||
static HRESULT CWavParseImpl_InitWAV( CParserImpl* pImpl, CWavParseImpl* This )
|
||||
{
|
||||
HRESULT hr;
|
||||
LONGLONG llOfs;
|
||||
DWORD dwChunkLength;
|
||||
|
||||
hr = RIFF_SearchChunk(
|
||||
pImpl, PARSER_RIFF_OfsFirst,
|
||||
PARSER_fmt, &llOfs, &dwChunkLength );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
if ( hr != S_OK || ( dwChunkLength < (sizeof(WAVEFORMATEX)-2) ) )
|
||||
return E_FAIL;
|
||||
llOfs += 8;
|
||||
|
||||
This->cbFmt = dwChunkLength;
|
||||
if ( dwChunkLength < sizeof(WAVEFORMATEX) )
|
||||
This->cbFmt = sizeof(WAVEFORMATEX);
|
||||
This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( dwChunkLength );
|
||||
if ( This->pFmt == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
ZeroMemory( This->pFmt, This->cbFmt );
|
||||
|
||||
hr = IAsyncReader_SyncRead(
|
||||
pImpl->m_pReader, llOfs, dwChunkLength, (BYTE*)This->pFmt );
|
||||
if ( hr != S_OK )
|
||||
{
|
||||
if ( SUCCEEDED(hr) )
|
||||
hr = E_FAIL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
hr = RIFF_SearchChunk(
|
||||
pImpl, PARSER_RIFF_OfsFirst,
|
||||
PARSER_data, &llOfs, &dwChunkLength );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
if ( hr != S_OK || dwChunkLength == 0 )
|
||||
return E_FAIL;
|
||||
|
||||
This->llDataStart = llOfs;
|
||||
This->llBytesTotal = (LONGLONG)dwChunkLength;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_InitAU( CParserImpl* pImpl, CWavParseImpl* This )
|
||||
{
|
||||
BYTE au_hdr[24];
|
||||
DWORD dataofs;
|
||||
DWORD datalen;
|
||||
DWORD datafmt;
|
||||
DWORD datarate;
|
||||
DWORD datachannels;
|
||||
HRESULT hr;
|
||||
WAVEFORMATEX wfx;
|
||||
|
||||
hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 24, au_hdr );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
dataofs = PARSER_BE_UINT32(&au_hdr[4]);
|
||||
datalen = PARSER_BE_UINT32(&au_hdr[8]);
|
||||
datafmt = PARSER_BE_UINT32(&au_hdr[12]);
|
||||
datarate = PARSER_BE_UINT32(&au_hdr[16]);
|
||||
datachannels = PARSER_BE_UINT32(&au_hdr[20]);
|
||||
|
||||
if ( dataofs < 24U || datalen == 0U )
|
||||
return E_FAIL;
|
||||
if ( datachannels != 1 && datachannels != 2 )
|
||||
return E_FAIL;
|
||||
|
||||
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
|
||||
wfx.nChannels = datachannels;
|
||||
wfx.nSamplesPerSec = datarate;
|
||||
|
||||
switch ( datafmt )
|
||||
{
|
||||
case 1:
|
||||
wfx.wFormatTag = 7;
|
||||
wfx.nBlockAlign = datachannels;
|
||||
wfx.wBitsPerSample = 8;
|
||||
break;
|
||||
case 2:
|
||||
wfx.wFormatTag = 1;
|
||||
wfx.nBlockAlign = datachannels;
|
||||
wfx.wBitsPerSample = 8;
|
||||
This->iFmtType = WaveParse_Signed8;
|
||||
break;
|
||||
case 3:
|
||||
wfx.wFormatTag = 1;
|
||||
wfx.nBlockAlign = datachannels;
|
||||
wfx.wBitsPerSample = 16;
|
||||
This->iFmtType = WaveParse_Signed16BE;
|
||||
break;
|
||||
default:
|
||||
FIXME("audio/basic - unknown format %lu\n", datafmt );
|
||||
return E_FAIL;
|
||||
}
|
||||
wfx.nAvgBytesPerSec = (datarate * datachannels * (DWORD)wfx.wBitsPerSample) >> 3;
|
||||
|
||||
This->cbFmt = sizeof(WAVEFORMATEX);
|
||||
This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( sizeof(WAVEFORMATEX) );
|
||||
if ( This->pFmt == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy( This->pFmt, &wfx, sizeof(WAVEFORMATEX) );
|
||||
|
||||
This->llDataStart = dataofs;
|
||||
This->llBytesTotal = datalen;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_InitAIFF( CParserImpl* pImpl, CWavParseImpl* This )
|
||||
{
|
||||
FIXME( "AIFF is not supported now.\n" );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
|
||||
{
|
||||
CWavParseImpl* This = NULL;
|
||||
HRESULT hr;
|
||||
BYTE header[12];
|
||||
|
||||
TRACE("(%p,%p)\n",pImpl,pcStreams);
|
||||
|
||||
if ( pImpl->m_pReader == NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
This = (CWavParseImpl*)QUARTZ_AllocMem( sizeof(CWavParseImpl) );
|
||||
if ( This == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
pImpl->m_pUserData = This;
|
||||
|
||||
/* construct */
|
||||
This->cbFmt = 0;
|
||||
This->pFmt = NULL;
|
||||
This->dwBlockSize = 0;
|
||||
This->llDataStart = 0;
|
||||
This->llBytesTotal = 0;
|
||||
This->llBytesProcessed = 0;
|
||||
This->iFmtType = WaveParse_Native;
|
||||
|
||||
hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 12, header );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
if ( hr != S_OK )
|
||||
return E_FAIL;
|
||||
|
||||
if ( !memcmp( &header[0], "RIFF", 4 ) &&
|
||||
!memcmp( &header[8], "WAVE", 4 ) )
|
||||
{
|
||||
TRACE( "(%p) - it's audio/wav.\n", pImpl );
|
||||
hr = CWavParseImpl_InitWAV( pImpl, This );
|
||||
}
|
||||
else
|
||||
if ( !memcmp( &header[0], ".snd", 4 ) )
|
||||
{
|
||||
TRACE( "(%p) - it's audio/basic.\n", pImpl );
|
||||
hr = CWavParseImpl_InitAU( pImpl, This );
|
||||
}
|
||||
else
|
||||
if ( !memcmp( &header[0], "FORM", 4 ) &&
|
||||
!memcmp( &header[8], "AIFF", 4 ) )
|
||||
{
|
||||
TRACE( "(%p) - it's audio/aiff.\n", pImpl );
|
||||
hr = CWavParseImpl_InitAIFF( pImpl, This );
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME( "(%p) - unknown format.\n", pImpl );
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* initialized successfully. */
|
||||
*pcStreams = 1;
|
||||
|
||||
This->dwBlockSize = (This->pFmt->nAvgBytesPerSec + (DWORD)This->pFmt->nBlockAlign - 1U) / (DWORD)This->pFmt->nBlockAlign;
|
||||
|
||||
TRACE( "(%p) returned successfully.\n", pImpl );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_UninitParser( CParserImpl* pImpl )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if ( This == NULL )
|
||||
return NOERROR;
|
||||
|
||||
/* destruct */
|
||||
if ( This->pFmt != NULL ) QUARTZ_FreeMem(This->pFmt);
|
||||
|
||||
QUARTZ_FreeMem( This );
|
||||
pImpl->m_pUserData = NULL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static LPCWSTR CWavParseImpl_GetOutPinName( CParserImpl* pImpl, ULONG nStreamIndex )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
return QUARTZ_WaveParserOutPin_Name;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if ( This == NULL || This->pFmt == NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
|
||||
memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
|
||||
QUARTZ_MediaSubType_FromFourCC( &pmt->subtype, (DWORD)This->pFmt->wFormatTag );
|
||||
pmt->bFixedSizeSamples = 1;
|
||||
pmt->bTemporalCompression = 0;
|
||||
pmt->lSampleSize = This->pFmt->nBlockAlign;
|
||||
memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
|
||||
pmt->pUnk = NULL;
|
||||
|
||||
pmt->pbFormat = (BYTE*)CoTaskMemAlloc( This->cbFmt );
|
||||
if ( pmt->pbFormat == NULL )
|
||||
return E_OUTOFMEMORY;
|
||||
pmt->cbFormat = This->cbFmt;
|
||||
memcpy( pmt->pbFormat, This->pFmt, This->cbFmt );
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
|
||||
{
|
||||
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) ||
|
||||
!IsEqualGUID( &pmt->formattype, &FORMAT_WaveFormatEx ) )
|
||||
return E_FAIL;
|
||||
if ( pmt->pbFormat == NULL || pmt->cbFormat < sizeof(WAVEFORMATEX) )
|
||||
return E_FAIL;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if ( This == NULL || This->pFmt == NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
ZeroMemory( pReqProp, sizeof(ALLOCATOR_PROPERTIES) );
|
||||
pReqProp->cBuffers = 1;
|
||||
pReqProp->cbBuffer = This->dwBlockSize;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
LONGLONG llAvail;
|
||||
LONGLONG llStart;
|
||||
LONGLONG llEnd;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if ( This == NULL || This->pFmt == NULL )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
llAvail = This->llBytesTotal - This->llBytesProcessed;
|
||||
if ( llAvail > (LONGLONG)This->dwBlockSize )
|
||||
llAvail = (LONGLONG)This->dwBlockSize;
|
||||
llStart = This->llBytesProcessed;
|
||||
llEnd = llStart + llAvail;
|
||||
This->llBytesProcessed = llEnd;
|
||||
|
||||
*pllStart = This->llBytesProcessed;
|
||||
*plLength = (LONG)llAvail;
|
||||
*prtStart = llStart * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;
|
||||
*prtStop = llEnd * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
static HRESULT CWavParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
|
||||
{
|
||||
CWavParseImpl* This = (CWavParseImpl*)pImpl->m_pUserData;
|
||||
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
switch ( This->iFmtType )
|
||||
{
|
||||
case WaveParse_Native:
|
||||
break;
|
||||
default:
|
||||
FIXME("(%p) - %d not implemented\n", This, This->iFmtType );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
static const struct ParserHandlers CWavParseImpl_Handlers =
|
||||
{
|
||||
CWavParseImpl_InitParser,
|
||||
CWavParseImpl_UninitParser,
|
||||
CWavParseImpl_GetOutPinName,
|
||||
CWavParseImpl_GetStreamType,
|
||||
CWavParseImpl_CheckStreamType,
|
||||
CWavParseImpl_GetAllocProp,
|
||||
CWavParseImpl_GetNextRequest,
|
||||
CWavParseImpl_ProcessSample,
|
||||
|
||||
/* for IQualityControl */
|
||||
NULL, /* pQualityNotify */
|
||||
|
||||
/* for seeking */
|
||||
NULL, /* pGetSeekingCaps */
|
||||
NULL, /* pIsTimeFormatSupported */
|
||||
NULL, /* pGetCurPos */
|
||||
NULL, /* pSetCurPos */
|
||||
NULL, /* pGetDuration */
|
||||
NULL, /* pSetDuration */
|
||||
NULL, /* pGetStopPos */
|
||||
NULL, /* pSetStopPos */
|
||||
NULL, /* pGetPreroll */
|
||||
NULL, /* pSetPreroll */
|
||||
};
|
||||
|
||||
HRESULT QUARTZ_CreateWaveParser(IUnknown* punkOuter,void** ppobj)
|
||||
{
|
||||
return QUARTZ_CreateParser(
|
||||
punkOuter,ppobj,
|
||||
&CLSID_quartzWaveParser,
|
||||
QUARTZ_WaveParser_Name,
|
||||
QUARTZ_WaveParserInPin_Name,
|
||||
&CWavParseImpl_Handlers );
|
||||
}
|
||||
|
||||
|
|
@ -4,12 +4,76 @@
|
|||
#include "ole2.h"
|
||||
#include "ddraw.h"
|
||||
|
||||
|
||||
typedef struct IBaseVideoMixer IBaseVideoMixer;
|
||||
typedef struct IDirectDrawVideo IDirectDrawVideo;
|
||||
typedef struct IFullScreenVideo IFullScreenVideo;
|
||||
typedef struct IFullScreenVideoEx IFullScreenVideoEx;
|
||||
typedef struct IQualProp IQualProp;
|
||||
|
||||
|
||||
#define iEGA_COLORS 16
|
||||
#define iPALETTE_COLORS 256
|
||||
#define iMASK_COLORS 3
|
||||
#define iRED 0
|
||||
#define iGREEN 1
|
||||
#define iBLUE 2
|
||||
|
||||
#define WIDTHBYTES(bits) ((DWORD)((((DWORD)(bits)+31U)&(~31U))>>3))
|
||||
#define DIBWIDTHBYTES(bi) ((DWORD)WIDTHBYTES((bi).biWidth*(bi).biBitCount))
|
||||
#define DIBSIZE(bi) (DIBWIDTHBYTES(bi)*(DWORD)abs((bi).biHeight))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwBitMasks[iMASK_COLORS];
|
||||
RGBQUAD bmiColors[iPALETTE_COLORS];
|
||||
} TRUECOLORINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RECT rcSource;
|
||||
RECT rcTarget;
|
||||
DWORD dwBitRate;
|
||||
DWORD dwBitErrorRate;
|
||||
REFERENCE_TIME AvgTimePerFrame;
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
} VIDEOINFOHEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RECT rcSource;
|
||||
RECT rcTarget;
|
||||
DWORD dwBitRate;
|
||||
DWORD dwBitErrorRate;
|
||||
REFERENCE_TIME AvgTimePerFrame;
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
|
||||
union {
|
||||
RGBQUAD bmiColors[iPALETTE_COLORS];
|
||||
DWORD dwBitMasks[iMASK_COLORS];
|
||||
TRUECOLORINFO TrueColorInfo;
|
||||
} DUMMYUNIONNAME;
|
||||
} VIDEOINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
VIDEOINFOHEADER hdr;
|
||||
DWORD dwStartTimeCode;
|
||||
DWORD cbSequenceHeader;
|
||||
BYTE bSequenceHeader[1];
|
||||
} MPEG1VIDEOINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RECT rcSource;
|
||||
RECT rcTarget;
|
||||
DWORD dwActiveWidth;
|
||||
DWORD dwActiveHeight;
|
||||
REFERENCE_TIME AvgTimePerFrame;
|
||||
} ANALOGVIDEOINFO;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* IBaseVideoMixer interface
|
||||
|
|
|
@ -328,6 +328,88 @@
|
|||
"CLSID"="{e30629d1-27e5-11ce-875d-00608cb78066}"
|
||||
"FriendlyName"="Waveout audio renderer"
|
||||
|
||||
# CLSID_VideoRenderer
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{70e102b0-5556-11ce-97c0-00aa0055595a}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{70e102b0-5556-11ce-97c0-00aa0055595a}]
|
||||
"CLSID"="{70e102b0-5556-11ce-97c0-00aa0055595a}"
|
||||
"FriendlyName"="Video Renderer"
|
||||
|
||||
# Wave Parser
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{D51BD5A1-7548-11CF-A520-0080C77EF58A}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{D51BD5A1-7548-11CF-A520-0080C77EF58A}]
|
||||
"CLSID"="{D51BD5A1-7548-11CF-A520-0080C77EF58A}"
|
||||
"FriendlyName"="Wave Parser"
|
||||
|
||||
# CLSID_AVIDec(AVI Decompressor) (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{CF49D4E0-1115-11CE-B03A-0020AF0BA770}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{CF49D4E0-1115-11CE-B03A-0020AF0BA770}]
|
||||
"CLSID"="{CF49D4E0-1115-11CE-B03A-0020AF0BA770}"
|
||||
"FriendlyName"="AVI Decompressor"
|
||||
|
||||
# CLSID_AsyncReader (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{E436EBB5-524F-11CE-9F53-0020AF0BA770}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{E436EBB5-524F-11CE-9F53-0020AF0BA770}]
|
||||
"CLSID"="{E436EBB5-524F-11CE-9F53-0020AF0BA770}"
|
||||
"FriendlyName"="Async Reader"
|
||||
|
||||
# CLSID_URLReader (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{E436EBB6-524F-11CE-9F53-0020AF0BA770}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{E436EBB6-524F-11CE-9F53-0020AF0BA770}]
|
||||
"CLSID"="{E436EBB6-524F-11CE-9F53-0020AF0BA770}"
|
||||
"FriendlyName"="URL Reader"
|
||||
|
||||
# CLSID_AviSplitter (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{1B544C20-FD0B-11CE-8C63-00AA0044B51E}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{1B544C20-FD0B-11CE-8C63-00AA0044B51E}]
|
||||
"CLSID"="{1B544C20-FD0B-11CE-8C63-00AA0044B51E}"
|
||||
"FriendlyName"="AVI Splitter"
|
||||
|
||||
# CLSID_QuickTimeParser (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{D51BD5A0-7548-11CF-A520-0080C77EF58A}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{D51BD5A0-7548-11CF-A520-0080C77EF58A}]
|
||||
"CLSID"="{D51BD5A0-7548-11CF-A520-0080C77EF58A}"
|
||||
"FriendlyName"="QuickTime Movie Parser"
|
||||
|
||||
# CLSID_Colour(Color space converter) (not implemented yet)
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{1643E180-90F5-11CE-97D5-00AA0055595A}\InprocServer32]
|
||||
@="quartz.dll"
|
||||
"ThreadingModel"="Both"
|
||||
|
||||
[HKEY_CLASSES_ROOT\CLSID\{083863F1-70DE-11D0-BD40-00A0C911CE86}\Instance\{1643E180-90F5-11CE-97D5-00AA0055595A}]
|
||||
"CLSID"="{1643E180-90F5-11CE-97D5-00AA0055595A}"
|
||||
"FriendlyName"="Color space converter"
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Entries for Mozilla ActiveX control support
|
||||
|
|
Loading…
Reference in New Issue