X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdenoise.c;h=26e2535a5767078c8915ead4bf144057707099b0;hb=033e32de9c380f54c7d1362a3979da205ebc3a29;hp=5022d4721f18aed62f8f8de366158b4d432ccd4c;hpb=53e2779d92fae78e365b89358ee55b08eeb3c340;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/denoise.c b/libhb/denoise.c index 5022d472..26e2535a 100644 --- a/libhb/denoise.c +++ b/libhb/denoise.c @@ -1,23 +1,23 @@ /* Copyright (C) 2003 Daniel Moreno - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "hb.h" -#include "ffmpeg/avcodec.h" +#include "hbffmpeg.h" #include "mpeg2dec/mpeg2.h" #define HQDN3D_SPATIAL_LUMA_DEFAULT 4.0f @@ -26,37 +26,37 @@ #define ABS(A) ( (A) > 0 ? (A) : -(A) ) -struct hb_filter_private_s +struct hb_filter_private_s { int pix_fmt; int width[3]; - int height[3]; - + int height[3]; + int hqdn3d_coef[4][512*16]; unsigned int * hqdn3d_line; unsigned short * hqdn3d_frame[3]; - + AVPicture pic_in; - AVPicture pic_out; + AVPicture pic_out; hb_buffer_t * buf_out; }; -hb_filter_private_t * hb_denoise_init( int pix_fmt, - int width, +hb_filter_private_t * hb_denoise_init( int pix_fmt, + int width, int height, char * settings ); int hb_denoise_work( const hb_buffer_t * buf_in, hb_buffer_t ** buf_out, int pix_fmt, - int width, + int width, int height, hb_filter_private_t * pv ); void hb_denoise_close( hb_filter_private_t * pv ); hb_filter_object_t hb_filter_denoise = -{ +{ FILTER_DENOISE, "Denoise (hqdn3d)", NULL, @@ -65,26 +65,26 @@ hb_filter_object_t hb_filter_denoise = hb_denoise_close, }; -static void hqdn3d_precalc_coef( int * ct, +static void hqdn3d_precalc_coef( int * ct, double dist25 ) { int i; double gamma, simil, c; - + gamma = log( 0.25 ) / log( 1.0 - dist25/255.0 - 0.00001 ); - + for( i = -255*16; i <= 255*16; i++ ) { simil = 1.0 - ABS(i) / (16*255.0); c = pow( simil, gamma ) * 65536.0 * (double)i / 16.0; ct[16*256+i] = (c<0) ? (c-0.5) : (c+0.5); } - + ct[0] = (dist25 != 0); } -static inline unsigned int hqdn3d_lowpass_mul( unsigned int prev_mul, - unsigned int curr_mul, +static inline unsigned int hqdn3d_lowpass_mul( unsigned int prev_mul, + unsigned int curr_mul, int * coef ) { int diff_mul = prev_mul - curr_mul; @@ -92,27 +92,27 @@ static inline unsigned int hqdn3d_lowpass_mul( unsigned int prev_mul, return curr_mul + coef[d]; } -static void hqdn3d_denoise_temporal( unsigned char * frame_src, +static void hqdn3d_denoise_temporal( unsigned char * frame_src, unsigned char * frame_dst, unsigned short * frame_ant, - int w, int h, + int w, int h, int * temporal) { int x, y; unsigned int pixel_dst; - + for( y = 0; y < h; y++ ) { for( x = 0; x < w; x++ ) { - pixel_dst = hqdn3d_lowpass_mul( frame_ant[x]<<8, - frame_src[x]<<16, + pixel_dst = hqdn3d_lowpass_mul( frame_ant[x]<<8, + frame_src[x]<<16, temporal ); - + frame_ant[x] = ((pixel_dst+0x1000007F)>>8); frame_dst[x] = ((pixel_dst+0x10007FFF)>>16); } - + frame_src += w; frame_dst += w; frame_ant += w; @@ -130,45 +130,45 @@ static void hqdn3d_denoise_spatial( unsigned char * frame_src, int line_offset_src = 0, line_offset_dst = 0; unsigned int pixel_ant; unsigned int pixel_dst; - + /* First pixel has no left nor top neighbor. */ pixel_dst = line_ant[0] = pixel_ant = frame_src[0]<<16; frame_dst[0] = ((pixel_dst+0x10007FFF)>>16); - + /* First line has no top neighbor, only left. */ for( x = 1; x < w; x++ ) { - pixel_dst = line_ant[x] = hqdn3d_lowpass_mul(pixel_ant, - frame_src[x]<<16, + pixel_dst = line_ant[x] = hqdn3d_lowpass_mul(pixel_ant, + frame_src[x]<<16, horizontal); - + frame_dst[x] = ((pixel_dst+0x10007FFF)>>16); } - + for( y = 1; y < h; y++ ) { unsigned int pixel_ant; line_offset_src += w, line_offset_dst += w; - + /* First pixel on each line doesn't have previous pixel */ pixel_ant = frame_src[line_offset_src]<<16; - - pixel_dst = line_ant[0] = hqdn3d_lowpass_mul( line_ant[0], - pixel_ant, + + pixel_dst = line_ant[0] = hqdn3d_lowpass_mul( line_ant[0], + pixel_ant, vertical); - + frame_dst[line_offset_dst] = ((pixel_dst+0x10007FFF)>>16); - + /* The rest of the pixels in the line are normal */ for( x = 1; x < w; x++ ) { unsigned int pixel_dst; - pixel_ant = hqdn3d_lowpass_mul( pixel_ant, - frame_src[line_offset_src+x]<<16, + pixel_ant = hqdn3d_lowpass_mul( pixel_ant, + frame_src[line_offset_src+x]<<16, horizontal ); - pixel_dst = line_ant[x] = hqdn3d_lowpass_mul( line_ant[x], - pixel_ant, + pixel_dst = line_ant[x] = hqdn3d_lowpass_mul( line_ant[x], + pixel_ant, vertical ); frame_dst[line_offset_dst+x]= ((pixel_dst+0x10007FFF)>>16); @@ -180,10 +180,10 @@ static void hqdn3d_denoise( unsigned char * frame_src, unsigned char * frame_dst, unsigned int * line_ant, unsigned short ** frame_ant_ptr, - int w, + int w, int h, - int * horizontal, - int * vertical, + int * horizontal, + int * vertical, int * temporal) { int x, y; @@ -191,7 +191,7 @@ static void hqdn3d_denoise( unsigned char * frame_src, unsigned int pixel_ant; unsigned int pixel_dst; unsigned short* frame_ant = (*frame_ant_ptr); - + if( !frame_ant) { (*frame_ant_ptr) = frame_ant = malloc( w*h*sizeof(unsigned short) ); @@ -199,102 +199,102 @@ static void hqdn3d_denoise( unsigned char * frame_src, { unsigned short* dst = &frame_ant[y*w]; unsigned char* src = frame_src + y*w; - + for( x = 0; x < w; x++ ) { dst[x] = src[x] << 8; } } } - + /* If no spatial coefficients, do temporal denoise only */ if( !horizontal[0] && !vertical[0] ) { - hqdn3d_denoise_temporal( frame_src, - frame_dst, + hqdn3d_denoise_temporal( frame_src, + frame_dst, frame_ant, - w, h, + w, h, temporal); return; } - + /* If no temporal coefficients, do spatial denoise only */ if( !temporal[0] ) { - hqdn3d_denoise_spatial( frame_src, - frame_dst, + hqdn3d_denoise_spatial( frame_src, + frame_dst, line_ant, - w, h, - horizontal, + w, h, + horizontal, vertical); return; } - + /* First pixel has no left nor top neighbor. Only previous frame */ line_ant[0] = pixel_ant = frame_src[0] << 16; - - pixel_dst = hqdn3d_lowpass_mul( frame_ant[0]<<8, - pixel_ant, + + pixel_dst = hqdn3d_lowpass_mul( frame_ant[0]<<8, + pixel_ant, temporal ); - + frame_ant[0] = ((pixel_dst+0x1000007F)>>8); frame_dst[0] = ((pixel_dst+0x10007FFF)>>16); - + /* First line has no top neighbor. Only left one for each pixel and last frame */ for( x = 1; x < w; x++ ) { - line_ant[x] = pixel_ant = hqdn3d_lowpass_mul( pixel_ant, - frame_src[x]<<16, + line_ant[x] = pixel_ant = hqdn3d_lowpass_mul( pixel_ant, + frame_src[x]<<16, horizontal); - - pixel_dst = hqdn3d_lowpass_mul( frame_ant[x]<<8, - pixel_ant, + + pixel_dst = hqdn3d_lowpass_mul( frame_ant[x]<<8, + pixel_ant, temporal); - + frame_ant[x] = ((pixel_dst+0x1000007F)>>8); frame_dst[x] = ((pixel_dst+0x10007FFF)>>16); } - + /* The rest of the lines in the frame are normal */ for( y = 1; y < h; y++ ) { unsigned int pixel_ant; unsigned short * line_prev = &frame_ant[y*w]; line_offset_src += w, line_offset_dst += w; - + /* First pixel on each line doesn't have previous pixel */ pixel_ant = frame_src[line_offset_src]<<16; - line_ant[0] = hqdn3d_lowpass_mul( line_ant[0], - pixel_ant, - vertical); - pixel_dst = hqdn3d_lowpass_mul( line_prev[0]<<8, - line_ant[0], - temporal); + line_ant[0] = hqdn3d_lowpass_mul( line_ant[0], + pixel_ant, + vertical); + pixel_dst = hqdn3d_lowpass_mul( line_prev[0]<<8, + line_ant[0], + temporal); line_prev[0] = ((pixel_dst+0x1000007F)>>8); frame_dst[line_offset_dst] = ((pixel_dst+0x10007FFF)>>16); - + /* The rest of the pixels in the line are normal */ for( x = 1; x < w; x++ ) { unsigned int pixel_dst; - pixel_ant = hqdn3d_lowpass_mul( pixel_ant, - frame_src[line_offset_src+x]<<16, + pixel_ant = hqdn3d_lowpass_mul( pixel_ant, + frame_src[line_offset_src+x]<<16, horizontal ); - line_ant[x] = hqdn3d_lowpass_mul( line_ant[x], + line_ant[x] = hqdn3d_lowpass_mul( line_ant[x], pixel_ant, vertical); - pixel_dst = hqdn3d_lowpass_mul( line_prev[x]<<8, - line_ant[x], + pixel_dst = hqdn3d_lowpass_mul( line_prev[x]<<8, + line_ant[x], temporal ); line_prev[x] = ((pixel_dst+0x1000007F)>>8); - + frame_dst[line_offset_dst+x] = ((pixel_dst+0x10007FFF)>>16); } } } -hb_filter_private_t * hb_denoise_init( int pix_fmt, - int width, +hb_filter_private_t * hb_denoise_init( int pix_fmt, + int width, int height, char * settings ) { @@ -302,70 +302,74 @@ hb_filter_private_t * hb_denoise_init( int pix_fmt, { return 0; } - + hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) ); - - pv->pix_fmt = pix_fmt; + + /* + * Clear the memory to avoid freeing uninitialised memory later. + */ + memset( pv, 0, sizeof( struct hb_filter_private_s ) ); + + pv->pix_fmt = pix_fmt; pv->width[0] = width; - pv->height[0] = height; + pv->height[0] = height; pv->width[1] = pv->width[2] = width >> 1; - pv->height[1] = pv->height[2] = height >> 1; - + pv->height[1] = pv->height[2] = height >> 1; + double spatial_luma, temporal_luma, spatial_chroma, temporal_chroma; if( settings ) { - switch( sscanf( settings, "%lf:%lf:%lf:%lf", - &spatial_luma, &spatial_chroma, + switch( sscanf( settings, "%lf:%lf:%lf:%lf", + &spatial_luma, &spatial_chroma, &temporal_luma, &temporal_chroma ) ) - { + { case 0: spatial_luma = HQDN3D_SPATIAL_LUMA_DEFAULT; - + spatial_chroma = HQDN3D_SPATIAL_CHROMA_DEFAULT; - - temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT; - - temporal_chroma = temporal_luma * + + temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT; + + temporal_chroma = temporal_luma * spatial_chroma / spatial_luma; break; - + case 1: - spatial_chroma = HQDN3D_SPATIAL_CHROMA_DEFAULT * + spatial_chroma = HQDN3D_SPATIAL_CHROMA_DEFAULT * spatial_luma / HQDN3D_SPATIAL_LUMA_DEFAULT; - - temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT * + + temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT * spatial_luma / HQDN3D_SPATIAL_LUMA_DEFAULT; - temporal_chroma = temporal_luma * + temporal_chroma = temporal_luma * spatial_chroma / spatial_luma; break; - + case 2: - temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT * + temporal_luma = HQDN3D_TEMPORAL_LUMA_DEFAULT * spatial_luma / HQDN3D_SPATIAL_LUMA_DEFAULT; - - temporal_chroma = temporal_luma * + + temporal_chroma = temporal_luma * spatial_chroma / spatial_luma; break; - + case 3: - temporal_chroma = temporal_luma * + temporal_chroma = temporal_luma * spatial_chroma / spatial_luma; break; } } - + pv->hqdn3d_line = malloc( width * sizeof(int) ); hqdn3d_precalc_coef( pv->hqdn3d_coef[0], spatial_luma ); hqdn3d_precalc_coef( pv->hqdn3d_coef[1], temporal_luma ); hqdn3d_precalc_coef( pv->hqdn3d_coef[2], spatial_chroma ); hqdn3d_precalc_coef( pv->hqdn3d_coef[3], temporal_chroma ); - - int buf_size = 3 * width * height / 2; - pv->buf_out = hb_buffer_init( buf_size ); - + + pv->buf_out = hb_video_buffer_init( width, height ); + return pv; } @@ -375,7 +379,7 @@ void hb_denoise_close( hb_filter_private_t * pv ) { return; } - + if( pv->hqdn3d_line ) { free( pv->hqdn3d_line ); @@ -400,64 +404,64 @@ void hb_denoise_close( hb_filter_private_t * pv ) { hb_buffer_close( &pv->buf_out ); } - + free( pv ); } int hb_denoise_work( const hb_buffer_t * buf_in, hb_buffer_t ** buf_out, int pix_fmt, - int width, + int width, int height, hb_filter_private_t * pv ) { - if( !pv || + if( !pv || pix_fmt != pv->pix_fmt || width != pv->width[0] || height != pv->height[0] ) { return FILTER_FAILED; } - - avpicture_fill( &pv->pic_in, buf_in->data, + + avpicture_fill( &pv->pic_in, buf_in->data, pix_fmt, width, height ); - - avpicture_fill( &pv->pic_out, pv->buf_out->data, + + avpicture_fill( &pv->pic_out, pv->buf_out->data, pix_fmt, width, height ); - - hqdn3d_denoise( pv->pic_in.data[0], + + hqdn3d_denoise( pv->pic_in.data[0], pv->pic_out.data[0], - pv->hqdn3d_line, - &pv->hqdn3d_frame[0], - pv->width[0], + pv->hqdn3d_line, + &pv->hqdn3d_frame[0], + pv->width[0], pv->height[0], pv->hqdn3d_coef[0], pv->hqdn3d_coef[0], pv->hqdn3d_coef[1] ); - - hqdn3d_denoise( pv->pic_in.data[1], + + hqdn3d_denoise( pv->pic_in.data[1], pv->pic_out.data[1], - pv->hqdn3d_line, - &pv->hqdn3d_frame[1], - pv->width[1], + pv->hqdn3d_line, + &pv->hqdn3d_frame[1], + pv->width[1], pv->height[1], pv->hqdn3d_coef[2], pv->hqdn3d_coef[2], pv->hqdn3d_coef[3] ); - - hqdn3d_denoise( pv->pic_in.data[2], + + hqdn3d_denoise( pv->pic_in.data[2], pv->pic_out.data[2], - pv->hqdn3d_line, - &pv->hqdn3d_frame[2], - pv->width[2], + pv->hqdn3d_line, + &pv->hqdn3d_frame[2], + pv->width[2], pv->height[2], pv->hqdn3d_coef[2], pv->hqdn3d_coef[2], pv->hqdn3d_coef[3] ); - + hb_buffer_copy_settings( pv->buf_out, buf_in ); *buf_out = pv->buf_out; - + return FILTER_OK; }