b7b925a9de95724ef44c045da3a06432a8734b45
[swftools.git] / lib / h.263 / video.c
1 /* video.c
2    Shows the structure of a swf file containing video
3
4    Part of the swftools package.
5    
6    Copyright (c) 2003 Matthias Kramm <kramm@quiss.org> */
7
8 #include "../config.h"
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <stdarg.h>
13 #include "../lib/rfxswf.h"
14 #include "../lib/args.h"
15
16 static char * filename = 0;
17 static char * indent = "                ";
18 int hex = 0;
19
20 struct options_t options[] =
21 {
22  {"v","verbose"},
23  {"V","version"},
24  {"d","hex"},
25  {"M","video"},
26  {0,0}
27 };
28
29 /* TODO:
30    * check rle tables
31 */
32 int args_callback_option(char*name,char*val)
33 {
34     if(!strcmp(name, "V")) {
35         printf("swfdump - part of %s %s\n", PACKAGE, VERSION);
36         exit(0);
37     }
38     else if(name[0]=='d') {
39         hex = 1;
40         return 0;
41     }
42     else {
43         printf("Unknown option: -%s\n", name);
44         exit(1);
45     }
46
47     return 0;
48 }
49 int args_callback_longoption(char*name,char*val)
50 {
51     return args_long2shortoption(options, name, val);
52 }
53 void args_callback_usage(char*name)
54 {
55     printf("Usage: %s [-at] file.swf\n", name);
56     printf("\t-h , --help\t\t Print help and exit\n");
57     printf("\t-d , --hex\t\t Print hex output of tag data, too\n");
58     printf("\t-V , --version\t\t Print program version and exit\n");
59 }
60 int args_callback_command(char*name,char*val)
61 {
62     if(filename) {
63         fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
64                  filename, name);
65     }
66     filename = name;
67     return 0;
68 }
69
70 #define DEBUG if(0)
71
72 void handleVideoStream(TAG*tag, char*prefix)
73 {
74     U16 id = swf_GetU16(tag);
75     U16 frames = swf_GetU16(tag);
76     U16 width = swf_GetU16(tag);
77     U16 height = swf_GetU16(tag);
78     U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on)
79     U8 codec = swf_GetU8(tag);
80     printf(" (%d frames, %dx%d", frames, width, height);
81     if(flags&1)
82         printf(" smoothed");
83     if(codec == 2)
84         printf(" sorenson h.263)");
85     else
86         printf(" codec 0x%02x)", codec);
87 }
88
89 struct huffcode {
90     char*code;
91     int len;
92     int index;
93 };
94
95 #define MCBPC_INTRA_STUFFING 8
96
97 struct huffcode mcbpc_intra[] = {
98 {"1",1, 0},              /*cbpc-00 mb type 3*/
99 {"001",3, 1},         /*cbpc-01 mb type 3*/
100 {"010",3, 2},         /*cbpc-10 mb type 3*/
101 {"011",3, 3},         /*cbpc-11 mb type 3*/
102 {"0001",4, 4},        /*cbpc-00 mb type 4*/
103 {"000001",6, 5},      /*cbpc-01 mb type 4*/
104 {"000010",6, 6},      /*cbpc-10 mb type 4*/
105 {"000011",6, 7},      /*cbpc-11 mb type 4*/
106 {"000000001",9, 8},   /* stuffing */
107 {0,0,0},
108 };
109
110 struct mcbpc_intra_params
111 {
112     int index;
113     int mb_type;
114     int cbpc;
115 } mcbpc_intra_params[] =
116 {{0, 3, 0}, //00 
117  {1, 3, 1}, //01 
118  {2, 3, 2}, //10 
119  {3, 3, 3}, //11 
120  {4, 4, 0}, //00 
121  {5, 4, 1}, //01 
122  {6, 4, 2}, //10 
123  {7, 4, 3}, //11 
124  {8 -1, -1}
125 };
126
127 #define MCBPC_INTER_STUFFING 20
128
129 struct huffcode mcbpc_inter[] = {
130 {"1", 1, 0},
131 {"0011", 4, 1},
132 {"0010", 4 ,2},
133 {"000101", 6, 3},
134 {"011", 3, 4},
135 {"0000111", 7, 5},
136 {"0000110", 7, 6},
137 {"000000101", 9, 7},
138 {"010", 3, 8},
139 {"0000101", 7, 9},
140 {"0000100", 7, 10},
141 {"00000101", 8, 11},
142 {"00011", 5, 12},
143 {"00000100", 8, 13},
144 {"00000011", 8, 14},
145 {"0000011", 7, 15},
146 {"000100", 6, 16},
147 {"000000100", 9, 17},
148 {"000000011", 9, 18},
149 {"000000010", 9, 19},
150 {"000000001", 9, 20}, /*stuffing*/
151
152 /* h.263+ only
153 {"00000000010", 11, 21},
154 {"0000000001100", 13, 22},
155 {"0000000001110", 13, 23},
156 {"0000000001111", 13, 24},
157 */
158 {0,0,0}
159 };
160
161 struct mcbpc_inter_params
162 {
163     int index;
164     int mb_type;
165     int cbpc;
166 } mcbpc_inter_params[] =
167 {{0, 0, 0}, {1, 0, 1}, {2, 0, 2}, {3, 0, 3}, {4, 1, 0},
168  {5, 1, 1}, {6, 1, 2}, {7, 1, 3}, {8, 2, 0}, {9, 2, 1},
169  {10, 2, 2}, {11, 2, 3}, {12, 3, 0}, {13, 3, 1}, {14, 3, 2},
170  {15, 3, 3}, {16, 4, 0}, {17, 4, 1}, {18, 4, 2}, {19, 4, 3},
171  {20, -1, -1}, //stuffing
172  //{21, 5, 0}, {22, 5, 1}, {23, 5, 2}, {24, 5, 3}, //h.263+ only
173 };
174
175 struct huffcode cbpy[] = {
176 {"0011", 4, 0},
177 {"00101", 5, 1},
178 {"00100", 5, 2},
179 {"1001", 4, 3},
180 {"00011", 5, 4},
181 {"0111", 4, 5},
182 {"000010", 6, 6},
183 {"1011", 4, 7},
184 {"00010", 5, 8},
185 {"000011", 6, 9},
186 {"0101", 4, 10},
187 {"1010", 4, 11},
188 {"0100", 4, 12},
189 {"1000", 4, 13},
190 {"0110", 4, 14},
191 {"11", 2, 15},
192 {0,0,0}
193 };
194
195 struct huffcode mvd[] = 
196 {
197 {"0000000000101", 13, 0},
198 {"0000000000111", 13, 1},
199 {"000000000101", 12, 2},
200 {"000000000111", 12, 3},
201 {"000000001001", 12, 4},
202 {"000000001011", 12, 5},
203 {"000000001101", 12, 6},
204 {"000000001111", 12, 7},
205 {"00000001001", 11, 8},
206 {"00000001011", 11, 9},
207 {"00000001101", 11, 10},
208 {"00000001111", 11, 11},
209 {"00000010001", 11, 12},
210 {"00000010011", 11, 13},
211 {"00000010101", 11, 14},
212 {"00000010111", 11, 15},
213 {"00000011001", 11, 16},
214 {"00000011011", 11, 17},
215 {"00000011101", 11, 18},
216 {"00000011111", 11, 19},
217 {"00000100001", 11, 20},
218 {"00000100011", 11, 21},
219 {"0000010011", 10, 22},
220 {"0000010101", 10, 23},
221 {"0000010111", 10, 24},
222 {"00000111", 8, 25},
223 {"00001001", 8, 26},
224 {"00001011", 8, 27},
225 {"0000111", 7, 28},
226 {"00011", 5, 29},
227 {"0011", 4, 30},
228 {"011", 3, 31},
229 {"1", 1, 32},
230 {"010", 3, 33},
231 {"0010", 4, 34},
232 {"00010", 5, 35},
233 {"0000110", 7, 36},
234 {"00001010", 8, 37},
235 {"00001000", 8, 38},
236 {"00000110", 8, 39},
237 {"0000010110", 10, 40},
238 {"0000010100", 10, 41},
239 {"0000010010", 10, 42},
240 {"00000100010", 11, 43},
241 {"00000100000", 11, 44},
242 {"00000011110", 11, 45},
243 {"00000011100", 11, 46},
244 {"00000011010", 11, 47},
245 {"00000011000", 11, 48},
246 {"00000010110", 11, 49},
247 {"00000010100", 11, 50},
248 {"00000010010", 11, 51},
249 {"00000010000", 11, 52},
250 {"00000001110", 11, 53},
251 {"00000001100", 11, 54},
252 {"00000001010", 11, 55},
253 {"00000001000", 11, 56},
254 {"000000001110", 12, 57},
255 {"000000001100", 12, 58},
256 {"000000001010", 12, 59},
257 {"000000001000", 12, 60},
258 {"000000000110", 12, 61},
259 {"000000000100", 12, 62},
260 {"0000000000110", 13, 63},
261 {0,0,0}};
262
263 struct huffcode rle[] = 
264 {
265 {"10", 2, 0},
266 {"1111", 4, 1},
267 {"010101", 6, 2},
268 {"0010111", 7, 3},
269 {"00011111", 8, 4},
270 {"000100101", 9, 5},
271 {"000100100", 9, 6},
272 {"0000100001", 10, 7},
273 {"0000100000", 10, 8},
274 {"00000000111", 11, 9},
275 {"00000000110", 11, 10},
276 {"00000100000", 11, 11},
277 {"110", 3, 12},
278 {"010100", 6, 13},
279 {"00011110", 8, 14},
280 {"0000001111", 10, 15},
281 {"00000100001", 11, 16},
282 {"000001010000", 12, 17},
283 {"1110", 4, 18},
284 {"00011101", 8, 19},
285 {"0000001110", 10, 20},
286 {"000001010001", 12, 21},
287 {"01101", 5, 22},
288 {"000100011", 9, 23},
289 {"0000001101", 10, 24},
290 {"01100", 5, 25},
291 {"000100010", 9, 26},
292 {"000001010010", 12, 27},
293 {"01011", 5, 28},
294 {"0000001100", 10, 29},
295 {"000001010011", 12, 30},
296 {"010011", 6, 31},
297 {"0000001011", 10, 32},
298 {"000001010100", 12, 33},
299 {"010010", 6, 34},
300 {"0000001010", 10, 35},
301 {"010001", 6, 36},
302 {"0000001001", 10, 37},
303 {"010000", 6, 38},
304 {"0000001000", 10, 39},
305 {"0010110", 7, 40},
306 {"000001010101", 12, 41},
307 {"0010101", 7, 42},
308 {"0010100", 7, 43},
309 {"00011100", 8, 44},
310 {"00011011", 8, 45},
311 {"000100001", 9, 46},
312 {"000100000", 9, 47},
313 {"000011111", 9, 48},
314 {"000011110", 9, 49},
315 {"000011101", 9, 50},
316 {"000011100", 9, 51},
317 {"000011011", 9, 52},
318 {"000011010", 9, 53},
319 {"00000100010", 11, 54},
320 {"00000100011", 11, 55},
321 {"000001010110", 12, 56},
322 {"000001010111", 12, 57},
323 {"0111", 4, 58},
324 {"000011001", 9, 59},
325 {"00000000101", 11, 60},
326 {"001111", 6, 61},
327 {"00000000100", 11, 62},
328 {"001110", 6, 63},
329 {"001101", 6, 64},
330 {"001100", 6, 65},
331 {"0010011", 7, 66},
332 {"0010010", 7, 67},
333 {"0010001", 7, 68},
334 {"0010000", 7, 69},
335 {"00011010", 8, 70},
336 {"00011001", 8, 71},
337 {"00011000", 8, 72},
338 {"00010111", 8, 73},
339 {"00010110", 8, 74},
340 {"00010101", 8, 75},
341 {"00010100", 8, 76},
342 {"00010011", 8, 77},
343 {"000011000", 9, 78},
344 {"000010111", 9, 79},
345 {"000010110", 9, 80},
346 {"000010101", 9, 81},
347 {"000010100", 9, 82},
348 {"000010011", 9, 83},
349 {"000010010", 9, 84},
350 {"000010001", 9, 85},
351 {"0000000111", 10, 86},
352 {"0000000110", 10, 87},
353 {"0000000101", 10, 88},
354 {"0000000100", 10, 89},
355 {"00000100100", 11, 90},
356 {"00000100101", 11, 91},
357 {"00000100110", 11, 92},
358 {"00000100111", 11, 93},
359 {"000001011000", 12, 94},
360 {"000001011001", 12, 95},
361 {"000001011010", 12, 96},
362 {"000001011011", 12, 97},
363 {"000001011100", 12, 98},
364 {"000001011101", 12, 99},
365 {"000001011110", 12, 100},
366 {"000001011111", 12, 101},
367 {"0000011", 7, 102}, /*ESCAPE*/
368 {0,0,0}
369 };
370
371 #define RLE_ESCAPE 102
372
373 struct rle_params
374 {
375     int index;
376     int last;
377     int run;
378     int level;
379 } rle_params[] =
380 {{0,0,0,1}, {1,0,0,2}, {2,0,0,3}, {3,0,0,4}, {4,0,0,5}, {5,0,0,6}, {6,0,0,7},
381 {7,0,0,8}, {8,0,0,9}, {9,0,0,10}, {10,0,0,11}, {11,0,0,12}, {12,0,1,1}, {13,0,1,2},
382 {14,0,1,3}, {15,0,1,4}, {16,0,1,5}, {17,0,1,6}, {18,0,2,1}, {19,0,2,2}, {20,0,2,3}, {21,0,2,4},
383 {22,0,3,1}, {23,0,3,2}, {24,0,3,3}, {25,0,4,1}, {26,0,4,2}, {27,0,4,3}, {28,0,5,1},
384 {29,0,5,2}, {30,0,5,3}, {31,0,6,1}, {32,0,6,2}, {33,0,6,3},
385 {34,0,7,1}, {35,0,7,2}, {36,0,8,1}, {37,0,8,2}, {38,0,9,1}, {39,0,9,2}, {40,0,10,1}, 
386 {41,0,10,2}, {42,0,11,1}, {43,0,12,1}, {44,0,13,1}, {45,0,14,1}, {46,0,15,1}, 
387 {47,0,16,1}, {48,0,17,1}, {49,0,18,1}, {50,0,19,1}, {51,0,20,1}, {52,0,21,1}, 
388 {53,0,22,1}, {54,0,23,1}, {55,0,24,1}, {56,0,25,1}, {57,0,26,1}, {58,1,0,1}, 
389 {59,1,0,2}, {60,1,0,3}, {61,1,1,1}, {62,1,1,2}, {63,1,2,1}, {64,1,3,1}, {65, 1,4,1}, 
390 {66,1,5,1}, {67,1,6,1}, {68,1,7,1}, {69,1,8,1}, {70,1,9,1}, {71,1,10,1}, 
391 {72,1,11,1}, {73,1,12,1}, {74,1,13,1}, {75,1,14,1}, {76,1,15,1}, {77,1,16,1}, 
392 {78,1,17,1}, {79,1,18,1}, {80,1,19,1}, {81,1,20,1}, {82,1,21,1}, {83,1,22,1}, 
393 {84,1,23,1}, {85,1,24,1}, {86,1,25,1}, {87,1,26,1}, {88,1,27,1}, {89,1,28,1}, 
394 {90,1,29,1}, {91,1,30,1}, {92,1,31,1}, {93,1,32,1}, {94,1,33,1}, {95,1,34,1}, 
395 {96,1,35,1}, {97,1,36,1}, {98,1,37,1}, {99,1,38,1}, {100,1,39,1}, {101,1,40,1}, 
396 {102,-1, -1, -1}
397 };
398
399 int checkhufftable(struct huffcode*code, char*name)
400 {
401     int t=0;
402     while(code[t].code) {
403         int s=0;
404         if(strlen(code[t].code)!=code[t].len) {
405             printf("len mismatch in %s, index %d\n", name, t);
406             exit(1);
407         }
408         if(t != code[t].index) {
409             printf("index mismatch in %s, index %d\n", name, t);
410             exit(1);
411         }
412         while(code[s].code) {
413             char*a = code[s].code;
414             char*b = code[t].code;
415             int ai = s;
416             int bi = t;
417             if(s==t) {s++;continue;}
418             if(code[t].len < code[s].len) {
419                  a = code[t].code;
420                  b = code[s].code;
421                  ai = t; bi = s;
422             }
423             if(!strncmp(a,b,strlen(a))) {
424                 printf("index %d (%s) is prefix of %d (%s)\n", ai, a, bi, b);
425                 exit(1);
426             }
427
428             s++;
429         }
430
431         t++;
432     }
433 }
434
435 int gethuffvalue(TAG*tag, struct huffcode*code)
436 {
437     int len = 0;
438     char bits[80];
439     while(1) {
440         int t=0,pot=0;
441         bits[len] = swf_GetBits(tag, 1)+0x30;
442         len++;
443         bits[len] = 0;
444         while(code[t].code) {
445             if(!strcmp(bits, code[t].code))
446                 return t;
447             t++;
448             if(code[t].len >= len)
449                 pot++;
450         }
451         if(!pot) {
452             int nr=0;
453             printf("error: %s\n", bits);
454             while(tag->pos < tag->len && nr<80) {
455                 int b = swf_GetBits(tag, 1);
456                 printf("%d", b);
457                 nr++;
458             }
459             if(nr==80)
460                 printf("...");
461             printf("\n");
462             exit(1);
463             return -1;
464         }
465     }
466
467         /*type = 0; // mb-type =3, cbpc = 00
468         if(!bit) {
469             printf("can't handle i-frame mcbpc bits %d yet\n", bit);
470         }
471         bit = swf_GetBits(tag, 1);
472         type = 0; // mb-type =0, cbpc = 00
473         if(!bit) {
474             bit = swf_GetBits(tag, 2);
475             type = 8; // mb-type =2, cbpc = 00
476             if(bit!=3) {
477                 printf("can't handle p-frame mcbpc bits 0-%d yet\n", bit);
478                 exit(1);
479             }
480         }*/
481 }
482                 
483 void getCoefficient(TAG*tag, int t, int has_dc, int has_tcoef)
484 {
485     int dc;
486     int ac;// = swf_GetBits();
487     int index;
488     int pos = 0;
489     //printf("DC:%d\n", dc);
490     if(has_dc) {
491         dc = swf_GetBits(tag, 8);
492         if(dc == 0 || dc == 128) {
493             printf("error: dc=%d\n", dc);
494             exit(1);
495         }
496         DEBUG printf(" %d ", dc);
497         pos++;
498     }
499
500     if(has_tcoef) {
501         DEBUG printf("[");
502         while(1) {
503             int last;
504             int run;
505             int level;
506             index = gethuffvalue(tag, rle);
507             last = rle_params[index].last;
508             run = rle_params[index].run;
509             level = rle_params[index].level;
510             //DEBUG printf("index:%d\n", index);
511             if(index == RLE_ESCAPE) {
512                 last = swf_GetBits(tag, 1);
513                 run = swf_GetBits(tag, 6);
514                 level = swf_GetBits(tag, 8);
515                 if(run)
516                     DEBUG printf("(%d) E%d", run, level);
517                 else
518                     DEBUG printf("E");
519                 if(level == 0 || level == 128) {
520                     printf("error: level=%d\n", level);
521                     exit(1);
522                 }
523                 level = (int)((signed char)level);
524             } else {
525                 int sign = swf_GetBits(tag, 1);
526                 if(sign)
527                     level = -level;
528                 if(run)
529                     DEBUG printf("(%d) %s%d", run, level>0?"+":"",level);
530                 else
531                     DEBUG printf("%s%d", level>0?"+":"",level);
532             }
533             pos += run+1;
534             //DEBUG printf("run:%d level:%d\n", run, level);
535             if(last) {
536                 DEBUG printf("] pos: %d", pos);
537                 if(pos>64) {
538                     printf("\n");
539                     exit(1);
540                 }
541                 return;
542             }
543         }
544     }
545 }
546             
547 void readMVD(TAG*tag)
548 {
549     int index = gethuffvalue(tag, mvd);
550     DEBUG printf("mvd index:%d\n", index);
551 }
552
553 char has_quant[] = {0,1,0,0,1};
554 char has_mvd[] = {1,1,3,0,0};
555
556 #define TYPE_INTRA 0
557 #define TYPE_INTER 1
558
559 int tagnr = 0;
560
561 void handleVideoFrame(TAG*tag, char*prefix)
562 {
563     U32 code, version, reference, sizeflags;
564     U32 width, height;
565     U8 blocktype, type, pictype;
566     U16 id = swf_GetU16(tag);
567     U16 frame = swf_GetU16(tag);
568     U8 deblock,flags, tmp, bit;
569     U32 quantizer, extrainfo;
570     int skipped = 0;
571     int pos=0;
572     int num;
573     int disposable = 0;
574     int blocknum;
575     int bx,by;
576     char*types[] = {"intra- (I-)frame", "inter- (P-)frame", "disposable interframe", "<reserved>"};
577     printf("============================= frame %d ===================================", frame);
578
579     /* video packet follows */
580     printf("\n");
581     code = swf_GetBits(tag, 17);
582     if(code!=1) {
583         printf("code: %x (?)\n", code);
584         return;
585     }
586     version = swf_GetBits(tag, 5); /*actually, part of the picture start code */
587     //printf("version: %x\n", version); /*usually 0*/
588     if(version >= 1) {
589         /* version 1 has some different transform coefficient coding which we
590            can't handle yet */
591         exit(1);
592     }
593     reference = swf_GetBits(tag, 8);
594     DEBUG printf("reference: %d\n", reference); /*usually same as frame number (unless frames were skipped while encoding)*/
595
596     sizeflags = swf_GetBits(tag, 3);
597     switch(sizeflags)
598     {
599         case 0: width = swf_GetU8(tag); height = swf_GetU8(tag); break;
600         case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break;
601         case 2: width = 352; height = 288; break;
602         case 3: width = 176; height = 144; break;
603         case 4: width = 128; height = 96; break;
604         case 5: width = 320; height = 240; break;
605         case 6: width = 160; height = 120; break;
606         case 7: width = -1; height = -1;/*reserved*/ break;
607     }
608     
609     pictype = swf_GetBits(tag, 2);
610     if(pictype==3) {
611         printf("pictype: %d\n", pictype);
612         exit(1);
613     }
614     if(pictype==2)  {
615         pictype = TYPE_INTER;
616         disposable = 1;
617     }
618     if(pictype==TYPE_INTER)
619         printf("INTER P%s", disposable?" (disposeable)":"");
620     else
621         printf("INTRA I");
622
623     deblock = swf_GetBits(tag, 1); /*usually 0*/
624     DEBUG printf("deblock: %d\n", deblock);
625     quantizer = swf_GetBits(tag, 5); /*usually 9*/
626     DEBUG printf("quantizer: %d\n", quantizer);
627
628     extrainfo = swf_GetBits(tag, 1); /*usually none */
629     while(extrainfo) {
630         extrainfo = swf_GetBits(tag, 8);
631         printf("extrainfo: %02x\n", extrainfo);
632         extrainfo = swf_GetBits(tag, 1);
633     }
634
635     /* macro block */
636     blocknum = ((width+15)/16)*((height+15)/16);
637     printf("%dx%d [blocks: %dx%d=%d]\n", width, height, width/16, height/16, blocknum);
638
639     /*if(pictype == TYPE_INTER)
640         return;*/
641     /*if(pictype == TYPE_INTRA)
642         return;*/
643
644     /*tagnr++;
645     if(tagnr!=2)
646         return;*/
647
648     DEBUG printf("\n");
649     while(1) {
650         int x,y,t;
651         int mb_type = -1, cbpc = -1;
652         int dbquant;
653         int cbpy_index, cbpy_value;
654         int intrablock = 0;
655         if(pictype == TYPE_INTER) /* non-intra pictures have a cod flag */
656         /* TODO: according to the flash spec, this field is always present */
657         {
658             int cod = swf_GetBits(tag, 1);
659             if(cod) {
660                 pos++;
661                 if(pos == blocknum)
662                     break;
663                 skipped++;
664                 continue; //don't do anything- block hasn't changed
665             }
666         }
667         if(skipped) {
668             DEBUG printf("skipped (cod):%d\n", skipped);
669             skipped = 0;
670         }
671         type = -1;
672         
673         DEBUG printf("---------> block %d\n", pos);
674
675         /* read mcbpc */
676
677         if(pictype == TYPE_INTRA) { /* I-frame */
678             type = gethuffvalue(tag, mcbpc_intra);
679             mb_type = mcbpc_intra_params[type].mb_type;
680             cbpc = mcbpc_intra_params[type].cbpc;
681             if(type == MCBPC_INTRA_STUFFING)
682                 exit(1); //TODO: goto COD
683         } 
684         else if(pictype == 1) { /* P-frame */
685             type = gethuffvalue(tag, mcbpc_inter);
686             mb_type = mcbpc_inter_params[type].mb_type;
687             cbpc = mcbpc_inter_params[type].cbpc;
688             if(type == MCBPC_INTER_STUFFING)
689                 exit(1); //TODO: goto COD
690         }
691
692         if(mb_type == 3 || mb_type == 4)
693         {
694             intrablock = 1;
695         }
696
697         DEBUG printf("mcbpc type: %d mb_type:%d cbpc:%d\n", type, mb_type, cbpc);
698
699         /* read cbpy */
700
701         cbpy_index = gethuffvalue(tag, cbpy);
702         cbpy_value = cbpy_index;
703         if(!intrablock)
704             cbpy_value ^= 15;
705         DEBUG printf("cbpy value:%d (%d)\n", cbpy_value, cbpy_index);
706
707
708         /* I 0: 00 mcbpc/cbpy 
709            P 0: 00 cod/mcbpc/cbpy/mvd
710            P 6: 10 cod/mcbpc/cbpy/dquant/mvd
711            P 8: 00 cod/mcbpc/cbpy/mvd/mvd24
712         */
713
714         /* quantizer */
715         if(has_quant[mb_type]) {
716             dbquant = swf_GetBits(tag, 2);
717             DEBUG printf("quantizer: %d\n", dbquant);
718         }
719
720         if(has_mvd[mb_type]&1) {
721             readMVD(tag); //horizontal
722             readMVD(tag); //vertical
723         }
724         if(has_mvd[mb_type]&2) {
725             /* only in advanced prediction mode */
726             readMVD(tag); //horizontal
727             readMVD(tag); //vertical
728             readMVD(tag); //horizontal
729             readMVD(tag); //vertical
730             readMVD(tag); //horizontal
731             readMVD(tag); //vertical
732         }
733
734         for(t=0;t<4;t++) {
735             int has_intradc = intrablock;
736             int has_tcoef = cbpy_value & (8>>t);
737             DEBUG printf("luminance%d ", t);
738             getCoefficient(tag, t, has_intradc, has_tcoef); /*luminance - affected by cbpy*/
739             DEBUG printf("\n");
740         }
741         for(t=0;t<2;t++) {
742             int has_intradc = intrablock;
743             int has_tcoef = cbpc & (2>>t);
744             DEBUG printf("chrominance%d ", t); 
745             getCoefficient(tag, t, has_intradc, has_tcoef); /*chrominance - affected by mcbc*/
746             DEBUG printf("\n");
747         }
748         pos++;
749         if(pos == blocknum)
750             break;
751     }
752 }
753
754 void hexdumpTag(TAG*tag, char* prefix)
755 {
756     int t;
757     printf("                %s-=> ",prefix);
758     for(t=0;t<tag->len;t++) {
759         printf("%02x ", tag->data[t]);
760         if((t && ((t&15)==15)) || (t==tag->len-1))
761         {
762             if(t==tag->len-1)
763                 printf("\n");
764             else
765                 printf("\n                %s-=> ",prefix);
766         }
767     }
768 }
769
770 int main (int argc,char ** argv)
771 {
772     TAG*tag;
773     SWF swf;
774     int f;
775     char prefix[128];
776     int filesize = 0;
777     prefix[0] = 0;
778
779     checkhufftable(rle, "rle");
780     checkhufftable(mcbpc_intra, "intra");
781     checkhufftable(mcbpc_inter, "inter");
782     checkhufftable(cbpy, "cbpy");
783     checkhufftable(mvd, "mvd");
784
785     processargs(argc, argv);
786     if(!filename) {
787         fprintf(stderr, "You must supply a filename.\n");
788         return 1;
789     }
790
791     f = open(filename,O_RDONLY);
792
793     if (f<0) {
794         perror("Couldn't open file: ");
795         exit(1);
796     }
797     if FAILED(swf_ReadSWF(f,&swf)) {
798         fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
799         close(f);
800         exit(1);
801     }
802
803     close(f);
804
805     printf("[HEADER]        File version: %d\n", swf.fileVersion);
806     if(swf.compressed) {
807         printf("[HEADER]        File is zlib compressed.");
808         if(filesize && swf.fileSize)
809             printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize));
810         else
811             printf("\n");
812     }
813     printf("[HEADER]        File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":"");
814     printf("[HEADER]        Frame rate: %f\n",swf.frameRate/256.0);
815     printf("[HEADER]        Frame count: %d\n",swf.frameCount);
816     printf("[HEADER]        Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0);
817     if(swf.movieSize.xmin)
818         printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0);
819     else
820         printf("\n");
821     printf("[HEADER]        Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0);
822     if(swf.movieSize.ymin)
823         printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0);
824     else
825         printf("\n");
826
827     tag = swf.firstTag;
828
829     while(tag) {
830         char*name = swf_TagGetName(tag);
831         char myprefix[128];
832         //printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag));
833
834         if(swf_isDefiningTag(tag)) {
835             U16 id = swf_GetDefineID(tag);
836             //printf(" defines id %04d", id);
837         }
838         else if(swf_isPseudoDefiningTag(tag)) {
839             U16 id = swf_GetDefineID(tag);
840             //printf(" adds information to id %04d", id);
841         }
842
843         if(tag->id == ST_VIDEOFRAME) {
844             handleVideoFrame(tag, myprefix);
845             //printf("\n");
846         }
847         else if(tag->id == ST_DEFINEVIDEOSTREAM) {
848             handleVideoStream(tag, myprefix);
849             printf("\n");
850         }
851         else {
852             //printf("\n");
853         }
854
855         sprintf(myprefix, "                %s", prefix);
856
857         if(tag->len && hex) {
858             hexdumpTag(tag, prefix);
859         }
860         tag = tag->next;
861         fflush(stdout);
862     }
863
864     swf_FreeTags(&swf);
865     return 0;
866 }
867
868