//avi.c
#include "stdafx.h"#include "avi.h"
#include <string.h>#include <stdio.h>#include <stdlib.h>
// header flags
const u32 AVIF_HASINDEX = 0x00000010; /* index at end of file */const u32 AVIF_MUSTUSEINDEX=0x00000020;const u32 AVIF_ISINTERLEAVED=0x00000100;const u32 AVIF_TRUSTCKTYPE=0x00000800;const u32 AVIF_WASCAPTUREFILE=0x00010000;const u32 AVIF_COPYRIGHTED=0x00020000;
int nframes;int totalsize;unsigned int* sizes;
void bzero(void *s, int n){ memset(s,0,n);}
void fprint_quartet(/*int fd*/FILE * fp, unsigned int i){ char data[4]; int rt = 0;
data[0] = (char) i%0x100; i /= 0x100; data[1] = (char) i%0x100; i /= 0x100; data[2] = (char) i%0x100; i /= 0x100; data[3] = (char) i%0x100;
/*write( fd, &data, 4 );*/ rt = fwrite(&data, 4, 1, fp); if(rt != 1) printf(" fprintf_quartet failed! /n ");}
// start writing an AVI file
void __stdcall avi_start(/*int fd*/FILE * fp, int frames){ int ofs = sizeof(struct riff_head)+ sizeof(struct list_head)+ sizeof(struct avi_head)+ sizeof(struct list_head)+ sizeof(struct stream_head)+ sizeof(struct frame_head)+ sizeof(struct list_head)+ sizeof(struct dmlh_head)+ sizeof(struct list_head);
printf( "avi_start: frames = %d/n", frames ); printf( "avi_start: ofs = %d/n", ofs );
/* lseek(fd, ofs, SEEK_SET);*/ fseek(fp,ofs, SEEK_SET);
nframes = 0; totalsize = 0;
sizes = (unsigned int*) calloc( sizeof(unsigned int), frames ); // hold size of each frame}
// add a jpeg frame to an AVI file void __stdcall avi_add(/*int fd*/FILE * fp, u8 *buf, int size){ struct db_head db = {"00db", 0};
printf( "avi_add: nframes = %d, totalsize = %d, size = %d/n", nframes, totalsize, size );
// overwrite JFIF type with AVI1 /*buf[6]='A'; buf[7]='V'; buf[8]='I'; buf[9]='1';*/
//while( size%4 ) // size++; // align 0 modulo 4*/ db.size = size;
/*write( fd, &db, sizeof(db) );*/ fwrite( &db, sizeof(db),1, fp);
/*write( fd, buf, size );*/ fwrite( buf, size,1, fp);
sizes[nframes] = size;
nframes++; totalsize += size; // total frame size}
// finish writing the AVI file - filling in the header void __stdcall avi_end(/*int fd*/FILE * fp, int width, int height, int fps){ struct idx1_head idx = {"idx1", 16*nframes }; struct db_head db = {"00db", 0}; struct riff_head rh = { "RIFF", 0, "AVI "}; struct list_head lh1 = {"LIST", 0, "hdrl"}; struct avi_head ah; struct list_head lh2 = {"LIST", 0, "strl"}; struct stream_head sh; struct frame_head fh; struct list_head lh3 = {"LIST", 0, "odml" }; struct dmlh_head dh = {"dmlh", 4, nframes }; struct list_head lh4 = {"LIST", 0, "movi"}; int i; unsigned int offset = 4;
printf( "avi_end: nframes = %d, fps = %d/n", nframes, fps );
// write index
/*write(fd, &idx, sizeof(idx));*/ fwrite(&idx, sizeof(idx), 1, fp);
for ( i = 0; i < nframes; i++ ) { //write(fd, &db, 4 ); // only need the 00db fwrite(&db, 4, 1, fp); fprint_quartet( fp/*fd*/, 18 ); // ??? fprint_quartet( fp/*fd*/, offset ); fprint_quartet( fp/*fd*/, sizes[i] ); offset += sizes[i] + 8; //+8 (for the additional header) }
free( sizes );
bzero( &ah, sizeof(ah) ); strcpy(ah.avih, "avih"); ah.time = 1000000 / fps; ah.maxbytespersec = 1000000.0*(totalsize/nframes)/ah.time; ah.nframes = nframes; ah.numstreams = 1; ah.flags = AVIF_HASINDEX; ah.width = width; ah.height = height;
bzero(&sh, sizeof(sh)); strcpy(sh.strh, "strh"); strcpy(sh.vids, "vids"); strcpy(sh.codec, "MJPG"); sh.scale = ah.time; sh.rate = 1000000; sh.length = nframes;
bzero(&fh, sizeof(fh)); strcpy(fh.strf, "strf"); fh.width = width; fh.height = height; fh.planes = 1; fh.bitcount = 24; strcpy(fh.codec,"MJPG"); fh.unpackedsize = 3*width*height;
rh.size = sizeof(lh1)+sizeof(ah)+sizeof(lh2)+sizeof(sh)+ sizeof(fh)+sizeof(lh3)+sizeof(dh)+sizeof(lh4)+ nframes*sizeof(struct db_head)+ totalsize + sizeof(struct idx1_head)+ (16*nframes) +4; // FIXME:16 bytes per nframe // the '4' - what for???
lh1.size = 4+sizeof(ah)+sizeof(lh2)+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); ah.size = sizeof(ah)-8; lh2.size = 4+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); //4+sizeof(sh)+sizeof(fh); sh.size = sizeof(sh)-8; fh.size = sizeof(fh)-8; fh.size2 = fh.size; lh3.size = 4+sizeof(dh); lh4.size = 4+ nframes*sizeof(struct db_head)+ totalsize;
/*lseek(fd, 0, SEEK_SET);*/ fseek(fp,0, SEEK_SET);
/* write(fd, &rh, sizeof(rh));*/ fwrite( &rh, sizeof(rh), 1, fp); /* write(fd, &lh1, sizeof(lh1));*/ fwrite( &lh1, sizeof(lh1), 1, fp); /*write(fd, &ah, sizeof(ah));*/ fwrite( &ah, sizeof(ah), 1, fp); /* write(fd, &lh2, sizeof(lh2));*/ fwrite( &lh2, sizeof(lh2), 1, fp); /*write(fd, &sh, sizeof(sh));*/ fwrite( &sh, sizeof(sh), 1, fp); /*write(fd, &fh, sizeof(fh));*/ fwrite( &fh, sizeof(fh), 1, fp); /* write(fd, &lh3, sizeof(lh3));*/ fwrite(&lh3, sizeof(lh3), 1, fp); /* write(fd, &dh, sizeof(dh));*/ fwrite(&dh, sizeof(dh), 1, fp); /* write(fd, &lh4, sizeof(lh4));*/ fwrite(&lh4, sizeof(lh4), 1, fp);}//avi.h
#ifndef AVI_H#define AVI_H
//#include <unistd.h>
#include <string.h>#include <stdio.h>#include <sys/types.h>
#ifdef __cplusplusextern "C" {#endif
void bzero(void *s, int n);
typedef unsigned char u8;typedef unsigned short u16;typedef unsigned u32;
// function prototypes
__declspec(dllexport) void __stdcall avi_start(/*int fd*/FILE * fp, int frame); __declspec(dllexport) void __stdcall avi_add(/*int fd*/FILE * fp, u8 *buf, int size); __declspec(dllexport) void __stdcall avi_end(/*int fd*/FILE * fp, int width, int height, int fps);void fprint_quartet(/*int fd*/FILE * fp, unsigned int i);
// the following structures are ordered as they appear in a typical AVI
struct riff_head { char riff[4]; // chunk type = "RIFF" u32 size; // chunk size char avistr[4]; // avi magic = "AVI "};
// the avih chunk contains a number of list chunks
struct avi_head { char avih[4]; // chunk type = "avih" u32 size; // chunk size u32 time; // microsec per frame == 1e6 / fps u32 maxbytespersec; // = 1e6*(total size/frames)/per_usec) u32 pad; // pad = 0 u32 flags; // e.g. AVIF_HASINDEX u32 nframes; // total number of frames u32 initialframes; // = 0 u32 numstreams; // = 1 for now (later = 2 because of audio) u32 suggested_bufsize; // = 0 (no suggestion) u32 width; // width u32 height; // height u32 reserved[4]; // reserved for future use = 0};
// the LIST chunk contains a number (==#numstreams) of stream chunks
struct list_head { char list[4]; // chunk type = "LIST" u32 size; char type[4];};
struct dmlh_head { char dmlh[4]; // chunk type dmlh u32 size; // 4 u32 nframes; // number of frames};
struct stream_head { char strh[4]; // chunk type = "strh" u32 size; // chunk size char vids[4]; // stream type = "vids" char codec[4]; // codec name (for us, = "MJPG") u32 flags; // contains AVIT_F* flags u16 priority; // = 0 u16 language; // = 0 u32 initialframes; // = 0 u32 scale; // = usec per frame u32 rate; // 1e6 u32 start; // = 0 u32 length; // number of frames u32 suggested_bufsize; // = 0 u32 quality; // = 0 ? u32 samplesize; // = 0 ?};
struct db_head { char db[4]; // "00db" u32 size;};
// a frame chunk contains one JPEG image
struct frame_head { char strf[4]; // chunk type = "strf" u32 size; // sizeof chunk (big endian) ? u32 size2; // sizeof chunk (little endian) ? u32 width; u32 height; u16 planes; // 1 bitplane u16 bitcount; // 24 bpl char codec[4]; // MJPG (for us) u32 unpackedsize; // = 3*w*h u32 r1; // reserved u32 r2; // reserved u32 clr_used; // reserved u32 clr_important; // reserved};
struct idx1_head { char idx1[4]; // chunk type = "idx1" u32 size; // chunk size};
#ifdef __cplusplus}#endif
#endif
//delphi中
unit Avi;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, jpeg;
procedure avi_start(fp : TFileStream; frame : Integer); stdcall;external 'avidll.dll' ;procedure avi_add(fp : TFileStream; buf : PByte; size : Integer); stdcall;external 'avidll.dll' ;procedure avi_end(fp : TFileStream; width, height, fps : Integer); stdcall;external 'avidll.dll' ;
type db_head = record db : array [0..3] of char; // "00db" size : Word; end;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);var fp2, PicFile : TFileStream; PData1, PData2 : ^Byte; Size1 : Integer; Sr : TSearchRec; FileName, PicPath : String; //buf: array[0..100-1] of Byte; //I : Integer; db : db_head;begin try FileName := 'F:/avi/AviDemo/test.avi'; //fp2 := nil; fp2 := TFileStream.Create(FileName,fmOpenWrite);
{for I := 0 to 99 do begin buf[I] := I + 1; end;} try fp2.Seek(240,soFromBeginning); {fp2.Write(buf,99); Exit;} except end; //tempstream.Create(''); {try avi_start(fp2, 300); except on E:Exception do begin ShowMessage('初始化时发生错误,原因:' + E.Message); Exit; end; end; } Size1 := 0; PicPath := 'E:/Console/AlarmControlClient/13Dev/20090824/8HH/40NN/'; if FindFirst(PicPath + '*.jpg',0,Sr) = 0 then begin repeat if ExtractFileExt(Sr.Name) = '.jpg' then begin Size1 := Sr.Size; PicFile := TFileStream.Create(PicPath + Sr.Name,fmOpenRead); PicFile.Read(PData1,Size1); StrPCopy(db.db,'00db'); db.size := Size1; fp2.Write(db,SizeOf(db)); fp2.Write(PData1,Size1); //fwrite( &db, sizeof(db),1, fp);fwrite( buf, size,1, fp);
//avi_add(fp2,PData1,Size1); end; until FindNext(Sr) <> 0; FindClose(Sr); end; //avi_end(fp2,352,288,12); finally //MYJpeg.Free; fp2.Free; end;end;
procedure TForm1.Button2Click(Sender: TObject);var FileName : string; FHandle : Integer;begin FileName := 'Test.avi'; if(not fileExists(FileName))then begin FHandle := FileCreate(FileName); FileClose(FHandle); ShowMessage('创建成功'); end;end;
end.
TMemoryStream.LoadFromFile('')
Load之后 TStream,有个Memory属性. 是指针类型 它指向数据流的开始处 Size属性是它的大小 var pData: PByte; ...... pData := YourStream.Memory; 然后就象一般的内存那样用了,比如内存拷贝: copyMemory(pDest, pData, YourStream.Size)
用TMemoryStream,LoadFromFileTMemoryStream,LoadFromStreamTMemoryStream,WriteMemory
PositionSize
http://blog.csdn.net/happydeer/archive/2004/04/16/8775.aspx
http://www.delphi-jedi.org/apilibrary.html