Libav
|
00001 /* 00002 * H.26L/H.264/AVC/JVT/14496-10/... loop filter 00003 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00028 #include "libavutil/intreadwrite.h" 00029 #include "internal.h" 00030 #include "dsputil.h" 00031 #include "avcodec.h" 00032 #include "mpegvideo.h" 00033 #include "h264.h" 00034 #include "mathops.h" 00035 #include "rectangle.h" 00036 00037 //#undef NDEBUG 00038 #include <assert.h> 00039 00040 /* Deblocking filter (p153) */ 00041 static const uint8_t alpha_table[52*3] = { 00042 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00043 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00045 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00046 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00047 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 00048 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 00049 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 00050 80, 90,101,113,127,144,162,182,203,226, 00051 255,255, 00052 255,255,255,255,255,255,255,255,255,255,255,255,255, 00053 255,255,255,255,255,255,255,255,255,255,255,255,255, 00054 255,255,255,255,255,255,255,255,255,255,255,255,255, 00055 255,255,255,255,255,255,255,255,255,255,255,255,255, 00056 }; 00057 static const uint8_t beta_table[52*3] = { 00058 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00059 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00060 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00061 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00062 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00063 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 00064 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, 00065 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 00066 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 00067 18, 18, 00068 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 00069 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 00070 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 00071 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 00072 }; 00073 static const uint8_t tc0_table[52*3][4] = { 00074 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00075 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00076 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00077 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00078 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00079 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00080 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00081 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00082 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00083 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00084 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, 00085 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 }, 00086 {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 }, 00087 {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, 00088 {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 }, 00089 {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 }, 00090 {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 }, 00091 {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 }, 00092 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00093 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00094 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00095 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00096 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00097 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00098 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00099 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00100 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, 00101 }; 00102 00103 static void av_always_inline filter_mb_edgev( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, H264Context *h) { 00104 const unsigned int index_a = qp + h->slice_alpha_c0_offset; 00105 const int alpha = alpha_table[index_a]; 00106 const int beta = beta_table[qp + h->slice_beta_offset]; 00107 if (alpha ==0 || beta == 0) return; 00108 00109 if( bS[0] < 4 ) { 00110 int8_t tc[4]; 00111 tc[0] = tc0_table[index_a][bS[0]]; 00112 tc[1] = tc0_table[index_a][bS[1]]; 00113 tc[2] = tc0_table[index_a][bS[2]]; 00114 tc[3] = tc0_table[index_a][bS[3]]; 00115 h->h264dsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc); 00116 } else { 00117 h->h264dsp.h264_h_loop_filter_luma_intra(pix, stride, alpha, beta); 00118 } 00119 } 00120 static void av_always_inline filter_mb_edgecv( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, H264Context *h ) { 00121 const unsigned int index_a = qp + h->slice_alpha_c0_offset; 00122 const int alpha = alpha_table[index_a]; 00123 const int beta = beta_table[qp + h->slice_beta_offset]; 00124 if (alpha ==0 || beta == 0) return; 00125 00126 if( bS[0] < 4 ) { 00127 int8_t tc[4]; 00128 tc[0] = tc0_table[index_a][bS[0]]+1; 00129 tc[1] = tc0_table[index_a][bS[1]]+1; 00130 tc[2] = tc0_table[index_a][bS[2]]+1; 00131 tc[3] = tc0_table[index_a][bS[3]]+1; 00132 h->h264dsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc); 00133 } else { 00134 h->h264dsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta); 00135 } 00136 } 00137 00138 static void filter_mb_mbaff_edgev( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int bsi, int qp ) { 00139 int i; 00140 int index_a = qp + h->slice_alpha_c0_offset; 00141 int alpha = alpha_table[index_a]; 00142 int beta = beta_table[qp + h->slice_beta_offset]; 00143 for( i = 0; i < 8; i++, pix += stride) { 00144 const int bS_index = (i >> 1) * bsi; 00145 00146 if( bS[bS_index] == 0 ) { 00147 continue; 00148 } 00149 00150 if( bS[bS_index] < 4 ) { 00151 const int tc0 = tc0_table[index_a][bS[bS_index]]; 00152 const int p0 = pix[-1]; 00153 const int p1 = pix[-2]; 00154 const int p2 = pix[-3]; 00155 const int q0 = pix[0]; 00156 const int q1 = pix[1]; 00157 const int q2 = pix[2]; 00158 00159 if( FFABS( p0 - q0 ) < alpha && 00160 FFABS( p1 - p0 ) < beta && 00161 FFABS( q1 - q0 ) < beta ) { 00162 int tc = tc0; 00163 int i_delta; 00164 00165 if( FFABS( p2 - p0 ) < beta ) { 00166 if(tc0) 00167 pix[-2] = p1 + av_clip( ( p2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( p1 << 1 ) ) >> 1, -tc0, tc0 ); 00168 tc++; 00169 } 00170 if( FFABS( q2 - q0 ) < beta ) { 00171 if(tc0) 00172 pix[1] = q1 + av_clip( ( q2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( q1 << 1 ) ) >> 1, -tc0, tc0 ); 00173 tc++; 00174 } 00175 00176 i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); 00177 pix[-1] = av_clip_uint8( p0 + i_delta ); /* p0' */ 00178 pix[0] = av_clip_uint8( q0 - i_delta ); /* q0' */ 00179 tprintf(h->s.avctx, "filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1); 00180 } 00181 }else{ 00182 const int p0 = pix[-1]; 00183 const int p1 = pix[-2]; 00184 const int p2 = pix[-3]; 00185 00186 const int q0 = pix[0]; 00187 const int q1 = pix[1]; 00188 const int q2 = pix[2]; 00189 00190 if( FFABS( p0 - q0 ) < alpha && 00191 FFABS( p1 - p0 ) < beta && 00192 FFABS( q1 - q0 ) < beta ) { 00193 00194 if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){ 00195 if( FFABS( p2 - p0 ) < beta) 00196 { 00197 const int p3 = pix[-4]; 00198 /* p0', p1', p2' */ 00199 pix[-1] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3; 00200 pix[-2] = ( p2 + p1 + p0 + q0 + 2 ) >> 2; 00201 pix[-3] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3; 00202 } else { 00203 /* p0' */ 00204 pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; 00205 } 00206 if( FFABS( q2 - q0 ) < beta) 00207 { 00208 const int q3 = pix[3]; 00209 /* q0', q1', q2' */ 00210 pix[0] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3; 00211 pix[1] = ( p0 + q0 + q1 + q2 + 2 ) >> 2; 00212 pix[2] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3; 00213 } else { 00214 /* q0' */ 00215 pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; 00216 } 00217 }else{ 00218 /* p0', q0' */ 00219 pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; 00220 pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; 00221 } 00222 tprintf(h->s.avctx, "filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, p2, p1, p0, q0, q1, q2, pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]); 00223 } 00224 } 00225 } 00226 } 00227 static void filter_mb_mbaff_edgecv( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int bsi, int qp ) { 00228 int i; 00229 int index_a = qp + h->slice_alpha_c0_offset; 00230 int alpha = alpha_table[index_a]; 00231 int beta = beta_table[qp + h->slice_beta_offset]; 00232 for( i = 0; i < 4; i++, pix += stride) { 00233 const int bS_index = i*bsi; 00234 00235 if( bS[bS_index] == 0 ) { 00236 continue; 00237 } 00238 00239 if( bS[bS_index] < 4 ) { 00240 const int tc = tc0_table[index_a][bS[bS_index]] + 1; 00241 const int p0 = pix[-1]; 00242 const int p1 = pix[-2]; 00243 const int q0 = pix[0]; 00244 const int q1 = pix[1]; 00245 00246 if( FFABS( p0 - q0 ) < alpha && 00247 FFABS( p1 - p0 ) < beta && 00248 FFABS( q1 - q0 ) < beta ) { 00249 const int i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); 00250 00251 pix[-1] = av_clip_uint8( p0 + i_delta ); /* p0' */ 00252 pix[0] = av_clip_uint8( q0 - i_delta ); /* q0' */ 00253 tprintf(h->s.avctx, "filter_mb_mbaff_edgecv i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1); 00254 } 00255 }else{ 00256 const int p0 = pix[-1]; 00257 const int p1 = pix[-2]; 00258 const int q0 = pix[0]; 00259 const int q1 = pix[1]; 00260 00261 if( FFABS( p0 - q0 ) < alpha && 00262 FFABS( p1 - p0 ) < beta && 00263 FFABS( q1 - q0 ) < beta ) { 00264 00265 pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ 00266 pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ 00267 tprintf(h->s.avctx, "filter_mb_mbaff_edgecv i:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, pix[-3], p1, p0, q0, q1, pix[2], pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]); 00268 } 00269 } 00270 } 00271 } 00272 00273 static void av_always_inline filter_mb_edgeh( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, H264Context *h ) { 00274 const unsigned int index_a = qp + h->slice_alpha_c0_offset; 00275 const int alpha = alpha_table[index_a]; 00276 const int beta = beta_table[qp + h->slice_beta_offset]; 00277 if (alpha ==0 || beta == 0) return; 00278 00279 if( bS[0] < 4 ) { 00280 int8_t tc[4]; 00281 tc[0] = tc0_table[index_a][bS[0]]; 00282 tc[1] = tc0_table[index_a][bS[1]]; 00283 tc[2] = tc0_table[index_a][bS[2]]; 00284 tc[3] = tc0_table[index_a][bS[3]]; 00285 h->h264dsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc); 00286 } else { 00287 h->h264dsp.h264_v_loop_filter_luma_intra(pix, stride, alpha, beta); 00288 } 00289 } 00290 00291 static void av_always_inline filter_mb_edgech( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, H264Context *h ) { 00292 const unsigned int index_a = qp + h->slice_alpha_c0_offset; 00293 const int alpha = alpha_table[index_a]; 00294 const int beta = beta_table[qp + h->slice_beta_offset]; 00295 if (alpha ==0 || beta == 0) return; 00296 00297 if( bS[0] < 4 ) { 00298 int8_t tc[4]; 00299 tc[0] = tc0_table[index_a][bS[0]]+1; 00300 tc[1] = tc0_table[index_a][bS[1]]+1; 00301 tc[2] = tc0_table[index_a][bS[2]]+1; 00302 tc[3] = tc0_table[index_a][bS[3]]+1; 00303 h->h264dsp.h264_v_loop_filter_chroma(pix, stride, alpha, beta, tc); 00304 } else { 00305 h->h264dsp.h264_v_loop_filter_chroma_intra(pix, stride, alpha, beta); 00306 } 00307 } 00308 00309 void ff_h264_filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { 00310 MpegEncContext * const s = &h->s; 00311 int mb_xy; 00312 int mb_type, left_type; 00313 int qp, qp0, qp1, qpc, qpc0, qpc1, qp_thresh; 00314 00315 mb_xy = h->mb_xy; 00316 00317 if(!h->top_type || !h->h264dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff) { 00318 ff_h264_filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize); 00319 return; 00320 } 00321 assert(!FRAME_MBAFF); 00322 left_type= h->left_type[0]; 00323 00324 mb_type = s->current_picture.mb_type[mb_xy]; 00325 qp = s->current_picture.qscale_table[mb_xy]; 00326 qp0 = s->current_picture.qscale_table[mb_xy-1]; 00327 qp1 = s->current_picture.qscale_table[h->top_mb_xy]; 00328 qpc = get_chroma_qp( h, 0, qp ); 00329 qpc0 = get_chroma_qp( h, 0, qp0 ); 00330 qpc1 = get_chroma_qp( h, 0, qp1 ); 00331 qp0 = (qp + qp0 + 1) >> 1; 00332 qp1 = (qp + qp1 + 1) >> 1; 00333 qpc0 = (qpc + qpc0 + 1) >> 1; 00334 qpc1 = (qpc + qpc1 + 1) >> 1; 00335 qp_thresh = 15+52 - h->slice_alpha_c0_offset; 00336 if(qp <= qp_thresh && qp0 <= qp_thresh && qp1 <= qp_thresh && 00337 qpc <= qp_thresh && qpc0 <= qp_thresh && qpc1 <= qp_thresh) 00338 return; 00339 00340 if( IS_INTRA(mb_type) ) { 00341 int16_t bS4[4] = {4,4,4,4}; 00342 int16_t bS3[4] = {3,3,3,3}; 00343 int16_t *bSH = FIELD_PICTURE ? bS3 : bS4; 00344 if(left_type) 00345 filter_mb_edgev( &img_y[4*0], linesize, bS4, qp0, h); 00346 if( IS_8x8DCT(mb_type) ) { 00347 filter_mb_edgev( &img_y[4*2], linesize, bS3, qp, h); 00348 filter_mb_edgeh( &img_y[4*0*linesize], linesize, bSH, qp1, h); 00349 filter_mb_edgeh( &img_y[4*2*linesize], linesize, bS3, qp, h); 00350 } else { 00351 filter_mb_edgev( &img_y[4*1], linesize, bS3, qp, h); 00352 filter_mb_edgev( &img_y[4*2], linesize, bS3, qp, h); 00353 filter_mb_edgev( &img_y[4*3], linesize, bS3, qp, h); 00354 filter_mb_edgeh( &img_y[4*0*linesize], linesize, bSH, qp1, h); 00355 filter_mb_edgeh( &img_y[4*1*linesize], linesize, bS3, qp, h); 00356 filter_mb_edgeh( &img_y[4*2*linesize], linesize, bS3, qp, h); 00357 filter_mb_edgeh( &img_y[4*3*linesize], linesize, bS3, qp, h); 00358 } 00359 if(left_type){ 00360 filter_mb_edgecv( &img_cb[2*0], uvlinesize, bS4, qpc0, h); 00361 filter_mb_edgecv( &img_cr[2*0], uvlinesize, bS4, qpc0, h); 00362 } 00363 filter_mb_edgecv( &img_cb[2*2], uvlinesize, bS3, qpc, h); 00364 filter_mb_edgecv( &img_cr[2*2], uvlinesize, bS3, qpc, h); 00365 filter_mb_edgech( &img_cb[2*0*uvlinesize], uvlinesize, bSH, qpc1, h); 00366 filter_mb_edgech( &img_cb[2*2*uvlinesize], uvlinesize, bS3, qpc, h); 00367 filter_mb_edgech( &img_cr[2*0*uvlinesize], uvlinesize, bSH, qpc1, h); 00368 filter_mb_edgech( &img_cr[2*2*uvlinesize], uvlinesize, bS3, qpc, h); 00369 return; 00370 } else { 00371 LOCAL_ALIGNED_8(int16_t, bS, [2], [4][4]); 00372 int edges; 00373 if( IS_8x8DCT(mb_type) && (h->cbp&7) == 7 ) { 00374 edges = 4; 00375 AV_WN64A(bS[0][0], 0x0002000200020002ULL); 00376 AV_WN64A(bS[0][2], 0x0002000200020002ULL); 00377 AV_WN64A(bS[1][0], 0x0002000200020002ULL); 00378 AV_WN64A(bS[1][2], 0x0002000200020002ULL); 00379 } else { 00380 int mask_edge1 = (3*(((5*mb_type)>>5)&1)) | (mb_type>>4); //(mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : (mb_type & MB_TYPE_16x8) ? 1 : 0; 00381 int mask_edge0 = 3*((mask_edge1>>1) & ((5*left_type)>>5)&1); // (mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) && (h->left_type[0] & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : 0; 00382 int step = 1+(mb_type>>24); //IS_8x8DCT(mb_type) ? 2 : 1; 00383 edges = 4 - 3*((mb_type>>3) & !(h->cbp & 15)); //(mb_type & MB_TYPE_16x16) && !(h->cbp & 15) ? 1 : 4; 00384 h->h264dsp.h264_loop_filter_strength( bS, h->non_zero_count_cache, h->ref_cache, h->mv_cache, 00385 h->list_count==2, edges, step, mask_edge0, mask_edge1, FIELD_PICTURE); 00386 } 00387 if( IS_INTRA(left_type) ) 00388 AV_WN64A(bS[0][0], 0x0004000400040004ULL); 00389 if( IS_INTRA(h->top_type) ) 00390 AV_WN64A(bS[1][0], FIELD_PICTURE ? 0x0003000300030003ULL : 0x0004000400040004ULL); 00391 00392 #define FILTER(hv,dir,edge)\ 00393 if(AV_RN64A(bS[dir][edge])) { \ 00394 filter_mb_edge##hv( &img_y[4*edge*(dir?linesize:1)], linesize, bS[dir][edge], edge ? qp : qp##dir, h );\ 00395 if(!(edge&1)) {\ 00396 filter_mb_edgec##hv( &img_cb[2*edge*(dir?uvlinesize:1)], uvlinesize, bS[dir][edge], edge ? qpc : qpc##dir, h );\ 00397 filter_mb_edgec##hv( &img_cr[2*edge*(dir?uvlinesize:1)], uvlinesize, bS[dir][edge], edge ? qpc : qpc##dir, h );\ 00398 }\ 00399 } 00400 if(left_type) 00401 FILTER(v,0,0); 00402 if( edges == 1 ) { 00403 FILTER(h,1,0); 00404 } else if( IS_8x8DCT(mb_type) ) { 00405 FILTER(v,0,2); 00406 FILTER(h,1,0); 00407 FILTER(h,1,2); 00408 } else { 00409 FILTER(v,0,1); 00410 FILTER(v,0,2); 00411 FILTER(v,0,3); 00412 FILTER(h,1,0); 00413 FILTER(h,1,1); 00414 FILTER(h,1,2); 00415 FILTER(h,1,3); 00416 } 00417 #undef FILTER 00418 } 00419 } 00420 00421 static int check_mv(H264Context *h, long b_idx, long bn_idx, int mvy_limit){ 00422 int v; 00423 00424 v= h->ref_cache[0][b_idx] != h->ref_cache[0][bn_idx]; 00425 if(!v && h->ref_cache[0][b_idx]!=-1) 00426 v= h->mv_cache[0][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | 00427 FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; 00428 00429 if(h->list_count==2){ 00430 if(!v) 00431 v = h->ref_cache[1][b_idx] != h->ref_cache[1][bn_idx] | 00432 h->mv_cache[1][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | 00433 FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit; 00434 00435 if(v){ 00436 if(h->ref_cache[0][b_idx] != h->ref_cache[1][bn_idx] | 00437 h->ref_cache[1][b_idx] != h->ref_cache[0][bn_idx]) 00438 return 1; 00439 return 00440 h->mv_cache[0][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | 00441 FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit | 00442 h->mv_cache[1][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | 00443 FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; 00444 } 00445 } 00446 00447 return v; 00448 } 00449 00450 static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize, int mb_xy, int mb_type, int mvy_limit, int first_vertical_edge_done, int dir) { 00451 MpegEncContext * const s = &h->s; 00452 int edge; 00453 const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy; 00454 const int mbm_type = dir == 0 ? h->left_type[0] : h->top_type; 00455 00456 // how often to recheck mv-based bS when iterating between edges 00457 static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1}, 00458 {0,3,1,1,3,3,3,3}}; 00459 const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7]; 00460 const int edges = mask_edge== 3 && !(h->cbp&15) ? 1 : 4; 00461 00462 // how often to recheck mv-based bS when iterating along each edge 00463 const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)); 00464 00465 if(mbm_type && !first_vertical_edge_done){ 00466 00467 if (FRAME_MBAFF && (dir == 1) && ((mb_y&1) == 0) 00468 && IS_INTERLACED(mbm_type&~mb_type) 00469 ) { 00470 // This is a special case in the norm where the filtering must 00471 // be done twice (one each of the field) even if we are in a 00472 // frame macroblock. 00473 // 00474 unsigned int tmp_linesize = 2 * linesize; 00475 unsigned int tmp_uvlinesize = 2 * uvlinesize; 00476 int mbn_xy = mb_xy - 2 * s->mb_stride; 00477 int j; 00478 00479 for(j=0; j<2; j++, mbn_xy += s->mb_stride){ 00480 DECLARE_ALIGNED(8, int16_t, bS)[4]; 00481 int qp; 00482 if( IS_INTRA(mb_type|s->current_picture.mb_type[mbn_xy]) ) { 00483 AV_WN64A(bS, 0x0003000300030003ULL); 00484 } else { 00485 if(!CABAC && IS_8x8DCT(s->current_picture.mb_type[mbn_xy])){ 00486 bS[0]= 1+((h->cbp_table[mbn_xy] & 4)||h->non_zero_count_cache[scan8[0]+0]); 00487 bS[1]= 1+((h->cbp_table[mbn_xy] & 4)||h->non_zero_count_cache[scan8[0]+1]); 00488 bS[2]= 1+((h->cbp_table[mbn_xy] & 8)||h->non_zero_count_cache[scan8[0]+2]); 00489 bS[3]= 1+((h->cbp_table[mbn_xy] & 8)||h->non_zero_count_cache[scan8[0]+3]); 00490 }else{ 00491 const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy] + 4+3*8; 00492 int i; 00493 for( i = 0; i < 4; i++ ) { 00494 bS[i] = 1 + !!(h->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]); 00495 } 00496 } 00497 } 00498 // Do not use s->qscale as luma quantizer because it has not the same 00499 // value in IPCM macroblocks. 00500 qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1; 00501 tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize); 00502 { int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } 00503 filter_mb_edgeh( &img_y[j*linesize], tmp_linesize, bS, qp, h ); 00504 filter_mb_edgech( &img_cb[j*uvlinesize], tmp_uvlinesize, bS, 00505 ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1, h); 00506 filter_mb_edgech( &img_cr[j*uvlinesize], tmp_uvlinesize, bS, 00507 ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1, h); 00508 } 00509 }else{ 00510 DECLARE_ALIGNED(8, int16_t, bS)[4]; 00511 int qp; 00512 00513 if( IS_INTRA(mb_type|mbm_type)) { 00514 AV_WN64A(bS, 0x0003000300030003ULL); 00515 if ( (!IS_INTERLACED(mb_type|mbm_type)) 00516 || ((FRAME_MBAFF || (s->picture_structure != PICT_FRAME)) && (dir == 0)) 00517 ) 00518 AV_WN64A(bS, 0x0004000400040004ULL); 00519 } else { 00520 int i; 00521 int mv_done; 00522 00523 if( dir && FRAME_MBAFF && IS_INTERLACED(mb_type ^ mbm_type)) { 00524 AV_WN64A(bS, 0x0001000100010001ULL); 00525 mv_done = 1; 00526 } 00527 else if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) { 00528 int b_idx= 8 + 4; 00529 int bn_idx= b_idx - (dir ? 8:1); 00530 00531 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, 8 + 4, bn_idx, mvy_limit); 00532 mv_done = 1; 00533 } 00534 else 00535 mv_done = 0; 00536 00537 for( i = 0; i < 4; i++ ) { 00538 int x = dir == 0 ? 0 : i; 00539 int y = dir == 0 ? i : 0; 00540 int b_idx= 8 + 4 + x + 8*y; 00541 int bn_idx= b_idx - (dir ? 8:1); 00542 00543 if( h->non_zero_count_cache[b_idx] | 00544 h->non_zero_count_cache[bn_idx] ) { 00545 bS[i] = 2; 00546 } 00547 else if(!mv_done) 00548 { 00549 bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); 00550 } 00551 } 00552 } 00553 00554 /* Filter edge */ 00555 // Do not use s->qscale as luma quantizer because it has not the same 00556 // value in IPCM macroblocks. 00557 if(bS[0]+bS[1]+bS[2]+bS[3]){ 00558 qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbm_xy] + 1 ) >> 1; 00559 //tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], s->current_picture.qscale_table[mbn_xy]); 00560 tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); 00561 //{ int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } 00562 if( dir == 0 ) { 00563 filter_mb_edgev( &img_y[0], linesize, bS, qp, h ); 00564 { 00565 int qp= ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbm_xy] ) + 1 ) >> 1; 00566 filter_mb_edgecv( &img_cb[0], uvlinesize, bS, qp, h); 00567 if(h->pps.chroma_qp_diff) 00568 qp= ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbm_xy] ) + 1 ) >> 1; 00569 filter_mb_edgecv( &img_cr[0], uvlinesize, bS, qp, h); 00570 } 00571 } else { 00572 filter_mb_edgeh( &img_y[0], linesize, bS, qp, h ); 00573 { 00574 int qp= ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbm_xy] ) + 1 ) >> 1; 00575 filter_mb_edgech( &img_cb[0], uvlinesize, bS, qp, h); 00576 if(h->pps.chroma_qp_diff) 00577 qp= ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbm_xy] ) + 1 ) >> 1; 00578 filter_mb_edgech( &img_cr[0], uvlinesize, bS, qp, h); 00579 } 00580 } 00581 } 00582 } 00583 } 00584 00585 /* Calculate bS */ 00586 for( edge = 1; edge < edges; edge++ ) { 00587 DECLARE_ALIGNED(8, int16_t, bS)[4]; 00588 int qp; 00589 00590 if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type) 00591 continue; 00592 00593 if( IS_INTRA(mb_type)) { 00594 AV_WN64A(bS, 0x0003000300030003ULL); 00595 } else { 00596 int i; 00597 int mv_done; 00598 00599 if( edge & mask_edge ) { 00600 AV_ZERO64(bS); 00601 mv_done = 1; 00602 } 00603 else if( mask_par0 ) { 00604 int b_idx= 8 + 4 + edge * (dir ? 8:1); 00605 int bn_idx= b_idx - (dir ? 8:1); 00606 00607 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, b_idx, bn_idx, mvy_limit); 00608 mv_done = 1; 00609 } 00610 else 00611 mv_done = 0; 00612 00613 for( i = 0; i < 4; i++ ) { 00614 int x = dir == 0 ? edge : i; 00615 int y = dir == 0 ? i : edge; 00616 int b_idx= 8 + 4 + x + 8*y; 00617 int bn_idx= b_idx - (dir ? 8:1); 00618 00619 if( h->non_zero_count_cache[b_idx] | 00620 h->non_zero_count_cache[bn_idx] ) { 00621 bS[i] = 2; 00622 } 00623 else if(!mv_done) 00624 { 00625 bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); 00626 } 00627 } 00628 00629 if(bS[0]+bS[1]+bS[2]+bS[3] == 0) 00630 continue; 00631 } 00632 00633 /* Filter edge */ 00634 // Do not use s->qscale as luma quantizer because it has not the same 00635 // value in IPCM macroblocks. 00636 qp = s->current_picture.qscale_table[mb_xy]; 00637 //tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], s->current_picture.qscale_table[mbn_xy]); 00638 tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); 00639 //{ int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } 00640 if( dir == 0 ) { 00641 filter_mb_edgev( &img_y[4*edge], linesize, bS, qp, h ); 00642 if( (edge&1) == 0 ) { 00643 filter_mb_edgecv( &img_cb[2*edge], uvlinesize, bS, h->chroma_qp[0], h); 00644 filter_mb_edgecv( &img_cr[2*edge], uvlinesize, bS, h->chroma_qp[1], h); 00645 } 00646 } else { 00647 filter_mb_edgeh( &img_y[4*edge*linesize], linesize, bS, qp, h ); 00648 if( (edge&1) == 0 ) { 00649 filter_mb_edgech( &img_cb[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], h); 00650 filter_mb_edgech( &img_cr[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], h); 00651 } 00652 } 00653 } 00654 } 00655 00656 void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { 00657 MpegEncContext * const s = &h->s; 00658 const int mb_xy= mb_x + mb_y*s->mb_stride; 00659 const int mb_type = s->current_picture.mb_type[mb_xy]; 00660 const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4; 00661 int first_vertical_edge_done = 0; 00662 av_unused int dir; 00663 00664 if (FRAME_MBAFF 00665 // and current and left pair do not have the same interlaced type 00666 && IS_INTERLACED(mb_type^h->left_type[0]) 00667 // and left mb is in available to us 00668 && h->left_type[0]) { 00669 /* First vertical edge is different in MBAFF frames 00670 * There are 8 different bS to compute and 2 different Qp 00671 */ 00672 DECLARE_ALIGNED(8, int16_t, bS)[8]; 00673 int qp[2]; 00674 int bqp[2]; 00675 int rqp[2]; 00676 int mb_qp, mbn0_qp, mbn1_qp; 00677 int i; 00678 first_vertical_edge_done = 1; 00679 00680 if( IS_INTRA(mb_type) ) { 00681 AV_WN64A(&bS[0], 0x0004000400040004ULL); 00682 AV_WN64A(&bS[4], 0x0004000400040004ULL); 00683 } else { 00684 static const uint8_t offset[2][2][8]={ 00685 { 00686 {7+8*0, 7+8*0, 7+8*0, 7+8*0, 7+8*1, 7+8*1, 7+8*1, 7+8*1}, 00687 {7+8*2, 7+8*2, 7+8*2, 7+8*2, 7+8*3, 7+8*3, 7+8*3, 7+8*3}, 00688 },{ 00689 {7+8*0, 7+8*1, 7+8*2, 7+8*3, 7+8*0, 7+8*1, 7+8*2, 7+8*3}, 00690 {7+8*0, 7+8*1, 7+8*2, 7+8*3, 7+8*0, 7+8*1, 7+8*2, 7+8*3}, 00691 } 00692 }; 00693 const uint8_t *off= offset[MB_FIELD][mb_y&1]; 00694 for( i = 0; i < 8; i++ ) { 00695 int j= MB_FIELD ? i>>2 : i&1; 00696 int mbn_xy = h->left_mb_xy[j]; 00697 int mbn_type= h->left_type[j]; 00698 00699 if( IS_INTRA( mbn_type ) ) 00700 bS[i] = 4; 00701 else{ 00702 bS[i] = 1 + !!(h->non_zero_count_cache[12+8*(i>>1)] | 00703 ((!h->pps.cabac && IS_8x8DCT(mbn_type)) ? 00704 (h->cbp_table[mbn_xy] & ((MB_FIELD ? (i&2) : (mb_y&1)) ? 8 : 2)) 00705 : 00706 h->non_zero_count[mbn_xy][ off[i] ])); 00707 } 00708 } 00709 } 00710 00711 mb_qp = s->current_picture.qscale_table[mb_xy]; 00712 mbn0_qp = s->current_picture.qscale_table[h->left_mb_xy[0]]; 00713 mbn1_qp = s->current_picture.qscale_table[h->left_mb_xy[1]]; 00714 qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1; 00715 bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) + 00716 get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1; 00717 rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) + 00718 get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1; 00719 qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1; 00720 bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) + 00721 get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1; 00722 rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) + 00723 get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1; 00724 00725 /* Filter edge */ 00726 tprintf(s->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize); 00727 { int i; for (i = 0; i < 8; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } 00728 if(MB_FIELD){ 00729 filter_mb_mbaff_edgev ( h, img_y , linesize, bS , 1, qp [0] ); 00730 filter_mb_mbaff_edgev ( h, img_y + 8* linesize, linesize, bS+4, 1, qp [1] ); 00731 filter_mb_mbaff_edgecv( h, img_cb, uvlinesize, bS , 1, bqp[0] ); 00732 filter_mb_mbaff_edgecv( h, img_cb + 4*uvlinesize, uvlinesize, bS+4, 1, bqp[1] ); 00733 filter_mb_mbaff_edgecv( h, img_cr, uvlinesize, bS , 1, rqp[0] ); 00734 filter_mb_mbaff_edgecv( h, img_cr + 4*uvlinesize, uvlinesize, bS+4, 1, rqp[1] ); 00735 }else{ 00736 filter_mb_mbaff_edgev ( h, img_y , 2* linesize, bS , 2, qp [0] ); 00737 filter_mb_mbaff_edgev ( h, img_y + linesize, 2* linesize, bS+1, 2, qp [1] ); 00738 filter_mb_mbaff_edgecv( h, img_cb, 2*uvlinesize, bS , 2, bqp[0] ); 00739 filter_mb_mbaff_edgecv( h, img_cb + uvlinesize, 2*uvlinesize, bS+1, 2, bqp[1] ); 00740 filter_mb_mbaff_edgecv( h, img_cr, 2*uvlinesize, bS , 2, rqp[0] ); 00741 filter_mb_mbaff_edgecv( h, img_cr + uvlinesize, 2*uvlinesize, bS+1, 2, rqp[1] ); 00742 } 00743 } 00744 00745 #if CONFIG_SMALL 00746 for( dir = 0; dir < 2; dir++ ) 00747 filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, dir ? 0 : first_vertical_edge_done, dir); 00748 #else 00749 filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, first_vertical_edge_done, 0); 00750 filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, 0, 1); 00751 #endif 00752 }