|
Will this generate OpenDML AVI files that aren't limited to 1 to 2 GB in file size?
|
|
|
|
|
Looks like AVI 1.0. I wrote a quick app to test, the header fell apart beyond 2GB. VLC asked to rebuild index and Media Player won't play the output AVI.
|
|
|
|
|
This worked great!
I took out the MFC stuff, so I could include this into a straight Win32 Console app (no MFC):
- CString -> const char *
- Commented out debug dump
- Changed the afxmessagebox to a "printf"
- Added a pragma to include the vfx lib.
- Pass a bitmap header info pointer and a pointer to the pixel bits to the functions, instead of DIB handle.
- Put abs() around the bitmap header height in case this is an upside down bitmap.
Maybe someone will find some of these changes helpful. If not, feel free to delete this post.
#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame.
#include <windows.h>
#include <memory.h>
#include <mmsystem.h>
#include <vfw.h>
#pragma comment(lib, "vfw32.lib")
BOOL AVI_Init()
{
WORD wVer = HIWORD(VideoForWindowsVersion());
if (wVer < 0x010a){
MessageBox(NULL, "Cant't init AVI File - Video for Windows version is to old", "Error", MB_OK|MB_ICONSTOP);
return FALSE;
}
AVIFileInit();
return TRUE;
}
BOOL AVI_FileOpenWrite(PAVIFILE * pfile, const char *filename)
{
HRESULT hr = AVIFileOpen(pfile, filename, OF_WRITE | OF_CREATE, NULL); if (hr != AVIERR_OK)
return FALSE;
return TRUE;
}
DWORD getFOURCC(const char *value)
{
if( stricmp(value, "DIB") == 0)
{
return mmioFOURCC(value[0],value[1],value[2],' ');
}
else if((stricmp(value, "CVID") == 0)
|| (stricmp(value, "IV32") == 0)
|| (stricmp(value, "MSVC") == 0)
|| (stricmp(value, "IV50") == 0))
{
return mmioFOURCC(value[0],value[1],value[2],value[3]);
}
else
{
return NULL;
}
}
BOOL AVI_CreateStream(PAVIFILE pfile, PAVISTREAM * ps, int rate, unsigned long buffersize, int rectwidth, int rectheight,
const char *_compressor)
{
AVISTREAMINFO strhdr;
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO; strhdr.fccHandler = getFOURCC(_compressor);
strhdr.dwScale = 1;
strhdr.dwRate = rate; strhdr.dwSuggestedBufferSize = buffersize;
strhdr.dwQuality = -1; SetRect(&strhdr.rcFrame, 0, 0, (int) rectwidth,
(int) rectheight);
HRESULT hr = AVIFileCreateStream(pfile, ps, &strhdr); if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
BOOL AVI_SetOptions(PAVISTREAM * ps, PAVISTREAM * psCompressed, LPBITMAPINFOHEADER lpbi,
const char * _compressor)
{
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
memset(&opts, 0, sizeof(opts));
opts.fccType = streamtypeVIDEO;
opts.fccHandler = getFOURCC(_compressor);
if(getFOURCC(_compressor) == NULL)
{
if (!AVISaveOptions(NULL, 0, 1, ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts))
{
return FALSE;
}
}
HRESULT hr = AVIMakeCompressedStream(psCompressed, *ps, &opts, NULL);
if (hr != AVIERR_OK) {
return FALSE;
}
hr = AVIStreamSetFormat(*psCompressed, 0,
lpbi, lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD)
);
if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
BOOL AVI_SetText(PAVIFILE pfile, PAVISTREAM psText, char *szText, int width, int height, int TextHeight)
{
AVISTREAMINFO strhdr;
DWORD dwTextFormat;
memset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeTEXT;
strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W');
strhdr.dwScale = 1;
strhdr.dwRate = 60;
strhdr.dwSuggestedBufferSize = sizeof(szText);
SetRect(&strhdr.rcFrame, 0, (int) height,
(int) width, (int) height + TextHeight);
HRESULT hr = AVIFileCreateStream(pfile, &psText, &strhdr);
if (hr != AVIERR_OK) {
return FALSE;
}
dwTextFormat = sizeof(dwTextFormat);
hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat));
if (hr != AVIERR_OK) {
return FALSE;
}
return TRUE;
}
BOOL AVI_AddFrame(PAVISTREAM psCompressed, int time, LPBITMAPINFOHEADER lpbi, void *bits)
{
int ImageSize = lpbi->biSizeImage;
if (ImageSize == 0)
{
if (lpbi->biBitCount == 24)
{
ImageSize = lpbi->biWidth * abs(lpbi->biHeight) * 3;
}
}
HRESULT hr = AVIStreamWrite(psCompressed, time, 1, bits,
ImageSize, AVIIF_KEYFRAME, NULL,
NULL);
if (hr != AVIERR_OK)
{
printf("Error: AVIStreamWrite, error %d",hr);
return FALSE;
}
return TRUE;
}
BOOL AVI_AddText(PAVISTREAM psText, int time, char *szText)
{
int iLen = strlen(szText);
HRESULT hr = AVIStreamWrite(psText,
time,
1,
szText,
iLen + 1,
AVIIF_KEYFRAME,
NULL,
NULL);
if (hr != AVIERR_OK)
return FALSE;
return TRUE;
}
BOOL AVI_CloseStream(PAVISTREAM ps, PAVISTREAM psCompressed, PAVISTREAM psText)
{
if (ps)
AVIStreamClose(ps);
if (psCompressed)
AVIStreamClose(psCompressed);
if (psText)
AVIStreamClose(psText);
return TRUE;
}
BOOL AVI_CloseFile(PAVIFILE pfile)
{
if (pfile)
AVIFileClose(pfile);
return TRUE;
}
BOOL AVI_Exit()
{
AVIFileExit();
return TRUE;
}
PAVIFILE pfile = NULL;
PAVISTREAM ps = NULL;
PAVISTREAM psCompressed = NULL;
int count = 0;
bool START_AVI(const char *file_name)
{
if(! AVI_Init())
{
return false;
}
if(! AVI_FileOpenWrite(&pfile, file_name))
{
return false;
}
return true;
}
bool ADD_FRAME_FROM_DIB_TO_AVI(LPBITMAPINFOHEADER lpbi, void *bits, const char *_compressor, int _frameRate)
{
if(count == 0)
{
if(! AVI_CreateStream(pfile, &ps, _frameRate,
(unsigned long) lpbi->biSizeImage,
(int) lpbi->biWidth,
(int) abs(lpbi->biHeight), _compressor))
{
return false;
}
if(! AVI_SetOptions(&ps, &psCompressed, lpbi, _compressor))
{
GlobalUnlock(lpbi);
return false;
}
}
if(! AVI_AddFrame(psCompressed, count * 1, lpbi, bits))
{
return false;
}
count++;
return true;
}
bool STOP_AVI()
{
if(! AVI_CloseStream(ps, psCompressed, NULL))
{
return false;
}
if(! AVI_CloseFile(pfile))
{
return false;
}
if(! AVI_Exit())
{
return false;
}
return true;
}
|
|
|
|
|
Wow.. Good jobs.
Thank you for your modification. It is very useful for me.
|
|
|
|
|
A big thank you to both Rod and John for this great contribution.
|
|
|
|
|
Can you give an example of how to use the new version of ADD_FRAME_FROM_DIB_TO_AVI? I'm using CxImage to load bitmaps and append to avi, so I imagine it's something like:
ADD_FRAME_FROM_DIB_TO_AVI(&image.GetDIB, image.GetBits(), "DIB", 100);
but not sure. Thanks!
|
|
|
|
|
as per my requirement i have to combine multiple avi video files to make a
single avi video file...i did it in following way....i had taken two avi
video files..nam1.avi and name2.avi...i got the individual avistreams from
both these files by using
AVIFileOpen and AVIFileGetStream functions....n after i followed AVISaveV
which builds a sigle file from indidvidual streams....and if i combine
nam1.avi(2sec play)
name2.avi( 2sec play) the target combined file has to be play for 4sec
duration...but it is playing for 2 sec only...n regarding size it's ok.. the
target file size is sum of two i/p file..i got this...can any one help me to
fix this problem...
and i paste my code below..
cout<<"my code starts"<<endl;
TCHAR szFile[MAX_PATH];
AVIFileInit();
cout<<"avi file initialized succesfully"<<endl;
PAVIFILE hFile,hFile2;
strcpy(szFile,"D:\\Avi\\patient1\\name2.avi");
cout<<szFile<<endl;
if(AVIFileOpen(&hFile,szFile ,OF_READ, NULL)==AVIERR_OK )
cout<<"avi file opened successfully"<<endl;
else
cout<<"not opened"<<endl;
// TODO: code your application's behavior here.
/*CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;*/
AVIFILEINFO obj;
if(AVIFileInfo(hFile,&obj,sizeof(AVIFILEINFO))==AVIERR_OK )
cout<<"avi file inf is received it contains"<< obj.dwStreams
<<"stream"<<endl;
PAVISTREAM ppavi,ppavi2;
if(AVIFileGetStream(hFile,&ppavi,streamtypeVIDEO,0)==AVIERR_OK )
cout<<"got stream interface "<<endl;
cout<<"_____________________________________________"<<endl;
if(AVIFileOpen(&hFile2,"D:\\Avi\\patient1\\name1.avi" ,OF_READ,
NULL)==AVIERR_OK )
cout<<"avi file 2 opened successfully"<<endl;
if(AVIFileGetStream(hFile2,&ppavi2,streamtypeVIDEO,0)==AVIERR_OK )
cout<<"got stream2 interface "<<endl;
PAVISTREAM pStreams[2]= { NULL, NULL };
cout<<"_____________________________________________"<<endl;
pStreams[0]=ppavi;
pStreams[1]=ppavi2;
PAVIFILE hFile3;
if(AVIMakeFileFromStreams(&hFile3,2,pStreams)==AVIERR_OK)
cout<<"avis are combined"<<endl;
//AVICOMPRESSOPTIONS gaAVIOptions[2];
if(AVISaveV("D:\\Avi\\target.avi",NULL,NULL,2,pStreams, NULL)==AVIERR_OK)
cout<<"avi combine has done"<<endl;
sukumar
|
|
|
|
|
Thanks! This is exactly what I need.
|
|
|
|
|
I tried the code but it won't compile.
Error says :-
stdafx.h: No such file or directory
mmsystem.h: No such file or directory
vfw.h: No such file or directory
what can I do about that?
Thanks a lot
|
|
|
|
|
I have lots of BMP images,i want to create a whole AVI video from lots of BMP images,but i do not know how and do not find enough information,Please Help me,Thanks!!!
|
|
|
|
|
Is it possible store top-down dibs into stream? (biHeight is negative)
If it is how can I do it (without image transformation)?
Thanks
Palo
|
|
|
|
|
If you want to write avi files many time! rember to chang the AVI_START as follow:
bool START_AVI(CString file_name)
{
pfile = NULL;
ps = NULL;
psCompressed = NULL;
count = 0;
//AfxMessageBox("AVI_Exit");
if(! AVI_Init())
{
AfxMessageBox("Error - AVI_Init()\n");
return false;
}
if(! AVI_FileOpenWrite(&pfile, file_name.GetBuffer(-1)))
{
AfxMessageBox("Error - AVI_FileOpenWrite()\n");
return false;
}
file_name.ReleaseBuffer(-1);
return true;
}
|
|
|
|
|
Compiling...
aaaDlg.cpp
Linking...
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIFileInit@0
aaaDlg.obj : error LNK2001: unresolved external symbol _VideoForWindowsVersion@0
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIFileOpenA@16
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIFileCreateStreamA@12
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIStreamSetFormat@16
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIMakeCompressedStream@16
aaaDlg.obj : error LNK2001: unresolved external symbol _AVISaveOptions@20
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIStreamWrite@32
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIStreamRelease@4
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIFileRelease@4
aaaDlg.obj : error LNK2001: unresolved external symbol _AVIFileExit@0
Debug/aaa.exe : fatal error LNK1120: 11 unresolved externals
Error executing link.exe.
-- modified at 3:24 Friday 12th May, 2006
LINK vfw32.lib cximage.lib zlib.lib jpeg.lib j2k.lib jasper.lib jbig.lib png.lib tiff.lib !!!!
|
|
|
|
|
Hi,
I checked your project. I suggest you use _T(...), so people can use in their
unicode projects without having to edit the files to get them compiling. Another suggestion is to really put the demo sample using the aviutil.h.
Thanks
Vipin
|
|
|
|
|
i used the code.it is really nice.it works normally.i start the avi file creation.after a few minutes i stop it.in the meanwhile i switch between windows.when i saw the avi the switched window is also there.how do i exactly extract the bitmaps from the window.
|
|
|
|
|
// get a BITMAP. This is not the same as a DIB!
HDC hdcCompatible = CreateCompatibleDC(0);
int w = GetDeviceCaps(hdcCompatible, HORZRES);
int h = GetDeviceCaps(hdcCompatible, VERTRES);
HBITMAP hbmScreen = CreateCompatibleBitmap(hdcCompatible, w, h);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcCompatible, hbmScreen);
HDC hdcScreen = GetDC(0);
BitBlt(hdcCompatible, 0, 0, w, h, hdcScreen, 0, 0, SRCCOPY);
ReleaseDC(0, hdcScreen);
// convert hbmScreen to a DIB. A DIB is really just a HANDLE
// to memory that contains a device independant representation
// of the BITMAP which can be written to a file (.bmp).
// To do this obtain and use dibutil.c and dibutil.h
// add DIB to AVI
ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, "DIB", 1);
Rod
|
|
|
|
|
hello,
could you help to transform a .tiff image series, which are visualize with Vision Common Box in a Visual C++ programm, in a .avi video ?
I don't very well Visual C++, MSDN, VCB .... I begin.
thank you
Dagim
|
|
|
|
|
How can I interface VfW in Vb.Net?
|
|
|
|
|
I do not do any programming in VB!
Rod
|
|
|
|
|
I am not able to understand how to use these functions which you had mentioned. So if possible please give me the complete source code for the same.
Thanking You
Rasik2005
|
|
|
|
|
<br />
<br />
<br />
<br />
<br />
if(! START_AVI("c:\\temp\\foo.avi"))<br />
{<br />
printf("Error - START_AVI()\n");<br />
return 1;<br />
}<br />
<br />
<br />
WIN32_FIND_DATA FindFileData;<br />
HANDLE hFind = NULL;<br />
char path[MAX_PATH] = {"\0"};<br />
strcpy(path, "c:\\temp\\images\\");<br />
char mask[MAX_PATH] = {"\0"};<br />
sprintf(mask, "%s%s", path, "*.jpg");<br />
char currentFile[MAX_PATH] = {"\0"};<br />
int frameRate = 30;<br />
char compressor[64] = {"\0"};<br />
strcpy(compressor, "DIB");<br />
if((hFind = FindFirstFile(mask, &FindFileData)) != INVALID_HANDLE_VALUE)<br />
{<br />
sprintf(currentFile, "%s%s", path, FindFileData.cFileName);<br />
printf("loading %s\n", currentFile);<br />
if(! ADD_FRAME_FROM_DIB_TO_AVI((new CxImage(currentFile, CXIMAGE_FORMAT_JPG))->GetDIB(), compressor, frameRate))<br />
{<br />
printf("Error - ADD_FRAME_FROM_DIB_TO_AVI()\n");<br />
return 1;<br />
}<br />
<br />
while(FindNextFile(hFind, &FindFileData))<br />
{<br />
sprintf(currentFile, "%s%s", path, FindFileData.cFileName);<br />
printf("loading %s\n", currentFile);<br />
if(! ADD_FRAME_FROM_DIB_TO_AVI((new CxImage(currentFile, CXIMAGE_FORMAT_JPG))->GetDIB(), compressor, frameRate))<br />
{<br />
printf("Error - ADD_FRAME_FROM_DIB_TO_AVI()\n");<br />
return 1;<br />
}<br />
}<br />
<br />
FindClose(hFind);<br />
}<br />
<br />
<br />
if(! STOP_AVI())<br />
{<br />
printf("Error - STOP_AVI()\n");<br />
return 1;<br />
}<br />
|
|
|
|
|
hi :
i want used ADD_FRAME_FROM_DIB_TO_AVI to create an avi from some bmp(0.bmp 1.bmp .... 20.bmp).
what can i do ?
|
|
|
|
|
Very nice! Thank you. Could you be so kind as to illustrate how one would implement a function ADD_FRAME_FROM_BUFFER_TO_AVI that would take a pointer to a buffer holding the bit data?
Thank you
|
|
|
|
|
You will need to pass in the address of a DIB(not a HBitmap).
CxImage img("c:\\temp\\foo.png", CXIMAGE_FORMAT_PNG); // for a .png
ADD_FRAME_FROM_DIB_TO_AVI(&img.GetDIB(), "CVID" /* or DIB */, 25); // for example (aviUtil.h)
or you can hack the ADD_FRAME_FROM_DIB_TO_AVI() function to take a LPBITMAPINFOHEADER instead of a DIB.
Hope that helps!
Rod
Rod
|
|
|
|
|
Is there a way that doesn't use the CxImage library loading from a file? I do not have an existing file, only direct draw surface data. Here's a bit of additional detail about what I'm doing and what I hope to do:
First I have:
CBitmap* bitmap = a_pImageView->GetBitmap();
The GetBitmap() method basically initializes a buffer to a predefined size:
int iSize = m_iAcquisitionWindowWidth * m_iAcquisitionWindowHeight;
BYTE* ImageBuffer = new BYTE[iSize*4];
InitializeBuffer(ImageBuffer, iSize*4);
and then calls another method to populate the buffer. This is accomplished by copying the bits from a direct-draw surface into the buffer:
.. (snip)
DDSURFACEDESC ddsd;
memset( &ddsd, 0, sizeof(ddsd) );
ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_pSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
if ( res == DD_OK )
{
CopySurfaceToBuffer(a_pBuffer, &ddsd, a_iNumBytes);
m_pSurface->Unlock(NULL);
}
.. (snip)
BOOL CViewer::CopySurfaceToBuffer(BYTE* a_pBuffer, DDSURFACEDESC *a_pDDSD, int a_iNumBytes)
.. (snip)
for( xx = 0, yy = 0; xx < a_iNumBytes; xx++, yy += 4)
{
// copy values to the buffer
a_pBuffer[yy] = ( (BYTE*) a_pDDSD->lpSurface)[yy]; // blue
a_pBuffer[yy+1] = ( (BYTE*) a_pDDSD->lpSurface)[yy+1]; // green
a_pBuffer[yy+2] = ( (BYTE*) a_pDDSD->lpSurface)[yy+2]; // red
//a_pBuffer[yy+3] = ( (BYTE*) a_pDDSD->lpSurface)[yy+3]; // in 32bpp this is the transparency bit, ignore for now.
}
break;
.. (snip)
----------
Finally once the buffer is populated with the data copied from the direct draw surface, I CreateBitmap:
pBitmap->CreateBitmap(m_iAcquisitionWindowWidth, m_iAcquisitionWindowHeight, 1, 32, ImageBuffer);
So, you can see my buffer contains data as captured from the direct-draw surface. I also have an instance of CBitmap
I would like to pass the buffer itself or the CBitmap, whichever makes more sense, to ADD_FRAME_FROM_DIB_TO_AVI or a similar method but I'm unsure as to how I need to proceed.
thanks!
-Paul
|
|
|
|
|