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 */ BOOL reinit_codec; /* FIXME: Should use sync points instead */
} ACMWrapperImpl; } 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; ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
AM_MEDIA_TYPE amt; AM_MEDIA_TYPE amt;
@ -230,6 +230,14 @@ static HRESULT ACMWrapper_Cleanup(TransformFilterImpl* pTransformFilter)
return S_OK; return S_OK;
} }
TransformFuncsTable ACMWrapper_FuncsTable = {
NULL,
ACMWrapper_ProcessSampleData,
NULL,
ACMWrapper_ConnectInput,
ACMWrapper_Cleanup
};
HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
{ {
HRESULT hr; HRESULT hr;
@ -248,7 +256,7 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
This->has = 0; This->has = 0;
This->reinit_codec = TRUE; 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)) if (FAILED(hr))
return hr; return hr;

View File

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

View File

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

View File

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