I am trying to save a video stream to an AVI file using VFW but i dont think i set it up correctly

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
I am using a specialized network streaming camera and I am trying to save the video stream off in a file. at the moment the code saves the video but in an ackward RGB format which screws up the color and then saves it using VFW. Am i doing this correctly
and this is supposed to create avi with mismatched colors or did i setup something wrong in the BITMAPINFOHEADER areas?<br/>
<br/>
<br/>
void PvSbProUISampleDlg::OnBnClickedSave()<br/>
{<br/>
// TODO: Add your control notification handler code here<br/>
<br/>
CString StringValue;<br/>
mMovieSave.GetWindowTextW(StringValue);<br/>
<br/>
if (StringValue == L"Save")<br/>
{<br/>
CString codecValue;<br/>
mMovieCodecSelected.GetWindowTextW(codecValue);<br/>
if (codecValue.IsEmpty()){<br/>
MessageBox( L"Please select a codec before saving to file",<br/>
L"Select Codec!",<br/>
MB_OK | MB_ICONEXCLAMATION );<br/>
return;<br/>
}<br/>
<br/>
CString fileNameValue;<br/>
mFileName.GetWindowTextW(fileNameValue);<br/>
if (fileNameValue.IsEmpty()){<br/>
MessageBox( L"Please select a file location",<br/>
L"Select File!",<br/>
MB_OK | MB_ICONEXCLAMATION );<br/>
return;<br/>
}<br/>
<br/>
<br/>
if (!StartMovie())<br/>
return;<br/>
<br/>
mSavingMovie = true;<br/>
mMovieSave.SetWindowTextW(L"Saving");<br/>
}<br/>
else<br/>
{<br/>
mVideoMutex.Lock();<br/>
PvResult aResult = mVideoCompressor->Stop();<br/>
mSavingMovie = false;<br/>
mVideoMutex.Unlock();<br/>
if (!aResult.IsOK())<br/>
{<br/>
MessageBox( mLocation,<br/>
L"Cant Stop Video Compressor!",<br/>
MB_OK | MB_ICONEXCLAMATION );<br/>
return;<br/>
}<br/>
<br/>
mMovieSave.SetWindowTextW(L"Save");<br/>
}<br/>
<br/>
}<br/>
<br/>
<br/>
I set up the video stream and select uncompressed AVI for my codec. I click "save" button which then calls the function below<br/>
<br/>
<br/>
<br/>
bool PvSbProUISampleDlg::StartMovie()<br/>
{<br/>
if ( !mDevice.IsConnected() )<br/>
{<br/>
MessageBox( L"Need to connect to device",<br/>
L"Cannot start Video Compressor!",<br/>
MB_OK | MB_ICONEXCLAMATION );<br/>
return false;<br/>
}<br/>
<br/>
if (!mPipeline.IsStarted() )<br/>
{<br/>
return false;<br/>
} <br/>
<br/>
if (mSavingMovie)<br/>
return false;<br/>
<br/>
PvInt64 width;<br/>
PvInt64 height;<br/>
PvInt64 bitCount;<br/>
<br/>
if (!GetImageWidth(width).IsOK())<br/>
return false;<br/>
<br/>
if (!GetImageHeight(height).IsOK())<br/>
return false;<br/>
<br/>
if (!GetPixelBitCount(bitCount).IsOK())<br/>
return false;<br/>
<br/>
// Start the movie compressor<br/>
if ( !mVideoCompressor->Start( mLocation,<br/>
width,<br/>
height,<br/>
bitCount/8,<br/>
59).IsOK())<br/>
{<br/>
MessageBox( mLocation,<br/>
L"Cannot start Video Compressor!",<br/>
MB_OK | MB_ICONEXCLAMATION );<br/>
return false;<br/>
}<br/>
<br/>
return true;<br/>
}<br/>
the function gets the video size info and then calls the actually compression to start<br/>
<br/>
<br/>
<br/>
PvResult VideoCompressor::Start(const CString& aFileName, unsigned short aSizeX, unsigned short aSizeY, unsigned short aBPP, double aFPS)<br/>
{<br/>
IAVIFile *lAVIFile = NULL;<br/>
IAVIStream *lAVIStream = NULL;<br/>
IAVIStream *lAVICompressedStream = NULL;<br/>
AVISTREAMINFO lAVISTREAMINFO;<br/>
AVICOMPRESSOPTIONS lAVICOMPRESSOPTIONS;<br/>
<br/>
// Try to match the image format with the Video Compressor capabilities<br/>
BITMAPINFO lTempBI;<br/>
lTempBI.bmiHeader.biSize = sizeof( BITMAPINFO );<br/>
lTempBI.bmiHeader.biWidth = aSizeX;<br/>
lTempBI.bmiHeader.biHeight = aSizeY;<br/>
lTempBI.bmiHeader.biPlanes = 1;<br/>
lTempBI.bmiHeader.biBitCount = aBPP * 8;<br/>
lTempBI.bmiHeader.biCompression = BI_RGB;<br/>
lTempBI.bmiHeader.biSizeImage = aSizeX * aSizeY * aBPP;<br/>
lTempBI.bmiHeader.biXPelsPerMeter = 1280;<br/>
lTempBI.bmiHeader.biYPelsPerMeter = 720;<br/>
lTempBI.bmiHeader.biClrUsed = 0;<br/>
lTempBI.bmiHeader.biClrImportant = 0;<br/>
//lTempBI.bmiHeader.<br/>
<br/>
if( ( mCOMPVARS.hic != NULL ) && // if not the "Full Frames (uncompressed)"<br/>
( ICCompressQuery( mCOMPVARS.hic, &lTempBI, NULL ) != ICERR_OK ) )<br/>
{<br/>
mLastVideoError = "Image format not accepted by compressor!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
// Try to open the stream for writing<br/>
if( mTempBuffer )<br/>
delete [] mTempBuffer;<br/>
<br/>
mTempBuffer = new unsigned char[ aSizeX * aSizeY * aBPP ];<br/>
if( mTempBuffer == NULL )<br/>
{<br/>
mLastVideoError = "Cannot allocate memory for a temporary buffer!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
if( AVIFileOpen( &lAVIFile, aFileName, OF_CREATE | OF_WRITE, NULL ) != 0 )<br/>
{<br/>
mLastVideoError = "Cannot open movie file for writing!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
// Fill out AVIStream information<br/>
memset( &lAVISTREAMINFO, 0, sizeof( AVISTREAMINFO ) );<br/>
lAVISTREAMINFO.fccType = streamtypeVIDEO;<br/>
lAVISTREAMINFO.fccHandler = mCOMPVARS.fccHandler;<br/>
lAVISTREAMINFO.dwFlags = 0;<br/>
lAVISTREAMINFO.dwCaps = 0;<br/>
lAVISTREAMINFO.wPriority = 0;<br/>
lAVISTREAMINFO.wLanguage = 0;<br/>
lAVISTREAMINFO.dwScale = 100;<br/>
lAVISTREAMINFO.dwRate = (unsigned long)( aFPS * 100.0 );<br/>
lAVISTREAMINFO.dwStart = 0;<br/>
lAVISTREAMINFO.dwLength = 0;<br/>
lAVISTREAMINFO.dwInitialFrames = 0;<br/>
lAVISTREAMINFO.dwQuality = mCOMPVARS.lQ;<br/>
lAVISTREAMINFO.dwSuggestedBufferSize = aSizeX * aSizeY * aBPP;<br/>
lAVISTREAMINFO.dwSampleSize = aSizeX * aSizeY * aBPP;<br/>
SetRect(&lAVISTREAMINFO.rcFrame, 0, aSizeY, aSizeX, 0);<br/>
// Convert to a wchar_t*<br/>
char *orig = "Video Stream";<br/>
size_t origsize = strlen(orig) + 1;<br/>
const size_t newsize = 64;<br/>
size_t convertedChars = 0;<br/>
<br/>
mbstowcs_s(&convertedChars, lAVISTREAMINFO.szName, origsize, orig, _TRUNCATE);<br/>
<br/>
if( AVIFileCreateStream( lAVIFile, &lAVIStream, &lAVISTREAMINFO ) != 0 )<br/>
{<br/>
mLastVideoError = "Cannot create video stream!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
BITMAPINFOHEADER lBIH;<br/>
lBIH.biSize = sizeof( BITMAPINFOHEADER );<br/>
lBIH.biWidth = aSizeX;<br/>
lBIH.biHeight = aSizeY;<br/>
lBIH.biPlanes = 1;<br/>
lBIH.biBitCount = aBPP * 8;<br/>
lBIH.biCompression = BI_RGB;<br/>
lBIH.biSizeImage = aSizeX * aSizeY * aBPP;<br/>
lBIH.biXPelsPerMeter = 1280;<br/>
lBIH.biYPelsPerMeter = 720;<br/>
lBIH.biClrUsed = 0;<br/>
lBIH.biClrImportant = 0;<br/>
<br/>
memset( &lAVICOMPRESSOPTIONS, 0, sizeof( AVICOMPRESSOPTIONS ) );<br/>
lAVICOMPRESSOPTIONS.fccType = streamtypeVIDEO;<br/>
lAVICOMPRESSOPTIONS.fccHandler = mCOMPVARS.fccHandler;<br/>
lAVICOMPRESSOPTIONS.dwKeyFrameEvery = 15;<br/>
lAVICOMPRESSOPTIONS.dwQuality = mCOMPVARS.lQ;<br/>
lAVICOMPRESSOPTIONS.dwBytesPerSecond = 0;<br/>
lAVICOMPRESSOPTIONS.dwFlags = AVICOMPRESSF_KEYFRAMES; //| AVICOMPRESSF_VALID;//|AVICOMPRESSF_DATARATE;<br/>
lAVICOMPRESSOPTIONS.lpFormat = &lBIH;<br/>
lAVICOMPRESSOPTIONS.cbFormat = sizeof( lBIH );<br/>
lAVICOMPRESSOPTIONS.lpParms = 0;<br/>
lAVICOMPRESSOPTIONS.cbParms = 0;<br/>
lAVICOMPRESSOPTIONS.dwInterleaveEvery = 0;<br/>
<br/>
HRESULT lR = AVIMakeCompressedStream( &lAVICompressedStream, lAVIStream, &lAVICOMPRESSOPTIONS, NULL);<br/>
if( lR == AVIERR_NOCOMPRESSOR )<br/>
{<br/>
mLastVideoError = "Cannot find a suitable compressor!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
} <br/>
else if( lR == AVIERR_MEMORY )<br/>
{<br/>
mLastVideoError = "Not enough memory to start the compressor!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
else if( lR == AVIERR_UNSUPPORTED )<br/>
{<br/>
mLastVideoError = "Compression is not supported for this image buffer!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
if( AVIStreamSetFormat( lAVICompressedStream, 0, &lBIH, sizeof( lBIH ) ) != 0 )<br/>
{<br/>
mLastVideoError = "Cannot set stream format. It probably isnt supported by the Codec!";<br/>
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
}<br/>
<br/>
///////////////////<br/>
<br/>
HRESULT hr;<br/>
//IBaseFilter mux = Null;<br/>
//IFileSinkFilter sink = null;<br/>
<br/>
// Guid x = new Guid( 0xe436eb88, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );<br/>
<br/>
//ICaptureGraphBuilder2::SetOutputFileName( <br/>
<br/>
<br/>
<br/>
//////////////////<br/>
<br/>
// finishing up<br/>
mAVIFile = lAVIFile;<br/>
mAVIStream = lAVIStream;<br/>
mAVICompressedStream = lAVICompressedStream;<br/>
<br/>
mSizeX = aSizeX;<br/>
mSizeY = aSizeY;<br/>
mBPP = aBPP;<br/>
mImageSize = aSizeX * aSizeY * aBPP;<br/>
<br/>
mLastSample = 0;<br/>
<br/>
mCompressing = true;<br/>
<br/>
return PvResult::Code::OK;<br/>
}<br/>
<br/>
this compresses the stream<br/>
<br/>
PvResult VideoCompressor::Compress(PvBuffer *aPvBuffer)<br/>
{<br/>
if (!mCompressing)<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
<br/>
ASSERT( mTempBuffer != NULL );<br/>
<br/>
long lSamplesWritten, lBytesWritten;<br/>
<br/>
int numberOfLines = 0;<br/>
<br/>
PvUInt8 * aBuffer = aPvBuffer->GetDataPointer();<br/>
<br/>
for( unsigned short lLine = 0; lLine < mSizeY; lLine++ )<br/>
{<br/>
numberOfLines = lLine;<br/>
unsigned char *lCurLine = (unsigned char *)aBuffer + (lLine ) * mSizeX * mBPP;<br/>
unsigned char *lCurLineInv = mTempBuffer + (mSizeY - lLine - 1) * mSizeX * mBPP;<br/>
::memcpy( lCurLineInv, lCurLine, mSizeX * mBPP );<br/>
}<br/>
<br/>
if( AVIStreamWrite( mAVICompressedStream, mLastSample, 1, mTempBuffer, mImageSize, 0,
<br/>
&lSamplesWritten, &lBytesWritten ) != 0 ||<br/>
lSamplesWritten < 1 ||<br/>
lBytesWritten < 1 )<br/>
{<br/>
mLastVideoError = "Cannot compress image!";<br/>
return PvResult::Code::GENERIC_ERROR;<br/>
<br/>
}<br/>
<br/>
mLastSample ++;<br/>
<br/>
return PvResult::Code::OK;<br/>
}<br/>
<br/>
<br/>
this is what it should look like:<br/>
http://i13.photobucket.com/albums/a269/Masterg_/Untitled-16.png<br/>
<br/>
this is what it saves as ( minus the guy):<br/>
http://i13.photobucket.com/albums/a269/Masterg_/vlcsnap-2011-06-07-13h11m34s97.png<br/>
<br/>

View the full article
 
Back
Top