libavcodec/msmpeg4.c
de6d9b64
 /*
124e2884
  * MSMPEG4 backend for encoder and decoder
406792e7
  * Copyright (c) 2001 Fabrice Bellard
8f2ab833
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
de6d9b64
  *
7b94177e
  * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
  *
b78e7197
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
ff4ec49e
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
b78e7197
  * version 2.1 of the License, or (at your option) any later version.
de6d9b64
  *
b78e7197
  * FFmpeg is distributed in the hope that it will be useful,
de6d9b64
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
ff4ec49e
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
de6d9b64
  *
ff4ec49e
  * You should have received a copy of the GNU Lesser General Public
b78e7197
  * License along with FFmpeg; if not, write to the Free Software
5509bffa
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
de6d9b64
  */
983e3246
 
 /**
ba87f080
  * @file
124e2884
  * MSMPEG4 backend for encoder and decoder
983e3246
  */
 
6000abfa
 #include "avcodec.h"
e3fcb143
 #include "idctdsp.h"
de6d9b64
 #include "mpegvideo.h"
cc6de104
 #include "msmpeg4.h"
c318626c
 #include "libavutil/x86/asm.h"
ca334dd1
 #include "h263.h"
 #include "mpeg4video.h"
2f4b476e
 #include "msmpeg4data.h"
378a0008
 #include "mpegvideodata.h"
bd7a647c
 #include "vc1data.h"
33181975
 #include "libavutil/imgutils.h"
92ba5ffb
 
de6d9b64
 /*
41ed7ab4
  * You can also call this codec: MPEG-4 with a twist!
de6d9b64
  *
115329f1
  * TODO:
de6d9b64
  *        - (encoding) select best mv table (two choices)
115329f1
  *        - (encoding) select best vlc/dc table
de6d9b64
  */
 
41ed7ab4
 /* This table is practically identical to the one from H.263
8380edd9
  * except that it is inverted. */
 static av_cold void init_h263_dc_for_msmpeg4(void)
 {
         int level, uni_code, uni_len;
 
6c8d259a
         if(ff_v2_dc_chroma_table[255 + 256][1])
             return;
 
8380edd9
         for(level=-256; level<256; level++){
             int size, v, l;
             /* find number of bits */
             size = 0;
             v = abs(level);
             while (v) {
                 v >>= 1;
                     size++;
             }
 
             if (level < 0)
                 l= (-level) ^ ((1 << size) - 1);
             else
                 l= level;
 
41ed7ab4
             /* luminance H.263 */
05b858b0
             uni_code= ff_mpeg4_DCtab_lum[size][0];
             uni_len = ff_mpeg4_DCtab_lum[size][1];
8380edd9
             uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
 
             if (size > 0) {
                 uni_code<<=size; uni_code|=l;
                 uni_len+=size;
                 if (size > 8){
                     uni_code<<=1; uni_code|=1;
                     uni_len++;
                 }
             }
2f4b476e
             ff_v2_dc_lum_table[level + 256][0] = uni_code;
             ff_v2_dc_lum_table[level + 256][1] = uni_len;
8380edd9
 
41ed7ab4
             /* chrominance H.263 */
05b858b0
             uni_code= ff_mpeg4_DCtab_chrom[size][0];
             uni_len = ff_mpeg4_DCtab_chrom[size][1];
8380edd9
             uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
 
             if (size > 0) {
                 uni_code<<=size; uni_code|=l;
                 uni_len+=size;
                 if (size > 8){
                     uni_code<<=1; uni_code|=1;
                     uni_len++;
                 }
             }
2f4b476e
             ff_v2_dc_chroma_table[level + 256][0] = uni_code;
             ff_v2_dc_chroma_table[level + 256][1] = uni_len;
8380edd9
 
         }
 }
 
2f4b476e
 av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
f5957f3f
 {
     switch(s->msmpeg4_version){
     case 1:
     case 2:
         s->y_dc_scale_table=
         s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
         break;
     case 3:
         if(s->workaround_bugs){
1fec0550
             s->y_dc_scale_table= ff_old_ff_y_dc_scale_table;
             s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
f5957f3f
         } else{
             s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table;
             s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
         }
         break;
     case 4:
1457ab52
     case 5:
1fec0550
         s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
         s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
f5957f3f
         break;
9be6f0d2
 #if CONFIG_VC1_DECODER
0d33db8a
     case 6:
5f2c159c
         s->y_dc_scale_table= ff_wmv3_dc_scale_table;
         s->c_dc_scale_table= ff_wmv3_dc_scale_table;
0d33db8a
         break;
8b975b7c
 #endif
0d33db8a
 
f5957f3f
     }
 
115329f1
 
1457ab52
     if(s->msmpeg4_version>=4){
e3fcb143
         ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,   ff_wmv1_scantable[1]);
         ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]);
         ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]);
         ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,   ff_wmv1_scantable[0]);
f5957f3f
     }
2ad1516a
     //Note the default tables are set in common_init in mpegvideo.c
115329f1
 
6c8d259a
     init_h263_dc_for_msmpeg4();
f5957f3f
 }
 
de6d9b64
 /* predict coded block */
85f601ee
 int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
de6d9b64
 {
dbbe8999
     int xy, wrap, pred, a, b, c;
de6d9b64
 
dbbe8999
     xy = s->block_index[n];
137c8468
     wrap = s->b8_stride;
de6d9b64
 
     /* B C
115329f1
      * A X
de6d9b64
      */
dbbe8999
     a = s->coded_block[xy - 1       ];
     b = s->coded_block[xy - 1 - wrap];
     c = s->coded_block[xy     - wrap];
115329f1
 
de6d9b64
     if (b == c) {
         pred = a;
     } else {
         pred = c;
     }
115329f1
 
de6d9b64
     /* store value */
dbbe8999
     *coded_block_ptr = &s->coded_block[xy];
de6d9b64
 
     return pred;
 }
 
5dba888d
 static int get_dc(uint8_t *src, int stride, int scale, int block_size)
de0f2f4c
 {
     int y;
     int sum=0;
5dba888d
     for(y=0; y<block_size; y++){
de0f2f4c
         int x;
5dba888d
         for(x=0; x<block_size; x++){
de0f2f4c
             sum+=src[x + y*stride];
         }
     }
d4961b35
     return FASTDIV((sum + (scale>>1)), scale);
de0f2f4c
 }
 
de6d9b64
 /* dir = 0: left, dir = 1: top prediction */
2f4b476e
 int ff_msmpeg4_pred_dc(MpegEncContext *s, int n,
                        int16_t **dc_val_ptr, int *dir_ptr)
de6d9b64
 {
dbbe8999
     int a, b, c, wrap, pred, scale;
b86216de
     int16_t *dc_val;
de6d9b64
 
     /* find prediction */
     if (n < 4) {
bb270c08
         scale = s->y_dc_scale;
de6d9b64
     } else {
bb270c08
         scale = s->c_dc_scale;
de6d9b64
     }
115329f1
 
dbbe8999
     wrap = s->block_wrap[n];
     dc_val= s->dc_val[0] + s->block_index[n];
de6d9b64
 
     /* B C
115329f1
      * A X
de6d9b64
      */
dbbe8999
     a = dc_val[ - 1];
     b = dc_val[ - 1 - wrap];
     c = dc_val[ - wrap];
115329f1
 
28269849
     if(s->first_slice_line && (n&2)==0 && s->msmpeg4_version<4){
4d2858de
         b=c=1024;
     }
de6d9b64
 
     /* XXX: the following solution consumes divisions, but it does not
        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 !) */
f2d702e1
 #if ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE
be449fca
     __asm__ volatile(
bb270c08
         "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"
c03dc440
         "imull %4               \n\t"
bb270c08
         "movl %%edx, %0         \n\t"
         "movl %1, %%eax         \n\t"
c03dc440
         "imull %4               \n\t"
bb270c08
         "movl %%edx, %1         \n\t"
         "movl %2, %%eax         \n\t"
c03dc440
         "imull %4               \n\t"
bb270c08
         "movl %%edx, %2         \n\t"
         : "+b" (a), "+c" (b), "+D" (c)
36cd3069
         : "g" (scale), "S" (ff_inverse[scale])
bb270c08
         : "%eax", "%edx"
6f903d8e
     );
320680d4
 #else
c7f7bfc9
     /* Divisions are costly everywhere; optimize the most common case. */
1e98dffb
     if (scale == 8) {
bb270c08
         a = (a + (8 >> 1)) / 8;
         b = (b + (8 >> 1)) / 8;
         c = (c + (8 >> 1)) / 8;
1e98dffb
     } else {
bb270c08
         a = FASTDIV((a + (scale >> 1)), scale);
         b = FASTDIV((b + (scale >> 1)), scale);
         c = FASTDIV((c + (scale >> 1)), scale);
1e98dffb
     }
6f903d8e
 #endif
41ed7ab4
     /* XXX: WARNING: they did not choose the same test as MPEG-4. This
de6d9b64
        is very important ! */
bd5e1c72
     if(s->msmpeg4_version>3){
de0f2f4c
         if(s->inter_intra_pred){
             uint8_t *dest;
             int wrap;
115329f1
 
de0f2f4c
             if(n==1){
                 pred=a;
                 *dir_ptr = 0;
             }else if(n==2){
                 pred=c;
                 *dir_ptr = 1;
             }else if(n==3){
                 if (abs(a - b) < abs(b - c)) {
                     pred = c;
                     *dir_ptr = 1;
                 } else {
                     pred = a;
                     *dir_ptr = 0;
                 }
             }else{
5dba888d
                 int bs = 8 >> s->avctx->lowres;
de0f2f4c
                 if(n<4){
                     wrap= s->linesize;
59a53842
                     dest= s->current_picture.f->data[0] + (((n >> 1) + 2*s->mb_y) * bs*  wrap ) + ((n & 1) + 2*s->mb_x) * bs;
de0f2f4c
                 }else{
0fd90455
                     wrap= s->uvlinesize;
59a53842
                     dest= s->current_picture.f->data[n - 3] + (s->mb_y * bs * wrap) + s->mb_x * bs;
de0f2f4c
                 }
                 if(s->mb_x==0) a= (1024 + (scale>>1))/scale;
5dba888d
                 else           a= get_dc(dest-bs, wrap, scale*8>>(2*s->avctx->lowres), bs);
de0f2f4c
                 if(s->mb_y==0) c= (1024 + (scale>>1))/scale;
5dba888d
                 else           c= get_dc(dest-bs*wrap, wrap, scale*8>>(2*s->avctx->lowres), bs);
115329f1
 
de0f2f4c
                 if (s->h263_aic_dir==0) {
                     pred= a;
                     *dir_ptr = 0;
                 }else if (s->h263_aic_dir==1) {
                     if(n==0){
                         pred= c;
                         *dir_ptr = 1;
                     }else{
                         pred= a;
                         *dir_ptr = 0;
                     }
                 }else if (s->h263_aic_dir==2) {
                     if(n==0){
                         pred= a;
                         *dir_ptr = 0;
                     }else{
                         pred= c;
                         *dir_ptr = 1;
                     }
                 } else {
                     pred= c;
                     *dir_ptr = 1;
                 }
             }
         }else{
             if (abs(a - b) < abs(b - c)) {
                 pred = c;
                 *dir_ptr = 1;
             } else {
                 pred = a;
                 *dir_ptr = 0;
             }
bd5e1c72
         }
     }else{
         if (abs(a - b) <= abs(b - c)) {
             pred = c;
             *dir_ptr = 1;
         } else {
             pred = a;
             *dir_ptr = 0;
         }
de6d9b64
     }
 
     /* update predictor */
dbbe8999
     *dc_val_ptr = &dc_val[0];
de6d9b64
     return pred;
 }