Started Implementing Video Renderer.
Started Implementing WAVE/AU/AIFF Parser.
Started Implementing file source.
Fixed some bugs.

diff --git a/dlls/quartz/wavparse.c b/dlls/quartz/wavparse.c
new file mode 100644
index 0000000..6514e99
--- /dev/null
+++ b/dlls/quartz/wavparse.c
@@ -0,0 +1,473 @@
+/*
+ * Implements WAVE/AU/AIFF Parser.
+ *
+ * hidenori@a2.ctktv.ne.jp
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "mmsystem.h"
+#include "winerror.h"
+#include "wine/obj_base.h"
+#include "strmif.h"
+#include "vfwmsgs.h"
+#include "uuids.h"
+
+#include "debugtools.h"
+DEFAULT_DEBUG_CHANNEL(quartz);
+
+#include "quartz_private.h"
+
+/* for CLSID_quartzWaveParser. */
+#include "initguid.h"
+#include "parser.h"
+
+
+static const WCHAR QUARTZ_WaveParser_Name[] =
+{ 'W','a','v','e',' ','P','a','r','s','e','r',0 };
+static const WCHAR QUARTZ_WaveParserInPin_Name[] =
+{ 'I','n',0 };
+static const WCHAR QUARTZ_WaveParserOutPin_Name[] =
+{ 'O','u','t',0 };
+
+
+/****************************************************************************/
+
+/* S_OK = found, S_FALSE = not found */
+HRESULT RIFF_GetNext(
+	CParserImpl* pImpl, LONGLONG llOfs,
+	DWORD* pdwCode, DWORD* pdwLength )
+{
+	BYTE bTemp[8];
+	HRESULT hr;
+
+	hr = IAsyncReader_SyncRead( pImpl->m_pReader, llOfs, 8, bTemp );
+	if ( hr == S_OK )
+	{
+		*pdwCode = mmioFOURCC(bTemp[0],bTemp[1],bTemp[2],bTemp[3]);
+		*pdwLength = PARSER_LE_UINT32(&bTemp[4]);
+	}
+	else
+	{
+		*pdwCode = 0;
+		*pdwLength = 0;
+	}
+
+	return hr;
+}
+
+/* S_OK = found, S_FALSE = not found */
+HRESULT RIFF_SearchChunk(
+	CParserImpl* pImpl,
+	LONGLONG llOfs, DWORD dwChunk,
+	LONGLONG* pllOfs, DWORD* pdwChunkLength )
+{
+	HRESULT hr;
+	DWORD dwCurCode;
+	DWORD dwCurLen;
+
+	while ( 1 )
+	{
+		hr = RIFF_GetNext( pImpl, llOfs, &dwCurCode, &dwCurLen );
+		if ( hr != S_OK )
+			break;
+		if ( dwChunk == dwCurCode )
+			break;
+		llOfs += 8 + (LONGLONG)((dwCurLen+1)&(~1));
+	}
+
+	*pllOfs = llOfs;
+	*pdwChunkLength = dwCurLen;
+
+	return hr;
+}
+
+
+
+
+/****************************************************************************
+ *
+ *	CWavParseImpl
+ */
+
+typedef enum WavParseFmtType
+{
+	WaveParse_Native,
+	WaveParse_Signed8,
+	WaveParse_Signed16BE,
+	WaveParse_Unsigned16LE,
+	WaveParse_Unsigned16BE,
+} WavParseFmtType;
+
+typedef struct CWavParseImpl
+{
+	DWORD	cbFmt;
+	WAVEFORMATEX*	pFmt;
+	DWORD	dwBlockSize;
+	LONGLONG	llDataStart;
+	LONGLONG	llBytesTotal;
+	LONGLONG	llBytesProcessed;
+	WavParseFmtType	iFmtType;
+} CWavParseImpl;
+
+
+static HRESULT CWavParseImpl_InitWAV( CParserImpl* pImpl, CWavParseImpl* This )
+{
+	HRESULT hr;
+	LONGLONG	llOfs;
+	DWORD	dwChunkLength;
+
+	hr = RIFF_SearchChunk(
+		pImpl, PARSER_RIFF_OfsFirst,
+		PARSER_fmt, &llOfs, &dwChunkLength );
+	if ( FAILED(hr) )
+		return hr;
+	if ( hr != S_OK || ( dwChunkLength < (sizeof(WAVEFORMATEX)-2) ) )
+		return E_FAIL;
+	llOfs += 8;
+
+	This->cbFmt = dwChunkLength;
+	if ( dwChunkLength < sizeof(WAVEFORMATEX) )
+		This->cbFmt = sizeof(WAVEFORMATEX);
+	This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( dwChunkLength );
+	if ( This->pFmt == NULL )
+		return E_OUTOFMEMORY;
+	ZeroMemory( This->pFmt, This->cbFmt );
+
+	hr = IAsyncReader_SyncRead(
+		pImpl->m_pReader, llOfs, dwChunkLength, (BYTE*)This->pFmt );
+	if ( hr != S_OK )
+	{
+		if ( SUCCEEDED(hr) )
+			hr = E_FAIL;
+		return hr;
+	}
+
+
+	hr = RIFF_SearchChunk(
+		pImpl, PARSER_RIFF_OfsFirst,
+		PARSER_data, &llOfs, &dwChunkLength );
+	if ( FAILED(hr) )
+		return hr;
+	if ( hr != S_OK || dwChunkLength == 0 )
+		return E_FAIL;
+
+	This->llDataStart = llOfs;
+	This->llBytesTotal = (LONGLONG)dwChunkLength;
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_InitAU( CParserImpl* pImpl, CWavParseImpl* This )
+{
+	BYTE	au_hdr[24];
+	DWORD	dataofs;
+	DWORD	datalen;
+	DWORD	datafmt;
+	DWORD	datarate;
+	DWORD	datachannels;
+	HRESULT hr;
+	WAVEFORMATEX	wfx;
+
+	hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 24, au_hdr );
+	if ( FAILED(hr) )
+		return hr;
+
+	dataofs = PARSER_BE_UINT32(&au_hdr[4]);
+	datalen = PARSER_BE_UINT32(&au_hdr[8]);
+	datafmt = PARSER_BE_UINT32(&au_hdr[12]);
+	datarate = PARSER_BE_UINT32(&au_hdr[16]);
+	datachannels = PARSER_BE_UINT32(&au_hdr[20]);
+
+	if ( dataofs < 24U || datalen == 0U )
+		return E_FAIL;
+	if ( datachannels != 1 && datachannels != 2 )
+		return E_FAIL;
+
+	ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
+	wfx.nChannels = datachannels;
+	wfx.nSamplesPerSec = datarate;
+
+	switch ( datafmt )
+	{
+	case 1:
+		wfx.wFormatTag = 7;
+		wfx.nBlockAlign = datachannels;
+		wfx.wBitsPerSample = 8;
+		break;
+	case 2:
+		wfx.wFormatTag = 1;
+		wfx.nBlockAlign = datachannels;
+		wfx.wBitsPerSample = 8;
+		This->iFmtType = WaveParse_Signed8;
+		break;
+	case 3:
+		wfx.wFormatTag = 1;
+		wfx.nBlockAlign = datachannels;
+		wfx.wBitsPerSample = 16;
+		This->iFmtType = WaveParse_Signed16BE;
+		break;
+	default:
+		FIXME("audio/basic - unknown format %lu\n", datafmt );
+		return E_FAIL;
+	}
+	wfx.nAvgBytesPerSec = (datarate * datachannels * (DWORD)wfx.wBitsPerSample) >> 3;
+
+	This->cbFmt = sizeof(WAVEFORMATEX);
+	This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( sizeof(WAVEFORMATEX) );
+	if ( This->pFmt == NULL )
+		return E_OUTOFMEMORY;
+	memcpy( This->pFmt, &wfx, sizeof(WAVEFORMATEX) );
+
+	This->llDataStart = dataofs;
+	This->llBytesTotal = datalen;
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_InitAIFF( CParserImpl* pImpl, CWavParseImpl* This )
+{
+	FIXME( "AIFF is not supported now.\n" );
+	return E_FAIL;
+}
+
+static HRESULT CWavParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
+{
+	CWavParseImpl*	This = NULL;
+	HRESULT hr;
+	BYTE	header[12];
+
+	TRACE("(%p,%p)\n",pImpl,pcStreams);
+
+	if ( pImpl->m_pReader == NULL )
+		return E_UNEXPECTED;
+
+	This = (CWavParseImpl*)QUARTZ_AllocMem( sizeof(CWavParseImpl) );
+	if ( This == NULL )
+		return E_OUTOFMEMORY;
+	pImpl->m_pUserData = This;
+
+	/* construct */
+	This->cbFmt = 0;
+	This->pFmt = NULL;
+	This->dwBlockSize = 0;
+	This->llDataStart = 0;
+	This->llBytesTotal = 0;
+	This->llBytesProcessed = 0;
+	This->iFmtType = WaveParse_Native;
+
+	hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 12, header );
+	if ( FAILED(hr) )
+		return hr;
+	if ( hr != S_OK )
+		return E_FAIL;
+
+	if ( !memcmp( &header[0], "RIFF", 4 ) &&
+		 !memcmp( &header[8], "WAVE", 4 ) )
+	{
+		TRACE( "(%p) - it's audio/wav.\n", pImpl );
+		hr = CWavParseImpl_InitWAV( pImpl, This );
+	}
+	else
+	if ( !memcmp( &header[0], ".snd", 4 ) )
+	{
+		TRACE( "(%p) - it's audio/basic.\n", pImpl );
+		hr = CWavParseImpl_InitAU( pImpl, This );
+	}
+	else
+	if ( !memcmp( &header[0], "FORM", 4 ) &&
+		 !memcmp( &header[8], "AIFF", 4 ) )
+	{
+		TRACE( "(%p) - it's audio/aiff.\n", pImpl );
+		hr = CWavParseImpl_InitAIFF( pImpl, This );
+	}
+	else
+	{
+		FIXME( "(%p) - unknown format.\n", pImpl );
+		hr = E_FAIL;
+	}
+
+	if ( FAILED(hr) )
+	{
+		return hr;
+	}
+
+	/* initialized successfully. */
+	*pcStreams = 1;
+
+	This->dwBlockSize = (This->pFmt->nAvgBytesPerSec + (DWORD)This->pFmt->nBlockAlign - 1U) / (DWORD)This->pFmt->nBlockAlign;
+
+	TRACE( "(%p) returned successfully.\n", pImpl );
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_UninitParser( CParserImpl* pImpl )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+
+	TRACE("(%p)\n",This);
+
+	if ( This == NULL )
+		return NOERROR;
+
+	/* destruct */
+	if ( This->pFmt != NULL ) QUARTZ_FreeMem(This->pFmt);
+
+	QUARTZ_FreeMem( This );
+	pImpl->m_pUserData = NULL;
+
+	return NOERROR;
+}
+
+static LPCWSTR CWavParseImpl_GetOutPinName( CParserImpl* pImpl, ULONG nStreamIndex )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+
+	TRACE("(%p)\n",This);
+
+	return QUARTZ_WaveParserOutPin_Name;
+}
+
+static HRESULT CWavParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+
+	TRACE("(%p)\n",This);
+
+	if ( This == NULL || This->pFmt == NULL )
+		return E_UNEXPECTED;
+
+	ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
+	memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
+	QUARTZ_MediaSubType_FromFourCC( &pmt->subtype, (DWORD)This->pFmt->wFormatTag );
+	pmt->bFixedSizeSamples = 1;
+	pmt->bTemporalCompression = 0;
+	pmt->lSampleSize = This->pFmt->nBlockAlign;
+	memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
+	pmt->pUnk = NULL;
+
+	pmt->pbFormat = (BYTE*)CoTaskMemAlloc( This->cbFmt );
+	if ( pmt->pbFormat == NULL )
+		return E_OUTOFMEMORY;
+	pmt->cbFormat = This->cbFmt;
+	memcpy( pmt->pbFormat, This->pFmt, This->cbFmt );
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
+{
+	if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) ||
+		 !IsEqualGUID( &pmt->formattype, &FORMAT_WaveFormatEx ) )
+		return E_FAIL;
+	if ( pmt->pbFormat == NULL || pmt->cbFormat < sizeof(WAVEFORMATEX) )
+		return E_FAIL;
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+
+	TRACE("(%p)\n",This);
+
+	if ( This == NULL || This->pFmt == NULL )
+		return E_UNEXPECTED;
+
+	ZeroMemory( pReqProp, sizeof(ALLOCATOR_PROPERTIES) );
+	pReqProp->cBuffers = 1;
+	pReqProp->cbBuffer = This->dwBlockSize;
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+	LONGLONG	llAvail;
+	LONGLONG	llStart;
+	LONGLONG	llEnd;
+
+	TRACE("(%p)\n",This);
+
+	if ( This == NULL || This->pFmt == NULL )
+		return E_UNEXPECTED;
+
+	llAvail = This->llBytesTotal - This->llBytesProcessed;
+	if ( llAvail > (LONGLONG)This->dwBlockSize )
+		llAvail = (LONGLONG)This->dwBlockSize;
+	llStart = This->llBytesProcessed;
+	llEnd = llStart + llAvail;
+	This->llBytesProcessed = llEnd;
+
+	*pllStart = This->llBytesProcessed;
+	*plLength = (LONG)llAvail;
+	*prtStart = llStart * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;
+	*prtStop = llEnd * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;
+
+	return NOERROR;
+}
+
+static HRESULT CWavParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
+{
+	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
+
+	TRACE("(%p)\n",This);
+
+	switch ( This->iFmtType )
+	{
+	case WaveParse_Native:
+		break;
+	default:
+		FIXME("(%p) - %d not implemented\n", This, This->iFmtType );
+		return E_FAIL;
+	}
+
+	return NOERROR;
+}
+
+
+static const struct ParserHandlers CWavParseImpl_Handlers =
+{
+	CWavParseImpl_InitParser,
+	CWavParseImpl_UninitParser,
+	CWavParseImpl_GetOutPinName,
+	CWavParseImpl_GetStreamType,
+	CWavParseImpl_CheckStreamType,
+	CWavParseImpl_GetAllocProp,
+	CWavParseImpl_GetNextRequest,
+	CWavParseImpl_ProcessSample,
+
+	/* for IQualityControl */
+	NULL, /* pQualityNotify */
+
+	/* for seeking */
+	NULL, /* pGetSeekingCaps */
+	NULL, /* pIsTimeFormatSupported */
+	NULL, /* pGetCurPos */
+	NULL, /* pSetCurPos */
+	NULL, /* pGetDuration */
+	NULL, /* pSetDuration */
+	NULL, /* pGetStopPos */
+	NULL, /* pSetStopPos */
+	NULL, /* pGetPreroll */
+	NULL, /* pSetPreroll */
+};
+
+HRESULT QUARTZ_CreateWaveParser(IUnknown* punkOuter,void** ppobj)
+{
+	return QUARTZ_CreateParser(
+		punkOuter,ppobj,
+		&CLSID_quartzWaveParser,
+		QUARTZ_WaveParser_Name,
+		QUARTZ_WaveParserInPin_Name,
+		&CWavParseImpl_Handlers );
+}
+
+