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