|
|
|
date: Thu, 24 Jul 2008 06:11:00 -0700,
group: microsoft.public.win32.programmer.mmedia
back
How to encode video using VFW?
Hi,
I've some problems with Video For Windows library, I looked previous posts
and couldn't find any relevant post...
I want to compress an uncompressed video file using mpeg2. After some search
it seems that Video For Windows (VFW) is suitable for the job. (I'm using
Visual c++ 6)
I have implemented some piece of code according to below pattern,
First, please have a look at the pattern and inform me if there is any
conceptual mistake.
1. select codec
2. open input video
3. get input video stream
4. get input video's stream format
5. get output video's stream format (by ICCompressGetFormat)
6. create output file
7. create output stream (how to fill avistreaminfo struct correctly?)
8. get frames by one by, compress frame, write compressed frame to
outputStream
9. Close streams and files...
I have written some piece of code but I have some diffuculties in filling
lots of header/information headers.
As a result my code compressed an uncompressed avi of 162 mbs into 165 mbs
and the video quality is awful::(
Here is the code,
What is the bug(s) ?
--------------------------------------
#define RETURN_IF_ERR(hr) if(hr!=0) \
void CVideoCapDlg::OnCodecSelect()
{
_pc.cbSize = sizeof(COMPVARS);
if (TRUE == ICCompressorChoose( NULL, ICMF_CHOOSE_ALLCOMPRESSORS, NULL,
NULL, &_pc, "Select Compressor"))
{
}else
{
// Codec did not selected
}
}
void CVideoCapDlg::OnCompress()
{
LONG hr;
char * cpInFileName = "video.avi";
char * cpOutFileName = "videoOut.avi";
PAVIFILE pInFile;
PAVIFILE pOutFile;
AVIFILEINFO pInFileInf;
PAVISTREAM pInStream;
PAVISTREAM pOutStream;
AVISTREAMINFO pOutStreamInf;
// open AVIFile library
AVIFileInit();
// open input avi file
hr = AVIFileOpen(&pInFile, cpInFileName, OF_SHARE_DENY_WRITE, NULL);
RETURN_IF_ERR(hr)
// get file info
hr = AVIFileInfo(pInFile, &pInFileInf, sizeof(AVIFILEINFO));
RETURN_IF_ERR(hr)
// get video stream
hr = AVIFileGetStream( pInFile, &pInStream, streamtypeVIDEO, 0);
RETURN_IF_ERR(hr)
// fill input stream bitmapInfoHeader
// size is set as sizeof(BITMAPINFOHEADER) bec we only want header info
LPBITMAPINFO pBitmapInfoIn = new BITMAPINFO();
long iHeaderSize = sizeof(BITMAPINFO);
hr = AVIStreamReadFormat( pInStream , 0,(void*) pBitmapInfoIn,
&iHeaderSize);
RETURN_IF_ERR(hr)
// get compressor output format
LPBITMAPINFO pBitmapInfoOut = new BITMAPINFO();
hr = ICCompressGetFormat(_pc.hic, pBitmapInfoIn, pBitmapInfoOut); //
get format
RETURN_IF_ERR(hr)
// is conversion possible?
DWORD res;
res = ICCompressQuery(_pc.hic, (LPBITMAPINFO) pBitmapInfoIn,
(LPBITMAPINFO)pBitmapInfoOut);
if (res==ICERR_BADFORMAT)
return;
// get frame start and count
int iFrameStart = AVIStreamStart(pInStream);
int iFrameCount = AVIStreamLength(pInStream);
int iFrameOffset = 0;
// open video stream for frame grab
PGETFRAME pFrameHandler ;
pFrameHandler = AVIStreamGetFrameOpen(pInStream, NULL);
// COMPRESS VIDEO STREAMS
// Find the worst-case buffer size used in compression.
DWORD dwCompressBufferSize = ICCompressGetSize(_pc.hic, pBitmapInfoIn,
pBitmapInfoOut);
// create output avi file
AVISTREAMINFO si;
hr = AVIFileOpen(&pOutFile, cpOutFileName, OF_WRITE | OF_CREATE, NULL);
RETURN_IF_ERR(hr)
ZeroMemory((LPVOID)&pOutStreamInf,sizeof(pOutStreamInf));
pOutStreamInf.fccType = streamtypeVIDEO;
pOutStreamInf.fccHandler = _pc.fccHandler;
pOutStreamInf.dwScale = 10000;
pOutStreamInf.dwRate = 300000;
pOutStreamInf.dwQuality = 10000;
pOutStreamInf.dwLength = 375;
pOutStreamInf.dwSuggestedBufferSize = dwCompressBufferSize ;
hr = AVIFileCreateStream(pOutFile, &pOutStream, &pOutStreamInf);
RETURN_IF_ERR(hr)
hr = AVIStreamSetFormat( pOutStream,0,pBitmapInfoOut,
sizeof(BITMAPINFOHEADER));
RETURN_IF_ERR(hr)
AVIStreamInfo( pOutStream, &si, sizeof(si));
// Allocate a buffer and get lpOutput to point to it.
HGLOBAL h = GlobalAlloc(GHND, dwCompressBufferSize);
LPVOID lpOutputBuffer = (LPVOID)GlobalLock(h);
LPVOID frame;
DWORD dwCkID;
DWORD dwCompFlags;
DWORD dwFlags = 0;
LPVOID lpNew = GlobalAlloc(GMEM_MOVEABLE,
pBitmapInfoOut->bmiHeader.biSizeImage);
if (ICCompressBegin(_pc.hic, pBitmapInfoIn, pBitmapInfoOut) == ICERR_OK)
{
while( (frame = AVIStreamGetFrame(pFrameHandler,iFrameStart +
iFrameOffset)) != NULL)
{
if (ICCompress( _pc.hic, dwFlags , &pBitmapInfoOut->bmiHeader,
lpOutputBuffer,&pBitmapInfoIn->bmiHeader , frame,
&dwCkID, &dwCompFlags, iFrameOffset,
0, 0, NULL, NULL) == ICERR_OK)
{
hr = AVIStreamWrite(pOutStream, iFrameOffset , 1,lpOutputBuffer ,
dwCompressBufferSize, 0 ,
NULL, NULL);
}
else
{
return;
}
iFrameOffset++;
}
AVIStreamRelease(pOutStream);
AVIFileRelease(pOutFile);
ICCompressEnd(_pc.hic); // terminate compression
}
else
{
// Handle the error identifying the unsupported format.
}
AVIStreamRelease(pInStream);
AVIFileRelease(pInFile);
delete pBitmapInfoIn;
delete pBitmapInfoOut;
}
date: Thu, 24 Jul 2008 06:11:00 -0700
author: yavuz gok yavuz
|
|