Improved AVIDec.

Added 2 new callback functions to the transform template and moved all
of them into a funcs table.
This commit is contained in:
Christian Costa 2005-02-21 20:37:45 +00:00 committed by Alexandre Julliard
parent d5e2b7c843
commit 56c701df3f
4 changed files with 109 additions and 42 deletions

View File

@ -59,7 +59,7 @@ typedef struct ACMWrapperImpl
BOOL reinit_codec; /* FIXME: Should use sync points instead */
} ACMWrapperImpl;
static DWORD ACMWrapper_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
{
ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
AM_MEDIA_TYPE amt;
@ -230,6 +230,14 @@ static HRESULT ACMWrapper_Cleanup(TransformFilterImpl* pTransformFilter)
return S_OK;
}
TransformFuncsTable ACMWrapper_FuncsTable = {
NULL,
ACMWrapper_ProcessSampleData,
NULL,
ACMWrapper_ConnectInput,
ACMWrapper_Cleanup
};
HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
HRESULT hr;
@ -248,7 +256,7 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
This->has = 0;
This->reinit_codec = TRUE;
hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, ACMWrapper_SendSampleData, ACMWrapper_ConnectInput, ACMWrapper_Cleanup);
hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable);
if (FAILED(hr))
return hr;

View File

@ -46,6 +46,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter);
typedef struct AVIDecImpl
{
TransformFilterImpl tf;
@ -54,7 +56,23 @@ typedef struct AVIDecImpl
BITMAPINFOHEADER* pBihOut;
} AVIDecImpl;
static DWORD AVIDec_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter)
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
DWORD result;
TRACE("(%p)->()\n", This);
result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut);
if (result != ICERR_OK)
{
ERR("Cannot start processing (%ld)\n", result);
return E_FAIL;
}
return S_OK;
}
static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
VIDEOINFOHEADER* format;
@ -115,25 +133,45 @@ error:
return hr;
}
static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter)
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
DWORD result;
TRACE("(%p)->()\n", This);
result = ICDecompressEnd(This->hvid);
if (result != ICERR_OK)
{
ERR("Cannot stop processing (%ld)\n", result);
return E_FAIL;
}
return S_OK;
}
static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt)
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
HRESULT hr = S_FALSE;
TRACE("(%p)->(%p)\n", This, pmt);
AVIDec_Cleanup(pTransformFilter);
if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
(!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */
(IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)))
{
HIC drv;
VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat;
drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
if (drv)
This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
if (This->hvid)
{
AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent;
const CLSID* outsubtype;
DWORD bih_size;
DWORD output_depth = format->bmiHeader.biBitCount;
DWORD result;
switch(format->bmiHeader.biBitCount)
{
@ -142,41 +180,46 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const
case 16: outsubtype = &MEDIASUBTYPE_RGB565; break;
case 8: outsubtype = &MEDIASUBTYPE_RGB8; break;
default:
FIXME("Depth %d not supported\n", format->bmiHeader.biBitCount);
ICClose(drv);
return S_FALSE;
TRACE("Non standard input depth %d, forced ouptut depth to 32\n", format->bmiHeader.biBitCount);
outsubtype = &MEDIASUBTYPE_RGB32;
output_depth = 32;
break;
}
CopyMediaType(outpmt, pmt);
outpmt->subtype = *outsubtype;
This->hvid = drv;
/* Copy bitmap header from media type to 1 for input and 1 for output */
if (This->pBihIn) {
CoTaskMemFree(This->pBihIn);
CoTaskMemFree(This->pBihOut);
}
bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4;
This->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
if (!This->pBihIn)
{
ICClose(drv);
return E_OUTOFMEMORY;
hr = E_OUTOFMEMORY;
goto failed;
}
This->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
if (!This->pBihOut)
{
CoTaskMemFree(This->pBihIn);
This->pBihIn = NULL;
ICClose(drv);
return E_OUTOFMEMORY;
hr = E_OUTOFMEMORY;
goto failed;
}
memcpy(This->pBihIn, &format->bmiHeader, bih_size);
memcpy(This->pBihOut, &format->bmiHeader, bih_size);
/* Update output format as non compressed bitmap */
This->pBihOut->biCompression = 0;
This->pBihOut->biBitCount = output_depth;
This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8;
result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut);
if (result != ICERR_OK)
{
TRACE("Unable to found a suitable output format (%ld)\n", result);
goto failed;
}
/* Update output media type */
CopyMediaType(outpmt, pmt);
outpmt->subtype = *outsubtype;
memcpy(&(((VIDEOINFOHEADER*)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize);
/* Update buffer size of media samples in output */
((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage;
@ -186,8 +229,11 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const
TRACE("Unable to find a suitable VFW decompressor\n");
}
failed:
AVIDec_Cleanup(pTransformFilter);
TRACE("Connection refused\n");
return S_FALSE;
return hr;
}
static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter)
@ -198,18 +244,26 @@ static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter)
if (This->hvid)
ICClose(This->hvid);
if (This->pBihIn) {
if (This->pBihIn)
CoTaskMemFree(This->pBihIn);
if (This->pBihOut)
CoTaskMemFree(This->pBihOut);
}
This->hvid = NULL;
This->pBihIn = NULL;
This->pBihOut = NULL;
return S_OK;
}
TransformFuncsTable AVIDec_FuncsTable = {
AVIDec_ProcessBegin,
AVIDec_ProcessSampleData,
AVIDec_ProcessEnd,
AVIDec_ConnectInput,
AVIDec_Cleanup
};
HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
HRESULT hr;
@ -227,8 +281,9 @@ HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
This->hvid = NULL;
This->pBihIn = NULL;
This->pBihOut = NULL;
hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, AVIDec_SendSampleData, AVIDec_ConnectInput, AVIDec_Cleanup);
hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, &AVIDec_FuncsTable);
if (FAILED(hr))
return hr;

View File

@ -92,7 +92,7 @@ static HRESULT TransformFilter_Sample(LPVOID iface, IMediaSample * pSample)
}
#endif
This->pfnProcessSample(This, pbSrcStream, cbSrcStream);
This->pFuncsTable->pfnProcessSampleData(This, pbSrcStream, cbSrcStream);
return S_OK;
}
@ -103,7 +103,7 @@ static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TY
TRACE("%p\n", iface);
dump_AM_MEDIA_TYPE(pmt);
return This->pfnConnectInput(This, pmt);
return This->pFuncsTable->pfnConnectInput(This, pmt);
}
@ -173,7 +173,7 @@ HRESULT TransformFilter_OutputPin_Construct(const PIN_INFO * pPinInfo, ALLOCATOR
return E_FAIL;
}
HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, PFN_PROCESS_SAMPLE pps, PFN_CONNECT_INPUT pci, PFN_CLEANUP pcu)
HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, TransformFuncsTable* pFuncsTable)
{
HRESULT hr;
PIN_INFO piInput;
@ -181,9 +181,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI
/* pTransformFilter is already allocated */
pTransformFilter->clsid = *pClsid;
pTransformFilter->pfnProcessSample = pps;
pTransformFilter->pfnConnectInput = pci;
pTransformFilter->pfnCleanup = pcu;
pTransformFilter->pFuncsTable = pFuncsTable;
pTransformFilter->lpVtbl = &TransformFilter_Vtbl;
@ -285,7 +283,7 @@ static ULONG WINAPI TransformFilter_Release(IBaseFilter * iface)
HeapFree(GetProcessHeap(), 0, This->ppPins);
This->lpVtbl = NULL;
This->pfnCleanup(This);
This->pFuncsTable->pfnCleanup(This);
TRACE("Destroying transform filter\n");
CoTaskMemFree(This);
@ -320,6 +318,8 @@ static HRESULT WINAPI TransformFilter_Stop(IBaseFilter * iface)
EnterCriticalSection(&This->csFilter);
{
This->state = State_Stopped;
if (This->pFuncsTable->pfnProcessEnd)
This->pFuncsTable->pfnProcessEnd(This);
}
LeaveCriticalSection(&This->csFilter);
@ -353,6 +353,8 @@ static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tS
This->rtStreamStart = tStart;
This->state = State_Running;
OutputPin_CommitAllocator((OutputPin *)This->ppPins[1]);
if (This->pFuncsTable->pfnProcessBegin)
This->pFuncsTable->pfnProcessBegin(This);
}
LeaveCriticalSection(&This->csFilter);
@ -540,7 +542,7 @@ HRESULT WINAPI TransformFilter_Output_Disconnect(IPin * iface)
if (hr == S_OK)
{
pTransformFilter->pfnCleanup(pTransformFilter);
pTransformFilter->pFuncsTable->pfnCleanup(pTransformFilter);
}
return hr;

View File

@ -20,9 +20,13 @@
typedef struct TransformFilterImpl TransformFilterImpl;
typedef DWORD (*PFN_PROCESS_SAMPLE) (TransformFilterImpl* This, LPBYTE data, DWORD size);
typedef HRESULT (*PFN_CONNECT_INPUT) (TransformFilterImpl* This, const AM_MEDIA_TYPE * pmt);
typedef HRESULT (*PFN_CLEANUP) (TransformFilterImpl* This);
typedef struct TransformFuncsTable {
HRESULT (*pfnProcessBegin) (TransformFilterImpl* This);
HRESULT (*pfnProcessSampleData) (TransformFilterImpl* This, LPBYTE data, DWORD size);
HRESULT (*pfnProcessEnd) (TransformFilterImpl* This);
HRESULT (*pfnConnectInput) (TransformFilterImpl* This, const AM_MEDIA_TYPE * pmt);
HRESULT (*pfnCleanup) (TransformFilterImpl* This);
} TransformFuncsTable;
struct TransformFilterImpl
{
@ -38,9 +42,7 @@ struct TransformFilterImpl
IPin ** ppPins;
PFN_PROCESS_SAMPLE pfnProcessSample;
PFN_CONNECT_INPUT pfnConnectInput;
PFN_CLEANUP pfnCleanup;
TransformFuncsTable * pFuncsTable;
};
HRESULT TransformFilter_Create(TransformFilterImpl*, const CLSID*, PFN_PROCESS_SAMPLE, PFN_CONNECT_INPUT, PFN_CLEANUP);
HRESULT TransformFilter_Create(TransformFilterImpl*, const CLSID*, TransformFuncsTable* pFuncsTable);