{AVI file format} unit fmt_AVI; {$include compilers.inc} interface uses wat_api; function ReadAVI(var Info:tSongInfo):boolean; cdecl; implementation uses windows,common,io,srv_format; type FOURCC = array [0..3] of AnsiChar; type tChunkHeader = packed record case byte of 0: (Lo,Hi:dword); {Common} 1: (ID:FOURCC; {RIFF} Length:dword); end; const sRIFF = $46464952; sLIST = $5453494C; savih = $68697661; { avi header } sstrf = $66727473; { stream format } sstrh = $68727473; { stream header } const smovi = $69766F6D; {movi list type} const svids = $73646976; {video} sauds = $73647561; {audio} const sIART = $54524149; {director} sICMT = $544D4349; {comment} sICRD = $44524349; {creation date} sIGNR = $524E4749; {genre} sINAM = $4D414E49; {title} sIPRT = $54525049; {part} sIPRO = $4F525049; {produced by} sISBJ = $4A425349; {subject description} type tWaveFormatEx = packed record wFormatTag :word; nChannels :word; nSamplesPerSec :dword; nAvgBytesPerSec:dword; nBlockAlign :word; wBitsPerSample :word; cbSize :word; Reserved1 :word; wID :word; fwFlags :word; nBlockSize :word; nFramesPerBlock:word; nCodecDelay :word; {ms} end; type tMainAVIHeader = packed record {avih} dwMicroSecPerFrame :dword; dwMaxBytesPerSec :dword; dwPaddingGranularity :dword; dwFlags :dword; dwTotalFrames :dword; { # frames in first movi list} dwInitialFrames :dword; dwStreams :dword; dwSuggestedBufferSize:dword; dwWidth :dword; dwHeight :dword; dwScale :dword; dwRate :dword; dwStart :dword; dwLength :dword; end; type TAVIExtHeader = packed record {dmlh} dwGrandFrames:dword; {total number of frames in the file} dwFuture:array[0..60] of dword; end; type tAVIStreamHeader = packed record {strh} fccType :FOURCC; {vids|auds} fccHandler :FOURCC; dwFlags :dword; wPriority :word; wLanguage :word; dwInitialFrames :dword; dwScale :dword; dwRate :dword; dwStart :dword; dwLength :dword; dwSuggestedBufferSize:dword; dwQuality :dword; dwSampleSize :dword; rcFrame: packed record left :word; top :word; right :word; bottom:word; end; end; var vora:dword; procedure Skip(f:THANDLE;bytes:dword); var i:dword; begin i:=FilePos(f); if bytes=0 then begin if odd(i) then Seek(f,i+1); end else Seek(f,i+bytes+(bytes mod 2)); end; procedure ProcessVideoFormat(f:THANDLE;Size:dword;var Info:tSongInfo); var bih:BitmapInfoHeader; begin BlockRead(f,bih,SizeOf(bih)); Info.codec :=bih.biCompression; Info.width :=bih.biWidth; Info.height:=bih.biHeight; Skip(f,Size-SizeOf(bih)); end; procedure ProcessAudioFormat(f:THANDLE;Size:dword;var Info:tSongInfo); {WAVEFORMATEX or PCMWAVEFORMAT} var AF:tWaveFormatEx; begin BlockRead(f,AF,SizeOf(AF)); Info.channels:=AF.nChannels; Info.khz :=AF.nSamplesPerSec div 1000; Info.kbps :=(AF.nAvgBytesPerSec*8) div 1000; Skip(f,Size-SizeOf(AF)); end; function ProcessASH(f:THANDLE;var Info:tSongInfo):dword; var ASH:tAVIStreamHeader; begin BlockRead(f,ASH,SizeOf(ASH)); with ASH do begin if dword(fccType)=svids then begin if ASH.dwScale<>0 then Info.fps:=(ASH.dwRate*100) div ASH.dwScale; if Info.fps<>0 then Info.total:=(ASH.dwLength*100) div Info.fps; ProcessASH:=1 end else if dword(fccType)=sauds then ProcessASH:=2 else ProcessASH:=0; end; end; procedure ProcessMAH(f:THANDLE;var Info:tSongInfo); var MAH:tMainAVIHeader; begin BlockRead(f,MAH,SizeOf(MAH)); // Info.width:=MAH.dwWidth; // Info.height:=MAH.dwHeight; // Info.fps:=100000000 div MAH.dwMicroSecPerFrame; end; function ProcessChunk(f:THANDLE;var Info:tSongInfo):dword; var lTotal:dword; Chunk:tChunkHeader; cType:FOURCC; ls:PAnsiChar; begin Skip(f,0); if (BlockRead(f,Chunk,SizeOF(Chunk))=0) or (Chunk.Lo=0) then begin result:=FileSize(f); Seek(f,FileSize(f)); exit; end; result:=Chunk.Length+SizeOf(Chunk); case Chunk.Lo of sRIFF,sLIST: begin BlockRead(f,cType,SizeOf(cType)); if dword(cType)=smovi then Skip(f,Chunk.Length-SizeOf(cType)) // result:=FileSize(f) else begin lTotal:=SizeOf(FOURCC); while lTotal