Modifies CLI help message for audio track selection, to make it clearer how to specif...
[HandBrake.git] / libhb / deblock.c
blob2d8b166585a268992c3bc8465450ff484fe57167
1 /*
2 Copyright (C) 2005 Michael Niedermayer <michaelni@gmx.at>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "hb.h"
20 #include "ffmpeg/avcodec.h"
21 #include "mpeg2dec/mpeg2.h"
23 #define PP7_QP_DEFAULT 0
24 #define PP7_MODE_DEFAULT 2
26 #define XMIN(a,b) ((a) < (b) ? (a) : (b))
27 #define XMAX(a,b) ((a) > (b) ? (a) : (b))
29 typedef short DCTELEM;
31 //===========================================================================//
32 static const uint8_t __attribute__((aligned(8))) pp7_dither[8][8] =
34 { 0, 48, 12, 60, 3, 51, 15, 63, },
35 { 32, 16, 44, 28, 35, 19, 47, 31, },
36 { 8, 56, 4, 52, 11, 59, 7, 55, },
37 { 40, 24, 36, 20, 43, 27, 39, 23, },
38 { 2, 50, 14, 62, 1, 49, 13, 61, },
39 { 34, 18, 46, 30, 33, 17, 45, 29, },
40 { 10, 58, 6, 54, 9, 57, 5, 53, },
41 { 42, 26, 38, 22, 41, 25, 37, 21, },
44 struct hb_filter_private_s
46 int pix_fmt;
47 int width[3];
48 int height[3];
50 int pp7_qp;
51 int pp7_mode;
52 int pp7_mpeg2;
53 int pp7_temp_stride;
54 uint8_t * pp7_src;
56 AVPicture pic_in;
57 AVPicture pic_out;
58 hb_buffer_t * buf_out;
61 hb_filter_private_t * hb_deblock_init( int pix_fmt,
62 int width,
63 int height,
64 char * settings );
66 int hb_deblock_work( const hb_buffer_t * buf_in,
67 hb_buffer_t ** buf_out,
68 int pix_fmt,
69 int width,
70 int height,
71 hb_filter_private_t * pv );
73 void hb_deblock_close( hb_filter_private_t * pv );
75 hb_filter_object_t hb_filter_deblock =
77 FILTER_DEBLOCK,
78 "Deblock (pp7)",
79 NULL,
80 hb_deblock_init,
81 hb_deblock_work,
82 hb_deblock_close,
85 static inline void pp7_dct_a( DCTELEM * dst, uint8_t * src, int stride )
87 int i;
89 for( i = 0; i < 4; i++ )
91 int s0 = src[0*stride] + src[6*stride];
92 int s1 = src[1*stride] + src[5*stride];
93 int s2 = src[2*stride] + src[4*stride];
94 int s3 = src[3*stride];
95 int s = s3+s3;
97 s3 = s - s0;
98 s0 = s + s0;
99 s = s2 + s1;
100 s2 = s2 - s1;
102 dst[0] = s0 + s;
103 dst[2] = s0 - s;
104 dst[1] = 2*s3 + s2;
105 dst[3] = s3 - s2*2;
107 src++;
108 dst += 4;
112 static void pp7_dct_b( DCTELEM * dst, DCTELEM * src )
114 int i;
116 for( i = 0; i < 4; i++ )
118 int s0 = src[0*4] + src[6*4];
119 int s1 = src[1*4] + src[5*4];
120 int s2 = src[2*4] + src[4*4];
121 int s3 = src[3*4];
122 int s = s3+s3;
124 s3 = s - s0;
125 s0 = s + s0;
126 s = s2 + s1;
127 s2 = s2 - s1;
129 dst[0*4] = s0 + s;
130 dst[2*4] = s0 - s;
131 dst[1*4] = 2*s3 + s2;
132 dst[3*4] = s3 - s2*2;
134 src++;
135 dst++;
139 #define N (1<<16)
140 #define N0 4
141 #define N1 5
142 #define N2 10
143 #define SN0 2
144 #define SN1 2.2360679775
145 #define SN2 3.16227766017
147 static const int pp7_factor[16] =
149 N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
150 N/(N1*N0), N/(N1*N1), N/(N1*N0),N/(N1*N2),
151 N/(N0*N0), N/(N0*N1), N/(N0*N0),N/(N0*N2),
152 N/(N2*N0), N/(N2*N1), N/(N2*N0),N/(N2*N2),
155 static int pp7_threshold[99][16];
157 static void pp7_init_threshold( void )
159 int qp, i;
160 int bias = 0;
162 for( qp = 0; qp < 99; qp++ )
164 for( i = 0; i < 16; i++ )
166 pp7_threshold[qp][i] =
167 ((i&1)?SN2:SN0) * ((i&4)?SN2:SN0) *
168 XMAX(1,qp) * (1<<2) - 1 - bias;
173 static int pp7_hard_threshold( DCTELEM * src, int qp )
175 int i;
176 int a;
178 a = src[0] * pp7_factor[0];
179 for( i = 1; i < 16; i++ )
181 unsigned int threshold1 = pp7_threshold[qp][i];
182 unsigned int threshold2 = (threshold1<<1);
183 int level= src[i];
184 if( ((unsigned)(level+threshold1)) > threshold2 )
186 a += level * pp7_factor[i];
189 return (a + (1<<11)) >> 12;
192 static int pp7_medium_threshold( DCTELEM * src, int qp )
194 int i;
195 int a;
197 a = src[0] * pp7_factor[0];
198 for( i = 1; i < 16; i++ )
200 unsigned int threshold1 = pp7_threshold[qp][i];
201 unsigned int threshold2 = (threshold1<<1);
202 int level= src[i];
203 if( ((unsigned)(level+threshold1)) > threshold2 )
205 if( ((unsigned)(level+2*threshold1)) > 2*threshold2 )
207 a += level * pp7_factor[i];
209 else
211 if( level>0 )
213 a += 2*(level - (int)threshold1) * pp7_factor[i];
215 else
217 a += 2*(level + (int)threshold1) * pp7_factor[i];
222 return (a + (1<<11)) >> 12;
225 static int pp7_soft_threshold( DCTELEM * src, int qp )
227 int i;
228 int a;
230 a = src[0] * pp7_factor[0];
231 for( i = 1; i < 16; i++ )
233 unsigned int threshold1 = pp7_threshold[qp][i];
234 unsigned int threshold2 = (threshold1<<1);
235 int level= src[i];
236 if( ((unsigned)(level+threshold1))>threshold2 )
238 if( level>0 )
240 a += (level - (int)threshold1) * pp7_factor[i];
242 else
244 a += (level + (int)threshold1) * pp7_factor[i];
248 return (a + (1<<11)) >> 12;
251 static int ( * pp7_requantize )( DCTELEM * src, int qp ) = pp7_hard_threshold;
253 static void pp7_filter( hb_filter_private_t * pv,
254 uint8_t * dst,
255 uint8_t * src,
256 int width,
257 int height,
258 uint8_t * qp_store,
259 int qp_stride,
260 int is_luma)
262 int x, y;
264 const int stride = is_luma ? pv->pp7_temp_stride : ((width+16+15)&(~15));
265 uint8_t * p_src = pv->pp7_src + 8*stride;
266 DCTELEM * block = (DCTELEM *)(pv->pp7_src);
267 DCTELEM * temp = (DCTELEM *)(pv->pp7_src + 32);
269 if( !src || !dst )
271 return;
274 for( y = 0; y < height; y++ )
276 int index = 8 + 8*stride + y*stride;
277 memcpy( p_src + index, src + y*width, width );
279 for( x = 0; x < 8; x++ )
281 p_src[index - x - 1] = p_src[index + x ];
282 p_src[index + width + x ] = p_src[index + width - x - 1];
286 for( y = 0; y < 8; y++ )
288 memcpy( p_src + ( 7-y)*stride,
289 p_src + ( y+8)*stride, stride );
290 memcpy( p_src + (height+8+y)*stride,
291 p_src + (height-y+7)*stride, stride );
294 for( y = 0; y < height; y++ )
296 for( x = -8; x < 0; x += 4 )
298 const int index = x + y*stride + (8-3)*(1+stride) + 8;
299 uint8_t * src = p_src + index;
300 DCTELEM * tp = temp+4*x;
302 pp7_dct_a( tp+4*8, src, stride );
305 for( x = 0; x < width; )
307 const int qps = 3 + is_luma;
308 int end = XMIN(x+8, width);
310 int qp;
311 if( pv->pp7_qp )
313 qp = pv->pp7_qp;
315 else
317 qp = qp_store[ (XMIN(x, width-1)>>qps) +
318 (XMIN(y, height-1)>>qps) * qp_stride ];
320 if( pv->pp7_mpeg2 )
322 qp >>= 1;
326 for( ; x < end; x++ )
328 const int index = x + y*stride + (8-3)*(1+stride) + 8;
329 uint8_t * src = p_src + index;
330 DCTELEM * tp = temp+4*x;
331 int v;
333 if( (x&3) == 0 )
335 pp7_dct_a( tp+4*8, src, stride );
338 pp7_dct_b( block, tp );
340 v = pp7_requantize( block, qp );
341 v = (v + pp7_dither[y&7][x&7]) >> 6;
342 if( (unsigned)v > 255 )
344 v = (-v) >> 31;
346 dst[x + y*width] = v;
352 hb_filter_private_t * hb_deblock_init( int pix_fmt,
353 int width,
354 int height,
355 char * settings )
357 if( pix_fmt != PIX_FMT_YUV420P )
359 return 0;
362 hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) );
364 pv->pix_fmt = pix_fmt;
366 pv->width[0] = width;
367 pv->height[0] = height;
369 pv->width[1] = pv->width[2] = width >> 1;
370 pv->height[1] = pv->height[2] = height >> 1;
373 pv->pp7_qp = PP7_QP_DEFAULT;
374 pv->pp7_mode = PP7_MODE_DEFAULT;
375 pv->pp7_mpeg2 = 1; /*mpi->qscale_type;*/
377 if( settings )
379 sscanf( settings, "%d:%d", &pv->pp7_qp, &pv->pp7_mode );
382 if( pv->pp7_qp < 0 )
384 pv->pp7_qp = 0;
387 pp7_init_threshold();
389 switch( pv->pp7_mode )
391 case 0:
392 pp7_requantize = pp7_hard_threshold;
393 break;
394 case 1:
395 pp7_requantize = pp7_soft_threshold;
396 break;
397 case 2:
398 pp7_requantize = pp7_medium_threshold;
399 break;
402 int h = (height+16+15)&(~15);
404 pv->pp7_temp_stride = (width+16+15)&(~15);
406 pv->pp7_src = (uint8_t*)malloc( pv->pp7_temp_stride*(h+8)*sizeof(uint8_t) );
408 int buf_size = 3 * width * height / 2;
409 pv->buf_out = hb_buffer_init( buf_size );
411 return pv;
414 void hb_deblock_close( hb_filter_private_t * pv )
416 if( !pv )
418 return;
421 if( pv->buf_out )
423 hb_buffer_close( &pv->buf_out );
426 free( pv );
429 int hb_deblock_work( const hb_buffer_t * buf_in,
430 hb_buffer_t ** buf_out,
431 int pix_fmt,
432 int width,
433 int height,
434 hb_filter_private_t * pv )
436 if( !pv ||
437 pix_fmt != pv->pix_fmt ||
438 width != pv->width[0] ||
439 height != pv->height[0] )
441 return FILTER_FAILED;
444 avpicture_fill( &pv->pic_in, buf_in->data,
445 pix_fmt, width, height );
447 avpicture_fill( &pv->pic_out, pv->buf_out->data,
448 pix_fmt, width, height );
450 if( /*TODO: mpi->qscale ||*/ pv->pp7_qp )
452 pp7_filter( pv,
453 pv->pic_out.data[0],
454 pv->pic_in.data[0],
455 pv->width[0],
456 pv->height[0],
457 NULL, /* TODO: mpi->qscale*/
458 0, /* TODO: mpi->qstride*/
459 1 );
461 pp7_filter( pv,
462 pv->pic_out.data[1],
463 pv->pic_in.data[1],
464 pv->width[1],
465 pv->height[1],
466 NULL, /* TODO: mpi->qscale*/
467 0, /* TODO: mpi->qstride*/
468 0 );
470 pp7_filter( pv,
471 pv->pic_out.data[2],
472 pv->pic_in.data[2],
473 pv->width[2],
474 pv->height[2],
475 NULL, /* TODO: mpi->qscale*/
476 0, /* TODO: mpi->qstride*/
477 0 );
479 else
481 memcpy( pv->buf_out->data, buf_in->data, buf_in->size );
484 hb_buffer_copy_settings( pv->buf_out, buf_in );
486 *buf_out = pv->buf_out;
488 return FILTER_OK;