aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2003-11-02 23:19:47 +0000
committerMichael Niedermayer <michaelni@gmx.at>2003-11-02 23:19:47 +0000
commit821cb11f76d55111dd747346313dad3b9568810b (patch)
tree99cd5a9ce5d46729bbd50f13098150c444868f76
parent432d84c395a0ccdbed383767a87ef037817e56f8 (diff)
downloadffmpeg-821cb11f76d55111dd747346313dad3b9568810b.tar.gz
noise reduction of dct coefficients
Originally committed as revision 2468 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/avcodec.h9
-rw-r--r--libavcodec/i386/mpegvideo_mmx.c1
-rw-r--r--libavcodec/i386/mpegvideo_mmx_template.c3
-rw-r--r--libavcodec/mpegvideo.c60
-rw-r--r--libavcodec/mpegvideo.h6
5 files changed, 77 insertions, 2 deletions
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; i<MAX_PICTURE_COUNT; i++){
@@ -1034,6 +1041,23 @@ int ff_find_unused_picture(MpegEncContext *s, int shared){
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
*/
@@ -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);