Fixed some bugs.

Implemented AVI Decompressor.
Started implementing Color Space Converter.
Started implementing seeking.
This commit is contained in:
Hidenori Takeshima 2001-10-22 19:03:26 +00:00 committed by Alexandre Julliard
parent f5a8b965f0
commit 17bee2ef58
31 changed files with 3169 additions and 172 deletions

View File

@ -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)

View File

@ -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@

View File

@ -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);
}
/***************************************************************************

View File

@ -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 */

View File

@ -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 )
@ -327,9 +346,31 @@ 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 );

View File

@ -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;

420
dlls/quartz/avidec.c Normal file
View File

@ -0,0 +1,420 @@
/*
* 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 );
}

View File

@ -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;

View File

@ -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 );

View File

@ -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 );

View File

@ -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 )

437
dlls/quartz/csconv.c Normal file
View File

@ -0,0 +1,437 @@
/*
* 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 );
}

View File

@ -1,8 +1,6 @@
/*
* 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);
}

View File

@ -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 );

View File

@ -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 },
};

View File

@ -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;
}

View File

@ -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;
}
/****************************************************************************/

View File

@ -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 );

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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

View File

@ -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 );

View File

@ -137,15 +137,35 @@ 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)
{
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)\n",punkOuter,ppobj);
TRACE("(%p,%p,%d,%p)\n",punkOuter,ppobj,(int)bRendering,pPin);
This = (CSeekingPassThru*)QUARTZ_AllocObj( sizeof(CSeekingPassThru) );
if ( This == NULL )
@ -153,6 +173,23 @@ HRESULT QUARTZ_CreateSeekingPassThru(IUnknown* punkOuter,void** ppobj)
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;
}

View File

@ -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 */

108
dlls/quartz/videoblt.c Normal file
View File

@ -0,0 +1,108 @@
#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;
}
}

33
dlls/quartz/videoblt.h Normal file
View File

@ -0,0 +1,33 @@
#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 */

View File

@ -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;

View File

@ -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;

View File

@ -14,6 +14,7 @@
#include "mmreg.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"

801
dlls/quartz/xform.c Normal file
View File

@ -0,0 +1,801 @@
/*
* 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;
}

109
dlls/quartz/xform.h Normal file
View File

@ -0,0 +1,109 @@
/*
* 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 */