00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00038 #include <assert.h>
00039
00040
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 );
00178 pix[0] = av_clip_uint8( q0 - i_delta );
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
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
00204 pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
00205 }
00206 if( FFABS( q2 - q0 ) < beta)
00207 {
00208 const int q3 = pix[3];
00209
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
00215 pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
00216 }
00217 }else{
00218
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 );
00252 pix[0] = av_clip_uint8( q0 - i_delta );
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;
00266 pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
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);
00381 int mask_edge0 = 3*((mask_edge1>>1) & ((5*left_type)>>5)&1);
00382 int step = 1+(mb_type>>24);
00383 edges = 4 - 3*((mb_type>>3) & !(h->cbp & 15));
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
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
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
00471
00472
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
00499
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
00555
00556
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
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
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
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)) )
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
00634
00635
00636 qp = s->current_picture.qscale_table[mb_xy];
00637
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
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
00666 && IS_INTERLACED(mb_type^h->left_type[0])
00667
00668 && h->left_type[0]) {
00669
00670
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
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 }