author | mickeyl <mickeyl> | 2003-04-18 00:37:32 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-04-18 00:37:32 (UTC) |
commit | 81776eb70dcad6748b8494ff13fbd048c60c1fae (patch) (unidiff) | |
tree | 9bb13dc582ccfd79e934ee30f6b647046b7a35c3 /noncore/multimedia/camera/jpegtoavi/jpegtoavi.c | |
parent | 39c72eb2d35aecb3a057b347df5231d1dbfdd37c (diff) | |
download | opie-81776eb70dcad6748b8494ff13fbd048c60c1fae.zip opie-81776eb70dcad6748b8494ff13fbd048c60c1fae.tar.gz opie-81776eb70dcad6748b8494ff13fbd048c60c1fae.tar.bz2 |
add jpeg2avi for postprocessing a series of jpeg frames into an avi
Diffstat (limited to 'noncore/multimedia/camera/jpegtoavi/jpegtoavi.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/multimedia/camera/jpegtoavi/jpegtoavi.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/noncore/multimedia/camera/jpegtoavi/jpegtoavi.c b/noncore/multimedia/camera/jpegtoavi/jpegtoavi.c new file mode 100644 index 0000000..10a2f81 --- a/dev/null +++ b/noncore/multimedia/camera/jpegtoavi/jpegtoavi.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | |||
3 | A simple converter of JPEGs to an AVI-MJPEG animation. | ||
4 | |||
5 | USAGE: | ||
6 | 1. jpegtoavi {usec per img} {img width} {img height} | ||
7 | {img1 .. imgN} | ||
8 | (writes AVI file to stdout) | ||
9 | |||
10 | 2. jpegtoavi -f {fps} {img width} {img height} | ||
11 | {img1 .. imgN} | ||
12 | (same as #1 but with period specified in terms of fps) | ||
13 | |||
14 | 3. jpegtoavi -fsz {img1 .. imgN} | ||
15 | (writes sz in bytes of such an AVI file to stdout) | ||
16 | */ | ||
17 | |||
18 | #define _LARGEFILE_SOURCE | ||
19 | #define _LARGEFILE64_SOURCE | ||
20 | |||
21 | #include <stdio.h> | ||
22 | #include "avifmt.h" | ||
23 | #include <string.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/stat.h> | ||
26 | #include <unistd.h> | ||
27 | #include <fcntl.h> | ||
28 | #include "byteswap.h" | ||
29 | #include <stdlib.h> | ||
30 | |||
31 | |||
32 | /* | ||
33 | spc: indicating file sz in bytes, -1 on error | ||
34 | */ | ||
35 | off_t file_sz(char *fn) | ||
36 | { | ||
37 | struct stat s; | ||
38 | if(stat(fn,&s)==-1) | ||
39 | return -1; | ||
40 | return s.st_size; | ||
41 | } | ||
42 | |||
43 | |||
44 | /* | ||
45 | spc: returning sum of sizes of named JPEGs, -1 on error; | ||
46 | file sizes adjusted to multiple of 4-bytes | ||
47 | pos: szarray, if non-0, contains true sizes of files | ||
48 | */ | ||
49 | off_t img_array_sz(char **img,int imgsz,DWORD *szarray) | ||
50 | { | ||
51 | off_t tmp,ret=0; | ||
52 | int i=0; | ||
53 | for(;i<imgsz;++i) { | ||
54 | if((tmp=file_sz(img[i]))==-1) | ||
55 | return -1; | ||
56 | if(szarray) | ||
57 | szarray[i]=(DWORD)tmp; | ||
58 | tmp+=((4-(tmp%4))%4); | ||
59 | ret+=tmp; | ||
60 | } | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | |||
65 | /* | ||
66 | spc: printing 4 byte word in little-endian fmt | ||
67 | */ | ||
68 | void print_quartet(unsigned int i) | ||
69 | { | ||
70 | putchar(i%0x100); i/=0x100; | ||
71 | putchar(i%0x100); i/=0x100; | ||
72 | putchar(i%0x100); i/=0x100; | ||
73 | putchar(i%0x100); | ||
74 | } | ||
75 | |||
76 | |||
77 | inline void show_help(int argc,char **argv) | ||
78 | { | ||
79 | fprintf(stderr,"USAGE: jpegtoavi {usec per img} {img width} {img height} {img1 .. imgN}\n"); | ||
80 | fprintf(stderr," jpegtoavi -f {fps} {img width} {img height} {img1 .. imgN}\n"); | ||
81 | fprintf(stderr," jpegtoavi --fsz {img1 .. imgN}\n"); | ||
82 | } | ||
83 | |||
84 | |||
85 | int main(int argc,char **argv) | ||
86 | { | ||
87 | DWORD per_usec=1; | ||
88 | DWORD width; | ||
89 | DWORD height; | ||
90 | DWORD frames=1; | ||
91 | unsigned int fps; | ||
92 | unsigned short img0; | ||
93 | off64_t jpg_sz_64,riff_sz_64; | ||
94 | long jpg_sz=1; | ||
95 | const off64_t MAX_RIFF_SZ=2147483648LL; /* 2 Gb limit */ | ||
96 | DWORD riff_sz; | ||
97 | |||
98 | int fd,f; | ||
99 | long nbr,nbw,tnbw=0; | ||
100 | char buff[512]; | ||
101 | DWORD *szarray=0; | ||
102 | DWORD *offsets=0; | ||
103 | off_t mfsz,remnant; | ||
104 | |||
105 | struct AVI_list_hdrl hdrl={ | ||
106 | /* header */ | ||
107 | { | ||
108 | {'L','I','S','T'}, | ||
109 | LILEND4(sizeof(struct AVI_list_hdrl)-8), | ||
110 | {'h','d','r','l'} | ||
111 | }, | ||
112 | |||
113 | /* chunk avih */ | ||
114 | {'a','v','i','h'}, | ||
115 | LILEND4(sizeof(struct AVI_avih)), | ||
116 | { | ||
117 | LILEND4(per_usec), | ||
118 | LILEND4(1000000*(jpg_sz/frames)/per_usec), | ||
119 | LILEND4(0), | ||
120 | LILEND4(AVIF_HASINDEX), | ||
121 | LILEND4(frames), | ||
122 | LILEND4(0), | ||
123 | LILEND4(1), | ||
124 | LILEND4(0), | ||
125 | LILEND4(width), | ||
126 | LILEND4(height), | ||
127 | {LILEND4(0),LILEND4(0),LILEND4(0),LILEND4(0)} | ||
128 | }, | ||
129 | |||
130 | /* list strl */ | ||
131 | { | ||
132 | { | ||
133 | {'L','I','S','T'}, | ||
134 | LILEND4(sizeof(struct AVI_list_strl)-8), | ||
135 | {'s','t','r','l'} | ||
136 | }, | ||
137 | |||
138 | /* chunk strh */ | ||
139 | {'s','t','r','h'}, | ||
140 | LILEND4(sizeof(struct AVI_strh)), | ||
141 | { | ||
142 | {'v','i','d','s'}, | ||
143 | {'M','J','P','G'}, | ||
144 | LILEND4(0), | ||
145 | LILEND4(0), | ||
146 | LILEND4(0), | ||
147 | LILEND4(per_usec), | ||
148 | LILEND4(1000000), | ||
149 | LILEND4(0), | ||
150 | LILEND4(frames), | ||
151 | LILEND4(0), | ||
152 | LILEND4(0), | ||
153 | LILEND4(0) | ||
154 | }, | ||
155 | |||
156 | /* chunk strf */ | ||
157 | {'s','t','r','f'}, | ||
158 | sizeof(struct AVI_strf), | ||
159 | { | ||
160 | LILEND4(sizeof(struct AVI_strf)), | ||
161 | LILEND4(width), | ||
162 | LILEND4(height), | ||
163 | LILEND4(1+24*256*256), | ||
164 | {'M','J','P','G'}, | ||
165 | LILEND4(width*height*3), | ||
166 | LILEND4(0), | ||
167 | LILEND4(0), | ||
168 | LILEND4(0), | ||
169 | LILEND4(0) | ||
170 | }, | ||
171 | |||
172 | /* list odml */ | ||
173 | { | ||
174 | { | ||
175 | {'L','I','S','T'}, | ||
176 | LILEND4(16), | ||
177 | {'o','d','m','l'} | ||
178 | }, | ||
179 | {'d','m','l','h'}, | ||
180 | LILEND4(4), | ||
181 | LILEND4(frames) | ||
182 | } | ||
183 | } | ||
184 | }; | ||
185 | |||
186 | /* parsing command line arguments */ | ||
187 | if(argc<2) { | ||
188 | show_help(argc,argv); | ||
189 | return -1; | ||
190 | } | ||
191 | else if(argc==2 && strcmp(argv[1],"--version")==0) { | ||
192 | printf("jpegtoavi v%d.%d\n",VERSION_MAJ,VERSION_MIN); | ||
193 | return 0; | ||
194 | } | ||
195 | else if(argc<3) { | ||
196 | show_help(argc,argv); | ||
197 | return -1; | ||
198 | } | ||
199 | else if(strcmp(argv[1],"-fsz")==0) { | ||
200 | img0=2; | ||
201 | } | ||
202 | else if(strcmp(argv[1],"-f")==0) { | ||
203 | if(argc<6 || sscanf(argv[2],"%u",&fps)!=1 | ||
204 | || fps==0 | ||
205 | || sscanf(argv[3],"%u",&width)!=1 | ||
206 | || sscanf(argv[4],"%u",&height)!=1) { | ||
207 | show_help(argc,argv); | ||
208 | return -1; | ||
209 | } | ||
210 | else { | ||
211 | per_usec=1000000/fps; | ||
212 | img0=5; | ||
213 | } | ||
214 | } | ||
215 | else if(argc<5 || sscanf(argv[1],"%u",&per_usec)!=1 | ||
216 | || sscanf(argv[2],"%u",&width)!=1 | ||
217 | || sscanf(argv[3],"%u",&height)!=1) { | ||
218 | show_help(argc,argv); | ||
219 | return -1; | ||
220 | } | ||
221 | else { | ||
222 | img0=4; | ||
223 | } | ||
224 | frames=argc-img0; | ||
225 | |||
226 | /* getting image, riff sizes */ | ||
227 | if(img0!=2) { | ||
228 | if((szarray=(DWORD *)malloc(frames*sizeof(DWORD)))==0) { | ||
229 | fprintf(stderr,"malloc error"); | ||
230 | free(offsets); | ||
231 | return -5; | ||
232 | } | ||
233 | } | ||
234 | jpg_sz_64=img_array_sz(&argv[img0],frames,szarray); | ||
235 | if(jpg_sz_64==-1) { | ||
236 | fprintf(stderr,"couldn't determine size of images\n"); | ||
237 | return -2; | ||
238 | } | ||
239 | riff_sz_64=sizeof(struct AVI_list_hdrl)+4+4+jpg_sz_64 | ||
240 | +8*frames+8+8+16*frames; | ||
241 | if(riff_sz_64>=MAX_RIFF_SZ) { | ||
242 | fprintf(stderr,"RIFF would exceed 2 Gb limit\n"); | ||
243 | return -3; | ||
244 | } | ||
245 | jpg_sz=(long)jpg_sz_64; | ||
246 | riff_sz=(DWORD)riff_sz_64; | ||
247 | |||
248 | /* printing RIFF size and quitting */ | ||
249 | if(img0==2) { | ||
250 | printf("%lu\n",(unsigned long)riff_sz+8UL); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* printing AVI.. riff hdr */ | ||
255 | printf("RIFF"); | ||
256 | print_quartet(riff_sz); | ||
257 | printf("AVI "); | ||
258 | |||
259 | /* list hdrl */ | ||
260 | hdrl.avih.us_per_frame=LILEND4(per_usec); | ||
261 | hdrl.avih.max_bytes_per_sec=LILEND4(1000000*(jpg_sz/frames) | ||
262 | /per_usec); | ||
263 | hdrl.avih.tot_frames=LILEND4(frames); | ||
264 | hdrl.avih.width=LILEND4(width); | ||
265 | hdrl.avih.height=LILEND4(height); | ||
266 | hdrl.strl.strh.scale=LILEND4(per_usec); | ||
267 | hdrl.strl.strh.rate=LILEND4(1000000); | ||
268 | hdrl.strl.strh.length=LILEND4(frames); | ||
269 | hdrl.strl.strf.width=LILEND4(width); | ||
270 | hdrl.strl.strf.height=LILEND4(height); | ||
271 | hdrl.strl.strf.image_sz=LILEND4(width*height*3); | ||
272 | hdrl.strl.list_odml.frames=LILEND4(frames); | ||
273 | fwrite(&hdrl,sizeof(hdrl),1,stdout); | ||
274 | |||
275 | /* list movi */ | ||
276 | printf("LIST"); | ||
277 | print_quartet(jpg_sz+8*frames+4); | ||
278 | printf("movi"); | ||
279 | |||
280 | if((offsets=(DWORD *)malloc(frames*sizeof(DWORD)))==0) { | ||
281 | fprintf(stderr,"malloc error"); | ||
282 | return -4; | ||
283 | } | ||
284 | |||
285 | for(f=img0;f<argc;++f) { | ||
286 | printf("00db"); | ||
287 | mfsz=szarray[f-img0]; | ||
288 | remnant=(4-(mfsz%4))%4; | ||
289 | print_quartet(mfsz+remnant); | ||
290 | szarray[f-img0]+=remnant; | ||
291 | if(f==img0) { | ||
292 | offsets[0]=4; | ||
293 | } | ||
294 | else { | ||
295 | offsets[f-img0]=offsets[f-img0-1]+szarray[f-img0-1]+8; | ||
296 | } | ||
297 | if((fd=open(argv[f],O_RDONLY))<0) { | ||
298 | fprintf(stderr,"couldn't open file!\n"); | ||
299 | free(offsets); | ||
300 | free(szarray); | ||
301 | return -6; | ||
302 | } | ||
303 | nbw=0; | ||
304 | |||
305 | if((nbr=read(fd,buff,6))!=6) { | ||
306 | fprintf(stderr,"error\n"); | ||
307 | free(offsets); | ||
308 | free(szarray); | ||
309 | return -7; | ||
310 | } | ||
311 | fwrite(buff,nbr,1,stdout); | ||
312 | read(fd,buff,4); | ||
313 | fwrite("AVI1",4,1,stdout); | ||
314 | nbw=10; | ||
315 | |||
316 | while((nbr=read(fd,buff,512))>0) { | ||
317 | fwrite(buff,nbr,1,stdout); | ||
318 | nbw+=nbr; | ||
319 | } | ||
320 | if(remnant>0) { | ||
321 | fwrite(buff,remnant,1,stdout); | ||
322 | nbw+=remnant; | ||
323 | } | ||
324 | tnbw+=nbw; | ||
325 | close(fd); | ||
326 | } | ||
327 | if(tnbw!=jpg_sz) { | ||
328 | fprintf(stderr,"error writing images (wrote %ld bytes, expected %ld bytes)\n", | ||
329 | tnbw,jpg_sz); | ||
330 | free(offsets); | ||
331 | free(szarray); | ||
332 | return -8; | ||
333 | } | ||
334 | |||
335 | // indices | ||
336 | printf("idx1"); | ||
337 | print_quartet(16*frames); | ||
338 | for(f=0;f<frames;++f) { | ||
339 | printf("00db"); | ||
340 | print_quartet(18); | ||
341 | print_quartet(offsets[f]); | ||
342 | print_quartet(szarray[f]); | ||
343 | } | ||
344 | |||
345 | free(offsets); | ||
346 | free(szarray); | ||
347 | return 0; | ||
348 | } | ||
349 | |||