Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > VSs > VSs__H264__App
comparison libavcodec/h264_deblock.c @ 2:897f711a7157
rearrange to work with autoconf
| author | Nina Engelhardt <nengel@mailbox.tu-berlin.de> |
|---|---|
| date | Tue, 25 Sep 2012 15:55:33 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:adbd31a9027f |
|---|---|
| 1 /* | |
| 2 * H.26L/H.264/AVC/JVT/14496-10/... loop filter | |
| 3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * @file | |
| 24 * H.264 / AVC / MPEG4 part10 loop filter. | |
| 25 * @author Michael Niedermayer <michaelni@gmx.at> | |
| 26 */ | |
| 27 | |
| 28 #include "dsputil.h" | |
| 29 #include "mathops.h" | |
| 30 #include "rectangle.h" | |
| 31 #include "h264_types.h" | |
| 32 #include "h264_misc.h" | |
| 33 #include "h264_data.h" | |
| 34 //#undef NDEBUG | |
| 35 #include <assert.h> | |
| 36 | |
| 37 /* Deblocking filter (p153) */ | |
| 38 static const uint8_t alpha_table[52*3] = { | |
| 39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 44 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, | |
| 45 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, | |
| 46 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, | |
| 47 80, 90,101,113,127,144,162,182,203,226, | |
| 48 255,255, | |
| 49 255,255,255,255,255,255,255,255,255,255,255,255,255, | |
| 50 255,255,255,255,255,255,255,255,255,255,255,255,255, | |
| 51 255,255,255,255,255,255,255,255,255,255,255,255,255, | |
| 52 255,255,255,255,255,255,255,255,255,255,255,255,255, | |
| 53 }; | |
| 54 static const uint8_t beta_table[52*3] = { | |
| 55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 60 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, | |
| 61 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, | |
| 62 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, | |
| 63 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, | |
| 64 18, 18, | |
| 65 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | |
| 66 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | |
| 67 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | |
| 68 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | |
| 69 }; | |
| 70 static const uint8_t tc0_table[52*3][4] = { | |
| 71 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 72 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 73 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 74 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 75 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 76 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 77 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 78 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 79 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 80 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 81 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, | |
| 82 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 }, | |
| 83 {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 }, | |
| 84 {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, | |
| 85 {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 }, | |
| 86 {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 }, | |
| 87 {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 }, | |
| 88 {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 }, | |
| 89 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 90 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 91 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 92 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 93 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 94 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 95 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 96 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 97 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, | |
| 98 }; | |
| 99 | |
| 100 av_always_inline static void filter_mb_edgev( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s) { | |
| 101 const unsigned int index_a = qp + s->slice_alpha_c0_offset; | |
| 102 const int alpha = alpha_table[index_a]; | |
| 103 const int beta = beta_table[qp + s->slice_beta_offset]; | |
| 104 if (alpha ==0 || beta == 0) return; | |
| 105 | |
| 106 if( bS[0] < 4 ) { | |
| 107 int8_t tc[4]; | |
| 108 tc[0] = tc0_table[index_a][bS[0]]; | |
| 109 tc[1] = tc0_table[index_a][bS[1]]; | |
| 110 tc[2] = tc0_table[index_a][bS[2]]; | |
| 111 tc[3] = tc0_table[index_a][bS[3]]; | |
| 112 mrc->hdsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc); | |
| 113 } else { | |
| 114 mrc->hdsp.h264_h_loop_filter_luma_intra(pix, stride, alpha, beta); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 av_always_inline static void filter_mb_edgecv( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) { | |
| 119 const unsigned int index_a = qp + s->slice_alpha_c0_offset; | |
| 120 const int alpha = alpha_table[index_a]; | |
| 121 const int beta = beta_table[qp + s->slice_beta_offset]; | |
| 122 if (alpha ==0 || beta == 0) return; | |
| 123 | |
| 124 if( bS[0] < 4 ) { | |
| 125 int8_t tc[4]; | |
| 126 tc[0] = tc0_table[index_a][bS[0]]+1; | |
| 127 tc[1] = tc0_table[index_a][bS[1]]+1; | |
| 128 tc[2] = tc0_table[index_a][bS[2]]+1; | |
| 129 tc[3] = tc0_table[index_a][bS[3]]+1; | |
| 130 mrc->hdsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc); | |
| 131 } else { | |
| 132 mrc->hdsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 | |
| 137 av_always_inline static void filter_mb_edgeh( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) { | |
| 138 const unsigned int index_a = qp + s->slice_alpha_c0_offset; | |
| 139 const int alpha = alpha_table[index_a]; | |
| 140 const int beta = beta_table[qp + s->slice_beta_offset]; | |
| 141 if (alpha ==0 || beta == 0) return; | |
| 142 | |
| 143 if( bS[0] < 4 ) { | |
| 144 int8_t tc[4]; | |
| 145 tc[0] = tc0_table[index_a][bS[0]]; | |
| 146 tc[1] = tc0_table[index_a][bS[1]]; | |
| 147 tc[2] = tc0_table[index_a][bS[2]]; | |
| 148 tc[3] = tc0_table[index_a][bS[3]]; | |
| 149 mrc->hdsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc); | |
| 150 } else { | |
| 151 mrc->hdsp.h264_v_loop_filter_luma_intra(pix, stride, alpha, beta); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 av_always_inline static void filter_mb_edgech( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) { | |
| 156 const unsigned int index_a = qp + s->slice_alpha_c0_offset; | |
| 157 const int alpha = alpha_table[index_a]; | |
| 158 const int beta = beta_table[qp + s->slice_beta_offset]; | |
| 159 if (alpha ==0 || beta == 0) return; | |
| 160 | |
| 161 if( bS[0] < 4 ) { | |
| 162 int8_t tc[4]; | |
| 163 tc[0] = tc0_table[index_a][bS[0]]+1; | |
| 164 tc[1] = tc0_table[index_a][bS[1]]+1; | |
| 165 tc[2] = tc0_table[index_a][bS[2]]+1; | |
| 166 tc[3] = tc0_table[index_a][bS[3]]+1; | |
| 167 mrc->hdsp.h264_v_loop_filter_chroma(pix, stride, alpha, beta, tc); | |
| 168 } else { | |
| 169 mrc->hdsp.h264_v_loop_filter_chroma_intra(pix, stride, alpha, beta); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 static av_always_inline void filter_mb_dir(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, int dir) { | |
| 174 const int mbm_type = dir == 0 ? mrs->left_type : mrs->top_type; | |
| 175 const int qp_xy= m->qscale_mb_xy; | |
| 176 const int qp_dir = dir == 0 ? m->qscale_left_mb_xy : m->qscale_top_mb_xy; | |
| 177 const int linesize = mrc->linesize; | |
| 178 const int uvlinesize = mrc->uvlinesize; | |
| 179 const int mb_type = m->mb_type; | |
| 180 int edge; | |
| 181 const int edges = mrs->edges[dir]; | |
| 182 | |
| 183 if(mbm_type){ | |
| 184 int16_t* bS=mrs->bS[dir][0]; | |
| 185 /* Filter edge */ | |
| 186 // Do not use s->qscale as luma quantizer because it has not the same | |
| 187 // value in IPCM macroblocks. | |
| 188 if(bS[0]+bS[1]+bS[2]+bS[3]){ | |
| 189 int qp = ( qp_xy + qp_dir + 1 ) >> 1; | |
| 190 if( dir == 0 ) { | |
| 191 filter_mb_edgev( &img_y[0], linesize, bS, qp, mrc, s ); | |
| 192 { | |
| 193 int qp= ( get_chroma_qp(s, 0, qp_xy) + get_chroma_qp( s, 0, qp_dir) + 1 ) >> 1; | |
| 194 filter_mb_edgecv( &img_cb[0], uvlinesize, bS, qp, mrc, s); | |
| 195 filter_mb_edgecv( &img_cr[0], uvlinesize, bS, qp, mrc, s); | |
| 196 } | |
| 197 } else { | |
| 198 filter_mb_edgeh( &img_y[0], linesize, bS, qp, mrc, s ); | |
| 199 { | |
| 200 int qp= ( get_chroma_qp(s, 0, qp_xy) + get_chroma_qp( s, 0, qp_dir) + 1 ) >> 1; | |
| 201 filter_mb_edgech( &img_cb[0], uvlinesize, bS, qp, mrc, s); | |
| 202 filter_mb_edgech( &img_cr[0], uvlinesize, bS, qp, mrc, s); | |
| 203 } | |
| 204 } | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 for( edge = 1; edge < edges; edge++ ) { | |
| 209 int16_t* bS=mrs->bS[dir][edge]; | |
| 210 int qp = qp_xy; | |
| 211 | |
| 212 if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type) | |
| 213 continue; | |
| 214 | |
| 215 if(bS[0]+bS[1]+bS[2]+bS[3] == 0) | |
| 216 continue; | |
| 217 | |
| 218 /* Filter edge */ | |
| 219 // Do not use s->qscale as luma quantizer because it has not the same | |
| 220 // value in IPCM macroblocks. | |
| 221 | |
| 222 if( dir == 0 ) { | |
| 223 filter_mb_edgev( &img_y[4*edge], linesize, bS, qp, mrc, s); | |
| 224 if( (edge&1) == 0 ) { | |
| 225 filter_mb_edgecv( &img_cb[2*edge], uvlinesize, bS, get_chroma_qp(s, 0, qp_xy), mrc, s); | |
| 226 filter_mb_edgecv( &img_cr[2*edge], uvlinesize, bS, get_chroma_qp(s, 1, qp_xy), mrc, s); | |
| 227 } | |
| 228 } else { | |
| 229 filter_mb_edgeh( &img_y[4*edge*linesize], linesize, bS, qp, mrc, s ); | |
| 230 if( (edge&1) == 0 ) { | |
| 231 filter_mb_edgech( &img_cb[2*edge*uvlinesize], uvlinesize, bS, get_chroma_qp(s, 0, qp_xy), mrc, s); | |
| 232 filter_mb_edgech( &img_cr[2*edge*uvlinesize], uvlinesize, bS, get_chroma_qp(s, 1, qp_xy), mrc, s); | |
| 233 } | |
| 234 } | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 static int check_mv(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, long b_idx, long bn_idx, int mvy_limit){ | |
| 239 int v; | |
| 240 v= mrs->ref_cache[0][b_idx] != mrs->ref_cache[0][bn_idx]; | |
| 241 if(!v && mrs->ref_cache[0][b_idx]!=-1) | |
| 242 // absolute value >= 7 | ... | |
| 243 v= ((unsigned) (mrs->mv_cache[0][b_idx][0] - mrs->mv_cache[0][bn_idx][0] + 3) >= 7U) | | |
| 244 ((FFABS( mrs->mv_cache[0][b_idx][1] - mrs->mv_cache[0][bn_idx][1] )) >= mvy_limit); | |
| 245 | |
| 246 if(s->list_count==2){ | |
| 247 if(!v) | |
| 248 v = (mrs->ref_cache[1][b_idx] != mrs->ref_cache[1][bn_idx]) | | |
| 249 ((unsigned) (mrs->mv_cache[1][b_idx][0] - mrs->mv_cache[1][bn_idx][0] + 3) >= 7U) | | |
| 250 ((FFABS( mrs->mv_cache[1][b_idx][1] - mrs->mv_cache[1][bn_idx][1] )) >= mvy_limit); | |
| 251 | |
| 252 if(v){ | |
| 253 if((mrs->ref_cache[0][b_idx] != mrs->ref_cache[1][bn_idx]) | | |
| 254 (mrs->ref_cache[1][b_idx] != mrs->ref_cache[0][bn_idx])) | |
| 255 return 1; | |
| 256 return | |
| 257 ((unsigned) (mrs->mv_cache[0][b_idx][0] - mrs->mv_cache[1][bn_idx][0] + 3) >= 7U) | | |
| 258 ((FFABS( mrs->mv_cache[0][b_idx][1] - mrs->mv_cache[1][bn_idx][1] )) >= mvy_limit) | | |
| 259 ((unsigned) (mrs->mv_cache[1][b_idx][0] - mrs->mv_cache[0][bn_idx][0] + 3) >= 7U) | | |
| 260 ((FFABS( mrs->mv_cache[1][b_idx][1] - mrs->mv_cache[0][bn_idx][1] )) >= mvy_limit); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 return v; | |
| 265 } | |
| 266 | |
| 267 static void calc_bS_values(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mvy_limit, int dir) { | |
| 268 int mb_type = m->mb_type; | |
| 269 int edge; | |
| 270 const int mbm_type = dir == 0 ? mrs->left_type : mrs->top_type; | |
| 271 | |
| 272 // how often to recheck mv-based bS when iterating between edges | |
| 273 static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1}, | |
| 274 {0,3,1,1,3,3,3,3}}; | |
| 275 const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7]; | |
| 276 const int edges = mask_edge== 3 && !(m->cbp&15) ? 1 : 4; | |
| 277 // how often to recheck mv-based bS when iterating along each edge | |
| 278 const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)); | |
| 279 | |
| 280 mrs->edges[dir]= edges; | |
| 281 | |
| 282 if(mbm_type){ | |
| 283 int16_t* bS=mrs->bS[dir][0]; | |
| 284 if( IS_INTRA(mb_type|mbm_type)) { | |
| 285 AV_WN64A(bS, 0x0004000400040004ULL); | |
| 286 } else { | |
| 287 int i; | |
| 288 int mv_done; | |
| 289 if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) { | |
| 290 int b_idx= 8 + 4; | |
| 291 int bn_idx= b_idx - (dir ? 8:1); | |
| 292 | |
| 293 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(mrc, mrs, s, 8 + 4, bn_idx, mvy_limit); | |
| 294 mv_done = 1; | |
| 295 } | |
| 296 else | |
| 297 mv_done = 0; | |
| 298 | |
| 299 for( i = 0; i < 4; i++ ) { | |
| 300 int x = dir == 0 ? 0 : i; | |
| 301 int y = dir == 0 ? i : 0; | |
| 302 int b_idx= 8 + 4 + x + 8*y; | |
| 303 int bn_idx= b_idx - (dir ? 8:1); | |
| 304 | |
| 305 if( mrs->non_zero_count_cache[b_idx] | | |
| 306 mrs->non_zero_count_cache[bn_idx] ) { | |
| 307 bS[i] = 2; | |
| 308 } | |
| 309 else if(!mv_done) | |
| 310 { | |
| 311 bS[i] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit); | |
| 312 } | |
| 313 } | |
| 314 } | |
| 315 } | |
| 316 | |
| 317 /* Calculate bS */ | |
| 318 for( edge = 1; edge < edges; edge++ ) { | |
| 319 int16_t* bS=mrs->bS[dir][edge]; | |
| 320 | |
| 321 if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type) | |
| 322 continue; | |
| 323 | |
| 324 if( IS_INTRA(mb_type)) { | |
| 325 AV_WN64A(bS, 0x0003000300030003ULL); | |
| 326 } else { | |
| 327 int i; | |
| 328 int mv_done; | |
| 329 | |
| 330 if( edge & mask_edge ) { | |
| 331 AV_ZERO64(bS); | |
| 332 mv_done = 1; | |
| 333 } | |
| 334 else if( mask_par0 ) { | |
| 335 int b_idx= 8 + 4 + edge * (dir ? 8:1); | |
| 336 int bn_idx= b_idx - (dir ? 8:1); | |
| 337 | |
| 338 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit); | |
| 339 mv_done = 1; | |
| 340 } | |
| 341 else | |
| 342 mv_done = 0; | |
| 343 | |
| 344 for( i = 0; i < 4; i++ ) { | |
| 345 int x = dir == 0 ? edge : i; | |
| 346 int y = dir == 0 ? i : edge; | |
| 347 int b_idx= 8 + 4 + x + 8*y; | |
| 348 int bn_idx= b_idx - (dir ? 8:1); | |
| 349 | |
| 350 if( mrs->non_zero_count_cache[b_idx] | | |
| 351 mrs->non_zero_count_cache[bn_idx] ) { | |
| 352 bS[i] = 2; | |
| 353 } | |
| 354 else if(!mv_done) | |
| 355 { | |
| 356 bS[i] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 if(bS[0]+bS[1]+bS[2]+bS[3] == 0) | |
| 361 continue; | |
| 362 } | |
| 363 | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 | |
| 368 /** | |
| 369 * | |
| 370 * @return zero if the loop filter can be skiped | |
| 371 */ | |
| 372 static int fill_filter_caches(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){ | |
| 373 H264Mb *m_top = m - mrc->mb_width; | |
| 374 H264Mb *m_left = m - 1; | |
| 375 const int mb_x = m->mb_x; | |
| 376 const int mb_y = m->mb_y; | |
| 377 int top_type, left_type; | |
| 378 int qp, top_qp, left_qp; | |
| 379 int qp_thresh = s->qp_thresh; //FIXME strictly we should store qp_thresh for each mb of a slice | |
| 380 | |
| 381 qp = m->qscale_mb_xy ; | |
| 382 left_qp = m->qscale_left_mb_xy ; | |
| 383 top_qp = m->qscale_top_mb_xy ; | |
| 384 | |
| 385 //for sufficiently low qp, filtering wouldn't do anything | |
| 386 //this is a conservative estimate: could also check beta_offset and more accurate chroma_qp | |
| 387 if(qp <= qp_thresh | |
| 388 && (!(mb_x+mb_y) || ((qp + left_qp + 1)>>1) <= qp_thresh) | |
| 389 && ( mb_y==0 || ((qp + top_qp + 1)>>1) <= qp_thresh)){ | |
| 390 return 0; | |
| 391 } | |
| 392 | |
| 393 if(IS_INTRA(mb_type)){ | |
| 394 return 1; | |
| 395 } | |
| 396 | |
| 397 { | |
| 398 int list; | |
| 399 for(list=0; list<s->list_count; list++){ | |
| 400 int8_t *ref; | |
| 401 | |
| 402 if(!USES_LIST(mb_type, list)){ | |
| 403 fill_rectangle( mrs->mv_cache[list][scan8[0]], 4, 4, 8, pack16to32(0,0), 4); | |
| 404 fill_rectangle( mrs->mv_cache[list][scan8[0]], 4, 4, 8, pack16to32(0,0), 4); | |
| 405 AV_WN32A(&mrs->ref_cache[list][scan8[ 0]], ((LIST_NOT_USED)&0xFF)*0x01010101u); | |
| 406 AV_WN32A(&mrs->ref_cache[list][scan8[ 2]], ((LIST_NOT_USED)&0xFF)*0x01010101u); | |
| 407 AV_WN32A(&mrs->ref_cache[list][scan8[ 8]], ((LIST_NOT_USED)&0xFF)*0x01010101u); | |
| 408 AV_WN32A(&mrs->ref_cache[list][scan8[10]], ((LIST_NOT_USED)&0xFF)*0x01010101u); | |
| 409 continue; | |
| 410 } | |
| 411 | |
| 412 ref = &mrs->ref_index[list][4*mb_x]; | |
| 413 { | |
| 414 int (*ref2frm)[64] =(void *) (s->ref2frm[0] + 2); | |
| 415 AV_WN32A(&mrs->ref_cache[list][scan8[ 0]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101); | |
| 416 AV_WN32A(&mrs->ref_cache[list][scan8[ 2]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101); | |
| 417 ref += 2; | |
| 418 | |
| 419 AV_WN32A(&mrs->ref_cache[list][scan8[ 8]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101); | |
| 420 AV_WN32A(&mrs->ref_cache[list][scan8[10]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101); | |
| 421 } | |
| 422 } | |
| 423 } | |
| 424 | |
| 425 /* | |
| 426 0 . T T. T T T T | |
| 427 1 L . .L . . . . | |
| 428 2 L . .L . . . . | |
| 429 3 . T TL . . . . | |
| 430 4 L . .L . . . . | |
| 431 5 L . .. . . . . | |
| 432 */ | |
| 433 | |
| 434 if (IS_SKIP(mb_type)){ | |
| 435 memset(mrs->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui | |
| 436 } | |
| 437 | |
| 438 //FIXME constraint_intra_pred & partitioning & nnz (let us hope this is just a typo in the spec) | |
| 439 top_type = mrs->top_type; | |
| 440 left_type = mrs->left_type; | |
| 441 if(top_type){ | |
| 442 AV_COPY32(&mrs->non_zero_count_cache[4+8*0], &m_top->non_zero_count[3*4]); | |
| 443 } | |
| 444 | |
| 445 if(left_type){ | |
| 446 mrs->non_zero_count_cache[3+8*1]= m_left->non_zero_count[3+0*4]; | |
| 447 mrs->non_zero_count_cache[3+8*2]= m_left->non_zero_count[3+1*4]; | |
| 448 mrs->non_zero_count_cache[3+8*3]= m_left->non_zero_count[3+2*4]; | |
| 449 mrs->non_zero_count_cache[3+8*4]= m_left->non_zero_count[3+3*4]; | |
| 450 } | |
| 451 | |
| 452 if(IS_INTER(mb_type) || IS_DIRECT(mb_type)){ | |
| 453 int list; | |
| 454 for(list=0; list<s->list_count; list++){ | |
| 455 if(USES_LIST(top_type, list)){ | |
| 456 const int b_xy= 4*mb_x + 3*mrc->b_stride; | |
| 457 const int b8_x= 4*mb_x + 2; | |
| 458 int (*ref2frm)[64] = (void *) (s->ref2frm[0] + 2); | |
| 459 AV_COPY128(mrs->mv_cache[list][scan8[0] + 0 - 1*8], mrs->motion_val_top[list][b_xy + 0]); | |
| 460 | |
| 461 mrs->ref_cache[list][scan8[0] + 0 - 1*8]= | |
| 462 mrs->ref_cache[list][scan8[0] + 1 - 1*8]= ref2frm[list][mrs->ref_index_top[list][b8_x + 0]]; | |
| 463 mrs->ref_cache[list][scan8[0] + 2 - 1*8]= | |
| 464 mrs->ref_cache[list][scan8[0] + 3 - 1*8]= ref2frm[list][mrs->ref_index_top[list][b8_x + 1]]; | |
| 465 }else{ | |
| 466 AV_ZERO128(mrs->mv_cache[list][scan8[0] + 0 - 1*8]); | |
| 467 AV_WN32A(&mrs->ref_cache[list][scan8[0] + 0 - 1*8], ((LIST_NOT_USED)&0xFF)*0x01010101u); | |
| 468 } | |
| 469 | |
| 470 if(USES_LIST(left_type, list)){ | |
| 471 const int b_x = 4*(mb_x-1) + 3; | |
| 472 const int b8_x= 4*(mb_x-1) + 1; | |
| 473 int (*ref2frm)[64] = (void *) (s->ref2frm[0] + 2); | |
| 474 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 + 0 ], mrs->motion_val[list][b_x + mrc->b_stride*0]); | |
| 475 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 + 8 ], mrs->motion_val[list][b_x + mrc->b_stride*1]); | |
| 476 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 +16 ], mrs->motion_val[list][b_x + mrc->b_stride*2]); | |
| 477 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 +24 ], mrs->motion_val[list][b_x + mrc->b_stride*3]); | |
| 478 | |
| 479 mrs->ref_cache[list][scan8[0] - 1 + 0 ]= | |
| 480 mrs->ref_cache[list][scan8[0] - 1 + 8 ]= ref2frm[list][mrs->ref_index[list][b8_x + 2*0]]; | |
| 481 mrs->ref_cache[list][scan8[0] - 1 +16 ]= | |
| 482 mrs->ref_cache[list][scan8[0] - 1 +24 ]= ref2frm[list][mrs->ref_index[list][b8_x + 2*1]]; | |
| 483 | |
| 484 }else{ | |
| 485 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 + 0 ]); | |
| 486 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 + 8 ]); | |
| 487 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 +16 ]); | |
| 488 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 +24 ]); | |
| 489 | |
| 490 mrs->ref_cache[list][scan8[0] - 1 + 0 ]= | |
| 491 mrs->ref_cache[list][scan8[0] - 1 + 8 ]= | |
| 492 mrs->ref_cache[list][scan8[0] - 1 + 16 ]= | |
| 493 mrs->ref_cache[list][scan8[0] - 1 + 24 ]= LIST_NOT_USED; | |
| 494 } | |
| 495 } | |
| 496 } | |
| 497 return 1; | |
| 498 } | |
| 499 | |
| 500 void ff_h264_filter_mb(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr) { | |
| 501 if (fill_filter_caches(mrc, mrs, s, m, m->mb_type)){ | |
| 502 calc_bS_values(mrc, mrs, s, m, 4, 0); | |
| 503 calc_bS_values(mrc, mrs, s, m, 4, 1); | |
| 504 filter_mb_dir(mrc, mrs, s, m, img_y, img_cb, img_cr, 0); | |
| 505 filter_mb_dir(mrc, mrs, s, m, img_y, img_cb, img_cr, 1); | |
| 506 } | |
| 507 } |
