1
|
1
|
|
2 void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){
|
|
3
|
|
4 fwrite(&id,4,1,f);
|
|
5 fwrite(&len,4,1,f);
|
|
6 if(len>0){
|
|
7 if(data){
|
|
8 // DATA
|
|
9 fwrite(data,len,1,f);
|
|
10 if(len&1){ // padding
|
|
11 unsigned char zerobyte=0;
|
|
12 fwrite(&zerobyte,1,1,f);
|
|
13 }
|
|
14 } else {
|
|
15 // JUNK
|
|
16 char *avi_junk_data="[= MPlayer junk data! =]";
|
|
17 if(len&1) ++len; // padding
|
|
18 while(len>0){
|
|
19 int l=strlen(avi_junk_data);
|
|
20 if(l>len) l=len;
|
|
21 fwrite(avi_junk_data,l,1,f);
|
|
22 len-=l;
|
|
23 }
|
|
24 }
|
|
25 }
|
|
26
|
|
27 }
|
|
28
|
|
29
|
|
30 void write_avi_list(FILE *f,unsigned int id,int len){
|
|
31 unsigned int list_id=FOURCC_LIST;
|
|
32 len+=4; // list fix
|
|
33 fwrite(&list_id,4,1,f);
|
|
34 fwrite(&len,4,1,f);
|
|
35 fwrite(&id,4,1,f);
|
|
36 }
|
|
37
|
|
38 struct {
|
|
39 MainAVIHeader avih;
|
|
40 AVIStreamHeader video;
|
|
41 BITMAPINFOHEADER bih;
|
|
42 unsigned int movi_start;
|
|
43 unsigned int movi_end;
|
|
44 unsigned int file_end;
|
|
45 } wah;
|
|
46
|
|
47 void write_avi_header(FILE *f){
|
|
48 unsigned int riff[3];
|
|
49 // RIFF header:
|
|
50 riff[0]=mmioFOURCC('R','I','F','F');
|
|
51 riff[1]=wah.file_end; // filesize
|
|
52 riff[2]=formtypeAVI; // 'AVI '
|
|
53 fwrite(&riff,12,1,f);
|
|
54 // AVI header:
|
|
55 write_avi_list(f,listtypeAVIHEADER,sizeof(wah.avih)+8+12+sizeof(wah.video)+8+sizeof(wah.bih)+8);
|
|
56 write_avi_chunk(f,ckidAVIMAINHDR,sizeof(wah.avih),&wah.avih);
|
|
57 // stream header:
|
|
58 write_avi_list(f,listtypeSTREAMHEADER,sizeof(wah.video)+8+sizeof(wah.bih)+8);
|
|
59 write_avi_chunk(f,ckidSTREAMHEADER,sizeof(wah.video),&wah.video);
|
|
60 write_avi_chunk(f,ckidSTREAMFORMAT,sizeof(wah.bih),&wah.bih);
|
|
61 // JUNK:
|
|
62 write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL);
|
|
63 // 'movi' header:
|
|
64 write_avi_list(f,listtypeAVIMOVIE,wah.movi_end-ftell(f)-12);
|
|
65 wah.movi_start=ftell(f);
|
|
66 }
|
|
67
|
|
68 // called _before_ encoding: (write placeholders and video info)
|
|
69 void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height){
|
|
70 int frames=8*3600*fps; // 8 hours
|
|
71
|
|
72 wah.file_end=
|
|
73 wah.movi_end=0x7f000000;
|
|
74
|
|
75 wah.avih.dwMicroSecPerFrame=1000000.0f/fps;
|
|
76 wah.avih.dwMaxBytesPerSec=fps*500000; // ?????
|
|
77 wah.avih.dwPaddingGranularity=1; // padding
|
|
78 wah.avih.dwFlags=AVIF_ISINTERLEAVED;
|
|
79 wah.avih.dwTotalFrames=frames;
|
|
80 wah.avih.dwInitialFrames=0;
|
|
81 wah.avih.dwStreams=1;
|
|
82 wah.avih.dwSuggestedBufferSize=0x10000; // 1MB
|
|
83 wah.avih.dwWidth=width;
|
|
84 wah.avih.dwHeight=height;
|
|
85 wah.avih.dwReserved[0]=
|
|
86 wah.avih.dwReserved[1]=
|
|
87 wah.avih.dwReserved[2]=
|
|
88 wah.avih.dwReserved[3]=0;
|
|
89
|
|
90 wah.video.fccType=streamtypeVIDEO;
|
|
91 wah.video.fccHandler=fcc;
|
|
92 wah.video.dwFlags=0;
|
|
93 wah.video.wPriority=0;
|
|
94 wah.video.wLanguage=0;
|
|
95 wah.video.dwInitialFrames=0;
|
|
96 wah.video.dwScale=10000;
|
|
97 wah.video.dwRate=fps*10000;
|
|
98 wah.video.dwStart=0;
|
|
99 wah.video.dwLength=frames;
|
|
100 wah.video.dwSuggestedBufferSize=0x100000; // 1MB ????
|
|
101 wah.video.dwQuality=10000;
|
|
102 wah.video.dwSampleSize=width*height*3;
|
|
103
|
|
104 wah.bih.biSize=sizeof(wah.bih); // 40 ?
|
|
105 wah.bih.biWidth=width;
|
|
106 wah.bih.biHeight=height;
|
|
107 wah.bih.biPlanes=1;
|
|
108 wah.bih.biBitCount=24;
|
|
109 wah.bih.biCompression=fcc;
|
|
110 wah.bih.biSizeImage=3*width*height;
|
|
111 wah.bih.biXPelsPerMeter=
|
|
112 wah.bih.biYPelsPerMeter=
|
|
113 wah.bih.biClrUsed=
|
|
114 wah.bih.biClrImportant=0;
|
|
115
|
|
116 write_avi_header(f);
|
|
117 }
|
|
118
|
|
119 void avi_fixate(){
|
|
120 // append index and fix avi headers:
|
|
121 FILE *f1=fopen(encode_name,"r+");
|
|
122 FILE *f2;
|
|
123
|
|
124 if(!f1) return; // error
|
|
125
|
|
126 fseek(f1,0,SEEK_END);
|
|
127 wah.file_end=wah.movi_end=ftell(f1);
|
|
128
|
|
129 // index:
|
|
130 if(encode_index_name && (f2=fopen(encode_index_name,"rb"))){
|
|
131 AVIINDEXENTRY idx;
|
|
132 unsigned int pos=0;
|
|
133 int frames=0;
|
|
134 write_avi_chunk(f1,ckidAVINEWINDEX,0,NULL);
|
|
135 while(fread(&idx,sizeof(idx),1,f2)>0){
|
|
136 idx.dwChunkOffset-=wah.movi_start-4;
|
|
137 fwrite(&idx,sizeof(idx),1,f1);
|
|
138 ++frames;
|
|
139 }
|
|
140 fclose(f2);
|
|
141 unlink(encode_index_name);
|
|
142 wah.file_end=ftell(f1);
|
|
143 // re-write idx1 length:
|
|
144 pos=wah.file_end-wah.movi_end-8;
|
|
145 fseek(f1,wah.movi_end+4,SEEK_SET);
|
|
146 fwrite(&pos,4,1,f1);
|
|
147 // fixup frames:
|
|
148 wah.avih.dwTotalFrames=frames;
|
|
149 wah.video.dwLength=frames;
|
|
150 }
|
|
151
|
|
152 // re-write avi header:
|
|
153 fseek(f1,0,SEEK_SET);
|
|
154 write_avi_header(f1);
|
|
155
|
|
156 fclose(f1);
|
|
157
|
|
158 }
|
|
159
|
|
160
|
|
161
|