#include <vfw.h>
void VideoSequenceCompressor::init(HIC hic, BITMAPINFO *pbiInput, BITMAPINFO *pbiOutput, long lQ, long lKeyRate) {
ICINFO info;
LRESULT res;
int cbSizeIn, cbSizeOut;
cbSizeIn = pbiInput->bmiHeader.biSize + pbiInput->bmiHeader.biClrUsed*4;
cbSizeOut = pbiOutput->bmiHeader.biSize + pbiOutput->bmiHeader.biClrUsed*4;
this->hic = hic;
this->pbiInput = (BITMAPINFO *) new char[cbSizeIn];
this->pbiOutput = (BITMAPINFO *) new char[cbSizeOut];
this->lKeyRate = lKeyRate;
memcpy(this->pbiInput, pbiInput, cbSizeIn);
memcpy(this->pbiOutput, pbiOutput, cbSizeOut);
lKeyRateCounter = 1;
// Retrieve compressor information.
res = ICGetInfo(hic, &info, sizeof info);
if (!res)
throw "Unable to retrieve video compressor information.";
// Analyze compressor.
this->dwFlags = info.dwFlags;
if (info.dwFlags & VIDCF_TEMPORAL) {
if (!(info.dwFlags & VIDCF_FASTTEMPORALC)) {
// Allocate backbuffer
if (!(pPrevBuffer = new char[pbiInput->bmiHeader.biSizeImage]))
throw "VideoSequenceCompressor::init - Memory allocation error";
}
}
if (info.dwFlags & VIDCF_QUALITY)
lQuality = lQ;
else
lQuality = 0;
// Allocate destination buffer
lMaxPackedSize = ICCompressGetSize(hic, pbiInput, pbiOutput);
if (!(pOutputBuffer = new char[lMaxPackedSize]))
throw "VideoSequenceCompressor::init - Memory allocation error";
// Save configuration state.
//
// Ordinarily, we wouldn't do this, but there seems to be a bug in
// the Microsoft MPEG-4 compressor that causes it to reset its
// configuration data after a compression session. This occurs
// in all versions from V1 through V3.
//
// Stupid fscking Matrox driver returns -1!!!
cbConfigData = ICGetStateSize(hic);
if (cbConfigData > 0) {
if (!(pConfigData = new char[cbConfigData]))
throw "VideoSequenceCompressor::init - Memory allocation error";
cbConfigData = ICGetState(hic, pConfigData, cbConfigData);
// As odd as this may seem, if this isn't done, then the Indeo5
// compressor won't allow data rate control until the next
// compression operation!
if (cbConfigData)
ICSetState(hic, pConfigData, cbConfigData);
}
lMaxFrameSize = 0;
lSlopSpace = 0;
}
bool VideoSequenceCompressor::GetInstalledCodecs()
{
// Fill video codec list
m_vInstalledCodecList.RemoveAll();
ICINFO codecInfo;
HIC hic;
int i=0,j=0;
for (i=0; ICInfo(ICTYPE_VIDEO, i, &codecInfo); i++)
{
hic = ICOpen(codecInfo.fccType, codecInfo.fccHandler, ICMODE_COMPRESS );
if (hic)
{
if(codecInfo.fccType != ICTYPE_VIDEO)
{
ICClose(hic);
continue;
}
// Find out the compressor name.
ICGetInfo(hic, &codecInfo, sizeof(codecInfo));
TVideoCodecInfo cnfo;
cnfo.hic = hic;
cnfo.fccHandler = codecInfo.fccHandler;
memcpy( cnfo.szDescription, codecInfo.szDescription, 128*sizeof(WCHAR) );
memcpy( cnfo.szDriver , codecInfo.szDriver , 128*sizeof(WCHAR) );
memcpy( cnfo.szName , codecInfo.szName , 16*sizeof(WCHAR) );
// Get State
#if 1
DWORD size;
size = ICGetStateSize(hic);
if( size )
{
PBYTE pv = new BYTE[size];
ICGetState( hic, pv, size );
cnfo.SetSettings( pv, size );
cnfo.SetSettings1st( pv, size);
cnfo.SetSettings2nd( pv, size );
delete []pv;
}
#endif
m_vInstalledCodecList.SetAtGrow( j++, cnfo );
}
}
EnumerateVideoCodecs( 640, 480 );
return true;
}
bool VideoSequenceCompressor::EnumerateVideoCodecs(int width, int height)
{
// Fill video codec list
m_vVideoCodecList.RemoveAll();
BITMAPINFO bmpInfo;
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(BITMAPINFOHEADER));
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bmpInfo.bmiHeader = bi;
HIC hic;
int i=0,j=0;
for (i=0; i<m_vInstalledCodecList.GetSize(); i++)
{
hic = m_vInstalledCodecList[i].hic;
DWORD dwSupportedFormats = 0;
// RGB
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = 24;
// Skip this compressor if it can't handle the format.
dwSupportedFormats = ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_RGB32 : 0;
// YV12
bmpInfo.bmiHeader.biCompression = '21VY';
bmpInfo.bmiHeader.biBitCount = 12;
// Skip this compressor if it can't handle the format.
dwSupportedFormats |= ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_YV12 : 0;
// YUY2
bmpInfo.bmiHeader.biCompression = '2YUY';
bmpInfo.bmiHeader.biBitCount = 16;
// Skip this compressor if it can't handle the format.
dwSupportedFormats |= ICCompressQuery(hic, &bmpInfo, NULL) == ICERR_OK ? FLO_VIDEO_YUY2 : 0;
m_vInstalledCodecList[i].dwSupportedFormats = dwSupportedFormats;
if( !dwSupportedFormats )
continue;
TVideoCodecInfo cnfo;
cnfo = m_vInstalledCodecList[i];
m_vVideoCodecList.SetAtGrow( j++, cnfo );
}
return true;
}