Commit bd3be7a9 authored by Hidenori Takeshima's avatar Hidenori Takeshima Committed by Alexandre Julliard

Started Implementing Video Renderer.

Started Implementing WAVE/AU/AIFF Parser. Started Implementing file source. Fixed some bugs.
parent 90d4b11b
......@@ -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@
......
/*
* 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;
}
/*
* 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 */
};
/***************************************************************************
......@@ -378,7 +380,7 @@ static HRESULT CAudioRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const
CAudioRendererPinImpl_THIS(pImpl,pin);
const WAVEFORMATEX* pwfx;
TRACE( "(%p,%p)\n",This,pmt );
TRACE("(%p,%p)\n",This,pmt);
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) )
return E_FAIL;
......@@ -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,
......
/*
* 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;
}
/*
* 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
......
......@@ -25,6 +25,147 @@ DEFAULT_DEBUG_CHANNEL(quartz);
/***************************************************************************
*
* 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 */
/*
* Implements CLSID_VideoRenderer.
*
* hidenori@a2.ctktv.ne.jp
*
* FIXME - use clock
*/
#include "config.h"
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "wine/obj_base.h"
#include "wine/obj_oleaut.h"
#include "mmsystem.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "amvideo.h"
#include "evcode.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "vidren.h"
static const WCHAR QUARTZ_VideoRenderer_Name[] =
{ 'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0 };
static const WCHAR QUARTZ_VideoRendererPin_Name[] =
{ 'I','n',0 };
#define VIDRENMSG_UPDATE (WM_APP+0)
#define VIDRENMSG_ENDTHREAD (WM_APP+1)
static const CHAR VIDREN_szWndClass[] = "Wine_VideoRenderer";
static const CHAR VIDREN_szWndName[] = "Wine Video Renderer";
static void VIDREN_OnPaint( CVideoRendererImpl* This, HWND hwnd )
{
PAINTSTRUCT ps;
const VIDEOINFOHEADER* pinfo;
const AM_MEDIA_TYPE* pmt;
TRACE("(%p,%08x)\n",This,hwnd);
if ( !BeginPaint( hwnd, &ps ) )
return;
pmt = This->pPin->pin.pmtConn;
if ( (!This->m_bSampleIsValid) || pmt == NULL )
goto err;
pinfo = (const VIDEOINFOHEADER*)pmt->pbFormat;
StretchDIBits(
ps.hdc,
0, 0,
abs(pinfo->bmiHeader.biWidth), abs(pinfo->bmiHeader.biHeight),
0, 0,
abs(pinfo->bmiHeader.biWidth), abs(pinfo->bmiHeader.biHeight),
This->m_pSampleData, (BITMAPINFO*)(&pinfo->bmiHeader),
DIB_RGB_COLORS, SRCCOPY );
err:
EndPaint( hwnd, &ps );
}
static void VIDREN_OnQueryNewPalette( CVideoRendererImpl* This, HWND hwnd )
{
FIXME("(%p,%08x)\n",This,hwnd);
}
static void VIDREN_OnUpdate( CVideoRendererImpl* This, HWND hwnd )
{
MSG msg;
TRACE("(%p,%08x)\n",This,hwnd);
InvalidateRect(hwnd,NULL,FALSE);
UpdateWindow(hwnd);
/* FIXME */
while ( PeekMessageA(&msg,hwnd,
VIDRENMSG_UPDATE,VIDRENMSG_UPDATE,
PM_REMOVE) != FALSE )
{
/* discard this message. */
}
}
static LRESULT CALLBACK
VIDREN_WndProc(
HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
CVideoRendererImpl* This = (CVideoRendererImpl*)
GetWindowLongA( hwnd, 0L );
TRACE("(%p) - %u/%u/%ld\n",This,message,wParam,lParam);
if ( message == WM_NCCREATE )
{
This = (CVideoRendererImpl*)(((CREATESTRUCTA*)lParam)->lpCreateParams);
SetWindowLongA( hwnd, 0L, (LONG)This );
This->m_hwnd = hwnd;
}
if ( message == WM_NCDESTROY )
{
PostQuitMessage(0);
This->m_hwnd = (HWND)NULL;
SetWindowLongA( hwnd, 0L, (LONG)NULL );
This = NULL;
}
if ( This != NULL )
{
switch ( message )
{
case WM_PAINT:
TRACE("WM_PAINT begin\n");
EnterCriticalSection( &This->m_csSample );
VIDREN_OnPaint( This, hwnd );
LeaveCriticalSection( &This->m_csSample );
TRACE("WM_PAINT end\n");
return 0;
case WM_CLOSE:
ShowWindow( hwnd, SW_HIDE );
return 0;
case WM_PALETTECHANGED:
if ( hwnd == (HWND)wParam )
break;
/* fall through */
case WM_QUERYNEWPALETTE:
VIDREN_OnQueryNewPalette( This, hwnd );
break;
case VIDRENMSG_UPDATE:
VIDREN_OnUpdate( This, hwnd );
return 0;
case VIDRENMSG_ENDTHREAD:
DestroyWindow(hwnd);
return 0;
default:
break;
}
}
return DefWindowProcA( hwnd, message, wParam, lParam );
}
static BOOL VIDREN_Register( HINSTANCE hInst )
{
WNDCLASSA wc;
ATOM atom;
wc.style = 0;
wc.lpfnWndProc = VIDREN_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG);
wc.hInstance = hInst;
wc.hIcon = LoadIconA((HINSTANCE)NULL,IDI_WINLOGOA);
wc.hCursor = LoadCursorA((HINSTANCE)NULL,IDC_ARROWA);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = VIDREN_szWndClass;
atom = RegisterClassA( &wc );
if ( atom != (ATOM)0 )
return TRUE;
/* FIXME */
return FALSE;
}
static HWND VIDREN_Create( HWND hwndOwner, CVideoRendererImpl* This )
{
HINSTANCE hInst = (HINSTANCE)GetModuleHandleA(NULL);
const VIDEOINFOHEADER* pinfo;
DWORD dwExStyle = 0;
DWORD dwStyle = WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
RECT rcWnd;
if ( !VIDREN_Register( hInst ) )
return (HWND)NULL;
pinfo = (const VIDEOINFOHEADER*)This->pPin->pin.pmtConn->pbFormat;
TRACE("width %ld, height %ld\n", pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight);
rcWnd.left = 0;
rcWnd.top = 0;
rcWnd.right = pinfo->bmiHeader.biWidth;
rcWnd.bottom = abs(pinfo->bmiHeader.biHeight);
AdjustWindowRectEx( &rcWnd, dwStyle, FALSE, dwExStyle );
TRACE("window width %d,height %d\n",
rcWnd.right-rcWnd.left,rcWnd.bottom-rcWnd.top);
return CreateWindowExA(
dwExStyle,
VIDREN_szWndClass, VIDREN_szWndName,
dwStyle | WS_VISIBLE,
100,100, /* FIXME */
rcWnd.right-rcWnd.left, rcWnd.bottom-rcWnd.top,
hwndOwner, (HMENU)NULL,
hInst, (LPVOID)This );
}
static DWORD WINAPI VIDREN_ThreadEntry( LPVOID pv )
{
CVideoRendererImpl* This = (CVideoRendererImpl*)pv;
MSG msg;
TRACE("(%p)\n",This);
if ( !VIDREN_Create( (HWND)NULL, This ) )
return 0;
TRACE("VIDREN_Create succeeded\n");
SetEvent( This->m_hEventInit );
TRACE("Enter message loop\n");
while ( GetMessageA(&msg,(HWND)NULL,0,0) )
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return 0;
}
static HRESULT VIDREN_StartThread( CVideoRendererImpl* This )
{
DWORD dwRes;
DWORD dwThreadId;
HANDLE hEvents[2];
if ( This->m_hEventInit != (HANDLE)NULL ||
This->m_hwnd != (HWND)NULL ||
This->m_hThread != (HANDLE)NULL ||
This->pPin->pin.pmtConn == NULL )
return E_UNEXPECTED;
This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
if ( This->m_hEventInit == (HANDLE)NULL )
return E_OUTOFMEMORY;
This->m_hThread = CreateThread(
NULL, 0,
VIDREN_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 S_OK;
}
static void VIDREN_EndThread( CVideoRendererImpl* This )
{
if ( This->m_hwnd != (HWND)NULL )
PostMessageA( This->m_hwnd, VIDRENMSG_ENDTHREAD, 0, 0 );
if ( This->m_hThread != (HANDLE)NULL )
{
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;
}
}
/***************************************************************************
*
* CVideoRendererImpl methods
*
*/
static HRESULT CVideoRendererImpl_OnActive( CBaseFilterImpl* pImpl )
{
CVideoRendererImpl_THIS(pImpl,basefilter);
FIXME( "(%p)\n", This );
This->m_bSampleIsValid = FALSE;
return NOERROR;
}
static HRESULT CVideoRendererImpl_OnInactive( CBaseFilterImpl* pImpl )
{
CVideoRendererImpl_THIS(pImpl,basefilter);
FIXME( "(%p)\n", This );
EnterCriticalSection( &This->m_csSample );
This->m_bSampleIsValid = FALSE;
LeaveCriticalSection( &This->m_csSample );
return NOERROR;
}
static const CBaseFilterHandlers filterhandlers =
{
CVideoRendererImpl_OnActive, /* pOnActive */
CVideoRendererImpl_OnInactive, /* pOnInactive */
NULL, /* pOnStop */
};
/***************************************************************************
*
* CVideoRendererPinImpl methods
*
*/
static HRESULT CVideoRendererPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
TRACE("(%p,%p)\n",This,pPin);
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
const VIDEOINFOHEADER* pinfo;
HRESULT hr;
TRACE("(%p,%p)\n",This,pPin);
if ( This->pRender->m_pSampleData != NULL )
{
QUARTZ_FreeMem(This->pRender->m_pSampleData);
This->pRender->m_pSampleData = NULL;
}
This->pRender->m_cbSampleData = 0;
This->pRender->m_bSampleIsValid = FALSE;
pinfo = (const VIDEOINFOHEADER*)This->pin.pmtConn->pbFormat;
if ( pinfo == NULL )
return E_FAIL;
This->pRender->m_bSampleIsValid = FALSE;
This->pRender->m_cbSampleData = DIBSIZE(pinfo->bmiHeader);
This->pRender->m_pSampleData = (BYTE*)QUARTZ_AllocMem(This->pRender->m_cbSampleData);
if ( This->pRender->m_pSampleData == NULL )
return E_OUTOFMEMORY;
hr = VIDREN_StartThread(This->pRender);
if ( FAILED(hr) )
return hr;
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
TRACE("(%p)\n",This);
VIDREN_EndThread(This->pRender);
if ( This->pRender->m_pSampleData != NULL )
{
QUARTZ_FreeMem(This->pRender->m_pSampleData);
This->pRender->m_pSampleData = NULL;
}
This->pRender->m_cbSampleData = 0;
This->pRender->m_bSampleIsValid = FALSE;
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
const VIDEOINFOHEADER* pinfo;
TRACE("(%p,%p)\n",This,pmt);
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Video ) )
return E_FAIL;
if ( !IsEqualGUID( &pmt->formattype, &FORMAT_VideoInfo ) )
return E_FAIL;
/*
* check subtype.
*/
if ( !IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB555 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB565 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB24 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB32 ) )
return E_FAIL;
/****
*
*
if ( !IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB8 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB555 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB565 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB24 ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_RGB32 ) )
return E_FAIL;
*
****/
pinfo = (const VIDEOINFOHEADER*)pmt->pbFormat;
if ( pinfo == NULL ||
pinfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER) ||
pinfo->bmiHeader.biWidth <= 0 ||
pinfo->bmiHeader.biHeight == 0 ||
pinfo->bmiHeader.biPlanes != 1 ||
pinfo->bmiHeader.biCompression != 0 )
return E_FAIL;
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
HWND hwnd;
BYTE* pData = NULL;
LONG lLength;
HRESULT hr;
TRACE( "(%p,%p)\n",This,pSample );
hwnd = This->pRender->m_hwnd;
if ( hwnd == (HWND)NULL ||
This->pRender->m_hThread == (HWND)NULL )
return E_UNEXPECTED;
if ( This->pRender->m_fInFlush )
return S_FALSE;
if ( pSample == NULL )
return E_POINTER;
/* FIXME - wait/skip/qualitycontrol */
/* duplicate this sample. */
hr = IMediaSample_GetPointer(pSample,&pData);
if ( FAILED(hr) )
return hr;
lLength = (LONG)IMediaSample_GetActualDataLength(pSample);
if ( lLength <= 0 || (lLength < (LONG)This->pRender->m_cbSampleData) )
{
ERR( "invalid length: %ld\n", lLength );
return NOERROR;
}
EnterCriticalSection( &This->pRender->m_csSample );
memcpy(This->pRender->m_pSampleData,pData,lLength);
This->pRender->m_bSampleIsValid = TRUE;
PostMessageA( hwnd, VIDRENMSG_UPDATE, 0, 0 );
LeaveCriticalSection( &This->pRender->m_csSample );
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_ReceiveCanBlock( CPinBaseImpl* pImpl )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
/* might block. */
return S_OK;
}
static HRESULT CVideoRendererPinImpl_EndOfStream( CPinBaseImpl* pImpl )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
This->pRender->m_fInFlush = FALSE;
/* 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 CVideoRendererPinImpl_BeginFlush( CPinBaseImpl* pImpl )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
This->pRender->m_fInFlush = TRUE;
EnterCriticalSection( &This->pRender->m_csSample );
This->pRender->m_bSampleIsValid = FALSE;
LeaveCriticalSection( &This->pRender->m_csSample );
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_EndFlush( CPinBaseImpl* pImpl )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
This->pRender->m_fInFlush = FALSE;
return NOERROR;
}
static HRESULT CVideoRendererPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
{
CVideoRendererPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
This->pRender->m_fInFlush = FALSE;
return NOERROR;
}
static const CBasePinHandlers pinhandlers =
{
CVideoRendererPinImpl_OnPreConnect, /* pOnPreConnect */
CVideoRendererPinImpl_OnPostConnect, /* pOnPostConnect */
CVideoRendererPinImpl_OnDisconnect, /* pOnDisconnect */
CVideoRendererPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
CVideoRendererPinImpl_Receive, /* pReceive */
CVideoRendererPinImpl_ReceiveCanBlock, /* pReceiveCanBlock */
CVideoRendererPinImpl_EndOfStream, /* pEndOfStream */
CVideoRendererPinImpl_BeginFlush, /* pBeginFlush */
CVideoRendererPinImpl_EndFlush, /* pEndFlush */
CVideoRendererPinImpl_NewSegment, /* pNewSegment */
};
/***************************************************************************
*
* new/delete CVideoRendererImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry FilterIFEntries[] =
{
{ &IID_IPersist, offsetof(CVideoRendererImpl,basefilter)-offsetof(CVideoRendererImpl,unk) },
{ &IID_IMediaFilter, offsetof(CVideoRendererImpl,basefilter)-offsetof(CVideoRendererImpl,unk) },
{ &IID_IBaseFilter, offsetof(CVideoRendererImpl,basefilter)-offsetof(CVideoRendererImpl,unk) },
{ &IID_IBasicVideo, offsetof(CVideoRendererImpl,basvid)-offsetof(CVideoRendererImpl,unk) },
{ &IID_IBasicVideo2, offsetof(CVideoRendererImpl,basvid)-offsetof(CVideoRendererImpl,unk) },
{ &IID_IVideoWindow, offsetof(CVideoRendererImpl,vidwin)-offsetof(CVideoRendererImpl,unk) },
};
static void QUARTZ_DestroyVideoRenderer(IUnknown* punk)
{
CVideoRendererImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
CVideoRendererImpl_OnInactive(&This->basefilter);
VIDREN_EndThread(This);
if ( This->pPin != NULL )
{
IUnknown_Release(This->pPin->unk.punkControl);
This->pPin = NULL;
}
CVideoRendererImpl_UninitIBasicVideo2(This);
CVideoRendererImpl_UninitIVideoWindow(This);
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
DeleteCriticalSection( &This->m_csSample );
}
HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj)
{
CVideoRendererImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p)\n",punkOuter,ppobj);
This = (CVideoRendererImpl*)
QUARTZ_AllocObj( sizeof(CVideoRendererImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
This->pPin = NULL;
This->m_fInFlush = FALSE;
This->m_hEventInit = (HANDLE)NULL;
This->m_hThread = (HANDLE)NULL;
This->m_hwnd = (HWND)NULL;
This->m_bSampleIsValid = FALSE;
This->m_pSampleData = NULL;
This->m_cbSampleData = 0;
QUARTZ_IUnkInit( &This->unk, punkOuter );
hr = CBaseFilterImpl_InitIBaseFilter(
&This->basefilter,
This->unk.punkControl,
&CLSID_VideoRenderer,
QUARTZ_VideoRenderer_Name,
&filterhandlers );
if ( SUCCEEDED(hr) )
{
hr = CVideoRendererImpl_InitIBasicVideo2(This);
if ( SUCCEEDED(hr) )
{
hr = CVideoRendererImpl_InitIVideoWindow(This);
if ( FAILED(hr) )
{
CVideoRendererImpl_UninitIBasicVideo2(This);
}
}
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_DestroyVideoRenderer;
hr = QUARTZ_CreateVideoRendererPin(
This,
&This->basefilter.csFilter,
&This->pPin );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
This->basefilter.pInPins,
(IUnknown*)&This->pPin->pin,
NULL, 0 );
if ( FAILED(hr) )
{
IUnknown_Release( This->unk.punkControl );
return hr;
}
InitializeCriticalSection( &This->m_csSample );
*ppobj = (void*)&(This->unk);
return S_OK;
}
/***************************************************************************
*
* new/delete CVideoRendererPinImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry PinIFEntries[] =
{
{ &IID_IPin, offsetof(CVideoRendererPinImpl,pin)-offsetof(CVideoRendererPinImpl,unk) },
{ &IID_IMemInputPin, offsetof(CVideoRendererPinImpl,meminput)-offsetof(CVideoRendererPinImpl,unk) },
};
static void QUARTZ_DestroyVideoRendererPin(IUnknown* punk)
{
CVideoRendererPinImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
CPinBaseImpl_UninitIPin( &This->pin );
CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
}
HRESULT QUARTZ_CreateVideoRendererPin(
CVideoRendererImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CVideoRendererPinImpl** ppPin)
{
CVideoRendererPinImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
This = (CVideoRendererPinImpl*)
QUARTZ_AllocObj( sizeof(CVideoRendererPinImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, NULL );
This->pRender = pFilter;
hr = CPinBaseImpl_InitIPin(
&This->pin,
This->unk.punkControl,
pcsPin,
&pFilter->basefilter,
QUARTZ_VideoRendererPin_Name,
FALSE,
&pinhandlers );
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 = PinIFEntries;
This->unk.dwEntries = sizeof(PinIFEntries)/sizeof(PinIFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroyVideoRendererPin;
*ppPin = This;
TRACE("returned successfully.\n");
return S_OK;
}
/***************************************************************************
*
* CVideoRendererImpl::IBasicVideo2
*
*/
static HRESULT WINAPI
IBasicVideo2_fnQueryInterface(IBasicVideo2* iface,REFIID riid,void** ppobj)
{
CVideoRendererImpl_THIS(iface,basvid);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IBasicVideo2_fnAddRef(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IBasicVideo2_fnRelease(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IBasicVideo2_fnGetTypeInfoCount(IBasicVideo2* iface,UINT* pcTypeInfo)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetTypeInfo(IBasicVideo2* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetIDsOfNames(IBasicVideo2* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnInvoke(IBasicVideo2* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_AvgTimePerFrame(IBasicVideo2* iface,REFTIME* prefTime)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_BitRate(IBasicVideo2* iface,long* plRate)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_BitErrorRate(IBasicVideo2* iface,long* plRate)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_VideoWidth(IBasicVideo2* iface,long* plWidth)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_VideoHeight(IBasicVideo2* iface,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_SourceLeft(IBasicVideo2* iface,long lLeft)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_SourceLeft(IBasicVideo2* iface,long* plLeft)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_SourceWidth(IBasicVideo2* iface,long lWidth)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_SourceWidth(IBasicVideo2* iface,long* plWidth)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_SourceTop(IBasicVideo2* iface,long lTop)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_SourceTop(IBasicVideo2* iface,long* plTop)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_SourceHeight(IBasicVideo2* iface,long lHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_SourceHeight(IBasicVideo2* iface,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_DestinationLeft(IBasicVideo2* iface,long lLeft)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_DestinationLeft(IBasicVideo2* iface,long* plLeft)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_DestinationWidth(IBasicVideo2* iface,long lWidth)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_DestinationWidth(IBasicVideo2* iface,long* plWidth)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_DestinationTop(IBasicVideo2* iface,long lTop)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_DestinationTop(IBasicVideo2* iface,long* plTop)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnput_DestinationHeight(IBasicVideo2* iface,long lHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnget_DestinationHeight(IBasicVideo2* iface,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnSetSourcePosition(IBasicVideo2* iface,long lLeft,long lTop,long lWidth,long lHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetSourcePosition(IBasicVideo2* iface,long* plLeft,long* plTop,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnSetDefaultSourcePosition(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnSetDestinationPosition(IBasicVideo2* iface,long lLeft,long lTop,long lWidth,long lHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetDestinationPosition(IBasicVideo2* iface,long* plLeft,long* plTop,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnSetDefaultDestinationPosition(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetVideoSize(IBasicVideo2* iface,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetVideoPaletteEntries(IBasicVideo2* iface,long lStart,long lCount,long* plRet,long* plPaletteEntry)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetCurrentImage(IBasicVideo2* iface,long* plBufferSize,long* plDIBBuffer)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnIsUsingDefaultSource(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnIsUsingDefaultDestination(IBasicVideo2* iface)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IBasicVideo2_fnGetPreferredAspectRatio(IBasicVideo2* iface,long* plRateX,long* plRateY)
{
CVideoRendererImpl_THIS(iface,basvid);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IBasicVideo2) ibasicvideo =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IBasicVideo2_fnQueryInterface,
IBasicVideo2_fnAddRef,
IBasicVideo2_fnRelease,
/* IDispatch fields */
IBasicVideo2_fnGetTypeInfoCount,
IBasicVideo2_fnGetTypeInfo,
IBasicVideo2_fnGetIDsOfNames,
IBasicVideo2_fnInvoke,
/* IBasicVideo fields */
IBasicVideo2_fnget_AvgTimePerFrame,
IBasicVideo2_fnget_BitRate,
IBasicVideo2_fnget_BitErrorRate,
IBasicVideo2_fnget_VideoWidth,
IBasicVideo2_fnget_VideoHeight,
IBasicVideo2_fnput_SourceLeft,
IBasicVideo2_fnget_SourceLeft,
IBasicVideo2_fnput_SourceWidth,
IBasicVideo2_fnget_SourceWidth,
IBasicVideo2_fnput_SourceTop,
IBasicVideo2_fnget_SourceTop,
IBasicVideo2_fnput_SourceHeight,
IBasicVideo2_fnget_SourceHeight,
IBasicVideo2_fnput_DestinationLeft,
IBasicVideo2_fnget_DestinationLeft,
IBasicVideo2_fnput_DestinationWidth,
IBasicVideo2_fnget_DestinationWidth,
IBasicVideo2_fnput_DestinationTop,
IBasicVideo2_fnget_DestinationTop,
IBasicVideo2_fnput_DestinationHeight,
IBasicVideo2_fnget_DestinationHeight,
IBasicVideo2_fnSetSourcePosition,
IBasicVideo2_fnGetSourcePosition,
IBasicVideo2_fnSetDefaultSourcePosition,
IBasicVideo2_fnSetDestinationPosition,
IBasicVideo2_fnGetDestinationPosition,
IBasicVideo2_fnSetDefaultDestinationPosition,
IBasicVideo2_fnGetVideoSize,
IBasicVideo2_fnGetVideoPaletteEntries,
IBasicVideo2_fnGetCurrentImage,
IBasicVideo2_fnIsUsingDefaultSource,
IBasicVideo2_fnIsUsingDefaultDestination,
/* IBasicVideo2 fields */
IBasicVideo2_fnGetPreferredAspectRatio,
};
HRESULT CVideoRendererImpl_InitIBasicVideo2( CVideoRendererImpl* This )
{
TRACE("(%p)\n",This);
ICOM_VTBL(&This->basvid) = &ibasicvideo;
return NOERROR;
}
void CVideoRendererImpl_UninitIBasicVideo2( CVideoRendererImpl* This )
{
TRACE("(%p)\n",This);
}
/***************************************************************************
*
* CVideoRendererImpl::IVideoWindow
*
*/
static HRESULT WINAPI
IVideoWindow_fnQueryInterface(IVideoWindow* iface,REFIID riid,void** ppobj)
{
CVideoRendererImpl_THIS(iface,vidwin);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IVideoWindow_fnAddRef(IVideoWindow* iface)
{
CVideoRendererImpl_THIS(iface,vidwin);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IVideoWindow_fnRelease(IVideoWindow* iface)
{
CVideoRendererImpl_THIS(iface,vidwin);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IVideoWindow_fnGetTypeInfoCount(IVideoWindow* iface,UINT* pcTypeInfo)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetTypeInfo(IVideoWindow* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetIDsOfNames(IVideoWindow* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnInvoke(IVideoWindow* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Caption(IVideoWindow* iface,BSTR strCaption)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Caption(IVideoWindow* iface,BSTR* pstrCaption)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_WindowStyle(IVideoWindow* iface,long lStyle)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_WindowStyle(IVideoWindow* iface,long* plStyle)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_WindowStyleEx(IVideoWindow* iface,long lExStyle)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_WindowStyleEx(IVideoWindow* iface,long* plExStyle)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_AutoShow(IVideoWindow* iface,long lAutoShow)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_AutoShow(IVideoWindow* iface,long* plAutoShow)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_WindowState(IVideoWindow* iface,long lState)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_WindowState(IVideoWindow* iface,long* plState)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_BackgroundPalette(IVideoWindow* iface,long lBackPal)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_BackgroundPalette(IVideoWindow* iface,long* plBackPal)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Visible(IVideoWindow* iface,long lVisible)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Visible(IVideoWindow* iface,long* plVisible)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Left(IVideoWindow* iface,long lLeft)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Left(IVideoWindow* iface,long* plLeft)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Width(IVideoWindow* iface,long lWidth)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Width(IVideoWindow* iface,long* plWidth)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Top(IVideoWindow* iface,long lTop)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Top(IVideoWindow* iface,long* plTop)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Height(IVideoWindow* iface,long lHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Height(IVideoWindow* iface,long* plHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_Owner(IVideoWindow* iface,OAHWND hwnd)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_Owner(IVideoWindow* iface,OAHWND* phwnd)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_MessageDrain(IVideoWindow* iface,OAHWND hwnd)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_MessageDrain(IVideoWindow* iface,OAHWND* phwnd)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_BorderColor(IVideoWindow* iface,long* plColor)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_BorderColor(IVideoWindow* iface,long lColor)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnget_FullScreenMode(IVideoWindow* iface,long* plMode)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnput_FullScreenMode(IVideoWindow* iface,long lMode)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnSetWindowForeground(IVideoWindow* iface,long lFocus)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnNotifyOwnerMessage(IVideoWindow* iface,OAHWND hwnd,long message,LONG_PTR wParam,LONG_PTR lParam)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnSetWindowPosition(IVideoWindow* iface,long lLeft,long lTop,long lWidth,long lHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetWindowPosition(IVideoWindow* iface,long* plLeft,long* plTop,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetMinIdealImageSize(IVideoWindow* iface,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetMaxIdealImageSize(IVideoWindow* iface,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnGetRestorePosition(IVideoWindow* iface,long* plLeft,long* plTop,long* plWidth,long* plHeight)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnHideCursor(IVideoWindow* iface,long lHide)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IVideoWindow_fnIsCursorHidden(IVideoWindow* iface,long* plHide)
{
CVideoRendererImpl_THIS(iface,vidwin);
FIXME("(%p)->()\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IVideoWindow) ivideowindow =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IVideoWindow_fnQueryInterface,
IVideoWindow_fnAddRef,
IVideoWindow_fnRelease,
/* IDispatch fields */
IVideoWindow_fnGetTypeInfoCount,
IVideoWindow_fnGetTypeInfo,
IVideoWindow_fnGetIDsOfNames,
IVideoWindow_fnInvoke,
/* IVideoWindow fields */
IVideoWindow_fnput_Caption,
IVideoWindow_fnget_Caption,
IVideoWindow_fnput_WindowStyle,
IVideoWindow_fnget_WindowStyle,
IVideoWindow_fnput_WindowStyleEx,
IVideoWindow_fnget_WindowStyleEx,
IVideoWindow_fnput_AutoShow,
IVideoWindow_fnget_AutoShow,
IVideoWindow_fnput_WindowState,
IVideoWindow_fnget_WindowState,
IVideoWindow_fnput_BackgroundPalette,
IVideoWindow_fnget_BackgroundPalette,
IVideoWindow_fnput_Visible,
IVideoWindow_fnget_Visible,
IVideoWindow_fnput_Left,
IVideoWindow_fnget_Left,
IVideoWindow_fnput_Width,
IVideoWindow_fnget_Width,
IVideoWindow_fnput_Top,
IVideoWindow_fnget_Top,
IVideoWindow_fnput_Height,
IVideoWindow_fnget_Height,
IVideoWindow_fnput_Owner,
IVideoWindow_fnget_Owner,
IVideoWindow_fnput_MessageDrain,
IVideoWindow_fnget_MessageDrain,
IVideoWindow_fnget_BorderColor,
IVideoWindow_fnput_BorderColor,
IVideoWindow_fnget_FullScreenMode,
IVideoWindow_fnput_FullScreenMode,
IVideoWindow_fnSetWindowForeground,
IVideoWindow_fnNotifyOwnerMessage,
IVideoWindow_fnSetWindowPosition,
IVideoWindow_fnGetWindowPosition,
IVideoWindow_fnGetMinIdealImageSize,
IVideoWindow_fnGetMaxIdealImageSize,
IVideoWindow_fnGetRestorePosition,
IVideoWindow_fnHideCursor,
IVideoWindow_fnIsCursorHidden,
};
HRESULT CVideoRendererImpl_InitIVideoWindow( CVideoRendererImpl* This )
{
TRACE("(%p)\n",This);
ICOM_VTBL(&This->vidwin) = &ivideowindow;
return NOERROR;
}
void CVideoRendererImpl_UninitIVideoWindow( CVideoRendererImpl* This )
{
TRACE("(%p)\n",This);
}
/*
* 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 */
/*
* 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment