Commit 17bee2ef authored by Hidenori Takeshima's avatar Hidenori Takeshima Committed by Alexandre Julliard

Fixed some bugs.

Implemented AVI Decompressor. Started implementing Color Space Converter. Started implementing seeking.
parent f5a8b965
......@@ -566,8 +566,8 @@ psapi/libpsapi.$(LIBEXT): dummy libkernel32.$(LIBEXT) libntdll.$(LIBEXT)
@cd psapi && $(MAKE) libpsapi.$(LIBEXT)
quartz/libquartz.$(LIBEXT): dummy liboleaut32.$(LIBEXT) libole32.$(LIBEXT) \
libwinmm.$(LIBEXT) libuser32.$(LIBEXT) libgdi32.$(LIBEXT) libadvapi32.$(LIBEXT) \
libkernel32.$(LIBEXT) libntdll.$(LIBEXT)
libmsvfw32.$(LIBEXT) libwinmm.$(LIBEXT) libuser32.$(LIBEXT) libgdi32.$(LIBEXT) \
libadvapi32.$(LIBEXT) libkernel32.$(LIBEXT) libntdll.$(LIBEXT)
@cd quartz && $(MAKE) libquartz.$(LIBEXT)
rasapi32/librasapi32.$(LIBEXT): dummy libkernel32.$(LIBEXT) libntdll.$(LIBEXT)
......
......@@ -13,10 +13,12 @@ C_SRCS = \
asyncsrc.c \
audioutl.c \
audren.c \
avidec.c \
aviparse.c \
basefilt.c \
basepin.c \
complist.c \
csconv.c \
devenum.c \
devmon.c \
enumunk.c \
......@@ -38,8 +40,10 @@ C_SRCS = \
sample.c \
seekpass.c \
sysclock.c \
videoblt.c \
vidren.c \
wavparse.c
wavparse.c \
xform.c
@MAKE_DLL_RULES@
......
......@@ -142,10 +142,13 @@ void CAsyncReaderImpl_PostReply( CAsyncReaderImpl* This, AsyncSourceRequest* pRe
}
static
void CAsyncReaderImpl_ReleaseReqList( CAsyncReaderImpl* This, AsyncSourceRequest* pReq, BOOL bReleaseMem )
void CAsyncReaderImpl_ReleaseReqList( CAsyncReaderImpl* This, AsyncSourceRequest** ppReq, BOOL bReleaseMem )
{
AsyncSourceRequest* pReq;
AsyncSourceRequest* pReqNext;
TRACE("(%p,%p,%d)\n",This,*ppReq,bReleaseMem);
pReq = *ppReq; *ppReq = NULL;
while ( pReq != NULL )
{
pReqNext = pReq->pNext;
......@@ -544,7 +547,7 @@ CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
EnterCriticalSection( &This->m_csRequest );
This->m_bInFlushing = TRUE;
SetEvent( This->m_hEventCancel );
CAsyncReaderImpl_ReleaseReqList(This,This->m_pRequestFirst,FALSE);
CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,FALSE);
LeaveCriticalSection( &This->m_csRequest );
return NOERROR;
......@@ -622,16 +625,18 @@ HRESULT CAsyncReaderImpl_InitIAsyncReader(
void CAsyncReaderImpl_UninitIAsyncReader(
CAsyncReaderImpl* This )
{
TRACE("(%p)\n",This);
TRACE("(%p) enter\n",This);
CAsyncReaderImpl_ReleaseReqList(This,This->m_pRequestFirst,TRUE);
CAsyncReaderImpl_ReleaseReqList(This,This->m_pReplyFirst,TRUE);
CAsyncReaderImpl_ReleaseReqList(This,This->m_pFreeFirst,TRUE);
CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,TRUE);
CAsyncReaderImpl_ReleaseReqList(This,&This->m_pReplyFirst,TRUE);
CAsyncReaderImpl_ReleaseReqList(This,&This->m_pFreeFirst,TRUE);
DeleteCriticalSection( &This->m_csReader );
DeleteCriticalSection( &This->m_csRequest );
DeleteCriticalSection( &This->m_csReply );
DeleteCriticalSection( &This->m_csFree );
TRACE("(%p) leave\n",This);
}
/***************************************************************************
......
......@@ -134,7 +134,7 @@ HRESULT QUARTZ_CreateAsyncSourcePin(
HRESULT QUARTZ_CreateAsyncReader(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateURLReader(IUnknown* punkOuter,void** ppobj);
#define ASYNCSRC_FILE_BLOCKSIZE 4096
#define ASYNCSRC_FILE_BLOCKSIZE 16384
#endif /* WINE_DSHOW_ASYNCSRC_H */
......@@ -27,6 +27,7 @@ DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "audren.h"
#include "seekpass.h"
static const WCHAR QUARTZ_AudioRender_Name[] =
......@@ -132,7 +133,7 @@ HRESULT CAudioRendererImpl_waveOutInit(
DWORD dwBlockSize;
if ( This->m_fWaveOutInit )
return E_UNEXPECTED;
return NOERROR;
if ( pwfx == NULL )
return E_POINTER;
......@@ -194,6 +195,24 @@ err:
return hr;
}
static HRESULT CAudioRendererImpl_waveOutPause( CAudioRendererImpl* This )
{
if ( !This->m_fWaveOutInit )
return E_UNEXPECTED;
return QUARTZ_HRESULT_From_MMRESULT( waveOutPause(
This->m_hWaveOut ) );
}
static HRESULT CAudioRendererImpl_waveOutRun( CAudioRendererImpl* This )
{
if ( !This->m_fWaveOutInit )
return E_UNEXPECTED;
return QUARTZ_HRESULT_From_MMRESULT( waveOutRestart(
This->m_hWaveOut ) );
}
static
WAVEHDR* CAudioRendererImpl_waveOutGetBuffer(
CAudioRendererImpl* This )
......@@ -329,7 +348,29 @@ HRESULT CAudioRendererImpl_waveOutSetVolume(
static HRESULT CAudioRendererImpl_OnActive( CBaseFilterImpl* pImpl )
{
CAudioRendererImpl_THIS(pImpl,basefilter);
HRESULT hr;
FIXME( "(%p)\n", This );
if ( This->pPin->pin.pmtConn == NULL )
return NOERROR;
This->m_fInFlush = FALSE;
/* FIXME - don't work correctly.
hr = CAudioRendererImpl_waveOutRun(This);
if ( FAILED(hr) )
return hr;
*/
return NOERROR;
}
static HRESULT CAudioRendererImpl_OnInactive( CBaseFilterImpl* pImpl )
{
CAudioRendererImpl_THIS(pImpl,basefilter);
WAVEFORMATEX* pwfx;
HRESULT hr;
FIXME( "(%p)\n", This );
......@@ -342,10 +383,20 @@ static HRESULT CAudioRendererImpl_OnActive( CBaseFilterImpl* pImpl )
This->m_fInFlush = FALSE;
return CAudioRendererImpl_waveOutInit(This,pwfx);
hr = CAudioRendererImpl_waveOutInit(This,pwfx);
if ( FAILED(hr) )
return hr;
/* FIXME - may cause deadlock.
hr = CAudioRendererImpl_waveOutPause(This);
if ( FAILED(hr) )
return hr;
*/
return NOERROR;
}
static HRESULT CAudioRendererImpl_OnInactive( CBaseFilterImpl* pImpl )
static HRESULT CAudioRendererImpl_OnStop( CBaseFilterImpl* pImpl )
{
CAudioRendererImpl_THIS(pImpl,basefilter);
......@@ -364,7 +415,7 @@ static const CBaseFilterHandlers filterhandlers =
{
CAudioRendererImpl_OnActive, /* pOnActive */
CAudioRendererImpl_OnInactive, /* pOnInactive */
NULL, /* pOnStop */
CAudioRendererImpl_OnStop, /* pOnStop */
};
/***************************************************************************
......@@ -373,6 +424,23 @@ static const CBaseFilterHandlers filterhandlers =
*
*/
static HRESULT CAudioRendererPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CAudioRendererPinImpl_THIS(pImpl,pin);
TRACE("(%p)\n",This);
if ( This->meminput.pAllocator != NULL )
{
IMemAllocator_Decommit(This->meminput.pAllocator);
IMemAllocator_Release(This->meminput.pAllocator);
This->meminput.pAllocator = NULL;
}
return NOERROR;
}
static HRESULT CAudioRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CAudioRendererPinImpl_THIS(pImpl,pin);
......@@ -381,11 +449,24 @@ static HRESULT CAudioRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const
TRACE("(%p,%p)\n",This,pmt);
if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) )
{
TRACE("not audio\n");
return E_FAIL;
if ( !IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_PCM ) )
}
if ( !IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_NULL ) &&
!IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_PCM ) )
{
TRACE("not PCM\n");
return E_FAIL;
}
if ( !IsEqualGUID( &pmt->formattype, &FORMAT_WaveFormatEx ) )
{
TRACE("not WAVE\n");
return E_FAIL;
}
TRACE("testing WAVE header\n");
if ( pmt->cbFormat < (sizeof(WAVEFORMATEX)-sizeof(WORD)) )
return E_FAIL;
......@@ -395,6 +476,8 @@ static HRESULT CAudioRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const
if ( pwfx->wFormatTag != 1 )
return E_FAIL;
TRACE("returned successfully.\n");
return NOERROR;
}
......@@ -508,7 +591,7 @@ static const CBasePinHandlers pinhandlers =
{
NULL, /* pOnPreConnect */
NULL, /* pOnPostConnect */
NULL, /* pOnDisconnect */
CAudioRendererPinImpl_OnDisconnect, /* pOnDisconnect */
CAudioRendererPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
CAudioRendererPinImpl_Receive, /* pReceive */
......@@ -535,6 +618,24 @@ static QUARTZ_IFEntry FilterIFEntries[] =
{ &IID_IBasicAudio, offsetof(CAudioRendererImpl,basaud)-offsetof(CAudioRendererImpl,unk) },
};
static HRESULT CAudioRendererImpl_OnQueryInterface(
IUnknown* punk, const IID* piid, void** ppobj )
{
CAudioRendererImpl_THIS(punk,unk);
if ( This->pSeekPass == NULL )
return E_NOINTERFACE;
if ( IsEqualGUID( &IID_IMediaPosition, piid ) ||
IsEqualGUID( &IID_IMediaSeeking, piid ) )
{
TRACE( "IMediaSeeking(or IMediaPosition) is queried\n" );
return IUnknown_QueryInterface( (IUnknown*)(&This->pSeekPass->unk), piid, ppobj );
}
return E_NOINTERFACE;
}
static void QUARTZ_DestroyAudioRenderer(IUnknown* punk)
{
CAudioRendererImpl_THIS(punk,unk);
......@@ -546,6 +647,11 @@ static void QUARTZ_DestroyAudioRenderer(IUnknown* punk)
IUnknown_Release(This->pPin->unk.punkControl);
This->pPin = NULL;
}
if ( This->pSeekPass != NULL )
{
IUnknown_Release((IUnknown*)&This->pSeekPass->unk);
This->pSeekPass = NULL;
}
CAudioRendererImpl_UninitIBasicAudio(This);
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
......@@ -562,12 +668,16 @@ HRESULT QUARTZ_CreateAudioRenderer(IUnknown* punkOuter,void** ppobj)
QUARTZ_AllocObj( sizeof(CAudioRendererImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
This->pSeekPass = NULL;
This->pPin = NULL;
This->m_fInFlush = FALSE;
This->m_fWaveOutInit = FALSE;
This->m_hEventRender = (HANDLE)NULL;
QUARTZ_IUnkInit( &This->unk, punkOuter );
This->qiext.pNext = NULL;
This->qiext.pOnQueryInterface = &CAudioRendererImpl_OnQueryInterface;
QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
hr = CBaseFilterImpl_InitIBaseFilter(
&This->basefilter,
......@@ -603,6 +713,11 @@ HRESULT QUARTZ_CreateAudioRenderer(IUnknown* punkOuter,void** ppobj)
This->basefilter.pInPins,
(IUnknown*)&This->pPin->pin,
NULL, 0 );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CreateSeekingPassThruInternal(
(IUnknown*)&(This->unk), &This->pSeekPass,
TRUE, (IPin*)&(This->pPin->pin) );
if ( FAILED(hr) )
{
IUnknown_Release( This->unk.punkControl );
......
......@@ -12,6 +12,7 @@
#include "iunk.h"
#include "basefilt.h"
#include "seekpass.h"
#define WINE_QUARTZ_WAVEOUT_COUNT 4
......@@ -29,7 +30,9 @@ struct CAudioRendererImpl
QUARTZ_IUnkImpl unk;
CBaseFilterImpl basefilter;
AudRen_IBasicAudioImpl basaud;
QUARTZ_IFDelegation qiext;
CSeekingPassThru* pSeekPass;
CAudioRendererPinImpl* pPin;
BOOL m_fInFlush;
......
/*
* Implements AVI Decompressor(CLSID_AVIDec).
*
* FIXME - insufficient buffer for ICDecompress!!!!
*
* hidenori@a2.ctktv.ne.jp
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "vfw.h"
#include "strmif.h"
#include "control.h"
#include "amvideo.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "xform.h"
static const WCHAR AVIDec_FilterName[] =
{'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0};
typedef struct CAVIDecImpl
{
HIC hicCached;
HIC hicTrans;
AM_MEDIA_TYPE m_mtOut;
BITMAPINFO* m_pbiIn;
BITMAPINFO* m_pbiOut;
BYTE* m_pOutBuf;
} CAVIDecImpl;
/***************************************************************************
*
* CAVIDecImpl methods
*
*/
static void AVIDec_ReleaseDIBBuffers(CAVIDecImpl* This)
{
TRACE("(%p)\n",This);
if ( This->m_pbiIn != NULL )
{
QUARTZ_FreeMem(This->m_pbiIn); This->m_pbiIn = NULL;
}
if ( This->m_pbiOut != NULL )
{
QUARTZ_FreeMem(This->m_pbiOut); This->m_pbiOut = NULL;
}
if ( This->m_pOutBuf != NULL )
{
QUARTZ_FreeMem(This->m_pOutBuf); This->m_pOutBuf = NULL;
}
}
static BITMAPINFO* AVIDec_DuplicateBitmapInfo(const BITMAPINFO* pbi)
{
DWORD dwSize;
BITMAPINFO* pbiRet;
dwSize = pbi->bmiHeader.biSize;
if ( dwSize < sizeof(BITMAPINFOHEADER) )
return NULL;
if ( pbi->bmiHeader.biBitCount <= 8 )
{
if ( pbi->bmiHeader.biClrUsed == 0 )
dwSize += sizeof(RGBQUAD)*(1<<pbi->bmiHeader.biBitCount);
else
dwSize += sizeof(RGBQUAD)*pbi->bmiHeader.biClrUsed;
}
if ( pbi->bmiHeader.biCompression == 3 &&
dwSize == sizeof(BITMAPINFOHEADER) )
dwSize += sizeof(DWORD)*3;
pbiRet = (BITMAPINFO*)QUARTZ_AllocMem(dwSize);
if ( pbiRet != NULL )
memcpy( pbiRet, pbi, dwSize );
return pbiRet;
}
static HRESULT AVIDec_Init( CTransformBaseImpl* pImpl )
{
CAVIDecImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This != NULL )
return NOERROR;
This = (CAVIDecImpl*)QUARTZ_AllocMem( sizeof(CAVIDecImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This, sizeof(CAVIDecImpl) );
pImpl->m_pUserData = This;
/* construct */
This->hicCached = (HIC)NULL;
This->hicTrans = (HIC)NULL;
ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
This->m_pbiIn = NULL;
This->m_pbiOut = NULL;
This->m_pOutBuf = NULL;
return NOERROR;
}
static HRESULT AVIDec_Cleanup( CTransformBaseImpl* pImpl )
{
CAVIDecImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This == NULL )
return NOERROR;
/* destruct */
QUARTZ_MediaType_Free( &This->m_mtOut );
AVIDec_ReleaseDIBBuffers(This);
if ( This->hicCached != (HIC)NULL )
ICClose(This->hicCached);
if ( This->hicTrans != (HIC)NULL )
ICClose(This->hicTrans);
QUARTZ_FreeMem( This );
pImpl->m_pUserData = NULL;
return NOERROR;
}
static HRESULT AVIDec_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
{
CAVIDecImpl* This = pImpl->m_pUserData;
BITMAPINFO* pbiIn = NULL;
BITMAPINFO* pbiOut = NULL;
HIC hic;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Video ) )
return E_FAIL;
if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) )
return E_FAIL;
pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
if ( pmtOut != NULL )
{
if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Video ) )
return E_FAIL;
if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_VideoInfo ) )
return E_FAIL;
pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
}
if ( This->hicCached != (HIC)NULL &&
ICDecompressQuery( This->hicCached, pbiIn, pbiOut ) == ICERR_OK )
{
TRACE("supported format\n");
return NOERROR;
}
TRACE("try to find a decoder...\n");
hic = ICLocate(
mmioFOURCC('V','I','D','C'), 0,
&pbiIn->bmiHeader, &pbiOut->bmiHeader, ICMODE_DECOMPRESS );
if ( hic == (HIC)NULL )
{
WARN("no decoder for %c%c%c%c\n",
(int)(( pbiIn->bmiHeader.biCompression >> 0 ) & 0xff),
(int)(( pbiIn->bmiHeader.biCompression >> 8 ) & 0xff),
(int)(( pbiIn->bmiHeader.biCompression >> 16 ) & 0xff),
(int)(( pbiIn->bmiHeader.biCompression >> 24 ) & 0xff) );
return E_FAIL;
}
TRACE("found\n");
if ( This->hicCached != (HIC)NULL )
ICClose(This->hicCached);
This->hicCached = hic;
return NOERROR;
}
static HRESULT AVIDec_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
{
CAVIDecImpl* This = pImpl->m_pUserData;
HRESULT hr;
LONG cbFmt;
BITMAPINFO* pbiIn = NULL;
BITMAPINFO* pbiOut = NULL;
TRACE("(%p)\n",This);
hr = AVIDec_CheckMediaType( pImpl, pmtIn, NULL );
if ( FAILED(hr) )
return hr;
TRACE("(%p) - get size of format\n",This);
pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
cbFmt = (LONG)ICDecompressGetFormatSize( This->hicCached, pbiIn );
if ( cbFmt < sizeof(BITMAPINFOHEADER) )
return E_FAIL;
QUARTZ_MediaType_Free( &This->m_mtOut );
ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
memcpy( &This->m_mtOut.majortype, &MEDIATYPE_Video, sizeof(GUID) );
memcpy( &This->m_mtOut.formattype, &FORMAT_VideoInfo, sizeof(GUID) );
This->m_mtOut.cbFormat = sizeof(VIDEOINFOHEADER) + cbFmt;
This->m_mtOut.pbFormat = (BYTE*)CoTaskMemAlloc(This->m_mtOut.cbFormat);
if ( This->m_mtOut.pbFormat == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This->m_mtOut.pbFormat, This->m_mtOut.cbFormat );
pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)This->m_mtOut.pbFormat)->bmiHeader);
TRACE("(%p) - get format\n",This);
if ( ICDecompressGetFormat( This->hicCached, pbiIn, pbiOut ) != ICERR_OK )
return E_FAIL;
hr = QUARTZ_MediaSubType_FromBitmap( &This->m_mtOut.subtype, &pbiOut->bmiHeader );
if ( FAILED(hr) )
return hr;
if ( hr != S_OK )
QUARTZ_MediaSubType_FromFourCC( &This->m_mtOut.subtype, pbiOut->bmiHeader.biCompression );
This->m_mtOut.bFixedSizeSamples = (pbiOut->bmiHeader.biCompression == 0) ? 1 : 0;
This->m_mtOut.lSampleSize = (pbiOut->bmiHeader.biCompression == 0) ? DIBSIZE(pbiOut->bmiHeader) : pbiOut->bmiHeader.biSizeImage;
TRACE("(%p) - return format\n",This);
*ppmtAcceptTypes = &This->m_mtOut;
*pcAcceptTypes = 1;
return NOERROR;
}
static HRESULT AVIDec_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
{
CAVIDecImpl* This = pImpl->m_pUserData;
BITMAPINFO* pbiOut = NULL;
HRESULT hr;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = AVIDec_CheckMediaType( pImpl, pmtIn, pmtOut );
if ( FAILED(hr) )
return hr;
pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
pProp->cBuffers = 1;
if ( pbiOut->bmiHeader.biCompression == 0 )
pProp->cbBuffer = DIBSIZE(pbiOut->bmiHeader);
else
pProp->cbBuffer = pbiOut->bmiHeader.biSizeImage;
*pbTransInPlace = FALSE;
*pbTryToReuseSample = TRUE;
return NOERROR;
}
static HRESULT AVIDec_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
{
CAVIDecImpl* This = pImpl->m_pUserData;
BITMAPINFO* pbiIn = NULL;
BITMAPINFO* pbiOut = NULL;
HRESULT hr;
TRACE("(%p,%p,%p,%d)\n",This,pmtIn,pmtOut,bReuseSample);
if ( This == NULL ||
This->hicTrans != (HIC)NULL )
return E_UNEXPECTED;
hr = AVIDec_CheckMediaType( pImpl, pmtIn, pmtOut );
if ( FAILED(hr) )
return hr;
AVIDec_ReleaseDIBBuffers(This);
pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
This->m_pbiIn = AVIDec_DuplicateBitmapInfo(pbiIn);
This->m_pbiOut = AVIDec_DuplicateBitmapInfo(pbiOut);
if ( This->m_pbiIn == NULL || This->m_pbiOut == NULL )
return E_OUTOFMEMORY;
if ( This->m_pbiOut->bmiHeader.biCompression == 0 )
This->m_pbiOut->bmiHeader.biSizeImage = DIBSIZE(This->m_pbiOut->bmiHeader);
if ( !bReuseSample )
{
This->m_pOutBuf = QUARTZ_AllocMem(This->m_pbiOut->bmiHeader.biSizeImage);
if ( This->m_pOutBuf == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This->m_pOutBuf, This->m_pbiOut->bmiHeader.biSizeImage );
}
if ( ICERR_OK != ICDecompressBegin(
This->hicCached, This->m_pbiIn, This->m_pbiOut ) )
return E_FAIL;
This->hicTrans = This->hicCached;
This->hicCached = (HIC)NULL;
return NOERROR;
}
static HRESULT AVIDec_Transform( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut )
{
CAVIDecImpl* This = pImpl->m_pUserData;
DWORD dwFlags;
BYTE* pDataIn = NULL;
BYTE* pDataOut = NULL;
HRESULT hr;
TRACE("(%p)\n",This);
if ( This == NULL || pSampOut == NULL ||
This->hicTrans == (HIC)NULL ||
This->m_pbiIn == NULL ||
This->m_pbiOut == NULL )
return E_UNEXPECTED;
hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
if ( FAILED(hr) )
return hr;
hr = IMediaSample_GetPointer( pSampOut, &pDataOut );
if ( FAILED(hr) )
return hr;
dwFlags = 0;
/*** FIXME!!!
*
* if ( IMediaSample_IsSyncPoint(pSampIn) != S_OK )
* dwFlags |= ICDECOMPRESS_NOTKEYFRAME;
****/
if ( IMediaSample_IsPreroll(pSampIn) == S_OK )
dwFlags |= ICDECOMPRESS_PREROLL;
if ( ICERR_OK != ICDecompress(
This->hicTrans,
dwFlags,
&This->m_pbiIn->bmiHeader,
pDataIn,
&This->m_pbiOut->bmiHeader,
( This->m_pOutBuf != NULL ) ? This->m_pOutBuf : pDataOut ) )
return E_FAIL;
if ( This->m_pOutBuf != NULL )
memcpy( pDataOut, This->m_pOutBuf,
This->m_pbiOut->bmiHeader.biSizeImage );
return NOERROR;
}
static HRESULT AVIDec_EndTransform( CTransformBaseImpl* pImpl )
{
CAVIDecImpl* This = pImpl->m_pUserData;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
if ( This->hicTrans == (HIC)NULL )
return NOERROR;
ICDecompressEnd(This->hicTrans);
if ( This->hicCached != (HIC)NULL )
ICClose(This->hicCached);
This->hicCached = This->hicTrans;
This->hicTrans = (HIC)NULL;
AVIDec_ReleaseDIBBuffers(This);
return NOERROR;
}
static const TransformBaseHandlers transhandlers =
{
AVIDec_Init,
AVIDec_Cleanup,
AVIDec_CheckMediaType,
AVIDec_GetOutputTypes,
AVIDec_GetAllocProp,
AVIDec_BeginTransform,
AVIDec_Transform,
AVIDec_EndTransform,
};
HRESULT QUARTZ_CreateAVIDec(IUnknown* punkOuter,void** ppobj)
{
return QUARTZ_CreateTransformBase(
punkOuter,ppobj,
&CLSID_AVIDec,
AVIDec_FilterName,
NULL, NULL,
&transhandlers );
}
......@@ -14,6 +14,7 @@
#include "vfw.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "amvideo.h"
#include "uuids.h"
......@@ -385,10 +386,9 @@ static HRESULT CAVIParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamInd
if ( hr != S_OK )
QUARTZ_MediaSubType_FromFourCC( &pmt->subtype, (DWORD)pbi->biCompression );
pmt->bFixedSizeSamples = ( pbi->biCompression == 0 || pbi->biCompression == 3 ) ? 1 : 0;
pmt->bTemporalCompression = 0;
pmt->lSampleSize = ( pbi->biCompression == 0 || pbi->biCompression == 3 ) ?
DIBSIZE(*pbi) : pbi->biSize;
pmt->bFixedSizeSamples = QUARTZ_BitmapHasFixedSample( pbi ) ? 1 : 0;
pmt->bTemporalCompression = 0; /* FIXME - 1 if inter-frame compression is used */
pmt->lSampleSize = ( pbi->biCompression == 0 ) ? DIBSIZE(*pbi) : pbi->biSizeImage;
memcpy( &pmt->formattype, &FORMAT_VideoInfo, sizeof(GUID) );
cb = sizeof(VIDEOINFOHEADER) + cbFmt;
......@@ -545,6 +545,7 @@ static HRESULT CAVIParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERT
{
CAVIParseImpl* This = (CAVIParseImpl*)pImpl->m_pUserData;
TRACE("(%p,%p)\n",This,pReqProp);
if ( This == NULL )
return E_UNEXPECTED;
......
......@@ -85,6 +85,7 @@ CBaseFilterImpl_fnStop(IBaseFilter* iface)
hr = NOERROR;
EnterCriticalSection( &This->csFilter );
TRACE("(%p) state = %d\n",This,This->fstate);
if ( This->fstate == State_Running )
{
......@@ -117,6 +118,8 @@ CBaseFilterImpl_fnPause(IBaseFilter* iface)
hr = NOERROR;
EnterCriticalSection( &This->csFilter );
TRACE("(%p) state = %d\n",This,This->fstate);
if ( This->fstate != State_Paused )
{
if ( This->pHandlers->pOnInactive != NULL )
......@@ -142,6 +145,7 @@ CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart)
hr = NOERROR;
EnterCriticalSection( &This->csFilter );
TRACE("(%p) state = %d\n",This,This->fstate);
This->rtStart = rtStart;
......@@ -178,7 +182,7 @@ CBaseFilterImpl_fnGetState(IBaseFilter* iface,DWORD dw,FILTER_STATE* pState)
/* FIXME - ignore 'intermediate state' now */
EnterCriticalSection( &This->csFilter );
TRACE("state %d\n",This->fstate);
TRACE("(%p) state = %d\n",This,This->fstate);
*pState = This->fstate;
LeaveCriticalSection( &This->csFilter );
......
......@@ -159,6 +159,7 @@ void CQualityControlPassThruImpl_UninitIQualityControl(
HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample );
HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This );
HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This );
HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This );
HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This );
......
......@@ -64,11 +64,15 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
ICOM_THIS(CPinBaseImpl,iface);
HRESULT hr = E_NOTIMPL;
ULONG i;
FILTER_STATE fs;
FIXME("(%p)->(%p,%p)\n",This,pPin,pmt);
TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
if ( !This->bOutput )
{
TRACE("Connect() should not be sent to input pins\n");
return E_UNEXPECTED;
}
if ( pPin == NULL )
return E_POINTER;
......@@ -82,13 +86,23 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
goto err;
}
/* FIXME - return fail if running */
/* return fail if running */
hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
if ( hr != S_OK || fs != State_Stopped )
{
TRACE("not stopped\n");
hr = VFW_E_NOT_STOPPED;
goto err;
}
if ( This->pHandlers->pOnPreConnect != NULL )
{
hr = This->pHandlers->pOnPreConnect(This,pPin);
if ( FAILED(hr) )
{
TRACE("OnPreconnect() failed hr = %08lx\n",hr);
goto err;
}
}
if ( pmt != NULL )
......@@ -109,6 +123,7 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
if ( SUCCEEDED(hr) )
{
hr = IPin_ReceiveConnection(pPin,iface,pmt);
TRACE("ReceiveConnection - %08lx\n",hr);
if ( SUCCEEDED(hr) )
{
goto connected;
......@@ -133,6 +148,7 @@ connected:;
hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
if ( FAILED(hr) )
{
TRACE("no IMemInputPin\n");
IPin_Disconnect(pPin);
goto err;
}
......@@ -142,6 +158,7 @@ connected:;
hr = This->pHandlers->pOnPostConnect(This,pPin);
if ( FAILED(hr) )
{
TRACE("OnPostConnect() failed hr = %08lx\n",hr);
IPin_Disconnect(pPin);
goto err;
}
......@@ -156,6 +173,8 @@ err:
}
LeaveCriticalSection( This->pcsPin );
TRACE("return %08lx\n",hr);
return hr;
}
......@@ -164,11 +183,15 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt
{
ICOM_THIS(CPinBaseImpl,iface);
HRESULT hr = E_NOTIMPL;
FILTER_STATE fs;
FIXME("(%p)->(%p,%p)\n",This,pPin,pmt);
TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
if ( This->bOutput )
{
TRACE("ReceiveConnection() should not be sent to output pins\n");
return E_UNEXPECTED;
}
if ( pPin == NULL || pmt == NULL )
return E_POINTER;
......@@ -180,13 +203,23 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt
goto err;
}
/* FIXME - return fail if running */
/* return fail if running */
hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
if ( hr != S_OK || fs != State_Stopped )
{
TRACE("not stopped\n");
hr = VFW_E_NOT_STOPPED;
goto err;
}
if ( This->pHandlers->pOnPreConnect != NULL )
{
hr = This->pHandlers->pOnPreConnect(This,pPin);
if ( FAILED(hr) )
{
TRACE("OnPreConnect() failed hr = %08lx\n",hr);
goto err;
}
}
hr = IPin_QueryAccept(iface,pmt);
......@@ -204,7 +237,10 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt
{
hr = This->pHandlers->pOnPostConnect(This,pPin);
if ( FAILED(hr) )
{
TRACE("OnPostConnect() failed hr = %08lx\n",hr);
goto err;
}
}
hr = S_OK;
......@@ -223,12 +259,20 @@ CPinBaseImpl_fnDisconnect(IPin* iface)
{
ICOM_THIS(CPinBaseImpl,iface);
HRESULT hr = NOERROR;
FILTER_STATE fs;
FIXME("(%p)->() stub!\n",This);
TRACE("(%p)->()\n",This);
EnterCriticalSection( This->pcsPin );
/* FIXME - return fail if running */
/* return fail if running */
hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
if ( hr != S_OK || fs != State_Stopped )
{
TRACE("not stopped\n");
hr = VFW_E_NOT_STOPPED;
goto err;
}
if ( This->pHandlers->pOnDisconnect != NULL )
hr = This->pHandlers->pOnDisconnect(This);
......@@ -256,6 +300,7 @@ CPinBaseImpl_fnDisconnect(IPin* iface)
hr = S_FALSE; /* FIXME - is this correct??? */
}
err:
LeaveCriticalSection( This->pcsPin );
return hr;
......@@ -741,8 +786,6 @@ CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSamp
if ( ppSample == NULL || pnSampleProcessed == NULL )
return E_POINTER;
EnterCriticalSection( This->pPin->pcsPin );
hr = NOERROR;
for ( n = 0; n < nSample; n++ )
{
......@@ -751,8 +794,6 @@ CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSamp
break;
}
LeaveCriticalSection( This->pPin->pcsPin );
*pnSampleProcessed = n;
return hr;
}
......@@ -941,6 +982,14 @@ HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
return This->pHandlers->pReceive( This, pSample );
}
HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This )
{
if ( This->pHandlers->pReceiveCanBlock == NULL )
return E_NOTIMPL;
return This->pHandlers->pReceiveCanBlock( This );
}
HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
{
if ( This->pHandlers->pEndOfStream == NULL )
......
/*
* Implements Color Space Converter(CLSID_Colour).
*
* hidenori@a2.ctktv.ne.jp
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "vfw.h"
#include "strmif.h"
#include "control.h"
#include "amvideo.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "xform.h"
#include "videoblt.h"
static const WCHAR ColorConv_FilterName[] =
{'C','o','l','o','r',' ','S','p','a','c','e',' ','C','o','n','v','e','r','t','e','r',0};
struct BltHandler
{
const GUID* psubtypeIn;
const GUID* psubtypeOut;
pVIDEOBLT_Blt pBlt;
};
static const struct BltHandler conv_handlers[] =
{
{ &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB32, VIDEOBLT_Blt_888_to_8888 },
{ &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB565, VIDEOBLT_Blt_888_to_565 },
{ &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB555, VIDEOBLT_Blt_888_to_555 },
{ &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB8, VIDEOBLT_Blt_888_to_332 },
{ NULL, NULL, NULL },
};
typedef struct CColorConvImpl
{
pVIDEOBLT_Blt m_pBlt;
AM_MEDIA_TYPE* m_pmtConv;
DWORD m_cConv;
LONG pitchIn;
LONG pitchOut;
} CColorConvImpl;
/***************************************************************************
*
* CColorConvImpl methods
*
*/
static void ColorConv_FreeOutTypes(CColorConvImpl* This)
{
DWORD i;
if ( This->m_pmtConv == NULL )
return;
TRACE("cConv = %lu\n",This->m_cConv);
for ( i = 0; i < This->m_cConv; i++ )
{
QUARTZ_MediaType_Free(&This->m_pmtConv[i]);
}
QUARTZ_FreeMem(This->m_pmtConv);
This->m_pmtConv = NULL;
This->m_cConv = 0;
}
static HRESULT ColorConv_FillBitmapInfo( BITMAPINFO* pbiOut, LONG biWidth, LONG biHeight, const GUID* psubtype )
{
int i;
DWORD* pdwBitf;
HRESULT hr = E_FAIL;
pbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbiOut->bmiHeader.biWidth = biWidth;
pbiOut->bmiHeader.biHeight = biHeight;
pbiOut->bmiHeader.biPlanes = 1;
if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB8 ) )
{
pbiOut->bmiHeader.biBitCount = 8;
for ( i = 0; i < 256; i++ )
{
pbiOut->bmiColors[i].rgbRed = ((i>>5)&7)*255/7;
pbiOut->bmiColors[i].rgbGreen = ((i>>2)&7)*255/7;
pbiOut->bmiColors[i].rgbBlue = (i&3)*255/3;
}
hr = S_OK;
}
if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB555 ) )
{
pbiOut->bmiHeader.biBitCount = 16;
hr = S_OK;
}
if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB565 ) )
{
pbiOut->bmiHeader.biBitCount = 16;
pbiOut->bmiHeader.biCompression = 3;
pdwBitf = (DWORD*)(&pbiOut->bmiColors[0]);
pdwBitf[0] = 0xf800;
pdwBitf[1] = 0x07e0;
pdwBitf[2] = 0x001f;
hr = S_OK;
}
if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB24 ) )
{
pbiOut->bmiHeader.biBitCount = 24;
hr = S_OK;
}
if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB32 ) )
{
pbiOut->bmiHeader.biBitCount = 32;
hr = S_OK;
}
pbiOut->bmiHeader.biSizeImage = DIBSIZE(pbiOut->bmiHeader);
return hr;
}
static HRESULT ColorConv_Init( CTransformBaseImpl* pImpl )
{
CColorConvImpl* This = pImpl->m_pUserData;
if ( This != NULL )
return NOERROR;
This = (CColorConvImpl*)QUARTZ_AllocMem( sizeof(CColorConvImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This, sizeof(CColorConvImpl) );
pImpl->m_pUserData = This;
/* construct */
This->m_pBlt = NULL;
This->m_pmtConv = NULL;
This->m_cConv = 0;
return NOERROR;
}
static HRESULT ColorConv_Cleanup( CTransformBaseImpl* pImpl )
{
CColorConvImpl* This = pImpl->m_pUserData;
if ( This == NULL )
return NOERROR;
/* destruct */
ColorConv_FreeOutTypes(This);
QUARTZ_FreeMem( This );
pImpl->m_pUserData = NULL;
return NOERROR;
}
static HRESULT ColorConv_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
{
CColorConvImpl* This = pImpl->m_pUserData;
BITMAPINFOHEADER* pbiIn = NULL;
BITMAPINFOHEADER* pbiOut = NULL;
HRESULT hr;
GUID stIn, stOut;
const struct BltHandler* phandler;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Video ) )
return E_FAIL;
if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) )
return E_FAIL;
pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
if ( pbiIn->biCompression != 0 &&
pbiIn->biCompression != 3 )
return E_FAIL;
hr = QUARTZ_MediaSubType_FromBitmap( &stIn, pbiIn );
if ( hr != S_OK || !IsEqualGUID( &pmtIn->subtype, &stIn ) )
return E_FAIL;
if ( pmtOut != NULL )
{
if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Video ) )
return E_FAIL;
if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_VideoInfo ) )
return E_FAIL;
pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
if ( pbiOut->biCompression != 0 &&
pbiOut->biCompression != 3 )
return E_FAIL;
hr = QUARTZ_MediaSubType_FromBitmap( &stOut, pbiOut );
if ( hr != S_OK || !IsEqualGUID( &pmtOut->subtype, &stOut ) )
return E_FAIL;
if ( pbiIn->biWidth != pbiOut->biWidth ||
pbiIn->biHeight != pbiOut->biHeight ||
pbiIn->biPlanes != 1 || pbiOut->biPlanes != 1 )
return E_FAIL;
}
phandler = conv_handlers;
while ( phandler->psubtypeIn != NULL )
{
if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
{
if ( pmtOut == NULL )
return S_OK;
if ( IsEqualGUID( &pmtOut->subtype, phandler->psubtypeOut ) )
return S_OK;
}
phandler ++;
}
return E_FAIL;
}
static HRESULT ColorConv_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
{
CColorConvImpl* This = pImpl->m_pUserData;
HRESULT hr;
const struct BltHandler* phandler;
DWORD cConv;
BITMAPINFOHEADER* pbiIn = NULL;
BITMAPINFOHEADER* pbiOut = NULL;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = ColorConv_CheckMediaType( pImpl, pmtIn, NULL );
if ( FAILED(hr) )
return hr;
pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
ColorConv_FreeOutTypes(This);
cConv = 0;
phandler = conv_handlers;
while ( phandler->psubtypeIn != NULL )
{
if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
cConv ++;
phandler ++;
}
This->m_cConv = cConv;
This->m_pmtConv = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
sizeof(AM_MEDIA_TYPE) * cConv );
if ( This->m_pmtConv == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This->m_pmtConv, sizeof(AM_MEDIA_TYPE) * cConv );
cConv = 0;
phandler = conv_handlers;
while ( phandler->psubtypeIn != NULL )
{
if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
{
memcpy( &This->m_pmtConv[cConv].majortype, &MEDIATYPE_Video, sizeof(GUID) );
memcpy( &This->m_pmtConv[cConv].subtype, phandler->psubtypeOut, sizeof(GUID) );
This->m_pmtConv[cConv].bFixedSizeSamples = 1;
This->m_pmtConv[cConv].bTemporalCompression = 0;
This->m_pmtConv[cConv].lSampleSize = DIBSIZE(*pbiIn);
memcpy( &This->m_pmtConv[cConv].formattype, &FORMAT_VideoInfo, sizeof(GUID) );
This->m_pmtConv[cConv].cbFormat = sizeof(VIDEOINFO);
This->m_pmtConv[cConv].pbFormat = (BYTE*)CoTaskMemAlloc( This->m_pmtConv[cConv].cbFormat );
if ( This->m_pmtConv[cConv].pbFormat == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This->m_pmtConv[cConv].pbFormat, This->m_pmtConv[cConv].cbFormat );
pbiOut = &(((VIDEOINFOHEADER*)(This->m_pmtConv[cConv].pbFormat))->bmiHeader);
hr = ColorConv_FillBitmapInfo( (BITMAPINFO*)pbiOut, pbiIn->biWidth, pbiIn->biHeight, phandler->psubtypeOut );
if ( FAILED(hr) )
return hr;
cConv ++;
}
phandler ++;
}
*ppmtAcceptTypes = This->m_pmtConv;
*pcAcceptTypes = This->m_cConv;
return NOERROR;
}
static HRESULT ColorConv_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
{
CColorConvImpl* This = pImpl->m_pUserData;
HRESULT hr;
BITMAPINFOHEADER* pbiOut = NULL;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = ColorConv_CheckMediaType( pImpl, pmtIn, pmtOut );
if ( FAILED(hr) )
return hr;
pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
pProp->cBuffers = 1;
pProp->cbBuffer = DIBSIZE(*pbiOut);
TRACE("%ldx%ldx%u cbBuffer = %ld\n",pbiOut->biWidth,pbiOut->biHeight,(unsigned)pbiOut->biBitCount,pProp->cbBuffer);
return NOERROR;
}
static HRESULT ColorConv_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
{
CColorConvImpl* This = pImpl->m_pUserData;
HRESULT hr;
BITMAPINFOHEADER* pbiIn = NULL;
BITMAPINFOHEADER* pbiOut = NULL;
const struct BltHandler* phandler;
TRACE("(%p)\n",This);
if ( This == NULL )
return E_UNEXPECTED;
hr = ColorConv_CheckMediaType( pImpl, pmtIn, pmtOut );
if ( FAILED(hr) )
return hr;
pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
This->pitchIn = DIBWIDTHBYTES(*pbiIn);
This->pitchOut = DIBWIDTHBYTES(*pbiOut);
This->m_pBlt = NULL;
phandler = conv_handlers;
while ( phandler->psubtypeIn != NULL )
{
if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
{
if ( IsEqualGUID( &pmtOut->subtype, phandler->psubtypeOut ) )
{
This->m_pBlt = phandler->pBlt;
return S_OK;
}
}
phandler ++;
}
return E_FAIL;
}
static HRESULT ColorConv_Transform( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut )
{
CColorConvImpl* This = pImpl->m_pUserData;
BYTE* pDataIn = NULL;
BYTE* pDataOut = NULL;
BITMAPINFO* pbiIn;
BITMAPINFO* pbiOut;
HRESULT hr;
if ( This == NULL )
return E_UNEXPECTED;
hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
if ( FAILED(hr) )
return hr;
hr = IMediaSample_GetPointer( pSampOut, &pDataOut );
if ( FAILED(hr) )
return hr;
if ( This->m_pBlt != NULL )
{
pbiIn = (BITMAPINFO*)&(((VIDEOINFOHEADER*)pImpl->pInPin->pin.pmtConn->pbFormat)->bmiHeader);
pbiOut = (BITMAPINFO*)&(((VIDEOINFOHEADER*)pImpl->pOutPin->pin.pmtConn->pbFormat)->bmiHeader);
This->m_pBlt(
pDataOut, This->pitchOut,
pDataIn, This->pitchIn,
pbiIn->bmiHeader.biWidth,
abs(pbiIn->bmiHeader.biHeight),
&pbiIn->bmiColors[0], pbiIn->bmiHeader.biClrUsed );
hr = IMediaSample_SetActualDataLength(pSampOut,DIBSIZE(pbiOut->bmiHeader));
if ( FAILED(hr) )
return hr;
}
return NOERROR;
}
static HRESULT ColorConv_EndTransform( CTransformBaseImpl* pImpl )
{
CColorConvImpl* This = pImpl->m_pUserData;
if ( This == NULL )
return E_UNEXPECTED;
This->m_pBlt = NULL;
return NOERROR;
}
static const TransformBaseHandlers transhandlers =
{
ColorConv_Init,
ColorConv_Cleanup,
ColorConv_CheckMediaType,
ColorConv_GetOutputTypes,
ColorConv_GetAllocProp,
ColorConv_BeginTransform,
ColorConv_Transform,
ColorConv_EndTransform,
};
HRESULT QUARTZ_CreateColour(IUnknown* punkOuter,void** ppobj)
{
return QUARTZ_CreateTransformBase(
punkOuter,ppobj,
&CLSID_Colour,
ColorConv_FilterName,
NULL, NULL,
&transhandlers );
}
/*
* Implementation of IBasicAudio, IBasicVideo2, IVideoWindow for FilterGraph.
*
* FIXME - stub.
*
* hidenori@a2.ctktv.ne.jp
*/
......@@ -24,33 +22,53 @@ DEFAULT_DEBUG_CHANNEL(quartz);
#include "fgraph.h"
static HRESULT CFilterGraph_QIFilters(
CFilterGraph* This, REFIID riid, void** ppvobj )
{
QUARTZ_CompListItem* pItem;
HRESULT hr = E_NOINTERFACE;
TRACE( "(%p,%p,%p)\n",This,riid,ppvobj);
QUARTZ_CompList_Lock( This->m_pFilterList );
pItem = QUARTZ_CompList_GetLast( This->m_pFilterList );
while ( pItem != NULL )
{
if ( IUnknown_QueryInterface( QUARTZ_CompList_GetItemPtr(pItem),riid,ppvobj) == S_OK )
{
hr = S_OK;
break;
}
pItem = QUARTZ_CompList_GetPrev( This->m_pFilterList, pItem );
}
QUARTZ_CompList_Unlock( This->m_pFilterList );
return hr;
}
static HRESULT CFilterGraph_QueryBasicAudio(
CFilterGraph* This, IBasicAudio** ppAudio )
{
FIXME("(%p,%p) stub!\n",This,ppAudio);
return E_NOTIMPL;
return CFilterGraph_QIFilters(This,&IID_IBasicAudio,(void**)ppAudio);
}
static HRESULT CFilterGraph_QueryBasicVideo(
CFilterGraph* This, IBasicVideo** ppVideo )
{
FIXME("(%p,%p) stub!\n",This,ppVideo);
return E_NOTIMPL;
return CFilterGraph_QIFilters(This,&IID_IBasicVideo,(void**)ppVideo);
}
static HRESULT CFilterGraph_QueryBasicVideo2(
CFilterGraph* This, IBasicVideo2** ppVideo )
{
FIXME("(%p,%p) stub!\n",This,ppVideo);
return E_NOTIMPL;
return CFilterGraph_QIFilters(This,&IID_IBasicVideo2,(void**)ppVideo);
}
static HRESULT CFilterGraph_QueryVideoWindow(
CFilterGraph* This, IVideoWindow** ppVidWin )
{
FIXME("(%p,%p) stub!\n",This,ppVidWin);
return E_NOTIMPL;
return CFilterGraph_QIFilters(This,&IID_IVideoWindow,(void**)ppVidWin);
}
......
......@@ -40,6 +40,7 @@ HRESULT CFilterGraph_PollGraphState(
IBaseFilter* pFilter;
hr = S_OK;
*pState = State_Stopped;
EnterCriticalSection( &This->m_csGraphState );
QUARTZ_CompList_Lock( This->m_pFilterList );
......
......@@ -35,6 +35,8 @@ DEFAULT_DEBUG_CHANNEL(quartz);
#include "vidren.h"
#include "parser.h"
#include "asyncsrc.h"
#include "xform.h"
typedef struct QUARTZ_CLASSENTRY
{
......@@ -84,6 +86,8 @@ static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] =
{ &CLSID_AviSplitter, &QUARTZ_CreateAVISplitter },
{ &CLSID_AsyncReader, &QUARTZ_CreateAsyncReader },
{ &CLSID_URLReader, &QUARTZ_CreateURLReader },
{ &CLSID_AVIDec, &QUARTZ_CreateAVIDec },
{ &CLSID_Colour, &QUARTZ_CreateColour },
{ NULL, NULL },
};
......
......@@ -13,6 +13,7 @@
#include "winerror.h"
#include "strmif.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
......@@ -75,6 +76,91 @@ HRESULT QUARTZ_CreateMemoryAllocator(IUnknown* punkOuter,void** ppobj)
*
*/
static HRESULT
IMemAllocator_LockUnusedBuffer(CMemoryAllocator* This,IMediaSample** ppSample)
{
HRESULT hr = E_FAIL;
LONG i;
TRACE("(%p) try to enter critical section\n",This);
EnterCriticalSection( &This->csMem );
TRACE("(%p) enter critical section\n",This);
if ( This->pData == NULL || This->ppSamples == NULL ||
This->prop.cBuffers <= 0 )
{
hr = VFW_E_NOT_COMMITTED;
goto end;
}
for ( i = 0; i < This->prop.cBuffers; i++ )
{
if ( This->ppSamples[i] == NULL )
{
hr = VFW_E_NOT_COMMITTED;
goto end;
}
if ( This->ppSamples[i]->ref == 0 )
{
*ppSample = (IMediaSample*)(This->ppSamples[i]);
IMediaSample_AddRef( *ppSample );
hr = NOERROR;
goto end;
}
}
hr = VFW_E_TIMEOUT;
end:
LeaveCriticalSection( &This->csMem );
TRACE("(%p) leave critical section\n",This);
return hr;
}
/* TRUE = all samples are released */
static BOOL
IMemAllocator_ReleaseUnusedBuffer(CMemoryAllocator* This)
{
LONG i;
BOOL bRet = TRUE;
TRACE("(%p) try to enter critical section\n",This);
EnterCriticalSection( &This->csMem );
TRACE("(%p) enter critical section\n",This);
if ( This->pData == NULL || This->ppSamples == NULL ||
This->prop.cBuffers <= 0 )
goto end;
for ( i = 0; i < This->prop.cBuffers; i++ )
{
if ( This->ppSamples[i]->ref == 0 )
{
QUARTZ_DestroyMemMediaSample( This->ppSamples[i] );
This->ppSamples[i] = NULL;
}
else
{
bRet = FALSE;
}
}
if ( bRet )
{
QUARTZ_FreeMem(This->ppSamples);
This->ppSamples = NULL;
QUARTZ_FreeMem(This->pData);
This->pData = NULL;
}
end:
LeaveCriticalSection( &This->csMem );
TRACE("(%p) leave critical section\n",This);
return bRet;
}
static HRESULT WINAPI
IMemAllocator_fnQueryInterface(IMemAllocator* iface,REFIID riid,void** ppobj)
......@@ -121,10 +207,17 @@ IMemAllocator_fnSetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pPropRe
pPropReq->cbBuffer < 0 ||
pPropReq->cbAlign < 0 ||
pPropReq->cbPrefix < 0 )
{
TRACE("pPropReq is invalid\n");
return E_INVALIDARG;
}
if ( ( pPropReq->cbAlign & (pPropReq->cbAlign-1) ) != 0 )
return E_INVALIDARG;
if ( pPropReq->cbAlign == 0 ||
( pPropReq->cbAlign & (pPropReq->cbAlign-1) ) != 0 )
{
WARN("cbAlign is invalid - %ld\n",pPropReq->cbAlign);
return VFW_E_BADALIGN;
}
hr = NOERROR;
......@@ -133,6 +226,7 @@ IMemAllocator_fnSetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pPropRe
if ( This->pData != NULL || This->ppSamples != NULL )
{
/* if commited, properties must not be changed. */
TRACE("already commited\n");
hr = E_UNEXPECTED;
goto end;
}
......@@ -154,6 +248,8 @@ IMemAllocator_fnSetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pPropRe
end:
LeaveCriticalSection( &This->csMem );
TRACE("returned successfully.\n");
return hr;
}
......@@ -190,6 +286,7 @@ IMemAllocator_fnCommit(IMemAllocator* iface)
EnterCriticalSection( &This->csMem );
hr = NOERROR;
/* FIXME - handle in Decommitting */
if ( This->pData != NULL || This->ppSamples != NULL ||
This->prop.cBuffers <= 0 )
goto end;
......@@ -244,70 +341,27 @@ static HRESULT WINAPI
IMemAllocator_fnDecommit(IMemAllocator* iface)
{
CMemoryAllocator_THIS(iface,memalloc);
HRESULT hr;
LONG i;
BOOL bBlock;
TRACE( "(%p)->()\n", This );
EnterCriticalSection( &This->csMem );
hr = NOERROR;
if ( This->pData == NULL && This->ppSamples == NULL )
goto end;
while ( 1 )
{
bBlock = FALSE;
i = 0;
ResetEvent( This->hEventSample );
while ( 1 )
{
if ( i >= This->prop.cBuffers )
break;
if ( This->ppSamples[i] != NULL )
{
if ( This->ppSamples[i]->ref == 0 )
{
QUARTZ_DestroyMemMediaSample( This->ppSamples[i] );
This->ppSamples[i] = NULL;
}
else
{
bBlock = TRUE;
}
}
i++;
}
if ( !bBlock )
{
QUARTZ_FreeMem(This->ppSamples);
This->ppSamples = NULL;
QUARTZ_FreeMem(This->pData);
This->pData = NULL;
hr = NOERROR;
/* to avoid deadlock, don't hold critical section while blocking */
if ( IMemAllocator_ReleaseUnusedBuffer(This) )
break;
}
WaitForSingleObject( This->hEventSample, INFINITE );
}
end:
LeaveCriticalSection( &This->csMem );
return hr;
return NOERROR;
}
static HRESULT WINAPI
IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd,DWORD dwFlags)
{
CMemoryAllocator_THIS(iface,memalloc);
LONG i;
HRESULT hr;
TRACE( "(%p)->(%p,%p,%p,%lu)\n", This, ppSample, prtStart, prtEnd, dwFlags );
......@@ -315,46 +369,19 @@ IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE
if ( ppSample == NULL )
return E_POINTER;
EnterCriticalSection( &This->csMem );
TRACE("(%p) enter critical section\n",This);
hr = NOERROR;
if ( This->pData == NULL || This->ppSamples == NULL ||
This->prop.cBuffers <= 0 )
{
hr = E_FAIL; /* FIXME? */
goto end;
}
while ( 1 )
{
ResetEvent( This->hEventSample );
for ( i = 0; i < This->prop.cBuffers; i++ )
{
if ( This->ppSamples[i]->ref == 0 )
{
*ppSample = (IMediaSample*)(This->ppSamples[i]);
IMediaSample_AddRef( *ppSample );
hr = NOERROR;
goto end;
}
}
if ( dwFlags & AM_GBF_NOWAIT )
{
hr = E_FAIL; /* FIXME? */
/* to avoid deadlock, don't hold critical section while blocking */
hr = IMemAllocator_LockUnusedBuffer(This,ppSample);
if ( ( hr != VFW_E_TIMEOUT ) || ( dwFlags & AM_GBF_NOWAIT ) )
goto end;
}
WaitForSingleObject( This->hEventSample, INFINITE );
}
end:
LeaveCriticalSection( &This->csMem );
TRACE("(%p) leave critical section\n",This);
return hr;
}
......
......@@ -219,6 +219,28 @@ HRESULT QUARTZ_MediaSubType_FromBitmap(
return hr;
}
BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
{
switch ( pbi->biCompression )
{
case 0:
case 3:
case mmioFOURCC('I','4','2','0'):
case mmioFOURCC('I','Y','U','V'):
case mmioFOURCC('Y','U','Y','V'):
case mmioFOURCC('Y','V','U','9'):
case mmioFOURCC('Y','4','1','1'):
case mmioFOURCC('Y','4','1','P'):
case mmioFOURCC('Y','U','Y','2'):
case mmioFOURCC('Y','V','Y','U'):
case mmioFOURCC('U','Y','V','Y'):
case mmioFOURCC('Y','2','1','1'):
case mmioFOURCC('Y','V','1','2'):
return TRUE;
}
return FALSE;
}
/****************************************************************************/
......
......@@ -25,6 +25,9 @@ BOOL QUARTZ_MediaSubType_IsFourCC(
HRESULT QUARTZ_MediaSubType_FromBitmap(
GUID* psubtype, const BITMAPINFOHEADER* pbi );
BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi );
HRESULT QUARTZ_CreateEnumMediaTypes(
IEnumMediaTypes** ppobj,
const AM_MEDIA_TYPE* pTypes, ULONG cTypes );
......
......@@ -3,7 +3,8 @@
*
* hidenori@a2.ctktv.ne.jp
*
* FIXME - save the array of pSample and handle errors/flushing correctly.
* FIXME - handle errors/flushing correctly.
* FIXME - handle seeking.
*/
#include "config.h"
......@@ -15,6 +16,7 @@
#include "mmsystem.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"
......@@ -26,10 +28,14 @@ DEFAULT_DEBUG_CHANNEL(quartz);
#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)
#define QUARTZ_MSG_FLUSH (WM_APP+1)
#define QUARTZ_MSG_EXITTHREAD (WM_APP+2)
#define QUARTZ_MSG_SEEK (WM_APP+3)
HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This );
void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This );
HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This );
void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This );
/***************************************************************************
*
......@@ -74,36 +80,189 @@ void CParserImpl_ReleaseOutPins( CParserImpl* This )
}
static
BOOL CParserImpl_OutPinsAreConnected( CParserImpl* This )
{
QUARTZ_CompListItem* pItem;
IPin* pPin;
IPin* pPinPeer;
HRESULT hr;
QUARTZ_CompList_Lock( This->basefilter.pOutPins );
pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
while ( pItem != NULL )
{
if ( pItem == NULL )
break;
pPin = (IPin*)QUARTZ_CompList_GetItemPtr(pItem);
pPinPeer = NULL;
hr = IPin_ConnectedTo(pPin,&pPinPeer);
if ( hr == S_OK && pPinPeer != NULL )
{
IPin_Release(pPinPeer);
return TRUE;
}
pItem = QUARTZ_CompList_GetNext( This->basefilter.pOutPins, pItem );
}
QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
return FALSE;
}
static
void CParserImpl_ReleaseListOfOutPins( CParserImpl* This )
{
QUARTZ_CompListItem* pItem;
QUARTZ_CompList_Lock( This->basefilter.pOutPins );
while ( 1 )
{
pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
if ( pItem == NULL )
break;
QUARTZ_CompList_RemoveComp(
This->basefilter.pOutPins,
QUARTZ_CompList_GetItemPtr(pItem) );
}
QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
}
static
void CParserImpl_ClearAllRequests( CParserImpl* This )
{
ULONG nIndex;
TRACE("(%p)\n",This);
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
}
}
static
void CParserImpl_ReleaseAllRequests( CParserImpl* This )
{
ULONG nIndex;
TRACE("(%p)\n",This);
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
if ( This->m_ppOutPins[nIndex]->m_bReqUsed )
{
if ( This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
{
IMediaSample_Release(This->m_ppOutPins[nIndex]->m_pReqSample);
This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
}
This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
}
}
}
static
HRESULT CParserImpl_ReleaseAllPendingSamples( CParserImpl* This )
BOOL CParserImpl_HasPendingSamples( CParserImpl* This )
{
ULONG nIndex;
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
if ( This->m_ppOutPins[nIndex]->m_bReqUsed &&
This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
return TRUE;
}
return FALSE;
}
static
HRESULT CParserImpl_FlushAllPendingSamples( CParserImpl* This )
{
HRESULT hr;
IMediaSample* pSample;
DWORD_PTR dwContext;
IAsyncReader_BeginFlush(This->m_pReader);
TRACE("(%p)\n",This);
/* remove all samples from queue */
hr = IAsyncReader_BeginFlush(This->m_pReader);
if ( FAILED(hr) )
return hr;
IAsyncReader_EndFlush(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);
CParserImpl_ReleaseAllRequests(This);
if ( hr == VFW_E_TIMEOUT )
hr = NOERROR;
return NOERROR;
}
return hr;
static HRESULT CParserImpl_SendEndOfStream( CParserImpl* This )
{
ULONG nIndex;
HRESULT hr;
HRESULT hrRet;
CParserOutPinImpl* pOutPin;
TRACE("(%p)\n",This);
if ( This->m_bSendEOS )
return NOERROR;
This->m_bSendEOS = TRUE;
hrRet = S_OK;
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pOutPin = This->m_ppOutPins[nIndex];
hr = CPinBaseImpl_SendEndOfStream(&pOutPin->pin);
if ( FAILED(hr) )
{
if ( SUCCEEDED(hrRet) )
hrRet = hr;
}
else
{
if ( hr != S_OK && hrRet == S_OK )
hrRet = hr;
}
}
return hrRet;
}
static HRESULT CParserImpl_SendFlush( CParserImpl* This )
{
ULONG nIndex;
HRESULT hr;
HRESULT hrRet;
CParserOutPinImpl* pOutPin;
TRACE("(%p)\n",This);
hrRet = S_OK;
for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
{
pOutPin = This->m_ppOutPins[nIndex];
hr = CPinBaseImpl_SendBeginFlush(&pOutPin->pin);
if ( FAILED(hr) )
{
if ( SUCCEEDED(hrRet) )
hrRet = hr;
}
else
{
if ( hr != S_OK && hrRet == S_OK )
hrRet = hr;
hr = CPinBaseImpl_SendEndFlush(&pOutPin->pin);
if ( FAILED(hr) )
hrRet = hr;
}
}
return hrRet;
}
static
......@@ -123,23 +282,22 @@ HRESULT CParserImpl_ProcessNextSample( CParserImpl* This )
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 */
case QUARTZ_MSG_FLUSH:
TRACE("Flush\n");
CParserImpl_FlushAllPendingSamples(This);
hr = CParserImpl_SendFlush(This);
break;
case QUARTZ_MSG_EXITTHREAD:
FIXME("EndThread\n");
CParserImpl_ReleaseAllPendingSamples(This);
TRACE("(%p) EndThread\n",This);
CParserImpl_FlushAllPendingSamples(This);
CParserImpl_ClearAllRequests(This);
CParserImpl_SendFlush(This);
CParserImpl_SendEndOfStream(This);
TRACE("(%p) exit thread\n",This);
return S_FALSE;
case QUARTZ_MSG_SEEK:
FIXME("Seek\n");
CParserImpl_FlushAllPendingSamples(This);
break;
default:
FIXME( "invalid message %04u\n", (unsigned)msg.message );
......@@ -156,30 +314,51 @@ HRESULT CParserImpl_ProcessNextSample( CParserImpl* This )
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);
hr = This->m_pHandler->pProcessSample(This,nIndex,pOutPin->m_llReqStart,pOutPin->m_lReqLength,pOutPin->m_pReqSample);
if ( FAILED(hr) )
if ( SUCCEEDED(hr) )
{
/* Notify (ABORT) */
if ( pOutPin->m_pOutPinAllocator != NULL &&
pOutPin->m_pOutPinAllocator != This->m_pAllocator )
{
/* if pin has its own allocator, sample must be copied */
hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
if ( SUCCEEDED(hr) )
{
hr = QUARTZ_IMediaSample_Copy(
pSample, pOutPin->m_pReqSample, TRUE );
if ( SUCCEEDED(hr) )
hr = CPinBaseImpl_SendSample(&pOutPin->pin,pSample);
IMediaSample_Release(pSample);
}
}
else
{
hr = CPinBaseImpl_SendSample(&pOutPin->pin,pOutPin->m_pReqSample);
}
}
else
if ( FAILED(hr) )
{
/* FIXME - if pin has its own allocator, sample must be copied */
hr = CPinBaseImpl_SendSample(&pOutPin->pin,pSample);
/* Notify (ABORT) */
}
IMediaSample_Release(pOutPin->m_pReqSample);
pOutPin->m_pReqSample = NULL;
pOutPin->m_bReqUsed = FALSE;
}
if ( SUCCEEDED(hr) )
hr = NOERROR;
IMediaSample_Release(pSample);
TRACE("return %08lx\n",hr);
return hr;
......@@ -223,10 +402,29 @@ DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
}
if ( hr != S_OK )
{
/* Flush */
/* Notify (COMPLETE) */
/* Flush pending samples. */
hr = S_OK;
while ( CParserImpl_HasPendingSamples(This) )
{
hr = CParserImpl_ProcessNextSample(This);
if ( hr != S_OK )
break;
}
if ( hr != S_OK )
{
/* notification is already sent */
break;
}
/* Send End Of Stream. */
hr = CParserImpl_SendEndOfStream(This);
if ( hr != S_OK )
{
/* notification is already sent */
break;
}
/* Waiting... */
/* Blocking... */
hr = CParserImpl_ProcessNextSample(This);
if ( hr != S_OK )
{
......@@ -238,7 +436,7 @@ DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
if ( This->m_ppOutPins[nIndex]->pin.pPinConnectedTo == NULL )
continue;
rtSampleTimeStart = llReqStart * QUARTZ_TIMEUNITS;
rtSampleTimeStart = This->basefilter.rtStart + llReqStart * QUARTZ_TIMEUNITS;
rtSampleTimeEnd = (llReqStart + lReqLength) * QUARTZ_TIMEUNITS;
bReqNext = FALSE;
}
......@@ -261,6 +459,7 @@ DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
}
This->m_ppOutPins[nIndex]->m_bReqUsed = TRUE;
This->m_ppOutPins[nIndex]->m_pReqSample = pSample;
This->m_ppOutPins[nIndex]->m_llReqStart = llReqStart;
This->m_ppOutPins[nIndex]->m_lReqLength = lReqLength;
This->m_ppOutPins[nIndex]->m_rtReqStart = rtSampleTimeStart;
......@@ -286,9 +485,9 @@ HRESULT CParserImpl_BeginThread( CParserImpl* This )
DWORD dwRes;
HANDLE hEvents[2];
if ( This->m_hEventInit != (HANDLE)NULL ||
if ( This->m_hEventInit != (HANDLE)NULL &&
This->m_hThread != (HANDLE)NULL )
return E_UNEXPECTED;
return NOERROR;
This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
if ( This->m_hEventInit == (HANDLE)NULL )
......@@ -316,6 +515,7 @@ HRESULT CParserImpl_BeginThread( CParserImpl* This )
static
void CParserImpl_EndThread( CParserImpl* This )
{
TRACE("(%p)\n",This);
if ( This->m_hThread != (HANDLE)NULL )
{
if ( PostThreadMessageA(
......@@ -341,6 +541,8 @@ HRESULT CParserImpl_MemCommit( CParserImpl* This )
ULONG nIndex;
IMemAllocator* pAlloc;
TRACE("(%p)\n",This);
if ( This->m_pAllocator == NULL )
return E_UNEXPECTED;
......@@ -371,6 +573,8 @@ void CParserImpl_MemDecommit( CParserImpl* This )
ULONG nIndex;
IMemAllocator* pAlloc;
TRACE("(%p)\n",This);
if ( This->m_pAllocator != NULL )
IMemAllocator_Decommit( This->m_pAllocator );
......@@ -396,16 +600,11 @@ void CParserImpl_MemDecommit( CParserImpl* This )
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;
if ( !CParserImpl_OutPinsAreConnected(This) )
return NOERROR;
return NOERROR;
}
......@@ -413,11 +612,22 @@ static HRESULT CParserImpl_OnActive( CBaseFilterImpl* pImpl )
static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
{
CParserImpl_THIS(pImpl,basefilter);
HRESULT hr;
TRACE( "(%p)\n", This );
CParserImpl_EndThread(This);
CParserImpl_MemDecommit(This);
if ( !CParserImpl_OutPinsAreConnected(This) )
return NOERROR;
hr = CParserImpl_MemCommit(This);
if ( FAILED(hr) )
return hr;
hr = CParserImpl_BeginThread(This);
if ( FAILED(hr) )
{
CParserImpl_EndThread(This);
return hr;
}
return NOERROR;
}
......@@ -428,6 +638,10 @@ static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
FIXME( "(%p)\n", This );
CParserImpl_EndThread(This);
CParserImpl_MemDecommit(This);
This->m_bSendEOS = FALSE;
/* FIXME - reset streams. */
return NOERROR;
......@@ -473,6 +687,12 @@ static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
return E_NOTIMPL;
}
/* at first, release all output pins. */
if ( CParserImpl_OutPinsAreConnected(This->pParser) )
return E_FAIL;
CParserImpl_ReleaseListOfOutPins(This->pParser);
CParserImpl_ReleaseOutPins(This->pParser);
CParserImpl_SetAsyncReader( This->pParser, NULL );
hr = IPin_QueryInterface( pPin, &IID_IAsyncReader, (void**)&pReader );
if ( FAILED(hr) )
......@@ -495,6 +715,9 @@ static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
hr = This->pParser->m_pHandler->pGetAllocProp(This->pParser,&This->pParser->m_propAlloc);
if ( FAILED(hr) )
return hr;
if ( This->pParser->m_propAlloc.cbAlign == 0 )
This->pParser->m_propAlloc.cbAlign = 1;
if ( This->pParser->m_pAllocator == NULL )
{
hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
......@@ -524,7 +747,7 @@ static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
&This->pParser->m_ppOutPins[nIndex],
nIndex, pwszOutPinName );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
hr = QUARTZ_CompList_AddTailComp(
This->pParser->basefilter.pOutPins,
(IUnknown*)&(This->pParser->m_ppOutPins[nIndex]->pin),
NULL, 0 );
......@@ -557,6 +780,7 @@ static HRESULT CParserInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
CParserImpl_SetAsyncReader( This->pParser, NULL );
if ( This->pParser->m_pAllocator != NULL )
{
IMemAllocator_Decommit(This->pParser->m_pAllocator);
IMemAllocator_Release(This->pParser->m_pAllocator);
This->pParser->m_pAllocator = NULL;
}
......@@ -601,6 +825,7 @@ static HRESULT CParserOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin
{
CParserOutPinImpl_THIS(pImpl,pin);
ALLOCATOR_PROPERTIES propReq;
ALLOCATOR_PROPERTIES propActual;
IMemAllocator* pAllocator;
HRESULT hr;
BOOL bNewAllocator = FALSE;
......@@ -644,7 +869,9 @@ static HRESULT CParserOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin
This->pin.pMemInputPinConnectedTo, &pAllocator );
if ( FAILED(hr) )
return hr;
hr = IMemInputPin_NotifyAllocator(
hr = IMemAllocator_SetProperties( pAllocator, &This->pParser->m_propAlloc, &propActual );
if ( SUCCEEDED(hr) )
hr = IMemInputPin_NotifyAllocator(
This->pin.pMemInputPinConnectedTo, pAllocator, FALSE );
if ( FAILED(hr) )
{
......@@ -761,6 +988,7 @@ HRESULT QUARTZ_CreateParser(
QUARTZ_AllocObj( sizeof(CParserImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
ZeroMemory( This, sizeof(CParserImpl) );
This->m_pInPin = NULL;
This->m_cOutStreams = 0;
......@@ -771,6 +999,7 @@ HRESULT QUARTZ_CreateParser(
This->m_hEventInit = (HANDLE)NULL;
This->m_hThread = (HANDLE)NULL;
This->m_dwThreadId = 0;
This->m_bSendEOS = FALSE;
This->m_pHandler = pHandler;
This->m_pUserData = NULL;
......@@ -919,6 +1148,8 @@ static QUARTZ_IFEntry OutPinIFEntries[] =
{
{ &IID_IPin, offsetof(CParserOutPinImpl,pin)-offsetof(CParserOutPinImpl,unk) },
{ &IID_IQualityControl, offsetof(CParserOutPinImpl,qcontrol)-offsetof(CParserOutPinImpl,unk) },
{ &IID_IMediaSeeking, offsetof(CParserOutPinImpl,mediaseeking)-offsetof(CParserOutPinImpl,unk) },
{ &IID_IMediaPosition, offsetof(CParserOutPinImpl,mediaposition)-offsetof(CParserOutPinImpl,unk) },
};
static void QUARTZ_DestroyParserOutPin(IUnknown* punk)
......@@ -931,8 +1162,11 @@ static void QUARTZ_DestroyParserOutPin(IUnknown* punk)
if ( This->m_pOutPinAllocator != NULL )
IMemAllocator_Release(This->m_pOutPinAllocator);
CPinBaseImpl_UninitIPin( &This->pin );
CParserOutPinImpl_UninitIMediaPosition(This);
CParserOutPinImpl_UninitIMediaSeeking(This);
CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
CPinBaseImpl_UninitIPin( &This->pin );
}
HRESULT QUARTZ_CreateParserOutPin(
......@@ -959,6 +1193,7 @@ HRESULT QUARTZ_CreateParserOutPin(
This->m_pOutPinAllocator = NULL;
This->m_pUserData = NULL;
This->m_bReqUsed = FALSE;
This->m_pReqSample = NULL;
This->m_llReqStart = 0;
This->m_lReqLength = 0;
This->m_rtReqStart = 0;
......@@ -980,6 +1215,22 @@ HRESULT QUARTZ_CreateParserOutPin(
&This->qcontrol,
This->unk.punkControl,
&This->pin );
if ( SUCCEEDED(hr) )
{
hr = CParserOutPinImpl_InitIMediaSeeking(This);
if ( SUCCEEDED(hr) )
{
hr = CParserOutPinImpl_InitIMediaPosition(This);
if ( FAILED(hr) )
{
CParserOutPinImpl_UninitIMediaSeeking(This);
}
}
if ( FAILED(hr) )
{
CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
}
}
if ( FAILED(hr) )
{
CPinBaseImpl_UninitIPin( &This->pin );
......@@ -1003,3 +1254,479 @@ HRESULT QUARTZ_CreateParserOutPin(
return S_OK;
}
/***************************************************************************
*
* IMediaSeeking for CParserOutPinImpl
*
*/
static HRESULT WINAPI
IMediaSeeking_fnQueryInterface(IMediaSeeking* iface,REFIID riid,void** ppobj)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IMediaSeeking_fnAddRef(IMediaSeeking* iface)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IMediaSeeking_fnRelease(IMediaSeeking* iface)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IMediaSeeking_fnGetCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnCheckCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnIsFormatSupported(IMediaSeeking* iface,const GUID* pidFormat)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnQueryPreferredFormat(IMediaSeeking* iface,GUID* pidFormat)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetTimeFormat(IMediaSeeking* iface,GUID* pidFormat)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnIsUsingTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnSetTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetDuration(IMediaSeeking* iface,LONGLONG* pllDuration)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
/* the following line may produce too many FIXMEs... */
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetStopPosition(IMediaSeeking* iface,LONGLONG* pllPos)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetCurrentPosition(IMediaSeeking* iface,LONGLONG* pllPos)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnConvertTimeFormat(IMediaSeeking* iface,LONGLONG* pllOut,const GUID* pidFmtOut,LONGLONG llIn,const GUID* pidFmtIn)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnSetPositions(IMediaSeeking* iface,LONGLONG* pllCur,DWORD dwCurFlags,LONGLONG* pllStop,DWORD dwStopFlags)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetPositions(IMediaSeeking* iface,LONGLONG* pllCur,LONGLONG* pllStop)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetAvailable(IMediaSeeking* iface,LONGLONG* pllFirst,LONGLONG* pllLast)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnSetRate(IMediaSeeking* iface,double dblRate)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetRate(IMediaSeeking* iface,double* pdblRate)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaSeeking_fnGetPreroll(IMediaSeeking* iface,LONGLONG* pllPreroll)
{
CParserOutPinImpl_THIS(iface,mediaseeking);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IMediaSeeking) imediaseeking =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IMediaSeeking_fnQueryInterface,
IMediaSeeking_fnAddRef,
IMediaSeeking_fnRelease,
/* IMediaSeeking fields */
IMediaSeeking_fnGetCapabilities,
IMediaSeeking_fnCheckCapabilities,
IMediaSeeking_fnIsFormatSupported,
IMediaSeeking_fnQueryPreferredFormat,
IMediaSeeking_fnGetTimeFormat,
IMediaSeeking_fnIsUsingTimeFormat,
IMediaSeeking_fnSetTimeFormat,
IMediaSeeking_fnGetDuration,
IMediaSeeking_fnGetStopPosition,
IMediaSeeking_fnGetCurrentPosition,
IMediaSeeking_fnConvertTimeFormat,
IMediaSeeking_fnSetPositions,
IMediaSeeking_fnGetPositions,
IMediaSeeking_fnGetAvailable,
IMediaSeeking_fnSetRate,
IMediaSeeking_fnGetRate,
IMediaSeeking_fnGetPreroll,
};
HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This )
{
TRACE("(%p)\n",This);
ICOM_VTBL(&This->mediaseeking) = &imediaseeking;
return NOERROR;
}
void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This )
{
TRACE("(%p)\n",This);
}
/***************************************************************************
*
* IMediaPosition for CParserOutPinImpl
*
*/
static HRESULT WINAPI
IMediaPosition_fnQueryInterface(IMediaPosition* iface,REFIID riid,void** ppobj)
{
CParserOutPinImpl_THIS(iface,mediaposition);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IMediaPosition_fnAddRef(IMediaPosition* iface)
{
CParserOutPinImpl_THIS(iface,mediaposition);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IMediaPosition_fnRelease(IMediaPosition* iface)
{
CParserOutPinImpl_THIS(iface,mediaposition);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IMediaPosition_fnGetTypeInfoCount(IMediaPosition* iface,UINT* pcTypeInfo)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnGetTypeInfo(IMediaPosition* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnGetIDsOfNames(IMediaPosition* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnInvoke(IMediaPosition* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnget_Duration(IMediaPosition* iface,REFTIME* prefTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnput_CurrentPosition(IMediaPosition* iface,REFTIME refTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnget_CurrentPosition(IMediaPosition* iface,REFTIME* prefTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnget_StopTime(IMediaPosition* iface,REFTIME* prefTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnput_StopTime(IMediaPosition* iface,REFTIME refTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnget_PrerollTime(IMediaPosition* iface,REFTIME* prefTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnput_PrerollTime(IMediaPosition* iface,REFTIME refTime)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnput_Rate(IMediaPosition* iface,double dblRate)
{
CParserOutPinImpl_THIS(iface,mediaposition);
return IMediaSeeking_SetRate(CParserOutPinImpl_IMediaSeeking(This),dblRate);
}
static HRESULT WINAPI
IMediaPosition_fnget_Rate(IMediaPosition* iface,double* pdblRate)
{
CParserOutPinImpl_THIS(iface,mediaposition);
return IMediaSeeking_GetRate(CParserOutPinImpl_IMediaSeeking(This),pdblRate);
}
static HRESULT WINAPI
IMediaPosition_fnCanSeekForward(IMediaPosition* iface,LONG* pCanSeek)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IMediaPosition_fnCanSeekBackward(IMediaPosition* iface,LONG* pCanSeek)
{
CParserOutPinImpl_THIS(iface,mediaposition);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IMediaPosition) imediaposition =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IMediaPosition_fnQueryInterface,
IMediaPosition_fnAddRef,
IMediaPosition_fnRelease,
/* IDispatch fields */
IMediaPosition_fnGetTypeInfoCount,
IMediaPosition_fnGetTypeInfo,
IMediaPosition_fnGetIDsOfNames,
IMediaPosition_fnInvoke,
/* IMediaPosition fields */
IMediaPosition_fnget_Duration,
IMediaPosition_fnput_CurrentPosition,
IMediaPosition_fnget_CurrentPosition,
IMediaPosition_fnget_StopTime,
IMediaPosition_fnput_StopTime,
IMediaPosition_fnget_PrerollTime,
IMediaPosition_fnput_PrerollTime,
IMediaPosition_fnput_Rate,
IMediaPosition_fnget_Rate,
IMediaPosition_fnCanSeekForward,
IMediaPosition_fnCanSeekBackward,
};
HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This )
{
TRACE("(%p)\n",This);
ICOM_VTBL(&This->mediaposition) = &imediaposition;
return NOERROR;
}
void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This )
{
TRACE("(%p)\n",This);
}
......@@ -35,8 +35,9 @@ struct CParserImpl
HANDLE m_hEventInit;
DWORD m_dwThreadId;
HANDLE m_hThread;
const ParserHandlers* m_pHandler;
BOOL m_bSendEOS;
const ParserHandlers* m_pHandler;
void* m_pUserData;
};
......@@ -54,6 +55,8 @@ struct CParserOutPinImpl
QUARTZ_IUnkImpl unk;
CPinBaseImpl pin;
CQualityControlPassThruImpl qcontrol;
struct { ICOM_VFIELD(IMediaSeeking); } mediaseeking;
struct { ICOM_VFIELD(IMediaPosition); } mediaposition;
CParserImpl* pParser;
ULONG nStreamIndex;
......@@ -64,6 +67,7 @@ struct CParserOutPinImpl
/* for parser */
BOOL m_bReqUsed;
IMediaSample* m_pReqSample;
LONGLONG m_llReqStart;
LONG m_lReqLength;
REFERENCE_TIME m_rtReqStart;
......@@ -105,6 +109,9 @@ struct ParserHandlers
#define CParserOutPinImpl_THIS(iface,member) CParserOutPinImpl* This = ((CParserOutPinImpl*)(((char*)iface)-offsetof(CParserOutPinImpl,member)))
#define CParserOutPinImpl_IMediaSeeking(th) ((IMediaSeeking*)&((th)->mediaseeking))
#define CParserOutPinImpl_IMediaPosition(th) ((IMediaPosition*)&((th)->mediaposition))
HRESULT QUARTZ_CreateParser(
IUnknown* punkOuter,void** ppobj,
const CLSID* pclsidParser,
......
......@@ -4,6 +4,7 @@ init QUARTZ_DllMain
import oleaut32.dll
import ole32.dll
import msvfw32.dll
import winmm.dll
import user32.dll
import gdi32.dll
......
......@@ -112,7 +112,10 @@ HRESULT QUARTZ_IMediaSample_SetProperties(
hr = IMediaSample_SetDiscontinuity(pSample,
(prop.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) ? TRUE : FALSE);
if ( SUCCEEDED(hr) )
{
TRACE("length = %ld/%ld\n",prop.lActual,pProp->cbBuffer);
hr = IMediaSample_SetActualDataLength(pSample,prop.lActual);
}
if ( SUCCEEDED(hr) )
{
if ( ( prop.dwSampleFlags & AM_SAMPLE_TIMEVALID) &&
......@@ -142,6 +145,8 @@ HRESULT QUARTZ_IMediaSample_Copy(
hr = QUARTZ_IMediaSample_GetProperties( pSrcSample, &prop );
if ( FAILED(hr) )
return hr;
if ( !bCopyData )
prop.lActual = 0;
hr = QUARTZ_IMediaSample_SetProperties( pDstSample, &prop );
if ( prop.pMediaType != NULL )
QUARTZ_MediaType_Destroy( prop.pMediaType );
......
......@@ -137,22 +137,59 @@ static void QUARTZ_DestroySeekingPassThru(IUnknown* punk)
{
CSeekingPassThru_THIS(punk,unk);
TRACE("(%p)\n",This);
CPassThruImpl_UninitIMediaSeeking( &This->passthru );
CPassThruImpl_UninitIMediaPosition( &This->passthru );
CSeekingPassThru_UninitISeekingPassThru(This);
}
HRESULT QUARTZ_CreateSeekingPassThru(IUnknown* punkOuter,void** ppobj)
{
CSeekingPassThru* This;
HRESULT hr;
CSeekingPassThru* This;
TRACE("(%p,%p)\n",punkOuter,ppobj);
hr = QUARTZ_CreateSeekingPassThruInternal(punkOuter,&This,FALSE,NULL);
if ( hr != S_OK )
return hr;
ppobj = (void*)(&This->unk);
return NOERROR;
}
HRESULT QUARTZ_CreateSeekingPassThruInternal(IUnknown* punkOuter,CSeekingPassThru** ppobj,BOOL bRendering,IPin* pPin)
{
CSeekingPassThru* This;
HRESULT hr;
TRACE("(%p,%p,%d,%p)\n",punkOuter,ppobj,(int)bRendering,pPin);
This = (CSeekingPassThru*)QUARTZ_AllocObj( sizeof(CSeekingPassThru) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, punkOuter );
hr = CSeekingPassThru_InitISeekingPassThru(This);
if ( SUCCEEDED(hr) )
{
hr = CPassThruImpl_InitIMediaPosition( &This->passthru );
if ( SUCCEEDED(hr) )
{
hr = CPassThruImpl_InitIMediaSeeking( &This->passthru );
if ( FAILED(hr) )
{
CPassThruImpl_UninitIMediaPosition( &This->passthru );
}
}
else
{
CSeekingPassThru_UninitISeekingPassThru(This);
}
}
if ( FAILED(hr) )
{
QUARTZ_FreeObj( This );
......@@ -163,7 +200,17 @@ HRESULT QUARTZ_CreateSeekingPassThru(IUnknown* punkOuter,void** ppobj)
This->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroySeekingPassThru;
*ppobj = (void*)(&This->unk);
*ppobj = This;
if ( pPin != NULL )
{
hr = ISeekingPassThru_Init((ISeekingPassThru*)(&This->seekpass),bRendering,pPin);
if ( FAILED(hr) )
{
IUnknown_Release(This->unk.punkControl);
return hr;
}
}
return S_OK;
}
......
......@@ -57,6 +57,7 @@ typedef struct CSeekingPassThru
#define CSeekingPassThru_THIS(iface,member) CSeekingPassThru* This = ((CSeekingPassThru*)(((char*)iface)-offsetof(CSeekingPassThru,member)))
HRESULT QUARTZ_CreateSeekingPassThru(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateSeekingPassThruInternal(IUnknown* punkOuter,CSeekingPassThru** ppobj,BOOL bRendering,IPin* pPin);
#endif /* WINE_DSHOW_SEEKPASS_H */
#include "config.h"
#include "windef.h"
#include "wingdi.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "videoblt.h"
#define QUARTZ_LOBYTE(pix) ((BYTE)((pix)&0xff))
#define QUARTZ_HIBYTE(pix) ((BYTE)((pix)>>8))
void VIDEOBLT_Blt_888_to_332(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed )
{
LONG x,y;
for ( y = 0; y < height; y++ )
{
for ( x = 0; x < width; x++ )
{
*pDst++ = ((pSrc[2]&0xe0) ) |
((pSrc[1]&0xe0)>>3) |
((pSrc[0]&0xc0)>>6);
pSrc += 3;
}
pDst += pitchDst - width;
pSrc += pitchSrc - width*3;
}
}
void VIDEOBLT_Blt_888_to_555(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed )
{
LONG x,y;
unsigned pix;
for ( y = 0; y < height; y++ )
{
for ( x = 0; x < width; x++ )
{
pix = ((unsigned)(pSrc[2]&0xf8)<<7) |
((unsigned)(pSrc[1]&0xf8)<<2) |
((unsigned)(pSrc[0]&0xf8)>>3);
*pDst++ = QUARTZ_LOBYTE(pix);
*pDst++ = QUARTZ_HIBYTE(pix);
pSrc += 3;
}
pDst += pitchDst - width*2;
pSrc += pitchSrc - width*3;
}
}
void VIDEOBLT_Blt_888_to_565(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed )
{
LONG x,y;
unsigned pix;
for ( y = 0; y < height; y++ )
{
for ( x = 0; x < width; x++ )
{
pix = ((unsigned)(pSrc[2]&0xf8)<<8) |
((unsigned)(pSrc[1]&0xfc)<<3) |
((unsigned)(pSrc[0]&0xf8)>>3);
*pDst++ = QUARTZ_LOBYTE(pix);
*pDst++ = QUARTZ_HIBYTE(pix);
pSrc += 3;
}
pDst += pitchDst - width*2;
pSrc += pitchSrc - width*3;
}
}
void VIDEOBLT_Blt_888_to_8888(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed )
{
LONG x,y;
for ( y = 0; y < height; y++ )
{
for ( x = 0; x < width; x++ )
{
*pDst++ = *pSrc++;
*pDst++ = *pSrc++;
*pDst++ = *pSrc++;
*pDst++ = (BYTE)0xff;
}
pDst += pitchDst - width*4;
pSrc += pitchSrc - width*3;
}
}
#ifndef QUARTZ_VIDEOBLT_H
#define QUARTZ_VIDEOBLT_H
typedef void (*pVIDEOBLT_Blt)(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed );
void VIDEOBLT_Blt_888_to_332(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed );
void VIDEOBLT_Blt_888_to_555(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed );
void VIDEOBLT_Blt_888_to_565(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed );
void VIDEOBLT_Blt_888_to_8888(
BYTE* pDst, LONG pitchDst,
const BYTE* pSrc, LONG pitchSrc,
LONG width, LONG height,
const RGBQUAD* prgbSrc, LONG nClrUsed );
#endif /* QUARTZ_VIDEOBLT_H */
......@@ -27,6 +27,7 @@ DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "vidren.h"
#include "seekpass.h"
static const WCHAR QUARTZ_VideoRenderer_Name[] =
......@@ -392,6 +393,13 @@ static HRESULT CVideoRendererPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
This->pRender->m_cbSampleData = 0;
This->pRender->m_bSampleIsValid = FALSE;
if ( This->meminput.pAllocator != NULL )
{
IMemAllocator_Decommit(This->meminput.pAllocator);
IMemAllocator_Release(This->meminput.pAllocator);
This->meminput.pAllocator = NULL;
}
return NOERROR;
}
......@@ -577,6 +585,24 @@ static QUARTZ_IFEntry FilterIFEntries[] =
{ &IID_IVideoWindow, offsetof(CVideoRendererImpl,vidwin)-offsetof(CVideoRendererImpl,unk) },
};
static HRESULT CVideoRendererImpl_OnQueryInterface(
IUnknown* punk, const IID* piid, void** ppobj )
{
CVideoRendererImpl_THIS(punk,unk);
if ( This->pSeekPass == NULL )
return E_NOINTERFACE;
if ( IsEqualGUID( &IID_IMediaPosition, piid ) ||
IsEqualGUID( &IID_IMediaSeeking, piid ) )
{
TRACE( "IMediaSeeking(or IMediaPosition) is queried\n" );
return IUnknown_QueryInterface( (IUnknown*)(&This->pSeekPass->unk), piid, ppobj );
}
return E_NOINTERFACE;
}
static void QUARTZ_DestroyVideoRenderer(IUnknown* punk)
{
CVideoRendererImpl_THIS(punk,unk);
......@@ -590,6 +616,11 @@ static void QUARTZ_DestroyVideoRenderer(IUnknown* punk)
IUnknown_Release(This->pPin->unk.punkControl);
This->pPin = NULL;
}
if ( This->pSeekPass != NULL )
{
IUnknown_Release((IUnknown*)&This->pSeekPass->unk);
This->pSeekPass = NULL;
}
CVideoRendererImpl_UninitIBasicVideo2(This);
CVideoRendererImpl_UninitIVideoWindow(This);
......@@ -609,6 +640,7 @@ HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj)
QUARTZ_AllocObj( sizeof(CVideoRendererImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
This->pSeekPass = NULL;
This->pPin = NULL;
This->m_fInFlush = FALSE;
......@@ -620,6 +652,9 @@ HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj)
This->m_cbSampleData = 0;
QUARTZ_IUnkInit( &This->unk, punkOuter );
This->qiext.pNext = NULL;
This->qiext.pOnQueryInterface = &CVideoRendererImpl_OnQueryInterface;
QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
hr = CBaseFilterImpl_InitIBaseFilter(
&This->basefilter,
......@@ -654,6 +689,8 @@ HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj)
This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
This->unk.pOnFinalRelease = QUARTZ_DestroyVideoRenderer;
InitializeCriticalSection( &This->m_csSample );
hr = QUARTZ_CreateVideoRendererPin(
This,
&This->basefilter.csFilter,
......@@ -663,14 +700,17 @@ HRESULT QUARTZ_CreateVideoRenderer(IUnknown* punkOuter,void** ppobj)
This->basefilter.pInPins,
(IUnknown*)&This->pPin->pin,
NULL, 0 );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CreateSeekingPassThruInternal(
(IUnknown*)&(This->unk), &This->pSeekPass,
TRUE, (IPin*)&(This->pPin->pin) );
if ( FAILED(hr) )
{
IUnknown_Release( This->unk.punkControl );
return hr;
}
InitializeCriticalSection( &This->m_csSample );
*ppobj = (void*)&(This->unk);
return S_OK;
......
......@@ -9,6 +9,7 @@
#include "iunk.h"
#include "basefilt.h"
#include "seekpass.h"
typedef struct CVideoRendererImpl CVideoRendererImpl;
typedef struct CVideoRendererPinImpl CVideoRendererPinImpl;
......@@ -30,7 +31,9 @@ struct CVideoRendererImpl
CBaseFilterImpl basefilter;
VidRen_IBasicVideo basvid;
VidRen_IVideoWindow vidwin;
QUARTZ_IFDelegation qiext;
CSeekingPassThru* pSeekPass;
CVideoRendererPinImpl* pPin;
BOOL m_fInFlush;
......
......@@ -14,6 +14,7 @@
#include "mmreg.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"
......
/*
* Implements IBaseFilter for transform filters. (internal)
*
* hidenori@a2.ctktv.ne.jp
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "xform.h"
#include "sample.h"
static const WCHAR XFORM_DefInName[] =
{'X','F','o','r','m',' ','I','n',0};
static const WCHAR XFORM_DefOutName[] =
{'X','F','o','r','m',' ','O','u','t',0};
/***************************************************************************
*
* CTransformBaseImpl methods
*
*/
static HRESULT CTransformBaseImpl_OnActive( CBaseFilterImpl* pImpl )
{
CTransformBaseImpl_THIS(pImpl,basefilter);
TRACE( "(%p)\n", This );
return NOERROR;
}
static HRESULT CTransformBaseImpl_OnInactive( CBaseFilterImpl* pImpl )
{
CTransformBaseImpl_THIS(pImpl,basefilter);
HRESULT hr;
IMemAllocator* pAllocator;
TRACE( "(%p)\n", This );
if ( This->pInPin->pin.pPinConnectedTo == NULL ||
This->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
EnterCriticalSection( &This->csFilter );
pAllocator = This->m_pOutPinAllocator;
if ( pAllocator != NULL &&
This->pInPin->meminput.pAllocator != pAllocator )
{
hr = IMemAllocator_Commit( pAllocator );
if ( FAILED(hr) )
goto end;
}
if ( !This->m_bFiltering )
{
hr = This->m_pHandler->pBeginTransform( This, This->pInPin->pin.pmtConn, This->pOutPin->pin.pmtConn, This->m_bReuseSample );
if ( FAILED(hr) )
goto end;
This->m_bFiltering = TRUE;
}
hr = NOERROR;
end:
LeaveCriticalSection( &This->csFilter );
return hr;
}
static HRESULT CTransformBaseImpl_OnStop( CBaseFilterImpl* pImpl )
{
CTransformBaseImpl_THIS(pImpl,basefilter);
IMemAllocator* pAllocator;
TRACE( "(%p)\n", This );
EnterCriticalSection( &This->csFilter );
if ( This->m_bFiltering )
{
This->m_pHandler->pEndTransform( This );
This->m_bFiltering = FALSE;
}
if ( This->m_pSample != NULL )
{
IMediaSample_Release( This->m_pSample );
This->m_pSample = NULL;
}
pAllocator = This->m_pOutPinAllocator;
if ( pAllocator != NULL &&
This->pInPin->meminput.pAllocator != pAllocator )
{
IMemAllocator_Decommit( pAllocator );
}
LeaveCriticalSection( &This->csFilter );
return NOERROR;
}
static const CBaseFilterHandlers filterhandlers =
{
CTransformBaseImpl_OnActive, /* pOnActive */
CTransformBaseImpl_OnInactive, /* pOnInactive */
CTransformBaseImpl_OnStop, /* pOnStop */
};
/***************************************************************************
*
* CTransformBaseInPinImpl methods
*
*/
static HRESULT CTransformBaseInPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
HRESULT hr;
TRACE( "(%p,%p)\n", This, pPin );
EnterCriticalSection( &This->pFilter->csFilter );
hr = This->pFilter->m_pHandler->pGetOutputTypes( This->pFilter, This->pFilter->pInPin->pin.pmtConn, &This->pFilter->pOutPin->pin.pmtAcceptTypes, &This->pFilter->pOutPin->pin.cAcceptTypes );
if ( FAILED(hr) )
goto end;
hr = NOERROR;
end:
LeaveCriticalSection( &This->pFilter->csFilter );
return hr;
}
static HRESULT CTransformBaseInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
if ( This->meminput.pAllocator != NULL )
{
IMemAllocator_Decommit(This->meminput.pAllocator);
IMemAllocator_Release(This->meminput.pAllocator);
This->meminput.pAllocator = NULL;
}
return NOERROR;
}
static HRESULT CTransformBaseInPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
HRESULT hr;
TRACE( "(%p,%p)\n", This, pmt );
EnterCriticalSection( &This->pFilter->csFilter );
hr = This->pFilter->m_pHandler->pCheckMediaType( This->pFilter, pmt, (This->pFilter->pOutPin->pin.pPinConnectedTo != NULL) ? This->pFilter->pOutPin->pin.pmtConn : NULL );
LeaveCriticalSection( &This->pFilter->csFilter );
return hr;
}
static HRESULT CTransformBaseInPinImpl_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
HRESULT hr;
TRACE( "(%p,%p)\n", This, pSample );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
if ( !This->pFilter->m_bFiltering )
return E_UNEXPECTED;
if ( This->pFilter->m_bInFlush )
return S_FALSE;
if ( This->meminput.pAllocator != This->pFilter->m_pOutPinAllocator )
{
if ( This->pFilter->m_pSample == NULL )
{
hr = IMemAllocator_GetBuffer( This->pFilter->m_pOutPinAllocator, &This->pFilter->m_pSample, NULL, NULL, 0 );
if ( FAILED(hr) )
goto end;
}
hr = QUARTZ_IMediaSample_Copy(
This->pFilter->m_pSample, pSample, This->pFilter->m_bPreCopy );
if ( FAILED(hr) )
goto end;
}
if ( This->pFilter->m_bPreCopy )
hr = This->pFilter->m_pHandler->pTransform( This->pFilter, This->pFilter->m_pSample, NULL );
else
hr = This->pFilter->m_pHandler->pTransform( This->pFilter, pSample, This->pFilter->m_pSample );
if ( FAILED(hr) )
goto end;
if ( hr == NOERROR )
{
hr = CPinBaseImpl_SendSample(&This->pFilter->pOutPin->pin,This->pFilter->m_pSample);
if ( FAILED(hr) )
goto end;
}
hr = NOERROR;
end:
if ( !This->pFilter->m_bReuseSample )
{
if ( This->pFilter->m_pSample != NULL )
{
IMediaSample_Release( This->pFilter->m_pSample );
This->pFilter->m_pSample = NULL;
}
}
if ( FAILED(hr) )
{
/* Notify(ABORT) */
}
return hr;
}
static HRESULT CTransformBaseInPinImpl_ReceiveCanBlock( CPinBaseImpl* pImpl )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return S_FALSE;
return CPinBaseImpl_SendReceiveCanBlock( &This->pFilter->pOutPin->pin );
}
static HRESULT CTransformBaseInPinImpl_EndOfStream( CPinBaseImpl* pImpl )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
return CPinBaseImpl_SendEndOfStream( &This->pFilter->pOutPin->pin );
}
static HRESULT CTransformBaseInPinImpl_BeginFlush( CPinBaseImpl* pImpl )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
This->pFilter->m_bInFlush = TRUE;
return CPinBaseImpl_SendBeginFlush( &This->pFilter->pOutPin->pin );
}
static HRESULT CTransformBaseInPinImpl_EndFlush( CPinBaseImpl* pImpl )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
TRACE( "(%p)\n", This );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
This->pFilter->m_bInFlush = FALSE;
return CPinBaseImpl_SendEndFlush( &This->pFilter->pOutPin->pin );
}
static HRESULT CTransformBaseInPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
{
CTransformBaseInPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
if ( This->pin.pPinConnectedTo == NULL ||
This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
return NOERROR;
return CPinBaseImpl_SendNewSegment( &This->pFilter->pOutPin->pin,
rtStart, rtStop, rate );
}
static const CBasePinHandlers inputpinhandlers =
{
NULL, /* pOnPreConnect */
CTransformBaseInPinImpl_OnPostConnect, /* pOnPostConnect */
CTransformBaseInPinImpl_OnDisconnect, /* pOnDisconnect */
CTransformBaseInPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
CTransformBaseInPinImpl_Receive, /* pReceive */
CTransformBaseInPinImpl_ReceiveCanBlock, /* pReceiveCanBlock */
CTransformBaseInPinImpl_EndOfStream, /* pEndOfStream */
CTransformBaseInPinImpl_BeginFlush, /* pBeginFlush */
CTransformBaseInPinImpl_EndFlush, /* pEndFlush */
CTransformBaseInPinImpl_NewSegment, /* pNewSegment */
};
/***************************************************************************
*
* CTransformBaseOutPinImpl methods
*
*/
static HRESULT CTransformBaseOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
{
CTransformBaseOutPinImpl_THIS(pImpl,pin);
HRESULT hr;
ALLOCATOR_PROPERTIES propReqThis;
ALLOCATOR_PROPERTIES propReqPeer;
ALLOCATOR_PROPERTIES propActual;
BOOL bTransInPlace = FALSE;
BOOL bTryToReUseSample = FALSE;
BOOL bOutReadonly = FALSE;
IMemAllocator* pAllocator;
FIXME( "(%p,%p)\n", This, pPin );
if ( This->pFilter->pInPin->pin.pPinConnectedTo == NULL )
return E_FAIL;
if ( This->pin.pMemInputPinConnectedTo == NULL )
return E_UNEXPECTED;
ZeroMemory( &propReqThis, sizeof(ALLOCATOR_PROPERTIES) );
ZeroMemory( &propReqPeer, sizeof(ALLOCATOR_PROPERTIES) );
ZeroMemory( &propActual, sizeof(ALLOCATOR_PROPERTIES) );
hr = This->pFilter->m_pHandler->pGetAllocProp( This->pFilter, This->pFilter->pInPin->pin.pmtConn, This->pin.pmtConn, &propReqThis, &bTransInPlace, &bTryToReUseSample );
if ( FAILED(hr) )
goto end;
if ( propReqThis.cbAlign == 0 )
propReqThis.cbAlign = 1;
if ( bTransInPlace )
{
ZeroMemory( &propReqPeer, sizeof(ALLOCATOR_PROPERTIES) );
hr = IMemInputPin_GetAllocatorRequirements(
This->pin.pMemInputPinConnectedTo, &propReqPeer );
if ( propReqPeer.cbAlign != 0 && propReqPeer.cbAlign != 1 )
bTransInPlace = FALSE;
if ( propReqPeer.cbPrefix != 0 )
bTransInPlace = FALSE;
bOutReadonly = FALSE;
if ( bTransInPlace && This->pFilter->pInPin->meminput.bReadonly )
bOutReadonly = TRUE;
pAllocator = This->pFilter->pInPin->meminput.pAllocator;
hr = IMemInputPin_NotifyAllocator(
This->pin.pMemInputPinConnectedTo,
pAllocator, bOutReadonly );
if ( hr == NOERROR )
{
This->pFilter->m_pOutPinAllocator = pAllocator;
IMemAllocator_AddRef(pAllocator);
bTryToReUseSample = FALSE;
goto end;
}
}
hr = IMemInputPin_GetAllocator(
This->pin.pMemInputPinConnectedTo, &pAllocator );
if ( FAILED(hr) )
goto end;
hr = IMemAllocator_SetProperties( pAllocator, &propReqThis, &propActual );
if ( SUCCEEDED(hr) )
{
TRACE("cBuffers = %ld / cbBuffer = %ld\n",propActual.cBuffers,propActual.cbBuffer);
hr = IMemInputPin_NotifyAllocator(
This->pin.pMemInputPinConnectedTo, pAllocator,
bTryToReUseSample );
}
if ( FAILED(hr) )
{
IMemAllocator_Release(pAllocator);
goto end;
}
This->pFilter->m_pOutPinAllocator = pAllocator;
hr = NOERROR;
end:
This->pFilter->m_bPreCopy = FALSE;
This->pFilter->m_bReuseSample = FALSE;
if ( hr == NOERROR )
{
This->pFilter->m_bPreCopy = bTransInPlace && (This->pFilter->pInPin->meminput.pAllocator != This->pFilter->m_pOutPinAllocator);
This->pFilter->m_bReuseSample = bTryToReUseSample;
}
return hr;
}
static HRESULT CTransformBaseOutPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
{
CTransformBaseOutPinImpl_THIS(pImpl,pin);
FIXME( "(%p)\n", This );
if ( This->pFilter->m_pOutPinAllocator != NULL )
{
IMemAllocator_Decommit(This->pFilter->m_pOutPinAllocator);
IMemAllocator_Release(This->pFilter->m_pOutPinAllocator);
This->pFilter->m_pOutPinAllocator = NULL;
}
return NOERROR;
}
static HRESULT CTransformBaseOutPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
{
CTransformBaseOutPinImpl_THIS(pImpl,pin);
HRESULT hr;
TRACE( "(%p,%p)\n", This, pmt );
if ( This->pFilter->pInPin->pin.pPinConnectedTo == NULL )
return E_FAIL;
EnterCriticalSection( &This->pFilter->csFilter );
hr = This->pFilter->m_pHandler->pCheckMediaType( This->pFilter, This->pFilter->pInPin->pin.pmtConn, pmt );
LeaveCriticalSection( &This->pFilter->csFilter );
return hr;
}
static const CBasePinHandlers outputpinhandlers =
{
NULL, /* pOnPreConnect */
CTransformBaseOutPinImpl_OnPostConnect, /* pOnPostConnect */
CTransformBaseOutPinImpl_OnDisconnect, /* pOnDisconnect */
CTransformBaseOutPinImpl_CheckMediaType, /* pCheckMediaType */
NULL, /* pQualityNotify */
OutputPinSync_Receive, /* pReceive */
OutputPinSync_ReceiveCanBlock, /* pReceiveCanBlock */
OutputPinSync_EndOfStream, /* pEndOfStream */
OutputPinSync_BeginFlush, /* pBeginFlush */
OutputPinSync_EndFlush, /* pEndFlush */
OutputPinSync_NewSegment, /* pNewSegment */
};
/***************************************************************************
*
* new/delete CTransformBaseImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry FilterIFEntries[] =
{
{ &IID_IPersist, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
{ &IID_IMediaFilter, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
{ &IID_IBaseFilter, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
};
static void QUARTZ_DestroyTransformBase(IUnknown* punk)
{
CTransformBaseImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
This->m_pHandler->pCleanup(This);
if ( This->pInPin != NULL )
{
IUnknown_Release(This->pInPin->unk.punkControl);
This->pInPin = NULL;
}
if ( This->pOutPin != NULL )
{
IUnknown_Release(This->pOutPin->unk.punkControl);
This->pOutPin = NULL;
}
if ( This->pSeekPass != NULL )
{
IUnknown_Release((IUnknown*)&This->pSeekPass->unk);
This->pSeekPass = NULL;
}
CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
DeleteCriticalSection( &This->csFilter );
}
HRESULT QUARTZ_CreateTransformBase(
IUnknown* punkOuter,void** ppobj,
const CLSID* pclsidTransformBase,
LPCWSTR pwszTransformBaseName,
LPCWSTR pwszInPinName,
LPCWSTR pwszOutPinName,
const TransformBaseHandlers* pHandler )
{
CTransformBaseImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p)\n",punkOuter,ppobj);
if ( pwszInPinName == NULL )
pwszInPinName = XFORM_DefInName;
if ( pwszOutPinName == NULL )
pwszOutPinName = XFORM_DefOutName;
This = (CTransformBaseImpl*)
QUARTZ_AllocObj( sizeof(CTransformBaseImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
This->pInPin = NULL;
This->pOutPin = NULL;
This->pSeekPass = NULL;
This->m_pOutPinAllocator = NULL;
This->m_bPreCopy = FALSE; /* sample must be copied */
This->m_bReuseSample = FALSE; /* sample must be reused */
This->m_bInFlush = FALSE;
This->m_pSample = NULL;
This->m_bFiltering = FALSE;
This->m_pHandler = pHandler;
This->m_pUserData = NULL;
QUARTZ_IUnkInit( &This->unk, punkOuter );
hr = CBaseFilterImpl_InitIBaseFilter(
&This->basefilter,
This->unk.punkControl,
pclsidTransformBase,
pwszTransformBaseName,
&filterhandlers );
if ( SUCCEEDED(hr) )
{
/* construct this class. */
hr = This->m_pHandler->pInit( 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_DestroyTransformBase;
InitializeCriticalSection( &This->csFilter );
/* create pins. */
hr = QUARTZ_CreateTransformBaseInPin(
This, &This->csFilter,
&This->pInPin, pwszInPinName );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
This->basefilter.pInPins,
(IUnknown*)&(This->pInPin->pin),
NULL, 0 );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CreateTransformBaseOutPin(
This, &This->csFilter,
&This->pOutPin, pwszOutPinName );
if ( SUCCEEDED(hr) )
hr = QUARTZ_CompList_AddComp(
This->basefilter.pOutPins,
(IUnknown*)&(This->pOutPin->pin),
NULL, 0 );
if ( SUCCEEDED(hr) )
{
hr = QUARTZ_CreateSeekingPassThruInternal(
(IUnknown*)&(This->pOutPin->unk), &This->pSeekPass,
FALSE, (IPin*)&(This->pInPin->pin) );
}
if ( FAILED(hr) )
{
IUnknown_Release( This->unk.punkControl );
return hr;
}
*ppobj = (void*)&(This->unk);
return S_OK;
}
/***************************************************************************
*
* new/delete CTransformBaseInPinImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry InPinIFEntries[] =
{
{ &IID_IPin, offsetof(CTransformBaseInPinImpl,pin)-offsetof(CTransformBaseInPinImpl,unk) },
{ &IID_IMemInputPin, offsetof(CTransformBaseInPinImpl,meminput)-offsetof(CTransformBaseInPinImpl,unk) },
};
static void QUARTZ_DestroyTransformBaseInPin(IUnknown* punk)
{
CTransformBaseInPinImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
CPinBaseImpl_UninitIPin( &This->pin );
CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
}
HRESULT QUARTZ_CreateTransformBaseInPin(
CTransformBaseImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CTransformBaseInPinImpl** ppPin,
LPCWSTR pwszPinName )
{
CTransformBaseInPinImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
This = (CTransformBaseInPinImpl*)
QUARTZ_AllocObj( sizeof(CTransformBaseInPinImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, NULL );
This->pFilter = 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_DestroyTransformBaseInPin;
*ppPin = This;
TRACE("returned successfully.\n");
return S_OK;
}
/***************************************************************************
*
* new/delete CTransformBaseOutPinImpl
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry OutPinIFEntries[] =
{
{ &IID_IPin, offsetof(CTransformBaseOutPinImpl,pin)-offsetof(CTransformBaseOutPinImpl,unk) },
{ &IID_IQualityControl, offsetof(CTransformBaseOutPinImpl,qcontrol)-offsetof(CTransformBaseOutPinImpl,unk) },
};
static HRESULT CTransformBaseOutPinImpl_OnQueryInterface(
IUnknown* punk, const IID* piid, void** ppobj )
{
CTransformBaseOutPinImpl_THIS(punk,unk);
if ( This->pFilter == NULL || This->pFilter->pSeekPass == NULL )
return E_NOINTERFACE;
if ( IsEqualGUID( &IID_IMediaPosition, piid ) ||
IsEqualGUID( &IID_IMediaSeeking, piid ) )
{
TRACE( "IMediaSeeking(or IMediaPosition) is queried\n" );
return IUnknown_QueryInterface( (IUnknown*)(&This->pFilter->pSeekPass->unk), piid, ppobj );
}
return E_NOINTERFACE;
}
static void QUARTZ_DestroyTransformBaseOutPin(IUnknown* punk)
{
CTransformBaseOutPinImpl_THIS(punk,unk);
TRACE( "(%p)\n", This );
CPinBaseImpl_UninitIPin( &This->pin );
CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
}
HRESULT QUARTZ_CreateTransformBaseOutPin(
CTransformBaseImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CTransformBaseOutPinImpl** ppPin,
LPCWSTR pwszPinName )
{
CTransformBaseOutPinImpl* This = NULL;
HRESULT hr;
TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
This = (CTransformBaseOutPinImpl*)
QUARTZ_AllocObj( sizeof(CTransformBaseOutPinImpl) );
if ( This == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &This->unk, NULL );
This->qiext.pNext = NULL;
This->qiext.pOnQueryInterface = &CTransformBaseOutPinImpl_OnQueryInterface;
QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
This->pFilter = pFilter;
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_DestroyTransformBaseOutPin;
*ppPin = This;
TRACE("returned successfully.\n");
return S_OK;
}
/*
* Implements IBaseFilter for transform filters. (internal)
*
* hidenori@a2.ctktv.ne.jp
*/
#ifndef WINE_DSHOW_XFORM_H
#define WINE_DSHOW_XFORM_H
#include "iunk.h"
#include "basefilt.h"
#include "seekpass.h"
typedef struct CTransformBaseImpl CTransformBaseImpl;
typedef struct CTransformBaseInPinImpl CTransformBaseInPinImpl;
typedef struct CTransformBaseOutPinImpl CTransformBaseOutPinImpl;
typedef struct TransformBaseHandlers TransformBaseHandlers;
struct CTransformBaseImpl
{
QUARTZ_IUnkImpl unk;
CBaseFilterImpl basefilter;
CTransformBaseInPinImpl* pInPin;
CTransformBaseOutPinImpl* pOutPin;
CSeekingPassThru* pSeekPass;
CRITICAL_SECTION csFilter;
IMemAllocator* m_pOutPinAllocator;
BOOL m_bPreCopy; /* sample must be copied */
BOOL m_bReuseSample; /* sample must be reused */
BOOL m_bInFlush;
IMediaSample* m_pSample;
BOOL m_bFiltering;
const TransformBaseHandlers* m_pHandler;
void* m_pUserData;
};
struct CTransformBaseInPinImpl
{
QUARTZ_IUnkImpl unk;
CPinBaseImpl pin;
CMemInputPinBaseImpl meminput;
CTransformBaseImpl* pFilter;
};
struct CTransformBaseOutPinImpl
{
QUARTZ_IUnkImpl unk;
CPinBaseImpl pin;
CQualityControlPassThruImpl qcontrol;
QUARTZ_IFDelegation qiext;
CTransformBaseImpl* pFilter;
};
struct TransformBaseHandlers
{
/* all methods must be implemented */
HRESULT (*pInit)( CTransformBaseImpl* pImpl );
HRESULT (*pCleanup)( CTransformBaseImpl* pImpl );
/* pmtOut may be NULL */
HRESULT (*pCheckMediaType)( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut );
/* get output types */
HRESULT (*pGetOutputTypes)( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes );
/* get allocator properties */
HRESULT (*pGetAllocProp)( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample );
/* prepare the filter */
HRESULT (*pBeginTransform)( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample );
/* process a sample */
HRESULT (*pTransform)( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut );
/* unprepare the filter */
HRESULT (*pEndTransform)( CTransformBaseImpl* pImpl );
};
#define CTransformBaseImpl_THIS(iface,member) CTransformBaseImpl* This = ((CTransformBaseImpl*)(((char*)iface)-offsetof(CTransformBaseImpl,member)))
#define CTransformBaseInPinImpl_THIS(iface,member) CTransformBaseInPinImpl* This = ((CTransformBaseInPinImpl*)(((char*)iface)-offsetof(CTransformBaseInPinImpl,member)))
#define CTransformBaseOutPinImpl_THIS(iface,member) CTransformBaseOutPinImpl* This = ((CTransformBaseOutPinImpl*)(((char*)iface)-offsetof(CTransformBaseOutPinImpl,member)))
HRESULT QUARTZ_CreateTransformBase(
IUnknown* punkOuter,void** ppobj,
const CLSID* pclsidTransformBase,
LPCWSTR pwszTransformBaseName,
LPCWSTR pwszInPinName,
LPCWSTR pwszOutPinName,
const TransformBaseHandlers* pHandler );
HRESULT QUARTZ_CreateTransformBaseInPin(
CTransformBaseImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CTransformBaseInPinImpl** ppPin,
LPCWSTR pwszPinName );
HRESULT QUARTZ_CreateTransformBaseOutPin(
CTransformBaseImpl* pFilter,
CRITICAL_SECTION* pcsPin,
CTransformBaseOutPinImpl** ppPin,
LPCWSTR pwszPinName );
HRESULT QUARTZ_CreateAVIDec(IUnknown* punkOuter,void** ppobj);
HRESULT QUARTZ_CreateColour(IUnknown* punkOuter,void** ppobj);
#endif /* WINE_DSHOW_XFORM_H */
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