X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fh.263%2Fvideo.c;h=31391dbd56a39d76ad83cbdf156b3daf3eb18e58;hb=bbad613e3e1bd5c0399c7fcdeeeee7f930a512cb;hp=2c59d045e9c20f4dc84649442621b6f4b8ab95e9;hpb=b19e64503c65c68454fb12b5239e4a9f36f89cfb;p=swftools.git diff --git a/lib/h.263/video.c b/lib/h.263/video.c index 2c59d04..31391db 100644 --- a/lib/h.263/video.c +++ b/lib/h.263/video.c @@ -3,19 +3,36 @@ Part of the swftools package. - Copyright (c) 2003 Matthias Kramm */ - -#include "../config.h" + Copyright (c) 2003 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "../../config.h" #include #include #include #include -#include "../lib/rfxswf.h" -#include "../lib/args.h" +#include +#include "../rfxswf.h" +#include "../args.h" +#include "h263tables.h" static char * filename = 0; static char * indent = " "; int hex = 0; +int debug = 0; struct options_t options[] = { @@ -39,6 +56,10 @@ int args_callback_option(char*name,char*val) hex = 1; return 0; } + else if(name[0]=='v') { + debug = 1; + return 0; + } else { printf("Unknown option: -%s\n", name); exit(1); @@ -55,6 +76,7 @@ void args_callback_usage(char*name) printf("Usage: %s [-at] file.swf\n", name); printf("\t-h , --help\t\t Print help and exit\n"); printf("\t-d , --hex\t\t Print hex output of tag data, too\n"); + printf("\t-v , --verbose\t\t Print debugging information\n"); printf("\t-V , --version\t\t Print program version and exit\n"); } int args_callback_command(char*name,char*val) @@ -67,7 +89,7 @@ int args_callback_command(char*name,char*val) return 0; } -#define DEBUG if(0) +#define DEBUG if(debug) void handleVideoStream(TAG*tag, char*prefix) { @@ -86,316 +108,6 @@ void handleVideoStream(TAG*tag, char*prefix) printf(" codec 0x%02x)", codec); } -struct huffcode { - char*code; - int len; - int index; -}; - -#define MCBPC_INTRA_STUFFING 8 - -struct huffcode mcbpc_intra[] = { -{"1",1, 0}, /*cbpc-00 mb type 3*/ -{"001",3, 1}, /*cbpc-01 mb type 3*/ -{"010",3, 2}, /*cbpc-10 mb type 3*/ -{"011",3, 3}, /*cbpc-11 mb type 3*/ -{"0001",4, 4}, /*cbpc-00 mb type 4*/ -{"000001",6, 5}, /*cbpc-01 mb type 4*/ -{"000010",6, 6}, /*cbpc-10 mb type 4*/ -{"000011",6, 7}, /*cbpc-11 mb type 4*/ -{"000000001",9, 8}, /* stuffing */ -{0,0,0}, -}; - -struct mcbpc_intra_params -{ - int index; - int mb_type; - int cbpc; -} mcbpc_intra_params[] = -{{0, 3, 0}, //00 - {1, 3, 1}, //01 - {2, 3, 2}, //10 - {3, 3, 3}, //11 - {4, 4, 0}, //00 - {5, 4, 1}, //01 - {6, 4, 2}, //10 - {7, 4, 3}, //11 - {8 -1, -1} -}; - -#define MCBPC_INTER_STUFFING 20 - -struct huffcode mcbpc_inter[] = { -{"1", 1, 0}, -{"0011", 4, 1}, -{"0010", 4 ,2}, -{"000101", 6, 3}, -{"011", 3, 4}, -{"0000111", 7, 5}, -{"0000110", 7, 6}, -{"000000101", 9, 7}, -{"010", 3, 8}, -{"0000101", 7, 9}, -{"0000100", 7, 10}, -{"00000101", 8, 11}, -{"00011", 5, 12}, -{"00000100", 8, 13}, -{"00000011", 8, 14}, -{"0000011", 7, 15}, -{"000100", 6, 16}, -{"000000100", 9, 17}, -{"000000011", 9, 18}, -{"000000010", 9, 19}, -{"000000001", 9, 20}, /*stuffing*/ - -/* h.263+ only -{"00000000010", 11, 21}, -{"0000000001100", 13, 22}, -{"0000000001110", 13, 23}, -{"0000000001111", 13, 24}, -*/ -{0,0,0} -}; - -struct mcbpc_inter_params -{ - int index; - int mb_type; - int cbpc; -} mcbpc_inter_params[] = -{{0, 0, 0}, {1, 0, 1}, {2, 0, 2}, {3, 0, 3}, {4, 1, 0}, - {5, 1, 1}, {6, 1, 2}, {7, 1, 3}, {8, 2, 0}, {9, 2, 1}, - {10, 2, 2}, {11, 2, 3}, {12, 3, 0}, {13, 3, 1}, {14, 3, 2}, - {15, 3, 3}, {16, 4, 0}, {17, 4, 1}, {18, 4, 2}, {19, 4, 3}, - {20, -1, -1}, //stuffing - //{21, 5, 0}, {22, 5, 1}, {23, 5, 2}, {24, 5, 3}, //h.263+ only -}; - -struct huffcode cbpy[] = { -{"0011", 4, 0}, -{"00101", 5, 1}, -{"00100", 5, 2}, -{"1001", 4, 3}, -{"00011", 5, 4}, -{"0111", 4, 5}, -{"000010", 6, 6}, -{"1011", 4, 7}, -{"00010", 5, 8}, -{"000011", 6, 9}, -{"0101", 4, 10}, -{"1010", 4, 11}, -{"0100", 4, 12}, -{"1000", 4, 13}, -{"0110", 4, 14}, -{"11", 2, 15}, -{0,0,0} -}; - -struct huffcode mvd[] = -{ -{"0000000000101", 13, 0}, -{"0000000000111", 13, 1}, -{"000000000101", 12, 2}, -{"000000000111", 12, 3}, -{"000000001001", 12, 4}, -{"000000001011", 12, 5}, -{"000000001101", 12, 6}, -{"000000001111", 12, 7}, -{"00000001001", 11, 8}, -{"00000001011", 11, 9}, -{"00000001101", 11, 10}, -{"00000001111", 11, 11}, -{"00000010001", 11, 12}, -{"00000010011", 11, 13}, -{"00000010101", 11, 14}, -{"00000010111", 11, 15}, -{"00000011001", 11, 16}, -{"00000011011", 11, 17}, -{"00000011101", 11, 18}, -{"00000011111", 11, 19}, -{"00000100001", 11, 20}, -{"00000100011", 11, 21}, -{"0000010011", 10, 22}, -{"0000010101", 10, 23}, -{"0000010111", 10, 24}, -{"00000111", 8, 25}, -{"00001001", 8, 26}, -{"00001011", 8, 27}, -{"0000111", 7, 28}, -{"00011", 5, 29}, -{"0011", 4, 30}, -{"011", 3, 31}, -{"1", 1, 32}, -{"010", 3, 33}, -{"0010", 4, 34}, -{"00010", 5, 35}, -{"0000110", 7, 36}, -{"00001010", 8, 37}, -{"00001000", 8, 38}, -{"00000110", 8, 39}, -{"0000010110", 10, 40}, -{"0000010100", 10, 41}, -{"0000010010", 10, 42}, -{"00000100010", 11, 43}, -{"00000100000", 11, 44}, -{"00000011110", 11, 45}, -{"00000011100", 11, 46}, -{"00000011010", 11, 47}, -{"00000011000", 11, 48}, -{"00000010110", 11, 49}, -{"00000010100", 11, 50}, -{"00000010010", 11, 51}, -{"00000010000", 11, 52}, -{"00000001110", 11, 53}, -{"00000001100", 11, 54}, -{"00000001010", 11, 55}, -{"00000001000", 11, 56}, -{"000000001110", 12, 57}, -{"000000001100", 12, 58}, -{"000000001010", 12, 59}, -{"000000001000", 12, 60}, -{"000000000110", 12, 61}, -{"000000000100", 12, 62}, -{"0000000000110", 13, 63}, -{0,0,0}}; - -struct huffcode rle[] = -{ -{"10", 2, 0}, -{"1111", 4, 1}, -{"010101", 6, 2}, -{"0010111", 7, 3}, -{"00011111", 8, 4}, -{"000100101", 9, 5}, -{"000100100", 9, 6}, -{"0000100001", 10, 7}, -{"0000100000", 10, 8}, -{"00000000111", 11, 9}, -{"00000000110", 11, 10}, -{"00000100000", 11, 11}, -{"110", 3, 12}, -{"010100", 6, 13}, -{"00011110", 8, 14}, -{"0000001111", 10, 15}, -{"00000100001", 11, 16}, -{"000001010000", 12, 17}, -{"1110", 4, 18}, -{"00011101", 8, 19}, -{"0000001110", 10, 20}, -{"000001010001", 12, 21}, -{"01101", 5, 22}, -{"000100011", 9, 23}, -{"0000001101", 10, 24}, -{"01100", 5, 25}, -{"000100010", 9, 26}, -{"000001010010", 12, 27}, -{"01011", 5, 28}, -{"0000001100", 10, 29}, -{"000001010011", 12, 30}, -{"010011", 6, 31}, -{"0000001011", 10, 32}, -{"000001010100", 12, 33}, -{"010010", 6, 34}, -{"0000001010", 10, 35}, -{"010001", 6, 36}, -{"0000001001", 10, 37}, -{"010000", 6, 38}, -{"0000001000", 10, 39}, -{"0010110", 7, 40}, -{"000001010101", 12, 41}, -{"0010101", 7, 42}, -{"0010100", 7, 43}, -{"00011100", 8, 44}, -{"00011011", 8, 45}, -{"000100001", 9, 46}, -{"000100000", 9, 47}, -{"000011111", 9, 48}, -{"000011110", 9, 49}, -{"000011101", 9, 50}, -{"000011100", 9, 51}, -{"000011011", 9, 52}, -{"000011010", 9, 53}, -{"00000100010", 11, 54}, -{"00000100011", 11, 55}, -{"000001010110", 12, 56}, -{"000001010111", 12, 57}, -{"0111", 4, 58}, -{"000011001", 9, 59}, -{"00000000101", 11, 60}, -{"001111", 6, 61}, -{"00000000100", 11, 62}, -{"001110", 6, 63}, -{"001101", 6, 64}, -{"001100", 6, 65}, -{"0010011", 7, 66}, -{"0010010", 7, 67}, -{"0010001", 7, 68}, -{"0010000", 7, 69}, -{"00011010", 8, 70}, -{"00011001", 8, 71}, -{"00011000", 8, 72}, -{"00010111", 8, 73}, -{"00010110", 8, 74}, -{"00010101", 8, 75}, -{"00010100", 8, 76}, -{"00010011", 8, 77}, -{"000011000", 9, 78}, -{"000010111", 9, 79}, -{"000010110", 9, 80}, -{"000010101", 9, 81}, -{"000010100", 9, 82}, -{"000010011", 9, 83}, -{"000010010", 9, 84}, -{"000010001", 9, 85}, -{"0000000111", 10, 86}, -{"0000000110", 10, 87}, -{"0000000101", 10, 88}, -{"0000000100", 10, 89}, -{"00000100100", 11, 90}, -{"00000100101", 11, 91}, -{"00000100110", 11, 92}, -{"00000100111", 11, 93}, -{"000001011000", 12, 94}, -{"000001011001", 12, 95}, -{"000001011010", 12, 96}, -{"000001011011", 12, 97}, -{"000001011100", 12, 98}, -{"000001011101", 12, 99}, -{"000001011110", 12, 100}, -{"000001011111", 12, 101}, -{"0000011", 7, 102}, /*ESCAPE*/ -{0,0,0} -}; - -#define RLE_ESCAPE 102 - -struct rle_params -{ - int index; - int last; - int run; - int level; -} rle_params[] = -{{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}, -{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}, -{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}, -{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}, -{29,0,5,2}, {30,0,5,3}, {31,0,6,1}, {32,0,6,2}, {33,0,6,3}, -{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}, -{41,0,10,2}, {42,0,11,1}, {43,0,12,1}, {44,0,13,1}, {45,0,14,1}, {46,0,15,1}, -{47,0,16,1}, {48,0,17,1}, {49,0,18,1}, {50,0,19,1}, {51,0,20,1}, {52,0,21,1}, -{53,0,22,1}, {54,0,23,1}, {55,0,24,1}, {56,0,25,1}, {57,0,26,1}, {58,1,0,1}, -{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}, -{66,1,5,1}, {67,1,6,1}, {68,1,7,1}, {69,1,8,1}, {70,1,9,1}, {71,1,10,1}, -{72,1,11,1}, {73,1,12,1}, {74,1,13,1}, {75,1,14,1}, {76,1,15,1}, {77,1,16,1}, -{78,1,17,1}, {79,1,18,1}, {80,1,19,1}, {81,1,20,1}, {82,1,21,1}, {83,1,22,1}, -{84,1,23,1}, {85,1,24,1}, {86,1,25,1}, {87,1,26,1}, {88,1,27,1}, {89,1,28,1}, -{90,1,29,1}, {91,1,30,1}, {92,1,31,1}, {93,1,32,1}, {94,1,33,1}, {95,1,34,1}, -{96,1,35,1}, {97,1,36,1}, {98,1,37,1}, {99,1,38,1}, {100,1,39,1}, {101,1,40,1}, -{102,-1, -1, -1} -}; - int checkhufftable(struct huffcode*code, char*name) { int t=0; @@ -432,6 +144,62 @@ int checkhufftable(struct huffcode*code, char*name) } } + +struct hufftree +{ + struct hufftree*left;//0 + struct hufftree*right;//1 + int index; +}; + +struct hufftree * rle_tree; +struct hufftree * mcbpc_intra_tree; +struct hufftree * mcbpc_inter_tree; +struct hufftree * cbpy_tree; +struct hufftree * mvd_tree; + +static void insert(struct hufftree*tree, char*code, int index) +{ + if(!*code) { + assert(!tree->left); //shannon conditional + assert(!tree->right); + tree->left = 0; + tree->right = 0; + tree->index = index; + return; + } + if(code[0] == '0') { + if(!tree->left) { + tree->left = (struct hufftree*)malloc(sizeof(struct hufftree)); + memset(tree->left, 0, sizeof(struct hufftree)); + tree->left->index = -1; + } + insert(tree->left, code+1, index); + return; + } else { + assert(code[0] == '1'); + if(!tree->right) { + tree->right = (struct hufftree*)malloc(sizeof(struct hufftree)); + memset(tree->right, 0, sizeof(struct hufftree)); + tree->right->index = -1; + } + insert(tree->right, code+1, index); + return; + } +} + +struct hufftree* huffcode2tree(struct huffcode*code) +{ + struct hufftree* t = malloc(sizeof(struct hufftree)); + memset(t, 0, sizeof(struct hufftree)); + t->index = -1; + while(code->code) { + insert(t, code->code, code->index); + code++; + } + return t; +} + int gethuffvalue(TAG*tag, struct huffcode*code) { int len = 0; @@ -480,12 +248,32 @@ int gethuffvalue(TAG*tag, struct huffcode*code) }*/ } -void getCoefficient(TAG*tag, int t, int has_dc, int has_tcoef) +int gethuffvalue2(TAG*tag, struct huffcode*code, struct hufftree*tree) +{ + while(1) { + if(tree->index>=0) { + return tree->index; + } + if(!swf_GetBits(tag, 1)) { + assert(tree->left); + tree=tree->left; + } else { + assert(tree->right); + tree=tree->right; + } + } +} + +void get_DC_TCOEF(TAG*tag, int t, int has_dc, int has_tcoef) { int dc; int ac;// = swf_GetBits(); int index; int pos = 0; + int line[64]; + int show_rle_code=0; + memset(line, 0, sizeof(line)); + //printf("DC:%d\n", dc); if(has_dc) { dc = swf_GetBits(tag, 8); @@ -493,17 +281,18 @@ void getCoefficient(TAG*tag, int t, int has_dc, int has_tcoef) printf("error: dc=%d\n", dc); exit(1); } - DEBUG printf(" %d ", dc); + DEBUG if(show_rle_code) printf(" %d ", dc); + line[pos] = dc; pos++; } if(has_tcoef) { - DEBUG printf("["); + DEBUG if(show_rle_code) printf("["); while(1) { int last; int run; int level; - index = gethuffvalue(tag, rle); + index = gethuffvalue2(tag, rle, rle_tree); last = rle_params[index].last; run = rle_params[index].run; level = rle_params[index].level; @@ -512,10 +301,11 @@ void getCoefficient(TAG*tag, int t, int has_dc, int has_tcoef) last = swf_GetBits(tag, 1); run = swf_GetBits(tag, 6); level = swf_GetBits(tag, 8); - if(run) - DEBUG printf("(%d) E%d", run, level); - else - DEBUG printf("E"); + if(run) { + DEBUG if(show_rle_code) printf(" (%d) E%d", run, level); + } else { + DEBUG if(show_rle_code) printf("E"); + } if(level == 0 || level == 128) { printf("error: level=%d\n", level); exit(1); @@ -523,31 +313,47 @@ void getCoefficient(TAG*tag, int t, int has_dc, int has_tcoef) level = (int)((signed char)level); } else { int sign = swf_GetBits(tag, 1); - if(sign) + if(sign) { level = -level; - if(run) - DEBUG printf("(%d) %s%d", run, level>0?"+":"",level); - else - DEBUG printf("%s%d", level>0?"+":"",level); + } + if(run) { + DEBUG if(show_rle_code) printf(" (%d) %s%d", run, level>0?"+":"",level); + } else { + DEBUG if(show_rle_code) printf(" %s%d", level>0?"+":"",level); + } + } + pos += run; + if(pos>=64) { + printf("\nerror:bad pos: %d\n", pos); + exit(1); } - pos += run+1; + line[pos++] = level; //DEBUG printf("run:%d level:%d\n", run, level); if(last) { - DEBUG printf("] pos: %d", pos); + DEBUG if(show_rle_code) printf("] pos: %d", pos); if(pos>64) { - printf("\n"); + printf("\nerror:bad pos (%d)\n", pos); exit(1); } - return; + break; } } } + DEBUG if(show_rle_code) printf("\n"); + + DEBUG printf("["); + for(t=0;t>t); DEBUG printf("luminance%d ", t); - getCoefficient(tag, t, has_intradc, has_tcoef); /*luminance - affected by cbpy*/ - DEBUG printf("\n"); + get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*luminance - affected by cbpy*/ } for(t=0;t<2;t++) { int has_intradc = intrablock; int has_tcoef = cbpc & (2>>t); DEBUG printf("chrominance%d ", t); - getCoefficient(tag, t, has_intradc, has_tcoef); /*chrominance - affected by mcbc*/ - DEBUG printf("\n"); + get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*chrominance - affected by mcbc*/ } } @@ -684,6 +502,7 @@ void handleVideoFrame(TAG*tag, char*prefix) if(version >= 1) { /* version 1 has some different transform coefficient coding which we can't handle yet */ + printf("spark version %d not supported yet\n", version); exit(1); } reference = swf_GetBits(tag, 8); @@ -692,7 +511,7 @@ void handleVideoFrame(TAG*tag, char*prefix) sizeflags = swf_GetBits(tag, 3); switch(sizeflags) { - case 0: width = swf_GetU8(tag); height = swf_GetU8(tag); break; + case 0: width = swf_GetBits(tag,8); height = swf_GetBits(tag,8); break; case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break; case 2: width = 352; height = 288; break; case 3: width = 176; height = 144; break; @@ -704,7 +523,7 @@ void handleVideoFrame(TAG*tag, char*prefix) pictype = swf_GetBits(tag, 2); if(pictype==3) { - printf("pictype: %d\n", pictype); + printf("error: unknown pictype: %d\n", pictype); exit(1); } if(pictype==2) { @@ -785,6 +604,12 @@ int main (int argc,char ** argv) checkhufftable(cbpy, "cbpy"); checkhufftable(mvd, "mvd"); + rle_tree = huffcode2tree(rle); + mcbpc_intra_tree = huffcode2tree(mcbpc_intra); + mcbpc_inter_tree = huffcode2tree(mcbpc_inter); + cbpy_tree = huffcode2tree(cbpy); + mvd_tree = huffcode2tree(mvd); + processargs(argc, argv); if(!filename) { fprintf(stderr, "You must supply a filename.\n");