diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e3b47536f0..b169748ba0 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -16,7 +16,7 @@ extern "C" { #define FFMPEG_VERSION_INT 0x000408 #define FFMPEG_VERSION "0.4.8" -#define LIBAVCODEC_BUILD 4689 +#define LIBAVCODEC_BUILD 4690 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION FFMPEG_VERSION @@ -1358,6 +1358,13 @@ typedef struct AVCodecContext { * - decoding: set by user. */ struct AVPaletteControl *palctrl; + + /** + * noise reduction strength + * - encoding: set by user. + * - decoding: unused + */ + int noise_reduction; } AVCodecContext; diff --git a/libavcodec/i386/mpegvideo_mmx.c b/libavcodec/i386/mpegvideo_mmx.c index d217e10249..9302c7b83d 100644 --- a/libavcodec/i386/mpegvideo_mmx.c +++ b/libavcodec/i386/mpegvideo_mmx.c @@ -495,6 +495,7 @@ static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w) #define HAVE_MMX2 #undef RENAME +#undef RENAMEl #define RENAME(a) a ## _MMX2 #define RENAMEl(a) a ## _mmx2 #include "mpegvideo_mmx_template.c" diff --git a/libavcodec/i386/mpegvideo_mmx_template.c b/libavcodec/i386/mpegvideo_mmx_template.c index 2728a8dd95..f357e14035 100644 --- a/libavcodec/i386/mpegvideo_mmx_template.c +++ b/libavcodec/i386/mpegvideo_mmx_template.c @@ -45,6 +45,9 @@ static int RENAME(dct_quantize)(MpegEncContext *s, //s->fdct (block); RENAMEl(ff_fdct) (block); //cant be anything else ... + if(s->dct_error_sum) + ff_denoise_dct(s, block); + if (s->mb_intra) { int dummy; if (n < 4) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index c131e723b3..e459368c22 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -458,6 +458,11 @@ int MPV_common_init(MpegEncContext *s) CHECKED_ALLOCZ(s->q_inter_matrix16, 64*32*2 * sizeof(uint16_t)) CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) CHECKED_ALLOCZ(s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) + + if(s->avctx->noise_reduction){ + CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) + CHECKED_ALLOCZ(s->dct_offset, 2 * 64 * sizeof(uint16_t)) + } } CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM)) @@ -588,6 +593,8 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->blocks); av_freep(&s->input_picture); av_freep(&s->reordered_input_picture); + av_freep(&s->dct_error_sum); + av_freep(&s->dct_offset); if(s->picture){ for(i=0; idct_count[intra] > (1<<16)){ + for(i=0; i<64; i++){ + s->dct_error_sum[intra][i] >>=1; + } + s->dct_count[intra] >>= 1; + } + + for(i=0; i<64; i++){ + s->dct_offset[intra][i]= (s->avctx->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i]/2) / (s->dct_error_sum[intra][i]+1); + } + } +} + /** * generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded */ @@ -1136,6 +1160,12 @@ alloc: else s->dct_unquantize = s->dct_unquantize_mpeg1; + if(s->dct_error_sum){ + assert(s->avctx->noise_reduction && s->encoding); + + update_noise_reduction(s); + } + #ifdef HAVE_XVMC if(s->avctx->xvmc_acceleration) return XVMC_field_start(s, avctx); @@ -4042,6 +4072,28 @@ static void encode_picture(MpegEncContext *s, int picture_number) } } +void ff_denoise_dct(MpegEncContext *s, DCTELEM *block){ + const int intra= s->mb_intra; + int i; + + for(i=0; i<64; i++){ + int level= block[i]; + + if(level){ + if(level>0){ + s->dct_error_sum[intra][i] += level; + level -= s->dct_offset[intra][i]; + if(level<0) level=0; + }else{ + s->dct_error_sum[intra][i] -= level; + level += s->dct_offset[intra][i]; + if(level>0) level=0; + } + block[i]= level; + } + } +} + static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow){ @@ -4070,7 +4122,10 @@ static int dct_quantize_trellis_c(MpegEncContext *s, const int patch_table= s->out_format == FMT_MPEG1 && !s->mb_intra; s->dsp.fdct (block); - + + if(s->dct_error_sum) + ff_denoise_dct(s, block); + qmul= qscale*16; qadd= ((qscale-1)|1)*8; @@ -4362,6 +4417,9 @@ static int dct_quantize_c(MpegEncContext *s, s->dsp.fdct (block); + if(s->dct_error_sum) + ff_denoise_dct(s, block); + if (s->mb_intra) { if (!s->h263_aic) { if (n < 4) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 644eeeae78..53254e5813 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -468,6 +468,11 @@ typedef struct MpegEncContext { ScanTable intra_h_scantable; ScanTable intra_v_scantable; ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage + + /* noise reduction */ + int (*dct_error_sum)[64]; + int dct_count[2]; + uint16_t (*dct_offset)[64]; void *opaque; ///< private data for the user @@ -719,6 +724,7 @@ void ff_mpeg_flush(AVCodecContext *avctx); void ff_print_debug_info(MpegEncContext *s, Picture *pict); void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix); int ff_find_unused_picture(MpegEncContext *s, int shared); +void ff_denoise_dct(MpegEncContext *s, DCTELEM *block); void ff_er_frame_start(MpegEncContext *s); void ff_er_frame_end(MpegEncContext *s);