From 56c701df3f21709f9f1fe9cbd5330e1baebc404b Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Mon, 21 Feb 2005 20:37:45 +0000 Subject: [PATCH] Improved AVIDec. Added 2 new callback functions to the transform template and moved all of them into a funcs table. --- dlls/quartz/acmwrapper.c | 12 ++++- dlls/quartz/avidec.c | 105 +++++++++++++++++++++++++++++---------- dlls/quartz/transform.c | 18 ++++--- dlls/quartz/transform.h | 16 +++--- 4 files changed, 109 insertions(+), 42 deletions(-) diff --git a/dlls/quartz/acmwrapper.c b/dlls/quartz/acmwrapper.c index 64ae99735c2..efed8ed09a1 100644 --- a/dlls/quartz/acmwrapper.c +++ b/dlls/quartz/acmwrapper.c @@ -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; diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index b62e1323715..e3f1a85625e 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -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; diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c index 9c6b19a2faf..e05be42e07a 100644 --- a/dlls/quartz/transform.c +++ b/dlls/quartz/transform.c @@ -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; diff --git a/dlls/quartz/transform.h b/dlls/quartz/transform.h index 25cfe4afaef..24b9de1612b 100644 --- a/dlls/quartz/transform.h +++ b/dlls/quartz/transform.h @@ -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);