]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/msmpeg4.c
(commit by michael)
[ffmpeg] / libavcodec / msmpeg4.c
index ac14da68f3c6270c7b94f9866ab508e7fcd75f1e..d737bbca47df550c2cd8300effb725c8fad679f5 100644 (file)
@@ -347,24 +347,43 @@ void msmpeg4_encode_mb(MpegEncContext * s,
 /* strongly inspirated from MPEG4, but not exactly the same ! */
 void msmpeg4_dc_scale(MpegEncContext * s)
 {
-    int scale;
-
-    if (s->qscale < 5)
-        scale = 8;
-    else if (s->qscale < 9)
-        scale = 2 * s->qscale;
-    else 
-        scale = s->qscale + 8;
-    s->y_dc_scale = scale;
-    s->c_dc_scale = (s->qscale + 13) / 2;
+    if (s->qscale < 5){
+        s->y_dc_scale = 8;
+        s->c_dc_scale = 8;
+//        s->c_dc_scale = (s->qscale + 13)>>1;
+    }else if (s->qscale < 9){
+        s->y_dc_scale = 2 * s->qscale;
+        s->c_dc_scale = (s->qscale + 13)>>1;
+    }else{
+        s->y_dc_scale = s->qscale + 8;
+        s->c_dc_scale = (s->qscale + 13)>>1;
+    }
+    // this differs for quant >24 from mpeg4 
+    
+//    if(s->qscale==13) s->c_dc_scale=14;
+    
+//    if(s->qscale>=6)
+//     printf("%d", s->qscale);
+    
+    /* s->c_dc_scale values (found by Michael Nidermayer)
+     qscale=2 -> 8 (yes iam sure about that)
+     qscale=3 -> 8
+     qscale=4 -> 8
+     qscale=5 -> 9
+     qscale=6 -> 9 
+     qscale=7 -> 10
+     qscale=8 -> 10
+     qscale=9 -> 11
+     qscale=10-> 11
+    */
 }
 
 /* dir = 0: left, dir = 1: top prediction */
 static int msmpeg4_pred_dc(MpegEncContext * s, int n, 
-                           UINT16 **dc_val_ptr, int *dir_ptr)
+                           INT16 **dc_val_ptr, int *dir_ptr)
 {
     int a, b, c, x, y, wrap, pred, scale;
-    UINT16 *dc_val;
+    INT16 *dc_val;
 
     /* find prediction */
     if (n < 4) {
@@ -392,10 +411,34 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n,
        necessitate to modify mpegvideo.c. The problem comes from the
        fact they decided to store the quantized DC (which would lead
        to problems if Q could vary !) */
+#ifdef ARCH_X86
+    /* using 16bit divisions as they are large enough and 2x as fast */
+    asm volatile(
+        "movl %3, %%eax                \n\t"
+       "shrl $1, %%eax         \n\t"
+       "addl %%eax, %2         \n\t"
+       "addl %%eax, %1         \n\t"
+       "addl %0, %%eax         \n\t"
+       "xorl %%edx, %%edx      \n\t"
+        "divw %w3              \n\t"
+       "movzwl %%ax, %0        \n\t"
+       "movl %1, %%eax         \n\t"
+       "xorl %%edx, %%edx      \n\t"
+        "divw %w3              \n\t"
+       "movzwl %%ax, %1        \n\t"
+       "movl %2, %%eax         \n\t"
+       "xorl %%edx, %%edx      \n\t"
+        "divw %w3              \n\t"
+       "movzwl %%ax, %2        \n\t"
+        : "+r" (a), "+r" (b), "+r" (c)
+       : "r" (scale)
+       : "%eax", "%edx"
+    );
+#else    
     a = (a + (scale >> 1)) / scale;
     b = (b + (scale >> 1)) / scale;
     c = (c + (scale >> 1)) / scale;
-
+#endif
     /* XXX: WARNING: they did not choose the same test as MPEG4. This
        is very important ! */
     if (abs(a - b) <= abs(b - c)) {
@@ -417,7 +460,7 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr
 {
     int sign, code;
     int pred;
-    UINT16 *dc_val;
+    INT16 *dc_val;
 
     pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
 
@@ -592,7 +635,7 @@ int msmpeg4_decode_init_vlc(MpegEncContext *s)
     init_vlc(&mb_non_intra_vlc, 9, 128, 
              &table_mb_non_intra[0][1], 8, 4,
              &table_mb_non_intra[0][0], 8, 4);
-    init_vlc(&mb_intra_vlc, 9, 128
+    init_vlc(&mb_intra_vlc, 9, 64
              &table_mb_intra[0][1], 4, 2,
              &table_mb_intra[0][0], 4, 2);
     return 0;
@@ -601,16 +644,17 @@ int msmpeg4_decode_init_vlc(MpegEncContext *s)
 static int decode012(GetBitContext *gb)
 {
     int n;
-    n = get_bits(gb, 1);
+    n = get_bits1(gb);
     if (n == 0)
         return 0;
     else
-        return get_bits(gb, 1) + 1;
+        return get_bits1(gb) + 1;
 }
 
 int msmpeg4_decode_picture_header(MpegEncContext * s)
 {
     int code;
+static int weirdAl=0;
 
     s->pict_type = get_bits(&s->gb, 2) + 1;
     if (s->pict_type != I_TYPE &&
@@ -623,24 +667,39 @@ int msmpeg4_decode_picture_header(MpegEncContext * s)
         code = get_bits(&s->gb, 5); 
         /* 0x17: one slice, 0x18: three slices */
         /* XXX: implement it */
+       //printf("%d %d %d\n", code, s->slice_height, s->first_slice_line);
         if (code < 0x17)
             return -1;
         s->slice_height = s->mb_height / (code - 0x16);
         s->rl_chroma_table_index = decode012(&s->gb);
         s->rl_table_index = decode012(&s->gb);
 
-        s->dc_table_index = get_bits(&s->gb, 1);
+        s->dc_table_index = get_bits1(&s->gb);
         s->no_rounding = 1;
+/*     printf(" %d %d %d %d     \n", 
+               s->qscale,
+               s->rl_chroma_table_index,
+               s->rl_table_index, 
+               s->dc_table_index);*/
     } else {
-        s->use_skip_mb_code = get_bits(&s->gb, 1);
+        s->use_skip_mb_code = get_bits1(&s->gb);
         
         s->rl_table_index = decode012(&s->gb);
         s->rl_chroma_table_index = s->rl_table_index;
 
-        s->dc_table_index = get_bits(&s->gb, 1);
+        s->dc_table_index = get_bits1(&s->gb);
 
-        s->mv_table_index = get_bits(&s->gb, 1);
-        s->no_rounding ^= 1;
+        s->mv_table_index = get_bits1(&s->gb);
+/*     printf(" %d %d %d %d %d     \n", 
+               s->use_skip_mb_code, 
+               s->rl_table_index, 
+               s->rl_chroma_table_index, 
+               s->dc_table_index,
+               s->mv_table_index);*/
+  if(weirdAl)
+       s->no_rounding = 0;
+  else
+       s->no_rounding ^= 1;
     }
 #ifdef DEBUG
     printf("*****frame %d:\n", frame_count++);
@@ -664,7 +723,7 @@ int msmpeg4_decode_mb(MpegEncContext *s,
 
     /* special slice handling */
     if (s->mb_x == 0) {
-        if ((s->mb_y % s->slice_height) == 0) {
+        if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
             int wrap;
             /* reset DC pred (set previous line to 1024) */
             wrap = 2 * s->mb_width + 2;
@@ -675,6 +734,16 @@ int msmpeg4_decode_mb(MpegEncContext *s,
                     1024, s->mb_width);
             memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap], 
                     1024, s->mb_width);
+            
+            /* reset AC pred (set previous line to 0) */
+            wrap = s->mb_width * 2 + 2;
+            memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
+                    0, 2 * s->mb_width*16);
+            wrap = s->mb_width + 2;
+            memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
+                    0, s->mb_width*16);
+            memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
+                    0, s->mb_width*16);
 
             s->first_slice_line = 1;
         } else {
@@ -685,7 +754,7 @@ int msmpeg4_decode_mb(MpegEncContext *s,
     if (s->pict_type == P_TYPE) {
         set_stat(ST_INTER_MB);
         if (s->use_skip_mb_code) {
-            if (get_bits(&s->gb, 1)) {
+            if (get_bits1(&s->gb)) {
                 /* skip mb */
                 s->mb_intra = 0;
                 for(i=0;i<6;i++)
@@ -739,7 +808,7 @@ int msmpeg4_decode_mb(MpegEncContext *s,
         s->mv[0][0][1] = my;
     } else {
         set_stat(ST_INTRA_MB);
-        s->ac_pred = get_bits(&s->gb, 1);
+        s->ac_pred = get_bits1(&s->gb);
     }
 
     for (i = 0; i < 6; i++) {
@@ -756,8 +825,12 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
     int dc_pred_dir;
     RLTable *rl;
     const UINT8 *scan_table;
+    int qmul, qadd;
 
     if (s->mb_intra) {
+        qmul=1;
+        qadd=0;
+
        /* DC coef */
         set_stat(ST_DC);
         level = msmpeg4_decode_dc(s, n, &dc_pred_dir);
@@ -769,6 +842,7 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
         } else {
             rl = &rl_table[3 + s->rl_chroma_table_index];
         }
+
         run_diff = 0;
        i = 1;
         if (!coded) {
@@ -784,6 +858,8 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
         }
         set_stat(ST_INTRA_AC);
     } else {
+        qmul = s->qscale << 1;
+        qadd = (s->qscale - 1) | 1;
        i = 0;
         rl = &rl_table[3 + s->rl_table_index];
         run_diff = 1;
@@ -801,13 +877,15 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
             return -1;
         if (code == rl->n) {
             /* escape */
-            if (get_bits(&s->gb, 1) == 0) {
-                if (get_bits(&s->gb, 1) == 0) {
+            if (get_bits1(&s->gb) == 0) {
+                if (get_bits1(&s->gb) == 0) {
                     /* third escape */
-                    last = get_bits(&s->gb, 1);
+                    last = get_bits1(&s->gb);
                     run = get_bits(&s->gb, 6);
                     level = get_bits(&s->gb, 8);
                     level = (level << 24) >> 24; /* sign extend */
+                    if(level>0) level= level * qmul + qadd;
+                    else        level= level * qmul - qadd;
                 } else {
                     /* second escape */
                     code = get_vlc(&s->gb, &rl->vlc);
@@ -817,7 +895,8 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                     level = rl->table_level[code];
                     last = code >= rl->last;
                     run += rl->max_run[last][level] + run_diff;
-                    if (get_bits(&s->gb, 1))
+                    level= level * qmul + qadd;
+                    if (get_bits1(&s->gb))
                         level = -level;
                 }
             } else {
@@ -829,14 +908,15 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                 level = rl->table_level[code];
                 last = code >= rl->last;
                 level += rl->max_level[last][run];
-                if (get_bits(&s->gb, 1))
+                level= level * qmul + qadd;
+                if (get_bits1(&s->gb))
                     level = -level;
             }
         } else {
             run = rl->table_run[code];
-            level = rl->table_level[code];
+            level = rl->table_level[code] * qmul + qadd;
             last = code >= rl->last;
-            if (get_bits(&s->gb, 1))
+            if (get_bits1(&s->gb))
                 level = -level;
         }
         i += run;
@@ -863,7 +943,7 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
 static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
 {
     int level, pred;
-    UINT16 *dc_val;
+    INT16 *dc_val;
 
     if (n < 4) {
         level = get_vlc(&s->gb, &dc_lum_vlc[s->dc_table_index]);
@@ -875,10 +955,10 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
 
     if (level == DC_MAX) {
         level = get_bits(&s->gb, 8);
-        if (get_bits(&s->gb, 1))
+        if (get_bits1(&s->gb))
             level = -level;
     } else if (level != 0) {
-        if (get_bits(&s->gb, 1))
+        if (get_bits1(&s->gb))
             level = -level;
     }