//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 __cplusplus
extern "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,LoadFromFile
TMemoryStream,LoadFromStream
TMemoryStream,Write
Memory
Position
Size
http://blog.csdn.net/happydeer/archive/2004/04/16/8775.aspx