1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "smacker.h"
6
7 #define w(p,n) fwrite(p,1,n,fp)
8
9 #define LIST w("LIST",4);
10
11 #define lu(p) \
12 { \
13 b[0] = (p & 0x000000FF); \
14 b[1] = ((p & 0x0000FF00) >> 8); \
15 b[2] = ((p & 0x00FF0000) >> 16); \
16 b[3] = ((p & 0xFF000000) >> 24); \
17 w(b,4); \
18 }
19
20 #define su(p) \
21 { \
22 b[0] = (p & 0x00FF); \
23 b[1] = ((p & 0xFF00) >> 8); \
24 w(b,2); \
25 }
26
process(const char * fn)27 void process(const char *fn)
28 {
29 FILE *fp;
30 smk s;
31 char outfile[256];
32 unsigned char b[5];
33
34 int i,j,k;
35 unsigned long temp_u;
36
37 /* all and video info */
38 unsigned long w, h, f;
39 double usf;
40 unsigned long total_frame_size;
41
42 /* audio info */
43 unsigned char a_t, a_c[7], a_d[7];
44 unsigned long a_r[7];
45
46 unsigned char num_tracks = 0;
47 unsigned char **audio_data[7];
48 unsigned long *audio_size[7];
49 unsigned long total_audio_size[7] = {0};
50 unsigned long total_total_audio_size = 0;
51
52 unsigned char *pal,*frame;
53
54 unsigned long cur_frame;
55
56 printf("--------\nsmk2avi processing %s...\n",fn);
57
58 /* open the smk file */
59 s = smk_open_file(fn,SMK_MODE_MEMORY);
60 if (s == NULL) goto error;
61
62 /* get some info about the file */
63 smk_info_all(s, NULL, &f, &usf);
64 smk_info_video(s, &w, &h, NULL);
65 smk_info_audio(s, &a_t, a_c, a_d, a_r);
66
67 printf("\t\t\twidth: %u, height: %u, usec/frame: %lf, frames: %u\n",w,h,usf,f);
68
69 total_frame_size = w * h * 3;
70
71 /* make 2 passes through the file.
72 first one is to pull all the audio tracks only. */
73 smk_enable_all(s,a_t);
74 for (i = 0; i < 7; i ++)
75 {
76 if (a_t & (1 << i))
77 {
78 audio_size[i] = malloc(f * sizeof(unsigned long));
79 audio_data[i] = malloc(f * sizeof(unsigned char*));
80 num_tracks ++;
81 } else {
82 audio_size[i] = NULL;
83 audio_data[i] = NULL;
84 }
85 }
86
87 printf("\tAudio processing frame: ");
88 smk_first(s);
89 for (cur_frame = 0; cur_frame < f; cur_frame ++)
90 {
91 printf("%u... ",cur_frame);
92 fflush(stdout);
93 for (i = 0; i < 7; i ++)
94 {
95 if (audio_size[i] != NULL)
96 {
97 audio_size[i][cur_frame] = smk_get_audio_size(s,i);
98 total_audio_size[i] += smk_get_audio_size(s,i);
99 total_total_audio_size += smk_get_audio_size(s,i);
100 audio_data[i][cur_frame] = malloc(audio_size[i][cur_frame]);
101 memcpy(audio_data[i][cur_frame],smk_get_audio(s,i),audio_size[i][cur_frame]);
102 }
103 }
104 smk_next(s);
105 }
106 printf("done!\n");
107
108 smk_enable_all(s,SMK_VIDEO_TRACK);
109
110 sprintf(outfile,"%s.avi",fn);
111
112 fp = fopen(outfile,"wb");
113
114 printf("Writing AVI file...\n");
115
116 // riff header
117 w("RIFF",4);
118 temp_u = 4 + 4 + (8 + 64 + 124 + (num_tracks * 102)) +
119 8 + (4 + ((total_frame_size + 8) * f) + ( (num_tracks * 8) + total_total_audio_size));
120 lu(temp_u);
121 w("AVI ",4);
122
123 {
124 // avi header list
125 LIST;
126 temp_u = 8 + 64 + 124 + (num_tracks * 102);
127 lu(temp_u);
128 w("hdrl",4);
129
130 {
131 // avi header
132 w("avih",4);
133 lu(56);
134 {
135 lu( (unsigned long)usf ); // microsec per frame
136 temp_u = total_frame_size + total_total_audio_size;
137 lu( temp_u ); // max bytes per sec
138 lu( 1 ); // padding granularity
139 lu( 0 ); // flags
140 lu( f ); // total frames
141 lu( 0 ); // initial frames
142 temp_u = num_tracks + 1;
143 lu( temp_u ); // streams
144 temp_u = total_frame_size + total_total_audio_size;
145 lu( temp_u ); // suggested buf size
146 lu( w ); // width
147 lu( h ); // height
148 lu( 0 ); // reserved (0-3)
149 lu( 0 );
150 lu( 0 );
151 lu( 0 );
152 }
153
154 // stream list: video stream
155 puts("Video stream header list");
156 LIST
157 lu(116);
158 w("strl",4);
159
160 {
161 w("strh",4);
162 lu(56);
163 {
164 w("vids",4); // fourcc type
165 w("DIB ",4); // fourcc handler
166 lu(0); // flags
167 lu(0); // priority + language
168 lu(0); // init frames
169 lu ((unsigned long)usf); // scale
170 lu( 1000000 ); // rate
171 lu(0); // start
172 temp_u = (unsigned long) ((double)f * 100000.0 / usf);
173 lu( temp_u ); // length (time in seconds ?)
174 lu(total_frame_size); // suggested bufsize
175 lu(-1); // quality
176 lu(total_frame_size); // samplesize
177 lu(0); // rcFrame
178 su(w); su(h); // rcFrame: right, bottom
179 }
180
181 w("strf",4);
182 lu(40);
183 {
184 lu(40); // size
185 lu(w); // width
186 lu(h); // height
187 su(1); // planes
188 su(24); // bpp
189 lu(0); // compression
190 lu(total_frame_size); // total image frame size
191 lu(0); // xpels/meter
192 lu(0); // ypels/meter
193 lu(0); // colors used
194 lu(0); // colors important
195 }
196 }
197
198 // stream list: audio stream(s)
199 for (i = 0; i < 7; i++)
200 {
201 if (audio_size[i] != NULL)
202 {
203 printf("-> Audio header %d, %dhz, %d bits, %d channels\n",i,a_r[i],a_d[i],a_c[i]);
204 LIST
205 lu(94);
206 w("strl",4);
207
208 w("strh",4);
209 lu(56);
210 {
211 w("auds",4); // fourcc
212 lu(0); // handler (pcm)
213 lu(0); // flags
214 lu(0); // priority + language
215 lu(0); // initial frames
216 lu( a_c[i]); // scale
217 temp_u = a_r[i] * a_c[i];
218 lu( temp_u ); // framerate
219 lu(0); // start
220 temp_u = (unsigned long) ((double)f * 100000.0 / usf);
221 lu( temp_u ); // time in seconds
222 temp_u = total_audio_size[i] / a_c[i];
223 lu( temp_u ); // sugg. buf size
224 lu(-1); // quality
225 temp_u = total_audio_size[i];
226 lu(temp_u); // sample size
227 lu(0); // rect ??
228 lu(0); // rect ??
229 }
230
231 w("strf",4);
232 lu(18);
233 {
234 su(1); // format
235 su(a_c[i]); // channels
236 lu(a_r[i]); // samples/sec
237 temp_u = a_c[i] * a_r[i] * (a_d[i] / 8); // avg bytes/sec
238 lu(temp_u);
239 temp_u = a_c[i] * (a_d[i] / 8); // avg bytes/sec
240 su(temp_u);
241 su(a_d[i]);
242 su(0);
243 }
244 }
245 }
246 }
247
248 smk_first(s);
249 printf("\tVideo processing frame:\n");
250
251 // movie data
252 LIST
253 temp_u = 4 + ((total_frame_size + 8) * f) + ( (num_tracks * 8) + total_total_audio_size);
254 lu(temp_u);
255 w("movi",4);
256
257 for (i = 0; i < f; i ++)
258 {
259 w("00db",4);
260 lu(total_frame_size);
261
262 frame = smk_get_video(s);
263 pal = smk_get_palette(s);
264
265 if (frame == NULL || pal == NULL) goto error;
266
267 for (j = h - 1; j >= 0; j--)
268 {
269 for (k = 0; k < w; k++)
270 {
271 w(&pal[frame[(j * w) + k] * 3 + 2],1);
272 w(&pal[frame[(j * w) + k] * 3 + 1],1);
273 w(&pal[frame[(j * w) + k] * 3],1);
274 }
275 }
276 printf("%u...",i);
277 fflush(stdout);
278
279 smk_next(s);
280 }
281 printf("done!\n");
282
283 k = 0;
284 for (i = 0; i < 7; i++)
285 {
286 if (audio_size[i] != NULL)
287 {
288 k ++;
289 sprintf(b,"%02uwb",k);
290 w(b,4);
291 temp_u = total_audio_size[i];
292 lu(temp_u);
293
294 for (j = 0; j < f; j++)
295 {
296 w(audio_data[i][j],audio_size[i][j]);
297 }
298 }
299 }
300 }
301
302 fclose(fp);
303
304 smk_close(s);
305
306 printf("done.\n--------\n");
307 return;
308
309 error:
310 fclose(fp);
311
312 smk_close(s);
313 printf("!!HAD ERRORS!!\n--------\n");
314 return;
315
316 }
317
main(int argc,char * argv[])318 int main (int argc, char *argv[])
319 {
320 int i;
321 for (i = 1; i < argc; i ++)
322 {
323 process(argv[i]);
324 }
325 return 0;
326 }
327