1/* 2 * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder 3 * Copyright (c) 2003-2010 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 DSP functions. 25 * @author Michael Niedermayer <michaelni@gmx.at> 26 */ 27 28#include <stdint.h> 29#include "avcodec.h" 30#include "h264dsp.h" 31 32#define op_scale1(x) block[x] = av_clip_uint8( (block[x]*weight + offset) >> log2_denom ) 33#define op_scale2(x) dst[x] = av_clip_uint8( (src[x]*weights + dst[x]*weightd + offset) >> (log2_denom+1)) 34#define H264_WEIGHT(W,H) \ 35static void weight_h264_pixels ## W ## x ## H ## _c(uint8_t *block, int stride, int log2_denom, int weight, int offset){ \ 36 int y; \ 37 offset <<= log2_denom; \ 38 if(log2_denom) offset += 1<<(log2_denom-1); \ 39 for(y=0; y<H; y++, block += stride){ \ 40 op_scale1(0); \ 41 op_scale1(1); \ 42 if(W==2) continue; \ 43 op_scale1(2); \ 44 op_scale1(3); \ 45 if(W==4) continue; \ 46 op_scale1(4); \ 47 op_scale1(5); \ 48 op_scale1(6); \ 49 op_scale1(7); \ 50 if(W==8) continue; \ 51 op_scale1(8); \ 52 op_scale1(9); \ 53 op_scale1(10); \ 54 op_scale1(11); \ 55 op_scale1(12); \ 56 op_scale1(13); \ 57 op_scale1(14); \ 58 op_scale1(15); \ 59 } \ 60} \ 61static void biweight_h264_pixels ## W ## x ## H ## _c(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset){ \ 62 int y; \ 63 offset = ((offset + 1) | 1) << log2_denom; \ 64 for(y=0; y<H; y++, dst += stride, src += stride){ \ 65 op_scale2(0); \ 66 op_scale2(1); \ 67 if(W==2) continue; \ 68 op_scale2(2); \ 69 op_scale2(3); \ 70 if(W==4) continue; \ 71 op_scale2(4); \ 72 op_scale2(5); \ 73 op_scale2(6); \ 74 op_scale2(7); \ 75 if(W==8) continue; \ 76 op_scale2(8); \ 77 op_scale2(9); \ 78 op_scale2(10); \ 79 op_scale2(11); \ 80 op_scale2(12); \ 81 op_scale2(13); \ 82 op_scale2(14); \ 83 op_scale2(15); \ 84 } \ 85} 86 87H264_WEIGHT(16,16) 88H264_WEIGHT(16,8) 89H264_WEIGHT(8,16) 90H264_WEIGHT(8,8) 91H264_WEIGHT(8,4) 92H264_WEIGHT(4,8) 93H264_WEIGHT(4,4) 94H264_WEIGHT(4,2) 95H264_WEIGHT(2,4) 96H264_WEIGHT(2,2) 97 98#undef op_scale1 99#undef op_scale2 100#undef H264_WEIGHT 101 102static av_always_inline av_flatten void h264_loop_filter_luma_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0) 103{ 104 int i, d; 105 for( i = 0; i < 4; i++ ) { 106 if( tc0[i] < 0 ) { 107 pix += 4*ystride; 108 continue; 109 } 110 for( d = 0; d < 4; d++ ) { 111 const int p0 = pix[-1*xstride]; 112 const int p1 = pix[-2*xstride]; 113 const int p2 = pix[-3*xstride]; 114 const int q0 = pix[0]; 115 const int q1 = pix[1*xstride]; 116 const int q2 = pix[2*xstride]; 117 118 if( FFABS( p0 - q0 ) < alpha && 119 FFABS( p1 - p0 ) < beta && 120 FFABS( q1 - q0 ) < beta ) { 121 122 int tc = tc0[i]; 123 int i_delta; 124 125 if( FFABS( p2 - p0 ) < beta ) { 126 if(tc0[i]) 127 pix[-2*xstride] = p1 + av_clip( (( p2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - p1, -tc0[i], tc0[i] ); 128 tc++; 129 } 130 if( FFABS( q2 - q0 ) < beta ) { 131 if(tc0[i]) 132 pix[ xstride] = q1 + av_clip( (( q2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - q1, -tc0[i], tc0[i] ); 133 tc++; 134 } 135 136 i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); 137 pix[-xstride] = av_clip_uint8( p0 + i_delta ); /* p0' */ 138 pix[0] = av_clip_uint8( q0 - i_delta ); /* q0' */ 139 } 140 pix += ystride; 141 } 142 } 143} 144static void h264_v_loop_filter_luma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) 145{ 146 h264_loop_filter_luma_c(pix, stride, 1, alpha, beta, tc0); 147} 148static void h264_h_loop_filter_luma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) 149{ 150 h264_loop_filter_luma_c(pix, 1, stride, alpha, beta, tc0); 151} 152 153static av_always_inline av_flatten void h264_loop_filter_luma_intra_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta) 154{ 155 int d; 156 for( d = 0; d < 16; d++ ) { 157 const int p2 = pix[-3*xstride]; 158 const int p1 = pix[-2*xstride]; 159 const int p0 = pix[-1*xstride]; 160 161 const int q0 = pix[ 0*xstride]; 162 const int q1 = pix[ 1*xstride]; 163 const int q2 = pix[ 2*xstride]; 164 165 if( FFABS( p0 - q0 ) < alpha && 166 FFABS( p1 - p0 ) < beta && 167 FFABS( q1 - q0 ) < beta ) { 168 169 if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){ 170 if( FFABS( p2 - p0 ) < beta) 171 { 172 const int p3 = pix[-4*xstride]; 173 /* p0', p1', p2' */ 174 pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3; 175 pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2; 176 pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3; 177 } else { 178 /* p0' */ 179 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; 180 } 181 if( FFABS( q2 - q0 ) < beta) 182 { 183 const int q3 = pix[3*xstride]; 184 /* q0', q1', q2' */ 185 pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3; 186 pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2; 187 pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3; 188 } else { 189 /* q0' */ 190 pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; 191 } 192 }else{ 193 /* p0', q0' */ 194 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; 195 pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; 196 } 197 } 198 pix += ystride; 199 } 200} 201static void h264_v_loop_filter_luma_intra_c(uint8_t *pix, int stride, int alpha, int beta) 202{ 203 h264_loop_filter_luma_intra_c(pix, stride, 1, alpha, beta); 204} 205static void h264_h_loop_filter_luma_intra_c(uint8_t *pix, int stride, int alpha, int beta) 206{ 207 h264_loop_filter_luma_intra_c(pix, 1, stride, alpha, beta); 208} 209 210static av_always_inline av_flatten void h264_loop_filter_chroma_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0) 211{ 212 int i, d; 213 for( i = 0; i < 4; i++ ) { 214 const int tc = tc0[i]; 215 if( tc <= 0 ) { 216 pix += 2*ystride; 217 continue; 218 } 219 for( d = 0; d < 2; d++ ) { 220 const int p0 = pix[-1*xstride]; 221 const int p1 = pix[-2*xstride]; 222 const int q0 = pix[0]; 223 const int q1 = pix[1*xstride]; 224 225 if( FFABS( p0 - q0 ) < alpha && 226 FFABS( p1 - p0 ) < beta && 227 FFABS( q1 - q0 ) < beta ) { 228 229 int delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); 230 231 pix[-xstride] = av_clip_uint8( p0 + delta ); /* p0' */ 232 pix[0] = av_clip_uint8( q0 - delta ); /* q0' */ 233 } 234 pix += ystride; 235 } 236 } 237} 238static void h264_v_loop_filter_chroma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) 239{ 240 h264_loop_filter_chroma_c(pix, stride, 1, alpha, beta, tc0); 241} 242static void h264_h_loop_filter_chroma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) 243{ 244 h264_loop_filter_chroma_c(pix, 1, stride, alpha, beta, tc0); 245} 246 247static av_always_inline av_flatten void h264_loop_filter_chroma_intra_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta) 248{ 249 int d; 250 for( d = 0; d < 8; d++ ) { 251 const int p0 = pix[-1*xstride]; 252 const int p1 = pix[-2*xstride]; 253 const int q0 = pix[0]; 254 const int q1 = pix[1*xstride]; 255 256 if( FFABS( p0 - q0 ) < alpha && 257 FFABS( p1 - p0 ) < beta && 258 FFABS( q1 - q0 ) < beta ) { 259 260 pix[-xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ 261 pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ 262 } 263 pix += ystride; 264 } 265} 266static void h264_v_loop_filter_chroma_intra_c(uint8_t *pix, int stride, int alpha, int beta) 267{ 268 h264_loop_filter_chroma_intra_c(pix, stride, 1, alpha, beta); 269} 270static void h264_h_loop_filter_chroma_intra_c(uint8_t *pix, int stride, int alpha, int beta) 271{ 272 h264_loop_filter_chroma_intra_c(pix, 1, stride, alpha, beta); 273} 274 275void ff_h264dsp_init(H264DSPContext *c) 276{ 277 c->h264_idct_add= ff_h264_idct_add_c; 278 c->h264_idct8_add= ff_h264_idct8_add_c; 279 c->h264_idct_dc_add= ff_h264_idct_dc_add_c; 280 c->h264_idct8_dc_add= ff_h264_idct8_dc_add_c; 281 c->h264_idct_add16 = ff_h264_idct_add16_c; 282 c->h264_idct8_add4 = ff_h264_idct8_add4_c; 283 c->h264_idct_add8 = ff_h264_idct_add8_c; 284 c->h264_idct_add16intra= ff_h264_idct_add16intra_c; 285 286 c->weight_h264_pixels_tab[0]= weight_h264_pixels16x16_c; 287 c->weight_h264_pixels_tab[1]= weight_h264_pixels16x8_c; 288 c->weight_h264_pixels_tab[2]= weight_h264_pixels8x16_c; 289 c->weight_h264_pixels_tab[3]= weight_h264_pixels8x8_c; 290 c->weight_h264_pixels_tab[4]= weight_h264_pixels8x4_c; 291 c->weight_h264_pixels_tab[5]= weight_h264_pixels4x8_c; 292 c->weight_h264_pixels_tab[6]= weight_h264_pixels4x4_c; 293 c->weight_h264_pixels_tab[7]= weight_h264_pixels4x2_c; 294 c->weight_h264_pixels_tab[8]= weight_h264_pixels2x4_c; 295 c->weight_h264_pixels_tab[9]= weight_h264_pixels2x2_c; 296 c->biweight_h264_pixels_tab[0]= biweight_h264_pixels16x16_c; 297 c->biweight_h264_pixels_tab[1]= biweight_h264_pixels16x8_c; 298 c->biweight_h264_pixels_tab[2]= biweight_h264_pixels8x16_c; 299 c->biweight_h264_pixels_tab[3]= biweight_h264_pixels8x8_c; 300 c->biweight_h264_pixels_tab[4]= biweight_h264_pixels8x4_c; 301 c->biweight_h264_pixels_tab[5]= biweight_h264_pixels4x8_c; 302 c->biweight_h264_pixels_tab[6]= biweight_h264_pixels4x4_c; 303 c->biweight_h264_pixels_tab[7]= biweight_h264_pixels4x2_c; 304 c->biweight_h264_pixels_tab[8]= biweight_h264_pixels2x4_c; 305 c->biweight_h264_pixels_tab[9]= biweight_h264_pixels2x2_c; 306 307 c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_c; 308 c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_c; 309 c->h264_v_loop_filter_luma_intra= h264_v_loop_filter_luma_intra_c; 310 c->h264_h_loop_filter_luma_intra= h264_h_loop_filter_luma_intra_c; 311 c->h264_v_loop_filter_chroma= h264_v_loop_filter_chroma_c; 312 c->h264_h_loop_filter_chroma= h264_h_loop_filter_chroma_c; 313 c->h264_v_loop_filter_chroma_intra= h264_v_loop_filter_chroma_intra_c; 314 c->h264_h_loop_filter_chroma_intra= h264_h_loop_filter_chroma_intra_c; 315 c->h264_loop_filter_strength= NULL; 316 317 if (ARCH_ARM) ff_h264dsp_init_arm(c); 318 if (HAVE_ALTIVEC) ff_h264dsp_init_ppc(c); 319 if (HAVE_MMX) ff_h264dsp_init_x86(c); 320} 321