Sample code to parse an AVI header - uncompressed files, no audio, as created by VirtualDub. Supports 8.16 and 24bits per pixel
These are pulled from working applications - there will be bits you will need to tidy up but should be obvious-ish, and there will be some superfluous stuff .
Cross-reference between C and VB versions if necessary to figure out details.
After calling, the variable avi_start will hold the file offset of the first frame. Subsequent frames will be at (framesize)+8 byte intervals from there
---------------------------------------------------------------------------------------------------------------------------------------------
Dim avi_start As Long, avi_bpp As Long, avi_frames As Long,
avi_framesize As Long, aviname As String
Private Function fgw(ofs As Long) As Long
' gets a 32 bit value form file
Dim l As Long
Seek #1, ofs + 1
Get #1, , l
fgw = l
End Function
Private Function openavi() As Integer
Dim avibad As Integer
Dim e As String, s As String, ff As String, a As Integer
Dim l As Long, i As Integer, j As Integer
Dim fr As Long, smval As Long
Dim ll As Long, headerbuf(0 To 64) As Byte
Dim fp As Long, cn As Long, cl As Long, X As Long, Y As Long
Dim ox As Long, oy As Long, obpp As Long, bpp As Long, flen As Long
Dim smv As Long
avibad = 1
avi_start = 0
CommonDialog1.FileName = ""
CommonDialog1.DialogTitle = "Open AVI File"
CommonDialog1.CancelError = True
CommonDialog1.DefaultExt = ".avi"
CommonDialog1.Filter = "Uncompressed 5:6:5 AVI files (*.AVI)|*.AVI"
On Error GoTo loaderror ' in case of cancel
CommonDialog1.ShowOpen
bfname = CommonDialog1.FileName
aviname = bfname
On Error Resume Next
Open bfname For Input As #1
If Err.Number <> 0 Then MsgBox "Error opening " + bfname, ,
"Doh!"
On Error GoTo 0
Close #1
Open bfname For Binary As #1
If fgw(8) <> &H20495641 Then MsgBox "Not an AVI File :" + f: GoTo
badavi
fp = &HC
cn = fgw(fp)
cl = fgw(fp + 4)
If cn <> &H5453494C Then MsgBox ("Header LIST not found " + f): GoTo
badavi 'hdrl
If fgw(fp + 8) <> &H6C726468 Then MsgBox ("hdr chunk not found " + f):
GoTo badavi
fr = fgw(fp + &H14) ' frame rate in microsecs
avi_frames = fgw(fp + &H24) ' frames in file
ox = 240: oy = 240 ' desired size for error check
obpp = 2
X = fgw(fp + &H34)
Y = fgw(fp + &H38)
Do
fp = fp + cl + 8 ' -> next chunk
cn = fgw(fp) ' name of chunk
cl = fgw(fp + 4) ' length
Loop Until (cn = &H5453494C) Or fp > LOF(1)
If cn <> &H5453494C Then MsgBox ("Stream LIST not found " + f): GoTo
badavi 'hdrl
If fgw(fp + 8) <> &H69766F6D Then MsgBox ("movi chunk not found " +
f): GoTo badavi
fp = fp + 12
If fgw(fp) <> &H63643030 And fgw(fp) <> &H62643030 Then MsgBox
"00dc marker not found " + f: GoTo badavi
flen = fgw(fp + 4)
bpp = flen / (X * Y) ' bytes per pixel
If X <> ox Or Y <> oy Then MsgBox ("Not correct size (Appears to be
" + Format(X, "0") + " x " + Format(Y, "0") + "
Pixels) * " + Format(bpp, "0") + " Bytes/pixel " + f): GoTo
badavi
If bpp < obpp Then MsgBox "AVI has insufficient colour depth AVI =" +
Format(bpp, "0") + " Want >= " + Format(obpp, "0"): GoTo
badavi
avi_start = fp + 8 ' globals for play
avi_bpp = bpp
avi_framesize = X * Y * avi_bpp
avibad = 0
loaderror:
badavi:
If avibad <> 0 Then Close #1
openavi = avibad
End Function
___________________________________________________________________________________________________
C version ( Microchip
C30) using Microchip filesystem library
Note this is expecting a monochrome AVI - tweak bpp value check for 16bpp - see VB
code for reference if necessary
/===========================================================================
avi parsing stuff
unsigned long framerate,framelen,totframes,avistart,framenum;
unsigned int xpixels,ypixels;
FSFILE *fptr;
//=================================================================================
char fileerror=0;
unsigned long fgw(unsigned long offset)
{ // get word from offset in file
unsigned long d;
FSfseek(fptr,offset,SEEK_SET);
FSfread(&d,1,4,fptr);
return(d);
}
#define avihdrlen 0x80 // buffer for reading AVI header
char avibuf[avihdrlen];
unsigned long mgw(unsigned long offset) // return long at arbitary alignment from avi
buffer, faster than using fgw
{
return(avibuf[offset]|((unsigned long)avibuf[offset+1]<<8)|((unsigned
long)avibuf[offset+2]<<16)|((unsigned long)avibuf[offset+3]<<24));
}
//================================================================= openavi
char openavi(char fnum)//
{
char filenamebuf[13];
unsigned int xp;
unsigned long chunknum,chunklen,fileofs;
fptr=NULL;
filenamebuf[0]='F';
filenamebuf[1]=(fnum/10)+'0';
filenamebuf[2]=(fnum%10)+'0';
filenamebuf[3]='.';
filenamebuf[4]='A';
filenamebuf[5]='V';
filenamebuf[6]='I';
filenamebuf[7]=0;
fptr=FSfopen(filenamebuf,READ);
if(fptr==NULL) return(1); // file not found
FSfread(&avibuf,1,avihdrlen,fptr); // read first block to RAM buffer to avoid lots of
slow seeks and short reads, saves ~250mS
if(mgw(8) != 0x20495641) return(2); // not AVI
fileofs=0x0c;
chunknum=mgw(fileofs);
chunklen=mgw(fileofs+4);
if(chunknum!=0x5453494c) return(2); // Header LIST not found
if(mgw(fileofs+8)!=0x6c726468) return(2); // hdr chunk not found
framerate=mgw(fileofs+0x14); // frame period in microseconds
totframes=mgw(fileofs+0x24); // total frames
xpixels=mgw(fileofs+0x34);
ypixels=mgw(fileofs+0x38);
do {
fileofs=fileofs+chunklen+8;
chunknum=fgw(fileofs);
chunklen=fgw(fileofs+4);
} while ((chunknum!=0x5453494c) && (!FSfeof(fptr)));
if(chunknum!=0x5453494c) return(2); //Stream LIST not found
if(fgw(fileofs+8)!=0x69766f6d) return(2); // movi chunk not found
fileofs+=12;
chunknum=fgw(fileofs);
if((chunknum&0xfeffffff)!=0x62643030) return(2); // 00dc not found
framelen=fgw(fileofs+4);
xp=xpixels;while(xp&3) xp++; // round up to 4 bytes
if(framelen!=xp*ypixels) return(3); // not 8bpp
if(framelen>dmxbufsize-8) return(4); // frame too big for buffer
if(xpixels!=linelength_avi) return(5);
if(ypixels!=height) return(6);
avistart=fileofs+8;
framenum=0;
return(0);
}