more horizontal refactoring
[swftools.git] / lib / h.263 / video.c
index 2376017..31391db 100644 (file)
@@ -3,16 +3,31 @@
 
    Part of the swftools package.
    
-   Copyright (c) 2003 Matthias Kramm <kramm@quiss.org> */
-
-#include "../config.h"
+   Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
+   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 <unistd.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <stdarg.h>
-#include "../lib/rfxswf.h"
-#include "../lib/args.h"
-#include "h263tables.c"
+#include <assert.h>
+#include "../rfxswf.h"
+#include "../args.h"
+#include "h263tables.h"
 
 static char * filename = 0;
 static char * indent = "                ";
@@ -129,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;
@@ -177,12 +248,32 @@ int gethuffvalue(TAG*tag, struct huffcode*code)
        }*/
 }
                
+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);
@@ -190,17 +281,18 @@ void get_DC_TCOEF(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;
@@ -209,10 +301,11 @@ void get_DC_TCOEF(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);
@@ -220,31 +313,47 @@ void get_DC_TCOEF(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+1;
+           pos += run;
+           if(pos>=64) {
+               printf("\nerror:bad pos: %d\n", pos);
+               exit(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("\nerror:bad pos (%d)\n", pos);
                    exit(1);
                }
-               return;
+               break;
            }
        }
     }
+    DEBUG if(show_rle_code) printf("\n");
+
+    DEBUG printf("[");
+    for(t=0;t<pos;t++) {
+       DEBUG printf("%d", line[t]);
+       DEBUG if(t<pos-1) printf(" ");
+    }
+    DEBUG printf("]\n");
 }
            
-void readMVD(TAG*tag)
+int readMVD(TAG*tag)
 {
-    int index = gethuffvalue(tag, mvd);
+    int index = gethuffvalue2(tag, mvd, mvd_tree);
     DEBUG printf("mvd index:%d\n", index);
+    return index;
 }
 
 char has_quant[] = {0,1,0,0,1};
@@ -259,12 +368,11 @@ void decode_block(TAG*tag, int pictype)
 {
     int t;
     int mb_type = -1, cbpc = -1;
-    int dbquant;
+    int dquant;
     int cbpy_index, cbpy_value;
     int intrablock = 0;
     int type;
     if(pictype == TYPE_INTER) /* non-intra pictures have a cod flag */
-    /* TODO: according to the flash spec, this field is always present */
     {
        int cod = swf_GetBits(tag, 1);
        DEBUG printf("cod=%d\n",cod);
@@ -278,7 +386,7 @@ void decode_block(TAG*tag, int pictype)
     /* read mcbpc */
 
     if(pictype == TYPE_INTRA) { /* I-frame */
-       type = gethuffvalue(tag, mcbpc_intra);
+       type = gethuffvalue2(tag, mcbpc_intra, mcbpc_intra_tree);
        DEBUG printf("mcbpc=%d\n",type);
        mb_type = mcbpc_intra_params[type].mb_type;
        cbpc = mcbpc_intra_params[type].cbpc;
@@ -288,7 +396,7 @@ void decode_block(TAG*tag, int pictype)
        }
     } 
     else if(pictype == 1) { /* P-frame */
-       type = gethuffvalue(tag, mcbpc_inter);
+       type = gethuffvalue2(tag, mcbpc_inter, mcbpc_inter_tree);
        DEBUG printf("mcbpc=%d\n",type);
        mb_type = mcbpc_inter_params[type].mb_type;
        cbpc = mcbpc_inter_params[type].cbpc;
@@ -302,14 +410,14 @@ void decode_block(TAG*tag, int pictype)
     {
        intrablock = 1;
     }
-       
-    printf("%d", intrablock);
+
+    printf("%c", "vqVii"[mb_type]);
 
     DEBUG printf("mcbpc type: %d mb_type:%d cbpc:%d\n", type, mb_type, cbpc);
 
     /* read cbpy */
 
-    cbpy_index = gethuffvalue(tag, cbpy);
+    cbpy_index = gethuffvalue2(tag, cbpy, cbpy_tree);
     cbpy_value = cbpy_index;
     if(!intrablock)
        cbpy_value ^= 15;
@@ -324,13 +432,21 @@ void decode_block(TAG*tag, int pictype)
 
     /* quantizer */
     if(has_quant[mb_type]) {
-       dbquant = swf_GetBits(tag, 2);
-       DEBUG printf("quantizer: %d\n", dbquant);
+       dquant = swf_GetBits(tag, 2);
+       if(dquant == 0) dquant = -1;
+       else if(dquant == 1) dquant = -2;
+       else if(dquant == 2) dquant = +1;
+       else if(dquant == 3) dquant = +2;
+       DEBUG printf("dquant: %d\n", dquant);
     }
 
     if(has_mvd[mb_type]&1) {
-       readMVD(tag); //horizontal
-       readMVD(tag); //vertical
+       int x,y;
+       x = readMVD(tag); //horizontal
+       y = readMVD(tag); //vertical
+       /*if(x==32 && y==32)
+           printf("\b0"); // prediction was 100% match
+        */
     }
     if(has_mvd[mb_type]&2) {
        /* only in advanced prediction mode */
@@ -347,14 +463,12 @@ void decode_block(TAG*tag, int pictype)
        int has_tcoef = cbpy_value & (8>>t);
        DEBUG printf("luminance%d ", t);
        get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*luminance - affected by cbpy*/
-       DEBUG printf("\n");
     }
     for(t=0;t<2;t++) {
        int has_intradc = intrablock;
        int has_tcoef = cbpc & (2>>t);
        DEBUG printf("chrominance%d ", t); 
        get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*chrominance - affected by mcbc*/
-       DEBUG printf("\n");
     }
 }
 
@@ -397,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;
@@ -441,8 +555,8 @@ void handleVideoFrame(TAG*tag, char*prefix)
 
     /*if(pictype == TYPE_INTER)
        return;*/
-    if(pictype == TYPE_INTRA)
-       return;
+    /*if(pictype == TYPE_INTRA)
+       return;*/
 
     /*tagnr++;
     if(tagnr!=2)
@@ -490,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");