annotate libavcodec/h264_deblock.c @ 4:96e628866d41

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