www.pudn.com > DalsaNetlink.rar > CyVideoCompressor.cpp


// CyVideoCompressor.cpp: implementation of the CyVideoCompressor class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
 
#include  
using namespace std; 
 
#include  
#include  
#include  
#include "CyVideoCompressor.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
struct VideoCompressorInitializer 
{ 
	VideoCompressorInitializer() 
	{ 
		AVIFileInit(); 
	} 
 
	~VideoCompressorInitializer() 
	{ 
		AVIFileExit(); 
	} 
}; 
 
static VideoCompressorInitializer sVideoCompressorInitializer; 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CyVideoCompressor::CyVideoCompressor() 
	: mCompressing( false ) 
	, mTempBuffer( NULL ) 
{ 
	memset( &mCOMPVARS, 0, sizeof( COMPVARS ) ); 
} 
 
CyVideoCompressor::~CyVideoCompressor() 
{ 
	if( mCompressing ) 
	{ 
		Stop(); 
	} 
 
	if( mTempBuffer ) 
		delete [] mTempBuffer; 
 
	if( mCOMPVARS.hic ) 
		ICClose( mCOMPVARS.hic ); 
} 
 
CyResult CyVideoCompressor::ChooseCompressor(COMPVARS *aCOMPVARS, HWND aParent ) 
{ 
	CyAssert( aCOMPVARS != NULL ); 
 
	COMPVARS lCOMPVARS; 
	memcpy( &lCOMPVARS, aCOMPVARS, sizeof( lCOMPVARS ) ); 
	lCOMPVARS.cbSize = sizeof( lCOMPVARS ); 
 
	// prompt the user for the compressor to use 
	if( !ICCompressorChoose( aParent, ICMF_CHOOSE_ALLCOMPRESSORS, NULL, NULL, &lCOMPVARS, NULL ) ) 
		return CY_RESULT_ABORTED; 
 
	memcpy( aCOMPVARS, &lCOMPVARS, sizeof( lCOMPVARS ) ); 
 
	return CY_RESULT_OK; 
} 
 
CyResult CyVideoCompressor::GetCompressorName(COMPVARS *aCOMPVARS, string &aName) 
{ 
	CyAssert( aCOMPVARS != NULL ); 
 
	// init IC info 
	ICINFO lICINFO; 
	memset( &lICINFO, 0, sizeof( lICINFO ) ); 
	lICINFO.dwSize = sizeof( lICINFO ); 
 
	// if there are is no compressor selected, return an empty string 
	if( aCOMPVARS->fccType == 0 || aCOMPVARS->fccHandler == 0 ) 
	{ 
		aName = ""; 
		return CY_RESULT_OK; 
	} 
 
	// first check if this is the Uncompressed Frames selection ('DIB ') 
	if( mmioFOURCC('D','I','B',' ') == aCOMPVARS->fccHandler ) 
	{ 
		aName = "Full Frames (Uncompressed)"; 
		return CY_RESULT_OK; 
	} 
 
	HIC lIC = ICOpen( aCOMPVARS->fccType, aCOMPVARS->fccHandler, ICMODE_QUERY ); 
 
	if( lIC == NULL ) 
	{ 
		throw CyErrorInfo( "Cannot open the video compressor!", CY_RESULT_UNEXPECTED_EXCEPTION, 
			__FILE__, __LINE__, GetLastError() ); 
	} 
 
	if( ICGetInfo( lIC, &lICINFO, sizeof( lICINFO ) ) == 0 ) 
	{ 
		throw CyErrorInfo( "Cannot get compressor information!", CY_RESULT_UNEXPECTED_EXCEPTION, 
			__FILE__, __LINE__, GetLastError() ); 
	} 
 
	if( ICClose( lIC ) != ICERR_OK ) 
	{ 
		throw CyErrorInfo( "Cannot close compressor!", CY_RESULT_UNEXPECTED_EXCEPTION, 
			__FILE__, __LINE__, GetLastError() ); 
	} 
 
	aName = ""; 
	for( int lIdx = 0; lIdx < sizeof( lICINFO.szDescription ) && lICINFO.szDescription[ lIdx ] != 0; lIdx++ ) 
	{ 
		aName += (char)lICINFO.szDescription[ lIdx ]; 
	} 
 
	return CY_RESULT_OK; 
} 
 
CyResult CyVideoCompressor::ChooseCompressor( HWND aParent ) 
{ 
	return CyVideoCompressor::ChooseCompressor( &mCOMPVARS, aParent ); 
} 
 
CyResult CyVideoCompressor::GetCompressorName(string &aName) 
{ 
	try 
	{ 
		return CyVideoCompressor::GetCompressorName( &mCOMPVARS, aName ); 
	} 
	catch( CyErrorInfo &lEI ) 
	{ 
		return SetErrorInfo( lEI ); 
	} 
} 
 
CyResult CyVideoCompressor::Start(unsigned short aSizeX, unsigned short aSizeY, unsigned short aBPP, double aFPS) 
{ 
	IAVIFile *lAVIFile = NULL; 
	IAVIStream *lAVIStream = NULL; 
	IAVIStream *lAVICompressedStream = NULL; 
	AVISTREAMINFO lAVISTREAMINFO; 
	AVICOMPRESSOPTIONS lAVICOMPRESSOPTIONS; 
 
	try 
	{ 
		// Try to match the image format with the Video Compressor capabilities 
		BITMAPINFO lTempBI; 
		lTempBI.bmiHeader.biSize          = sizeof( BITMAPINFO ); 
		lTempBI.bmiHeader.biWidth         = aSizeX; 
		lTempBI.bmiHeader.biHeight        = aSizeY; 
		lTempBI.bmiHeader.biPlanes        = 1; 
		lTempBI.bmiHeader.biBitCount      = aBPP * 8; 
		lTempBI.bmiHeader.biCompression   = BI_RGB; 
		lTempBI.bmiHeader.biSizeImage     = aSizeX * aSizeY * aBPP; 
		lTempBI.bmiHeader.biXPelsPerMeter = 10000; 
		lTempBI.bmiHeader.biYPelsPerMeter = 10000; 
		lTempBI.bmiHeader.biClrUsed       = 0; 
		lTempBI.bmiHeader.biClrImportant  = 0; 
 
		if( ( mCOMPVARS.hic != NULL ) && // if not the "Full Frames (uncompressed)" 
			( ICCompressQuery( mCOMPVARS.hic, &lTempBI, NULL ) != ICERR_OK ) ) 
		{ 
			throw CyErrorInfo( "Image format not accepted by compressor!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		} 
 
 
		// Try to open the stream for writing 
		if( mTempBuffer ) 
			delete [] mTempBuffer; 
 
		mTempBuffer = new unsigned char[ aSizeX * aSizeY * aBPP ]; 
		if( mTempBuffer == NULL ) 
		{ 
			throw CyErrorInfo( "Cannot allocate memory for a temporary buffer!", 
							   CY_RESULT_CANNOT_OPEN_FILE, __FILE__, __LINE__, GetLastError() ); 
		} 
 
		if( AVIFileOpen( &lAVIFile, mFilename.c_str(), OF_CREATE | OF_WRITE, NULL ) != 0 ) 
		{ 
			throw CyErrorInfo( "Cannot open movie file for writing!", 
							   CY_RESULT_CANNOT_OPEN_FILE, __FILE__, __LINE__, GetLastError() ); 
		} 
 
		// Fill out AVIStream information 
		memset( &lAVISTREAMINFO, 0, sizeof( AVISTREAMINFO ) ); 
		lAVISTREAMINFO.fccType               = streamtypeVIDEO; 
		lAVISTREAMINFO.fccHandler            = mCOMPVARS.fccHandler; 
		lAVISTREAMINFO.dwFlags               = 0; 
		lAVISTREAMINFO.dwCaps                = 0; 
		lAVISTREAMINFO.wPriority             = 0; 
		lAVISTREAMINFO.wLanguage             = 0; 
		lAVISTREAMINFO.dwScale               = 100; 
		lAVISTREAMINFO.dwRate                = (unsigned long)( aFPS * 100.0 ); 
		lAVISTREAMINFO.dwStart               = 0; 
		lAVISTREAMINFO.dwLength              = 0; 
		lAVISTREAMINFO.dwInitialFrames       = 0; 
		lAVISTREAMINFO.dwQuality             = mCOMPVARS.lQ; 
		lAVISTREAMINFO.dwSuggestedBufferSize = aSizeX * aSizeY * aBPP; 
		lAVISTREAMINFO.dwSampleSize          = aSizeX * aSizeY * aBPP; 
		SetRect(&lAVISTREAMINFO.rcFrame, 0, aSizeY, aSizeX, 0); 
		strcpy( lAVISTREAMINFO.szName, "Video Stream" ); 
 
		if( AVIFileCreateStream( lAVIFile, &lAVIStream, &lAVISTREAMINFO ) != 0 ) 
		{ 
			throw CyErrorInfo( "Cannot create video stream!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		} 
 
		BITMAPINFOHEADER lBIH; 
		lBIH.biSize          = sizeof( BITMAPINFOHEADER ); 
		lBIH.biWidth         = aSizeX; 
		lBIH.biHeight        = aSizeY; 
		lBIH.biPlanes        = 1; 
		lBIH.biBitCount      = aBPP * 8; 
		lBIH.biCompression   = BI_RGB; 
		lBIH.biSizeImage     = aSizeX * aSizeY * aBPP; 
		lBIH.biXPelsPerMeter = 10000; 
		lBIH.biYPelsPerMeter = 10000; 
		lBIH.biClrUsed       = 0; 
		lBIH.biClrImportant  = 0; 
 
		memset( &lAVICOMPRESSOPTIONS, 0, sizeof( AVICOMPRESSOPTIONS ) ); 
		lAVICOMPRESSOPTIONS.fccType           = streamtypeVIDEO; 
		lAVICOMPRESSOPTIONS.fccHandler        = mCOMPVARS.fccHandler; 
		lAVICOMPRESSOPTIONS.dwKeyFrameEvery   = 15; 
		lAVICOMPRESSOPTIONS.dwQuality         = mCOMPVARS.lQ; 
		lAVICOMPRESSOPTIONS.dwBytesPerSecond  = 0; 
		lAVICOMPRESSOPTIONS.dwFlags           = AVICOMPRESSF_KEYFRAMES; //|AVICOMPRESSF_VALID;//|AVICOMPRESSF_DATARATE; 
		lAVICOMPRESSOPTIONS.lpFormat          = &lBIH; 
		lAVICOMPRESSOPTIONS.cbFormat          = sizeof( lBIH ); 
		lAVICOMPRESSOPTIONS.lpParms           = 0; 
		lAVICOMPRESSOPTIONS.cbParms           = 0; 
		lAVICOMPRESSOPTIONS.dwInterleaveEvery = 0; 
		 
		HRESULT lR = AVIMakeCompressedStream( &lAVICompressedStream, lAVIStream, &lAVICOMPRESSOPTIONS, NULL); 
		if( lR == AVIERR_NOCOMPRESSOR ) 
		{ 
			throw CyErrorInfo( "Cannot find a suitable compressor!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		}  
		else if( lR == AVIERR_MEMORY ) 
		{ 
			throw CyErrorInfo( "Not enough memory to start the compressor!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		} 
		else if( lR == AVIERR_UNSUPPORTED ) 
		{ 
			throw CyErrorInfo( "Compression is not supported for this image buffer!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		} 
 
		if( AVIStreamSetFormat( lAVICompressedStream, 0, &lBIH, sizeof( lBIH ) ) != 0 ) 
		{ 
			throw CyErrorInfo( "Cannot set stream format. It probably isn't supported by the Codec!", 
							   CY_RESULT_UNEXPECTED_EXCEPTION, __FILE__, __LINE__, GetLastError() ); 
		} 
	} 
	catch( CyErrorInfo& lEI ) 
	{ 
		// clean-up 
		if( lAVICompressedStream )  
		{ 
			AVIStreamRelease( lAVICompressedStream ); 
			lAVICompressedStream = NULL; 
		} 
 
		if( lAVIStream ) 
		{ 
			AVIStreamRelease( lAVIStream ); 
			lAVIStream = NULL; 
		} 
 
		if( lAVIFile ) 
		{ 
			AVIFileRelease( lAVIFile ); 
			lAVIFile = NULL; 
		} 
 
		return SetErrorInfo( lEI ); 
	} 
 
	// finishing up 
	mAVIFile             = lAVIFile; 
	mAVIStream           = lAVIStream; 
	mAVICompressedStream = lAVICompressedStream; 
 
	mSizeX     = aSizeX; 
	mSizeY     = aSizeY; 
	mBPP       = aBPP; 
	mImageSize = aSizeX * aSizeY * aBPP; 
 
	mLastSample = 0; 
 
	mCompressing = true; 
 
	return CY_RESULT_OK; 
} 
 
CyResult CyVideoCompressor::Compress(void *aBuffer) 
{ 
	CyAssert( mCompressing ); 
	CyAssert( mTempBuffer != NULL ); 
 
	long lSamplesWritten, lBytesWritten; 
 
	for( unsigned short lLine = 0; lLine < mSizeY; lLine++ ) 
	{ 
		unsigned char *lCurLine    = (unsigned char *)aBuffer + (lLine             ) * mSizeX * mBPP; 
		unsigned char *lCurLineInv = mTempBuffer              + (mSizeY - lLine - 1) * mSizeX * mBPP; 
		memcpy( lCurLineInv, lCurLine, mSizeX * mBPP ); 
	} 
 
	if( AVIStreamWrite( mAVICompressedStream, mLastSample, 1, mTempBuffer, mImageSize, 0,  
			&lSamplesWritten, &lBytesWritten ) != 0 || 
		lSamplesWritten < 1 || 
		lBytesWritten < 1 ) 
	{ 
		return SetErrorInfo( "Cannot compress image!", 
						   CY_RESULT_UNEXPECTED_EXCEPTION, 
						   __FILE__, 
						   __LINE__, 
						   GetLastError() ); 
	} 
 
	mLastSample ++; 
 
	return CY_RESULT_OK; 
} 
 
CyResult CyVideoCompressor::Stop() 
{ 
	CyAssert( mTempBuffer != NULL ); 
	CyAssert( mCompressing ); 
 
	mCompressing = false; 
 
	delete [] mTempBuffer; 
	mTempBuffer = NULL; 
 
	AVIStreamRelease( mAVICompressedStream ); 
	mAVICompressedStream = NULL; 
 
	AVIStreamRelease( mAVIStream ); 
	mAVIStream = NULL; 
 
	AVIFileRelease( mAVIFile ); 
	mAVIFile = NULL; 
 
	return CY_RESULT_OK; 
}