Commit 821cb11f authored by Michael Niedermayer's avatar Michael Niedermayer

noise reduction of dct coefficients

Originally committed as revision 2468 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 432d84c3
...@@ -16,7 +16,7 @@ extern "C" { ...@@ -16,7 +16,7 @@ extern "C" {
#define FFMPEG_VERSION_INT 0x000408 #define FFMPEG_VERSION_INT 0x000408
#define FFMPEG_VERSION "0.4.8" #define FFMPEG_VERSION "0.4.8"
#define LIBAVCODEC_BUILD 4689 #define LIBAVCODEC_BUILD 4690
#define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT
#define LIBAVCODEC_VERSION FFMPEG_VERSION #define LIBAVCODEC_VERSION FFMPEG_VERSION
...@@ -1359,6 +1359,13 @@ typedef struct AVCodecContext { ...@@ -1359,6 +1359,13 @@ typedef struct AVCodecContext {
*/ */
struct AVPaletteControl *palctrl; struct AVPaletteControl *palctrl;
/**
* noise reduction strength
* - encoding: set by user.
* - decoding: unused
*/
int noise_reduction;
} AVCodecContext; } AVCodecContext;
......
...@@ -495,6 +495,7 @@ static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w) ...@@ -495,6 +495,7 @@ static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w)
#define HAVE_MMX2 #define HAVE_MMX2
#undef RENAME #undef RENAME
#undef RENAMEl
#define RENAME(a) a ## _MMX2 #define RENAME(a) a ## _MMX2
#define RENAMEl(a) a ## _mmx2 #define RENAMEl(a) a ## _mmx2
#include "mpegvideo_mmx_template.c" #include "mpegvideo_mmx_template.c"
......
...@@ -45,6 +45,9 @@ static int RENAME(dct_quantize)(MpegEncContext *s, ...@@ -45,6 +45,9 @@ static int RENAME(dct_quantize)(MpegEncContext *s,
//s->fdct (block); //s->fdct (block);
RENAMEl(ff_fdct) (block); //cant be anything else ... RENAMEl(ff_fdct) (block); //cant be anything else ...
if(s->dct_error_sum)
ff_denoise_dct(s, block);
if (s->mb_intra) { if (s->mb_intra) {
int dummy; int dummy;
if (n < 4) if (n < 4)
......
...@@ -458,6 +458,11 @@ int MPV_common_init(MpegEncContext *s) ...@@ -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->q_inter_matrix16, 64*32*2 * sizeof(uint16_t))
CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*))
CHECKED_ALLOCZ(s->reordered_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)) CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM))
...@@ -588,6 +593,8 @@ void MPV_common_end(MpegEncContext *s) ...@@ -588,6 +593,8 @@ void MPV_common_end(MpegEncContext *s)
av_freep(&s->blocks); av_freep(&s->blocks);
av_freep(&s->input_picture); av_freep(&s->input_picture);
av_freep(&s->reordered_input_picture); av_freep(&s->reordered_input_picture);
av_freep(&s->dct_error_sum);
av_freep(&s->dct_offset);
if(s->picture){ if(s->picture){
for(i=0; i<MAX_PICTURE_COUNT; i++){ for(i=0; i<MAX_PICTURE_COUNT; i++){
...@@ -1034,6 +1041,23 @@ int ff_find_unused_picture(MpegEncContext *s, int shared){ ...@@ -1034,6 +1041,23 @@ int ff_find_unused_picture(MpegEncContext *s, int shared){
return -1; return -1;
} }
static void update_noise_reduction(MpegEncContext *s){
int intra, i;
for(intra=0; intra<2; intra++){
if(s->dct_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 * generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded
*/ */
...@@ -1136,6 +1160,12 @@ alloc: ...@@ -1136,6 +1160,12 @@ alloc:
else else
s->dct_unquantize = s->dct_unquantize_mpeg1; 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 #ifdef HAVE_XVMC
if(s->avctx->xvmc_acceleration) if(s->avctx->xvmc_acceleration)
return XVMC_field_start(s, avctx); return XVMC_field_start(s, avctx);
...@@ -4042,6 +4072,28 @@ static void encode_picture(MpegEncContext *s, int picture_number) ...@@ -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, static int dct_quantize_trellis_c(MpegEncContext *s,
DCTELEM *block, int n, DCTELEM *block, int n,
int qscale, int *overflow){ int qscale, int *overflow){
...@@ -4071,6 +4123,9 @@ static int dct_quantize_trellis_c(MpegEncContext *s, ...@@ -4071,6 +4123,9 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
s->dsp.fdct (block); s->dsp.fdct (block);
if(s->dct_error_sum)
ff_denoise_dct(s, block);
qmul= qscale*16; qmul= qscale*16;
qadd= ((qscale-1)|1)*8; qadd= ((qscale-1)|1)*8;
...@@ -4362,6 +4417,9 @@ static int dct_quantize_c(MpegEncContext *s, ...@@ -4362,6 +4417,9 @@ static int dct_quantize_c(MpegEncContext *s,
s->dsp.fdct (block); s->dsp.fdct (block);
if(s->dct_error_sum)
ff_denoise_dct(s, block);
if (s->mb_intra) { if (s->mb_intra) {
if (!s->h263_aic) { if (!s->h263_aic) {
if (n < 4) if (n < 4)
......
...@@ -469,6 +469,11 @@ typedef struct MpegEncContext { ...@@ -469,6 +469,11 @@ typedef struct MpegEncContext {
ScanTable intra_v_scantable; ScanTable intra_v_scantable;
ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage 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 void *opaque; ///< private data for the user
/* bit rate control */ /* bit rate control */
...@@ -719,6 +724,7 @@ void ff_mpeg_flush(AVCodecContext *avctx); ...@@ -719,6 +724,7 @@ void ff_mpeg_flush(AVCodecContext *avctx);
void ff_print_debug_info(MpegEncContext *s, Picture *pict); void ff_print_debug_info(MpegEncContext *s, Picture *pict);
void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix); void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix);
int ff_find_unused_picture(MpegEncContext *s, int shared); 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_start(MpegEncContext *s);
void ff_er_frame_end(MpegEncContext *s); void ff_er_frame_end(MpegEncContext *s);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment