1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * H.263/MPEG-4 backend for encoder and decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2000,2001 Fabrice Bellard 4cabdff1aSopenharmony_ci * H.263+ support. 5cabdff1aSopenharmony_ci * Copyright (c) 2001 Juan J. Sierralta P 6cabdff1aSopenharmony_ci * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * This file is part of FFmpeg. 9cabdff1aSopenharmony_ci * 10cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 11cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 12cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 13cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 14cabdff1aSopenharmony_ci * 15cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 16cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 17cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18cabdff1aSopenharmony_ci * Lesser General Public License for more details. 19cabdff1aSopenharmony_ci * 20cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 21cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 22cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23cabdff1aSopenharmony_ci */ 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci/** 26cabdff1aSopenharmony_ci * @file 27cabdff1aSopenharmony_ci * H.263/MPEG-4 codec. 28cabdff1aSopenharmony_ci */ 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/thread.h" 31cabdff1aSopenharmony_ci#include "mpegvideo.h" 32cabdff1aSopenharmony_ci#include "h263.h" 33cabdff1aSopenharmony_ci#include "h263data.h" 34cabdff1aSopenharmony_ci#include "h263dsp.h" 35cabdff1aSopenharmony_ci#include "idctdsp.h" 36cabdff1aSopenharmony_ci#include "mathops.h" 37cabdff1aSopenharmony_ci#include "mpegpicture.h" 38cabdff1aSopenharmony_ci#include "mpegutils.h" 39cabdff1aSopenharmony_ci#include "rl.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic av_cold void h263_init_rl_inter(void) 42cabdff1aSopenharmony_ci{ 43cabdff1aSopenharmony_ci static uint8_t h263_rl_inter_table[2][2 * MAX_RUN + MAX_LEVEL + 3]; 44cabdff1aSopenharmony_ci ff_rl_init(&ff_h263_rl_inter, h263_rl_inter_table); 45cabdff1aSopenharmony_ci} 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ciav_cold void ff_h263_init_rl_inter(void) 48cabdff1aSopenharmony_ci{ 49cabdff1aSopenharmony_ci static AVOnce init_static_once = AV_ONCE_INIT; 50cabdff1aSopenharmony_ci ff_thread_once(&init_static_once, h263_init_rl_inter); 51cabdff1aSopenharmony_ci} 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_civoid ff_h263_update_motion_val(MpegEncContext * s){ 54cabdff1aSopenharmony_ci const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; 55cabdff1aSopenharmony_ci //FIXME a lot of that is only needed for !low_delay 56cabdff1aSopenharmony_ci const int wrap = s->b8_stride; 57cabdff1aSopenharmony_ci const int xy = s->block_index[0]; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci s->current_picture.mbskip_table[mb_xy] = s->mb_skipped; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci if(s->mv_type != MV_TYPE_8X8){ 62cabdff1aSopenharmony_ci int motion_x, motion_y; 63cabdff1aSopenharmony_ci if (s->mb_intra) { 64cabdff1aSopenharmony_ci motion_x = 0; 65cabdff1aSopenharmony_ci motion_y = 0; 66cabdff1aSopenharmony_ci } else if (s->mv_type == MV_TYPE_16X16) { 67cabdff1aSopenharmony_ci motion_x = s->mv[0][0][0]; 68cabdff1aSopenharmony_ci motion_y = s->mv[0][0][1]; 69cabdff1aSopenharmony_ci } else /*if (s->mv_type == MV_TYPE_FIELD)*/ { 70cabdff1aSopenharmony_ci int i; 71cabdff1aSopenharmony_ci motion_x = s->mv[0][0][0] + s->mv[0][1][0]; 72cabdff1aSopenharmony_ci motion_y = s->mv[0][0][1] + s->mv[0][1][1]; 73cabdff1aSopenharmony_ci motion_x = (motion_x>>1) | (motion_x&1); 74cabdff1aSopenharmony_ci for(i=0; i<2; i++){ 75cabdff1aSopenharmony_ci s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0]; 76cabdff1aSopenharmony_ci s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1]; 77cabdff1aSopenharmony_ci } 78cabdff1aSopenharmony_ci s->current_picture.ref_index[0][4*mb_xy ] = 79cabdff1aSopenharmony_ci s->current_picture.ref_index[0][4*mb_xy + 1] = s->field_select[0][0]; 80cabdff1aSopenharmony_ci s->current_picture.ref_index[0][4*mb_xy + 2] = 81cabdff1aSopenharmony_ci s->current_picture.ref_index[0][4*mb_xy + 3] = s->field_select[0][1]; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci /* no update if 8X8 because it has been done during parsing */ 85cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy][0] = motion_x; 86cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy][1] = motion_y; 87cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + 1][0] = motion_x; 88cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + 1][1] = motion_y; 89cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + wrap][0] = motion_x; 90cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + wrap][1] = motion_y; 91cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + 1 + wrap][0] = motion_x; 92cabdff1aSopenharmony_ci s->current_picture.motion_val[0][xy + 1 + wrap][1] = motion_y; 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci if(s->encoding){ //FIXME encoding MUST be cleaned up 96cabdff1aSopenharmony_ci if (s->mv_type == MV_TYPE_8X8) 97cabdff1aSopenharmony_ci s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_8x8; 98cabdff1aSopenharmony_ci else if(s->mb_intra) 99cabdff1aSopenharmony_ci s->current_picture.mb_type[mb_xy] = MB_TYPE_INTRA; 100cabdff1aSopenharmony_ci else 101cabdff1aSopenharmony_ci s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_16x16; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci} 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_civoid ff_h263_loop_filter(MpegEncContext * s){ 106cabdff1aSopenharmony_ci int qp_c; 107cabdff1aSopenharmony_ci const int linesize = s->linesize; 108cabdff1aSopenharmony_ci const int uvlinesize= s->uvlinesize; 109cabdff1aSopenharmony_ci const int xy = s->mb_y * s->mb_stride + s->mb_x; 110cabdff1aSopenharmony_ci uint8_t *dest_y = s->dest[0]; 111cabdff1aSopenharmony_ci uint8_t *dest_cb= s->dest[1]; 112cabdff1aSopenharmony_ci uint8_t *dest_cr= s->dest[2]; 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci /* 115cabdff1aSopenharmony_ci Diag Top 116cabdff1aSopenharmony_ci Left Center 117cabdff1aSopenharmony_ci */ 118cabdff1aSopenharmony_ci if (!IS_SKIP(s->current_picture.mb_type[xy])) { 119cabdff1aSopenharmony_ci qp_c= s->qscale; 120cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize, linesize, qp_c); 121cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c); 122cabdff1aSopenharmony_ci }else 123cabdff1aSopenharmony_ci qp_c= 0; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci if(s->mb_y){ 126cabdff1aSopenharmony_ci int qp_dt, qp_tt, qp_tc; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci if (IS_SKIP(s->current_picture.mb_type[xy - s->mb_stride])) 129cabdff1aSopenharmony_ci qp_tt=0; 130cabdff1aSopenharmony_ci else 131cabdff1aSopenharmony_ci qp_tt = s->current_picture.qscale_table[xy - s->mb_stride]; 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci if(qp_c) 134cabdff1aSopenharmony_ci qp_tc= qp_c; 135cabdff1aSopenharmony_ci else 136cabdff1aSopenharmony_ci qp_tc= qp_tt; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci if(qp_tc){ 139cabdff1aSopenharmony_ci const int chroma_qp= s->chroma_qscale_table[qp_tc]; 140cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_y, linesize, qp_tc); 141cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_y + 8, linesize, qp_tc); 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_cb, uvlinesize, chroma_qp); 144cabdff1aSopenharmony_ci s->h263dsp.h263_v_loop_filter(dest_cr, uvlinesize, chroma_qp); 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci if(qp_tt) 148cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize + 8, linesize, qp_tt); 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci if(s->mb_x){ 151cabdff1aSopenharmony_ci if (qp_tt || IS_SKIP(s->current_picture.mb_type[xy - 1 - s->mb_stride])) 152cabdff1aSopenharmony_ci qp_dt= qp_tt; 153cabdff1aSopenharmony_ci else 154cabdff1aSopenharmony_ci qp_dt = s->current_picture.qscale_table[xy - 1 - s->mb_stride]; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci if(qp_dt){ 157cabdff1aSopenharmony_ci const int chroma_qp= s->chroma_qscale_table[qp_dt]; 158cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize, linesize, qp_dt); 159cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_cb - 8 * uvlinesize, uvlinesize, chroma_qp); 160cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_cr - 8 * uvlinesize, uvlinesize, chroma_qp); 161cabdff1aSopenharmony_ci } 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci } 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci if(qp_c){ 166cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y + 8, linesize, qp_c); 167cabdff1aSopenharmony_ci if(s->mb_y + 1 == s->mb_height) 168cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c); 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci if(s->mb_x){ 172cabdff1aSopenharmony_ci int qp_lc; 173cabdff1aSopenharmony_ci if (qp_c || IS_SKIP(s->current_picture.mb_type[xy - 1])) 174cabdff1aSopenharmony_ci qp_lc= qp_c; 175cabdff1aSopenharmony_ci else 176cabdff1aSopenharmony_ci qp_lc = s->current_picture.qscale_table[xy - 1]; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci if(qp_lc){ 179cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y, linesize, qp_lc); 180cabdff1aSopenharmony_ci if(s->mb_y + 1 == s->mb_height){ 181cabdff1aSopenharmony_ci const int chroma_qp= s->chroma_qscale_table[qp_lc]; 182cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize, linesize, qp_lc); 183cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_cb, uvlinesize, chroma_qp); 184cabdff1aSopenharmony_ci s->h263dsp.h263_h_loop_filter(dest_cr, uvlinesize, chroma_qp); 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci} 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ciint16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, 191cabdff1aSopenharmony_ci int *px, int *py) 192cabdff1aSopenharmony_ci{ 193cabdff1aSopenharmony_ci int wrap; 194cabdff1aSopenharmony_ci int16_t *A, *B, *C, (*mot_val)[2]; 195cabdff1aSopenharmony_ci static const int off[4]= {2, 1, 1, -1}; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci wrap = s->b8_stride; 198cabdff1aSopenharmony_ci mot_val = s->current_picture.motion_val[dir] + s->block_index[block]; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci A = mot_val[ - 1]; 201cabdff1aSopenharmony_ci /* special case for first (slice) line */ 202cabdff1aSopenharmony_ci if (s->first_slice_line && block<3) { 203cabdff1aSopenharmony_ci // we can't just change some MVs to simulate that as we need them for the B-frames (and ME) 204cabdff1aSopenharmony_ci // and if we ever support non rectangular objects than we need to do a few ifs here anyway :( 205cabdff1aSopenharmony_ci if(block==0){ //most common case 206cabdff1aSopenharmony_ci if(s->mb_x == s->resync_mb_x){ //rare 207cabdff1aSopenharmony_ci *px= *py = 0; 208cabdff1aSopenharmony_ci }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare 209cabdff1aSopenharmony_ci C = mot_val[off[block] - wrap]; 210cabdff1aSopenharmony_ci if(s->mb_x==0){ 211cabdff1aSopenharmony_ci *px = C[0]; 212cabdff1aSopenharmony_ci *py = C[1]; 213cabdff1aSopenharmony_ci }else{ 214cabdff1aSopenharmony_ci *px = mid_pred(A[0], 0, C[0]); 215cabdff1aSopenharmony_ci *py = mid_pred(A[1], 0, C[1]); 216cabdff1aSopenharmony_ci } 217cabdff1aSopenharmony_ci }else{ 218cabdff1aSopenharmony_ci *px = A[0]; 219cabdff1aSopenharmony_ci *py = A[1]; 220cabdff1aSopenharmony_ci } 221cabdff1aSopenharmony_ci }else if(block==1){ 222cabdff1aSopenharmony_ci if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare 223cabdff1aSopenharmony_ci C = mot_val[off[block] - wrap]; 224cabdff1aSopenharmony_ci *px = mid_pred(A[0], 0, C[0]); 225cabdff1aSopenharmony_ci *py = mid_pred(A[1], 0, C[1]); 226cabdff1aSopenharmony_ci }else{ 227cabdff1aSopenharmony_ci *px = A[0]; 228cabdff1aSopenharmony_ci *py = A[1]; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci }else{ /* block==2*/ 231cabdff1aSopenharmony_ci B = mot_val[ - wrap]; 232cabdff1aSopenharmony_ci C = mot_val[off[block] - wrap]; 233cabdff1aSopenharmony_ci if(s->mb_x == s->resync_mb_x) //rare 234cabdff1aSopenharmony_ci A[0]=A[1]=0; 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci *px = mid_pred(A[0], B[0], C[0]); 237cabdff1aSopenharmony_ci *py = mid_pred(A[1], B[1], C[1]); 238cabdff1aSopenharmony_ci } 239cabdff1aSopenharmony_ci } else { 240cabdff1aSopenharmony_ci B = mot_val[ - wrap]; 241cabdff1aSopenharmony_ci C = mot_val[off[block] - wrap]; 242cabdff1aSopenharmony_ci *px = mid_pred(A[0], B[0], C[0]); 243cabdff1aSopenharmony_ci *py = mid_pred(A[1], B[1], C[1]); 244cabdff1aSopenharmony_ci } 245cabdff1aSopenharmony_ci return *mot_val; 246cabdff1aSopenharmony_ci} 247