AVI decompressor:
- Make copies of bitmap header from media type for input and output and update them when needed. - Fixed subtype for 32-bit depth in QueryAccept. AVI splitter: - Fixed handling of rec list.
This commit is contained in:
parent
441becf85b
commit
161a6b4d21
|
@ -68,6 +68,8 @@ typedef struct AVIDecImpl
|
||||||
IPin ** ppPins;
|
IPin ** ppPins;
|
||||||
|
|
||||||
HIC hvid;
|
HIC hvid;
|
||||||
|
BITMAPINFOHEADER* pBihIn;
|
||||||
|
BITMAPINFOHEADER* pBihOut;
|
||||||
int init;
|
int init;
|
||||||
} AVIDecImpl;
|
} AVIDecImpl;
|
||||||
|
|
||||||
|
@ -75,7 +77,6 @@ static DWORD AVIDec_SendSampleData(AVIDecImpl* This, LPBYTE data, DWORD size)
|
||||||
{
|
{
|
||||||
VIDEOINFOHEADER* format;
|
VIDEOINFOHEADER* format;
|
||||||
AM_MEDIA_TYPE amt;
|
AM_MEDIA_TYPE amt;
|
||||||
BITMAPINFOHEADER bi;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD res;
|
DWORD res;
|
||||||
IMediaSample* pSample = NULL;
|
IMediaSample* pSample = NULL;
|
||||||
|
@ -89,14 +90,8 @@ static DWORD AVIDec_SendSampleData(AVIDecImpl* This, LPBYTE data, DWORD size)
|
||||||
}
|
}
|
||||||
format = (VIDEOINFOHEADER*)amt.pbFormat;
|
format = (VIDEOINFOHEADER*)amt.pbFormat;
|
||||||
|
|
||||||
/* Fill a bitmap header for output */
|
/* Update input size to match sample size */
|
||||||
bi.biSize = sizeof(bi);
|
This->pBihIn->biSizeImage = size;
|
||||||
bi.biWidth = format->bmiHeader.biWidth;
|
|
||||||
bi.biHeight = format->bmiHeader.biHeight;
|
|
||||||
bi.biPlanes = 1;
|
|
||||||
bi.biBitCount = format->bmiHeader.biBitCount;
|
|
||||||
bi.biCompression = 0;
|
|
||||||
bi.biSizeImage = bi.biWidth * bi.biHeight * bi.biBitCount / 8;
|
|
||||||
|
|
||||||
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->ppPins[1], &pSample, NULL, NULL, 0);
|
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->ppPins[1], &pSample, NULL, NULL, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -113,13 +108,13 @@ static DWORD AVIDec_SendSampleData(AVIDecImpl* This, LPBYTE data, DWORD size)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
cbDstStream = IMediaSample_GetSize(pSample);
|
cbDstStream = IMediaSample_GetSize(pSample);
|
||||||
if (cbDstStream < bi.biSizeImage) {
|
if (cbDstStream < This->pBihOut->biSizeImage) {
|
||||||
ERR("Sample size is too small %ld < %ld\n", cbDstStream, bi.biSizeImage);
|
ERR("Sample size is too small %ld < %ld\n", cbDstStream, This->pBihOut->biSizeImage);
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = ICDecompress(This->hvid, 0, &format->bmiHeader, data, &bi, pbDstStream);
|
res = ICDecompress(This->hvid, 0, This->pBihIn, data, This->pBihOut, pbDstStream);
|
||||||
if (res != ICERR_OK)
|
if (res != ICERR_OK)
|
||||||
ERR("Error occurred during the decompression (%lx)\n", res);
|
ERR("Error occurred during the decompression (%lx)\n", res);
|
||||||
|
|
||||||
|
@ -193,33 +188,63 @@ static HRESULT AVIDec_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
|
||||||
|
|
||||||
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;
|
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);
|
drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
|
||||||
if (drv)
|
if (drv)
|
||||||
{
|
{
|
||||||
AM_MEDIA_TYPE* outpmt = &((OutputPin*)pAVIDec->ppPins[1])->pin.mtCurrent;
|
AM_MEDIA_TYPE* outpmt = &((OutputPin*)pAVIDec->ppPins[1])->pin.mtCurrent;
|
||||||
const CLSID* outsubtype;
|
const CLSID* outsubtype;
|
||||||
switch(format->bmiHeader.biBitCount)
|
DWORD bih_size;
|
||||||
|
|
||||||
|
switch(format->bmiHeader.biBitCount)
|
||||||
{
|
{
|
||||||
case 32: outsubtype = &MEDIATYPE_Video; break;
|
case 32: outsubtype = &MEDIASUBTYPE_RGB32; break;
|
||||||
case 24: outsubtype = &MEDIASUBTYPE_RGB24; break;
|
case 24: outsubtype = &MEDIASUBTYPE_RGB24; break;
|
||||||
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);
|
FIXME("Depth %d not supported\n", format->bmiHeader.biBitCount);
|
||||||
ICClose(drv);
|
ICClose(drv);
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
CopyMediaType( outpmt, pmt);
|
CopyMediaType( outpmt, pmt);
|
||||||
outpmt->subtype = *outsubtype;
|
outpmt->subtype = *outsubtype;
|
||||||
pAVIDec->hvid = drv;
|
pAVIDec->hvid = drv;
|
||||||
|
|
||||||
|
/* Copy bitmap header from media type to 1 for input and 1 for output */
|
||||||
|
if (pAVIDec->pBihIn) {
|
||||||
|
CoTaskMemFree(pAVIDec->pBihIn);
|
||||||
|
CoTaskMemFree(pAVIDec->pBihOut);
|
||||||
|
}
|
||||||
|
bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4;
|
||||||
|
pAVIDec->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
|
||||||
|
if (!pAVIDec->pBihIn)
|
||||||
|
{
|
||||||
|
ICClose(drv);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
pAVIDec->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
|
||||||
|
if (!pAVIDec->pBihOut)
|
||||||
|
{
|
||||||
|
CoTaskMemFree(pAVIDec->pBihIn);
|
||||||
|
pAVIDec->pBihIn = NULL;
|
||||||
|
ICClose(drv);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
memcpy(pAVIDec->pBihIn, &format->bmiHeader, bih_size);
|
||||||
|
memcpy(pAVIDec->pBihOut, &format->bmiHeader, bih_size);
|
||||||
|
|
||||||
|
/* Update output format as non compressed bitmap */
|
||||||
|
pAVIDec->pBihOut->biCompression = 0;
|
||||||
|
pAVIDec->pBihOut->biSizeImage = pAVIDec->pBihOut->biWidth * pAVIDec->pBihOut->biHeight * pAVIDec->pBihOut->biBitCount / 8;
|
||||||
|
|
||||||
pAVIDec->init = 1;
|
pAVIDec->init = 1;
|
||||||
TRACE("Connection accepted\n");
|
TRACE("Connection accepted\n");
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
TRACE("Unable to find a suitable VFW decompressor\n");
|
TRACE("Unable to find a suitable VFW decompressor\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,6 +341,8 @@ HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
||||||
InitializeCriticalSection(&pAVIDec->csFilter);
|
InitializeCriticalSection(&pAVIDec->csFilter);
|
||||||
pAVIDec->state = State_Stopped;
|
pAVIDec->state = State_Stopped;
|
||||||
pAVIDec->pClock = NULL;
|
pAVIDec->pClock = NULL;
|
||||||
|
pAVIDec->pBihIn = NULL;
|
||||||
|
pAVIDec->pBihOut = NULL;
|
||||||
pAVIDec->init = 0;
|
pAVIDec->init = 0;
|
||||||
ZeroMemory(&pAVIDec->filterInfo, sizeof(FILTER_INFO));
|
ZeroMemory(&pAVIDec->filterInfo, sizeof(FILTER_INFO));
|
||||||
|
|
||||||
|
@ -404,6 +431,11 @@ static ULONG WINAPI AVIDec_Release(IBaseFilter * iface)
|
||||||
if (This->hvid)
|
if (This->hvid)
|
||||||
ICClose(This->hvid);
|
ICClose(This->hvid);
|
||||||
|
|
||||||
|
if (This->pBihIn) {
|
||||||
|
CoTaskMemFree(This->pBihIn);
|
||||||
|
CoTaskMemFree(This->pBihOut);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("Destroying AVI Decompressor\n");
|
TRACE("Destroying AVI Decompressor\n");
|
||||||
CoTaskMemFree(This);
|
CoTaskMemFree(This);
|
||||||
|
|
||||||
|
|
|
@ -563,6 +563,7 @@ static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample)
|
||||||
* This is not clean and the parser should be improved for that but it is enough for most AVI files. */
|
* This is not clean and the parser should be improved for that but it is enough for most AVI files. */
|
||||||
This->CurrentChunkOffset = MEDIATIME_FROM_BYTES(BYTES_FROM_MEDIATIME(This->CurrentChunkOffset) + sizeof(RIFFLIST));
|
This->CurrentChunkOffset = MEDIATIME_FROM_BYTES(BYTES_FROM_MEDIATIME(This->CurrentChunkOffset) + sizeof(RIFFLIST));
|
||||||
This->CurrentChunk = *(RIFFCHUNK*) (pbSrcStream + BYTES_FROM_MEDIATIME(This->CurrentChunkOffset-tStart));
|
This->CurrentChunk = *(RIFFCHUNK*) (pbSrcStream + BYTES_FROM_MEDIATIME(This->CurrentChunkOffset-tStart));
|
||||||
|
offset_src = (long)BYTES_FROM_MEDIATIME(This->CurrentChunkOffset - tStart) + sizeof(RIFFCHUNK);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream))
|
else if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream))
|
||||||
|
|
Loading…
Reference in New Issue