www.pudn.com > DalsaNetlink.rar > CyVideoCompressor.cpp
// CyVideoCompressor.cpp: implementation of the CyVideoCompressor class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #includeusing 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; }