libavcodec/h263.c
de6d9b64
 /*
124e2884
  * H263/MPEG4 backend for encoder and decoder
406792e7
  * Copyright (c) 2000,2001 Fabrice Bellard
6dbd39fe
  * H263+ support.
406792e7
  * Copyright (c) 2001 Juan J. Sierralta P
8f2ab833
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
de6d9b64
  *
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
  */
2ba8f6b8
 
 /**
ba87f080
  * @file
983e3246
  * h263/mpeg4 codec.
2ba8f6b8
  */
115329f1
 
1e209222
 //#define DEBUG
f2f6134b
 #include <limits.h>
 
de6d9b64
 #include "dsputil.h"
 #include "avcodec.h"
 #include "mpegvideo.h"
ca334dd1
 #include "h263.h"
de6d9b64
 #include "h263data.h"
199436b9
 #include "mathops.h"
685502cf
 #include "unary.h"
eb523769
 #include "flv.h"
ca334dd1
 #include "mpeg4video.h"
de6d9b64
 
c5d309f2
 //#undef NDEBUG
 //#include <assert.h>
 
fc53b6af
 uint8_t ff_h263_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3];
115329f1
 
841f65f2
 
7d1c3fc1
 void ff_h263_update_motion_val(MpegEncContext * s){
     const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
893bc624
                //FIXME a lot of that is only needed for !low_delay
137c8468
     const int wrap = s->b8_stride;
7d1c3fc1
     const int xy = s->block_index[0];
115329f1
 
657ccb5a
     s->current_picture.f.mbskip_table[mb_xy] = s->mb_skipped;
7d1c3fc1
 
     if(s->mv_type != MV_TYPE_8X8){
         int motion_x, motion_y;
         if (s->mb_intra) {
             motion_x = 0;
             motion_y = 0;
         } else if (s->mv_type == MV_TYPE_16X16) {
             motion_x = s->mv[0][0][0];
             motion_y = s->mv[0][0][1];
         } else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
             int i;
             motion_x = s->mv[0][0][0] + s->mv[0][1][0];
             motion_y = s->mv[0][0][1] + s->mv[0][1][1];
             motion_x = (motion_x>>1) | (motion_x&1);
             for(i=0; i<2; i++){
bb198e19
                 s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0];
                 s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1];
7d1c3fc1
             }
657ccb5a
             s->current_picture.f.ref_index[0][4*mb_xy    ] =
             s->current_picture.f.ref_index[0][4*mb_xy + 1] = s->field_select[0][0];
             s->current_picture.f.ref_index[0][4*mb_xy + 2] =
             s->current_picture.f.ref_index[0][4*mb_xy + 3] = s->field_select[0][1];
7d1c3fc1
         }
7c4f71c4
 
7d1c3fc1
         /* no update if 8X8 because it has been done during parsing */
657ccb5a
         s->current_picture.f.motion_val[0][xy][0]            = motion_x;
         s->current_picture.f.motion_val[0][xy][1]            = motion_y;
         s->current_picture.f.motion_val[0][xy + 1][0]        = motion_x;
         s->current_picture.f.motion_val[0][xy + 1][1]        = motion_y;
         s->current_picture.f.motion_val[0][xy + wrap][0]     = motion_x;
         s->current_picture.f.motion_val[0][xy + wrap][1]     = motion_y;
         s->current_picture.f.motion_val[0][xy + 1 + wrap][0] = motion_x;
         s->current_picture.f.motion_val[0][xy + 1 + wrap][1] = motion_y;
7d1c3fc1
     }
 
     if(s->encoding){ //FIXME encoding MUST be cleaned up
115329f1
         if (s->mv_type == MV_TYPE_8X8)
657ccb5a
             s->current_picture.f.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_8x8;
f7190f73
         else if(s->mb_intra)
657ccb5a
             s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA;
7d1c3fc1
         else
657ccb5a
             s->current_picture.f.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_16x16;
7d1c3fc1
     }
 }
 
6d1b9132
 int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr)
1436f317
 {
     int x, y, wrap, a, c, pred_dc;
     int16_t *dc_val;
 
     /* find prediction */
     if (n < 4) {
         x = 2 * s->mb_x + (n & 1);
         y = 2 * s->mb_y + ((n & 2) >> 1);
         wrap = s->b8_stride;
         dc_val = s->dc_val[0];
     } else {
         x = s->mb_x;
         y = s->mb_y;
         wrap = s->mb_stride;
         dc_val = s->dc_val[n - 4 + 1];
     }
     /* B C
      * A X
      */
     a = dc_val[(x - 1) + (y) * wrap];
     c = dc_val[(x) + (y - 1) * wrap];
 
     /* No prediction outside GOB boundary */
     if(s->first_slice_line && n!=3){
         if(n!=2) c= 1024;
         if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024;
     }
     /* just DC prediction */
     if (a != 1024 && c != 1024)
         pred_dc = (a + c) >> 1;
     else if (a != 1024)
         pred_dc = a;
     else
         pred_dc = c;
 
     /* we assume pred is positive */
     *dc_val_ptr = &dc_val[x + y * wrap];
     return pred_dc;
 }
 
cdb4e730
 void ff_h263_loop_filter(MpegEncContext * s){
332f9ac4
     int qp_c;
     const int linesize  = s->linesize;
     const int uvlinesize= s->uvlinesize;
     const int xy = s->mb_y * s->mb_stride + s->mb_x;
     uint8_t *dest_y = s->dest[0];
     uint8_t *dest_cb= s->dest[1];
     uint8_t *dest_cr= s->dest[2];
115329f1
 
ce5e49b0
 //    if(s->pict_type==AV_PICTURE_TYPE_B && !s->readable) return;
332f9ac4
 
     /*
        Diag Top
        Left Center
     */
657ccb5a
     if (!IS_SKIP(s->current_picture.f.mb_type[xy])) {
332f9ac4
         qp_c= s->qscale;
         s->dsp.h263_v_loop_filter(dest_y+8*linesize  , linesize, qp_c);
         s->dsp.h263_v_loop_filter(dest_y+8*linesize+8, linesize, qp_c);
     }else
         qp_c= 0;
 
     if(s->mb_y){
aaf0e267
         int qp_dt, qp_tt, qp_tc;
332f9ac4
 
657ccb5a
         if (IS_SKIP(s->current_picture.f.mb_type[xy - s->mb_stride]))
aaf0e267
             qp_tt=0;
115329f1
         else
657ccb5a
             qp_tt = s->current_picture.f.qscale_table[xy - s->mb_stride];
332f9ac4
 
115329f1
         if(qp_c)
332f9ac4
             qp_tc= qp_c;
         else
aaf0e267
             qp_tc= qp_tt;
115329f1
 
332f9ac4
         if(qp_tc){
             const int chroma_qp= s->chroma_qscale_table[qp_tc];
             s->dsp.h263_v_loop_filter(dest_y  ,   linesize, qp_tc);
             s->dsp.h263_v_loop_filter(dest_y+8,   linesize, qp_tc);
115329f1
 
332f9ac4
             s->dsp.h263_v_loop_filter(dest_cb , uvlinesize, chroma_qp);
             s->dsp.h263_v_loop_filter(dest_cr , uvlinesize, chroma_qp);
         }
115329f1
 
aaf0e267
         if(qp_tt)
             s->dsp.h263_h_loop_filter(dest_y-8*linesize+8  ,   linesize, qp_tt);
115329f1
 
332f9ac4
         if(s->mb_x){
657ccb5a
             if (qp_tt || IS_SKIP(s->current_picture.f.mb_type[xy - 1 - s->mb_stride]))
aaf0e267
                 qp_dt= qp_tt;
332f9ac4
             else
657ccb5a
                 qp_dt = s->current_picture.f.qscale_table[xy - 1 - s->mb_stride];
115329f1
 
332f9ac4
             if(qp_dt){
                 const int chroma_qp= s->chroma_qscale_table[qp_dt];
                 s->dsp.h263_h_loop_filter(dest_y -8*linesize  ,   linesize, qp_dt);
                 s->dsp.h263_h_loop_filter(dest_cb-8*uvlinesize, uvlinesize, chroma_qp);
b1114f18
                 s->dsp.h263_h_loop_filter(dest_cr-8*uvlinesize, uvlinesize, chroma_qp);
332f9ac4
             }
         }
     }
 
     if(qp_c){
         s->dsp.h263_h_loop_filter(dest_y +8,   linesize, qp_c);
         if(s->mb_y + 1 == s->mb_height)
             s->dsp.h263_h_loop_filter(dest_y+8*linesize+8,   linesize, qp_c);
     }
115329f1
 
332f9ac4
     if(s->mb_x){
         int qp_lc;
657ccb5a
         if (qp_c || IS_SKIP(s->current_picture.f.mb_type[xy - 1]))
332f9ac4
             qp_lc= qp_c;
         else
657ccb5a
             qp_lc = s->current_picture.f.qscale_table[xy - 1];
115329f1
 
332f9ac4
         if(qp_lc){
             s->dsp.h263_h_loop_filter(dest_y,   linesize, qp_lc);
             if(s->mb_y + 1 == s->mb_height){
                 const int chroma_qp= s->chroma_qscale_table[qp_lc];
                 s->dsp.h263_h_loop_filter(dest_y +8*  linesize,   linesize, qp_lc);
                 s->dsp.h263_h_loop_filter(dest_cb             , uvlinesize, chroma_qp);
                 s->dsp.h263_h_loop_filter(dest_cr             , uvlinesize, chroma_qp);
             }
         }
     }
 }
 
6d1b9132
 void ff_h263_pred_acdc(MpegEncContext * s, DCTELEM *block, int n)
d140623f
 {
9e15ad28
     int x, y, wrap, a, c, pred_dc, scale, i;
b86216de
     int16_t *dc_val, *ac_val, *ac_val1;
d140623f
 
     /* find prediction */
     if (n < 4) {
137c8468
         x = 2 * s->mb_x + (n & 1);
         y = 2 * s->mb_y + (n>> 1);
         wrap = s->b8_stride;
d140623f
         dc_val = s->dc_val[0];
9e15ad28
         ac_val = s->ac_val[0][0];
d140623f
         scale = s->y_dc_scale;
     } else {
137c8468
         x = s->mb_x;
         y = s->mb_y;
         wrap = s->mb_stride;
d140623f
         dc_val = s->dc_val[n - 4 + 1];
9e15ad28
         ac_val = s->ac_val[n - 4 + 1][0];
d140623f
         scale = s->c_dc_scale;
     }
115329f1
 
9e15ad28
     ac_val += ((y) * wrap + (x)) * 16;
     ac_val1 = ac_val;
115329f1
 
d140623f
     /* B C
115329f1
      * A X
d140623f
      */
     a = dc_val[(x - 1) + (y) * wrap];
     c = dc_val[(x) + (y - 1) * wrap];
115329f1
 
ef5b1b5a
     /* No prediction outside GOB boundary */
68b94c35
     if(s->first_slice_line && n!=3){
         if(n!=2) c= 1024;
         if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024;
     }
115329f1
 
d140623f
     if (s->ac_pred) {
68b94c35
         pred_dc = 1024;
d140623f
         if (s->h263_aic_dir) {
             /* left prediction */
9e15ad28
             if (a != 1024) {
                 ac_val -= 16;
                 for(i=1;i<8;i++) {
b0368839
                     block[s->dsp.idct_permutation[i<<3]] += ac_val[i];
9e15ad28
                 }
                 pred_dc = a;
d140623f
             }
         } else {
             /* top prediction */
9e15ad28
             if (c != 1024) {
                 ac_val -= 16 * wrap;
                 for(i=1;i<8;i++) {
b0368839
                     block[s->dsp.idct_permutation[i   ]] += ac_val[i + 8];
9e15ad28
                 }
                 pred_dc = c;
d140623f
             }
         }
9e15ad28
     } else {
         /* just DC prediction */
         if (a != 1024 && c != 1024)
             pred_dc = (a + c) >> 1;
         else if (a != 1024)
             pred_dc = a;
         else
             pred_dc = c;
d140623f
     }
115329f1
 
9e15ad28
     /* we assume pred is positive */
     block[0]=block[0]*scale + pred_dc;
115329f1
 
9e15ad28
     if (block[0] < 0)
         block[0] = 0;
115329f1
     else
68b94c35
         block[0] |= 1;
115329f1
 
9e15ad28
     /* Update AC/DC tables */
     dc_val[(x) + (y) * wrap] = block[0];
115329f1
 
d140623f
     /* left copy */
     for(i=1;i<8;i++)
b0368839
         ac_val1[i    ] = block[s->dsp.idct_permutation[i<<3]];
d140623f
     /* top copy */
     for(i=1;i<8;i++)
b0368839
         ac_val1[8 + i] = block[s->dsp.idct_permutation[i   ]];
d140623f
 }
 
6d1b9132
 int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir,
                              int *px, int *py)
de6d9b64
 {
137c8468
     int wrap;
b40cd4e0
     int16_t *A, *B, *C, (*mot_val)[2];
     static const int off[4]= {2, 1, 1, -1};
 
     wrap = s->b8_stride;
657ccb5a
     mot_val = s->current_picture.f.motion_val[dir] + s->block_index[block];
b40cd4e0
 
     A = mot_val[ - 1];
     /* special case for first (slice) line */
     if (s->first_slice_line && block<3) {
893bc624
         // we can't just change some MVs to simulate that as we need them for the B frames (and ME)
b40cd4e0
         // and if we ever support non rectangular objects than we need to do a few ifs here anyway :(
         if(block==0){ //most common case
             if(s->mb_x  == s->resync_mb_x){ //rare
                 *px= *py = 0;
             }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
                 C = mot_val[off[block] - wrap];
                 if(s->mb_x==0){
                     *px = C[0];
                     *py = C[1];
                 }else{
                     *px = mid_pred(A[0], 0, C[0]);
                     *py = mid_pred(A[1], 0, C[1]);
                 }
             }else{
                 *px = A[0];
                 *py = A[1];
             }
         }else if(block==1){
             if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
                 C = mot_val[off[block] - wrap];
                 *px = mid_pred(A[0], 0, C[0]);
                 *py = mid_pred(A[1], 0, C[1]);
             }else{
                 *px = A[0];
                 *py = A[1];
             }
         }else{ /* block==2*/
             B = mot_val[ - wrap];
             C = mot_val[off[block] - wrap];
             if(s->mb_x == s->resync_mb_x) //rare
                 A[0]=A[1]=0;
115329f1
 
b40cd4e0
             *px = mid_pred(A[0], B[0], C[0]);
             *py = mid_pred(A[1], B[1], C[1]);
         }
     } else {
         B = mot_val[ - wrap];
         C = mot_val[off[block] - wrap];
         *px = mid_pred(A[0], B[0], C[0]);
         *py = mid_pred(A[1], B[1], C[1]);
     }
     return *mot_val;
 }
 
fd7db0fd
 
4d2858de
 /**
  * Get the GOB height based on picture height.
  */
 int ff_h263_get_gob_height(MpegEncContext *s){
     if (s->height <= 400)
         return 1;
     else if (s->height <= 800)
         return  2;
     else
         return 4;
de6d9b64
 }