Add denoiser & noise estimation in the encoder.
This patch adds support to enable denosing and noise modeling on
buffers that are received by the encoder.
Enable CONFIG_DENOISE 1 in CMake configuration.
Use parameters:
--denoise-noise-level=50 (and optionally --denoise-block-size=32)
For less denoising try:
--denoise-noise-level=25
Change-Id: Ib72c8454ee483389fa9aa3f51e4b76dd27e0c0fd
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 4cdb5d3..e77e5f6 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -854,6 +854,12 @@
/*!\brief Codec control function to set the path to the film grain parameters
*/
AV1E_SET_FILM_GRAIN_TABLE,
+
+ /*!\brief Sets the noise level */
+ AV1E_SET_DENOISE_NOISE_LEVEL,
+
+ /*!\brief Sets the denoisers block size */
+ AV1E_SET_DENOISE_BLOCK_SIZE,
};
/*!\brief aom 1-D scaling mode
@@ -1165,6 +1171,14 @@
AOM_CTRL_USE_TYPE(AV1E_SET_CDF_UPDATE_MODE, int)
#define AOM_CTRL_AV1E_SET_CDF_UPDATE_MODE
+#ifdef CONFIG_DENOISE
+AOM_CTRL_USE_TYPE(AV1E_SET_DENOISE_NOISE_LEVEL, int);
+#define AOM_CTRL_AV1E_SET_DENOISE_NOISE_LEVEL
+
+AOM_CTRL_USE_TYPE(AV1E_SET_DENOISE_BLOCK_SIZE, unsigned int);
+#define AOM_CTRL_AV1E_SET_DENOISE_BLOCK_SIZE
+#endif
+
/*!\endcond */
/*! @} - end defgroup aom_encoder */
#ifdef __cplusplus
diff --git a/aom_dsp/noise_model.c b/aom_dsp/noise_model.c
index a1287f7..5975c62 100644
--- a/aom_dsp/noise_model.c
+++ b/aom_dsp/noise_model.c
@@ -1458,3 +1458,189 @@
}
return init_success;
}
+
+struct aom_denoise_and_model_t {
+ int block_size;
+ int bit_depth;
+ float noise_level;
+
+ // Size of current denoised buffer and flat_block buffer
+ int width;
+ int height;
+ int y_stride;
+ int uv_stride;
+ int num_blocks_w;
+ int num_blocks_h;
+
+ // Buffers for image and noise_psd allocated on the fly
+ float *noise_psd[3];
+ uint8_t *denoised[3];
+ uint8_t *flat_blocks;
+
+ aom_flat_block_finder_t flat_block_finder;
+ aom_noise_model_t noise_model;
+};
+
+struct aom_denoise_and_model_t *aom_denoise_and_model_alloc(int bit_depth,
+ int block_size,
+ float noise_level) {
+ struct aom_denoise_and_model_t *ctx =
+ (struct aom_denoise_and_model_t *)aom_malloc(
+ sizeof(struct aom_denoise_and_model_t));
+ if (!ctx) {
+ fprintf(stderr, "Unable to allocate denoise_and_model struct\n");
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->block_size = block_size;
+ ctx->noise_level = noise_level;
+ ctx->bit_depth = bit_depth;
+
+ ctx->noise_psd[0] =
+ aom_malloc(sizeof(*ctx->noise_psd[0]) * block_size * block_size);
+ ctx->noise_psd[1] =
+ aom_malloc(sizeof(*ctx->noise_psd[1]) * block_size * block_size);
+ ctx->noise_psd[2] =
+ aom_malloc(sizeof(*ctx->noise_psd[2]) * block_size * block_size);
+ if (!ctx->noise_psd[0] || !ctx->noise_psd[1] || !ctx->noise_psd[2]) {
+ fprintf(stderr, "Unable to allocate noise PSD buffers\n");
+ aom_denoise_and_model_free(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+void aom_denoise_and_model_free(struct aom_denoise_and_model_t *ctx) {
+ aom_free(ctx->flat_blocks);
+ for (int i = 0; i < 3; ++i) {
+ aom_free(ctx->denoised[i]);
+ aom_free(ctx->noise_psd[i]);
+ }
+ aom_noise_model_free(&ctx->noise_model);
+ aom_flat_block_finder_free(&ctx->flat_block_finder);
+ aom_free(ctx);
+}
+
+static int denoise_and_model_realloc_if_necessary(
+ struct aom_denoise_and_model_t *ctx, YV12_BUFFER_CONFIG *sd) {
+ if (ctx->width == sd->y_width && ctx->height == sd->y_height &&
+ ctx->y_stride == sd->y_stride && ctx->uv_stride == sd->uv_stride)
+ return 1;
+ const int use_highbd = (sd->flags & YV12_FLAG_HIGHBITDEPTH) != 0;
+ const int block_size = ctx->block_size;
+
+ ctx->width = sd->y_width;
+ ctx->height = sd->y_height;
+ ctx->y_stride = sd->y_stride;
+ ctx->uv_stride = sd->uv_stride;
+
+ for (int i = 0; i < 3; ++i) {
+ aom_free(ctx->denoised[i]);
+ ctx->denoised[i] = NULL;
+ }
+ aom_free(ctx->flat_blocks);
+ ctx->flat_blocks = NULL;
+
+ ctx->denoised[0] = aom_malloc((sd->y_stride * sd->y_height) << use_highbd);
+ ctx->denoised[1] = aom_malloc((sd->uv_stride * sd->uv_height) << use_highbd);
+ ctx->denoised[2] = aom_malloc((sd->uv_stride * sd->uv_height) << use_highbd);
+ if (!ctx->denoised[0] || !ctx->denoised[1] || !ctx->denoised[2]) {
+ fprintf(stderr, "Unable to allocate denoise buffers\n");
+ return 0;
+ }
+ ctx->num_blocks_w = (sd->y_width + ctx->block_size - 1) / ctx->block_size;
+ ctx->num_blocks_h = (sd->y_height + ctx->block_size - 1) / ctx->block_size;
+ ctx->flat_blocks = aom_malloc(ctx->num_blocks_w * ctx->num_blocks_h);
+
+ aom_flat_block_finder_free(&ctx->flat_block_finder);
+ if (!aom_flat_block_finder_init(&ctx->flat_block_finder, ctx->block_size,
+ ctx->bit_depth, use_highbd)) {
+ fprintf(stderr, "Unable to init flat block finder\n");
+ return 0;
+ }
+
+ const aom_noise_model_params_t params = { AOM_NOISE_SHAPE_SQUARE, 3,
+ ctx->bit_depth, use_highbd };
+ aom_noise_model_free(&ctx->noise_model);
+ if (!aom_noise_model_init(&ctx->noise_model, params)) {
+ fprintf(stderr, "Unable to init noise model\n");
+ return 0;
+ }
+
+ // Simply use a flat PSD (although we could use the flat blocks to estimate
+ // PSD) those to estimate an actual noise PSD)
+ const float y_noise_level =
+ aom_noise_psd_get_default_value(ctx->block_size, ctx->noise_level);
+ const float uv_noise_level = aom_noise_psd_get_default_value(
+ ctx->block_size >> sd->subsampling_x, ctx->noise_level);
+ for (int i = 0; i < block_size * block_size; ++i) {
+ ctx->noise_psd[0][i] = y_noise_level;
+ ctx->noise_psd[1][i] = ctx->noise_psd[2][i] = uv_noise_level;
+ }
+ return 1;
+}
+
+int aom_denoise_and_model_run(struct aom_denoise_and_model_t *ctx,
+ YV12_BUFFER_CONFIG *sd,
+ aom_film_grain_t *film_grain) {
+ const int block_size = ctx->block_size;
+ const int use_highbd = (sd->flags & YV12_FLAG_HIGHBITDEPTH) != 0;
+ uint8_t *raw_data[3] = {
+ use_highbd ? (uint8_t *)CONVERT_TO_SHORTPTR(sd->y_buffer) : sd->y_buffer,
+ use_highbd ? (uint8_t *)CONVERT_TO_SHORTPTR(sd->u_buffer) : sd->u_buffer,
+ use_highbd ? (uint8_t *)CONVERT_TO_SHORTPTR(sd->v_buffer) : sd->v_buffer,
+ };
+ const uint8_t *const data[3] = { raw_data[0], raw_data[1], raw_data[2] };
+ int strides[3] = { sd->y_stride, sd->uv_stride, sd->uv_stride };
+ int chroma_sub_log2[2] = { sd->subsampling_x, sd->subsampling_y };
+
+ if (!denoise_and_model_realloc_if_necessary(ctx, sd)) {
+ fprintf(stderr, "Unable to realloc buffers\n");
+ return 0;
+ }
+
+ aom_flat_block_finder_run(&ctx->flat_block_finder, data[0], sd->y_width,
+ sd->y_height, strides[0], ctx->flat_blocks);
+
+ if (!aom_wiener_denoise_2d(data, ctx->denoised, sd->y_width, sd->y_height,
+ strides, chroma_sub_log2, ctx->noise_psd,
+ block_size, ctx->bit_depth, use_highbd)) {
+ fprintf(stderr, "Unable to denoise image\n");
+ return 0;
+ }
+
+ const aom_noise_status_t status = aom_noise_model_update(
+ &ctx->noise_model, data, (const uint8_t *const *)ctx->denoised,
+ sd->y_width, sd->y_height, strides, chroma_sub_log2, ctx->flat_blocks,
+ block_size);
+ int have_noise_estimate = 0;
+ if (status == AOM_NOISE_STATUS_OK) {
+ have_noise_estimate = 1;
+ } else if (status == AOM_NOISE_STATUS_DIFFERENT_NOISE_TYPE) {
+ aom_noise_model_save_latest(&ctx->noise_model);
+ have_noise_estimate = 1;
+ } else {
+ // Unable to update noise model; proceed if we have a previous estimate.
+ have_noise_estimate =
+ (ctx->noise_model.combined_state[0].strength_solver.num_equations > 0);
+ }
+
+ film_grain->apply_grain = 0;
+ if (have_noise_estimate) {
+ if (!aom_noise_model_get_grain_parameters(&ctx->noise_model, film_grain)) {
+ fprintf(stderr, "Unable to get grain parameters.\n");
+ return 0;
+ }
+ if (!film_grain->random_seed) {
+ film_grain->random_seed = 1071;
+ }
+ memcpy(raw_data[0], ctx->denoised[0],
+ (strides[0] * sd->y_height) << use_highbd);
+ memcpy(raw_data[1], ctx->denoised[1],
+ (strides[1] * sd->uv_height) << use_highbd);
+ memcpy(raw_data[2], ctx->denoised[2],
+ (strides[2] * sd->uv_height) << use_highbd);
+ }
+ return 1;
+}
diff --git a/aom_dsp/noise_model.h b/aom_dsp/noise_model.h
index dabeacc..b07bf86 100644
--- a/aom_dsp/noise_model.h
+++ b/aom_dsp/noise_model.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include "aom_dsp/grain_synthesis.h"
+#include "aom_scale/yv12config.h"
/*!\brief Wrapper of data required to represent linear system of eqns and soln.
*/
@@ -280,6 +281,42 @@
int w, int h, int stride[3], int chroma_sub_log2[2],
float *noise_psd[3], int block_size, int bit_depth,
int use_highbd);
+
+struct aom_denoise_and_model_t;
+
+/*!\brief Denoise the buffer and model the residual noise.
+ *
+ * This is meant to be called sequentially on input frames. The input buffer
+ * is denoised and the residual noise is modelled. The current noise estimate
+ * is populated in film_grain. Returns true on success. The grain.apply_grain
+ * parameter will be true when the input buffer was successfully denoised and
+ * grain was modelled. Returns false on error.
+ *
+ * \param[in] ctx Struct allocated with aom_denoise_and_model_alloc
+ * that holds some buffers for denoising and the current
+ * noise estimate.
+ * \param[in/out] buf The raw input buffer to be denoised.
+ * \param[out] grain Output film grain parameters
+ */
+int aom_denoise_and_model_run(struct aom_denoise_and_model_t *ctx,
+ YV12_BUFFER_CONFIG *buf, aom_film_grain_t *grain);
+
+/*!\brief Allocates a context that can be used for denoising and noise modeling.
+ *
+ * \param[in] bit_depth Bit depth of buffers this will be run on.
+ * \param[in] block_size Block size for noise modeling and flat block
+ * estimation
+ * \param[in] noise_level The noise_level (2.5 for moderate noise, and 5 for
+ * higher levels of noise)
+ */
+struct aom_denoise_and_model_t *aom_denoise_and_model_alloc(int bit_depth,
+ int block_size,
+ float noise_level);
+
+/*!\brief Frees the denoise context allocated with aom_denoise_and_model_alloc
+ */
+void aom_denoise_and_model_free(struct aom_denoise_and_model_t *denoise_model);
+
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
diff --git a/apps/aomenc.c b/apps/aomenc.c
index db09102..31cb662 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -475,6 +475,13 @@
static const arg_def_t film_grain_table =
ARG_DEF(NULL, "film-grain-table", 1,
"Path to file containing film grain parameters");
+#if CONFIG_DENOISE
+static const arg_def_t denoise_noise_level =
+ ARG_DEF(NULL, "denoise-noise-level", 1,
+ "Amount of noise (from 0 = don't denoise, to 50)");
+static const arg_def_t denoise_block_size =
+ ARG_DEF(NULL, "denoise-block-size", 1, "Denoise block size (default = 32)");
+#endif
static const arg_def_t enable_ref_frame_mvs =
ARG_DEF(NULL, "enable-ref-frame-mvs", 1,
"Enable temporal mv prediction (default is 1)");
@@ -656,6 +663,10 @@
&timing_info,
&film_grain_test,
&film_grain_table,
+#if CONFIG_DENOISE
+ &denoise_noise_level,
+ &denoise_block_size,
+#endif
&enable_ref_frame_mvs,
&bitdeptharg,
&inbitdeptharg,
@@ -708,6 +719,10 @@
AV1E_SET_TIMING_INFO_TYPE,
AV1E_SET_FILM_GRAIN_TEST_VECTOR,
AV1E_SET_FILM_GRAIN_TABLE,
+#if CONFIG_DENOISE
+ AV1E_SET_DENOISE_NOISE_LEVEL,
+ AV1E_SET_DENOISE_BLOCK_SIZE,
+#endif
AV1E_SET_ENABLE_REF_FRAME_MVS,
AV1E_SET_ENABLE_DF,
AV1E_SET_ENABLE_ORDER_HINT,
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 58c2417..71294cb 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -94,6 +94,10 @@
int enable_warped_motion; // sequence level
int allow_warped_motion; // frame level
int enable_superres;
+#if CONFIG_DENOISE
+ float noise_level;
+ int noise_block_size;
+#endif
};
static struct av1_extracfg default_extra_cfg = {
@@ -160,6 +164,10 @@
1, // enable_warped_motion at sequence level
1, // allow_warped_motion at frame level
1, // superres
+#if CONFIG_DENOISE
+ 0, // noise_level
+ 32, // noise_block_size
+#endif
};
struct aom_codec_alg_priv {
@@ -612,6 +620,10 @@
oxcf->film_grain_test_vector = extra_cfg->film_grain_test_vector;
oxcf->film_grain_table_filename = extra_cfg->film_grain_table_filename;
}
+#if CONFIG_DENOISE
+ oxcf->noise_level = extra_cfg->noise_level;
+ oxcf->noise_block_size = extra_cfg->noise_block_size;
+#endif
oxcf->large_scale_tile = cfg->large_scale_tile;
oxcf->single_tile_decoding =
(oxcf->large_scale_tile) ? extra_cfg->single_tile_decoding : 0;
@@ -1055,6 +1067,23 @@
return update_extra_cfg(ctx, &extra_cfg);
}
+#if CONFIG_DENOISE
+static aom_codec_err_t ctrl_set_denoise_noise_level(aom_codec_alg_priv_t *ctx,
+ va_list args) {
+ struct av1_extracfg extra_cfg = ctx->extra_cfg;
+ extra_cfg.noise_level =
+ ((float)CAST(AV1E_SET_DENOISE_NOISE_LEVEL, args)) / 10.0f;
+ return update_extra_cfg(ctx, &extra_cfg);
+}
+
+static aom_codec_err_t ctrl_set_denoise_block_size(aom_codec_alg_priv_t *ctx,
+ va_list args) {
+ struct av1_extracfg extra_cfg = ctx->extra_cfg;
+ extra_cfg.noise_block_size = CAST(AV1E_SET_DENOISE_BLOCK_SIZE, args);
+ return update_extra_cfg(ctx, &extra_cfg);
+}
+#endif
+
static aom_codec_err_t ctrl_set_deltaq_mode(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
@@ -1710,6 +1739,10 @@
{ AV1E_SET_SINGLE_TILE_DECODING, ctrl_set_single_tile_decoding },
{ AV1E_SET_FILM_GRAIN_TEST_VECTOR, ctrl_set_film_grain_test_vector },
{ AV1E_SET_FILM_GRAIN_TABLE, ctrl_set_film_grain_table },
+#if CONFIG_DENOISE
+ { AV1E_SET_DENOISE_NOISE_LEVEL, ctrl_set_denoise_noise_level },
+ { AV1E_SET_DENOISE_BLOCK_SIZE, ctrl_set_denoise_block_size },
+#endif // CONFIG_FILM_GRAIN
{ AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
// Getters
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 1d0ec63..f8d8e1f 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -493,9 +493,9 @@
ENTROPY_CONTEXT **above_context[MAX_MB_PLANE];
TXFM_CONTEXT **above_txfm_context;
WarpedMotionParams global_motion[REF_FRAMES];
- aom_film_grain_table_t *film_grain_table;
int film_grain_params_present;
aom_film_grain_t film_grain_params;
+
int cdef_pri_damping;
int cdef_sec_damping;
int nb_cdef_strengths;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 5844db2..9296837 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -56,6 +56,11 @@
#include "av1/encoder/grain_test_vectors.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/aom_filter.h"
+#if CONFIG_DENOISE
+#include "aom_dsp/grain_table.h"
+#include "aom_dsp/noise_util.h"
+#include "aom_dsp/noise_model.h"
+#endif
#include "aom_ports/aom_timer.h"
#include "aom_ports/mem.h"
#include "aom_ports/system_state.h"
@@ -443,11 +448,11 @@
AV1_COMMON *const cm = &cpi->common;
cpi->oxcf = *oxcf;
- if (cm->film_grain_table) {
- aom_film_grain_table_free(cm->film_grain_table);
- aom_free(cm->film_grain_table);
+ if (cpi->film_grain_table) {
+ aom_film_grain_table_free(cpi->film_grain_table);
+ aom_free(cpi->film_grain_table);
+ cpi->film_grain_table = NULL;
}
- cm->film_grain_table = 0;
if (oxcf->film_grain_test_vector) {
cm->film_grain_params_present = 1;
@@ -462,10 +467,10 @@
}
}
} else if (oxcf->film_grain_table_filename) {
- cm->film_grain_table = aom_malloc(sizeof(*cm->film_grain_table));
- memset(cm->film_grain_table, 0, sizeof(aom_film_grain_table_t));
+ cpi->film_grain_table = aom_malloc(sizeof(*cpi->film_grain_table));
+ memset(cpi->film_grain_table, 0, sizeof(aom_film_grain_table_t));
- aom_film_grain_table_read(cm->film_grain_table,
+ aom_film_grain_table_read(cpi->film_grain_table,
oxcf->film_grain_table_filename, &cm->error);
} else {
cm->film_grain_params_present = 0;
@@ -525,6 +530,17 @@
av1_free_pc_tree(&cpi->td, num_planes);
aom_free(cpi->td.mb.palette_buffer);
+
+#if CONFIG_DENOISE
+ if (cpi->denoise_and_model) {
+ aom_denoise_and_model_free(cpi->denoise_and_model);
+ cpi->denoise_and_model = NULL;
+ }
+#endif
+ if (cpi->film_grain_table) {
+ aom_film_grain_table_free(cpi->film_grain_table);
+ cpi->film_grain_table = NULL;
+ }
}
static void save_coding_context(AV1_COMP *cpi) {
@@ -5295,6 +5311,40 @@
return AOM_CODEC_OK;
}
+#if CONFIG_DENOISE
+static int apply_denoise_2d(AV1_COMP *cpi, YV12_BUFFER_CONFIG *sd,
+ int block_size, float noise_level,
+ int64_t time_stamp, int64_t end_time) {
+ AV1_COMMON *const cm = &cpi->common;
+ if (!cpi->denoise_and_model) {
+ cpi->denoise_and_model =
+ aom_denoise_and_model_alloc(cm->bit_depth, block_size, noise_level);
+ if (!cpi->denoise_and_model) {
+ aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
+ "Error allocating denoise and model");
+ return -1;
+ }
+ }
+ if (!cpi->film_grain_table) {
+ cpi->film_grain_table = aom_malloc(sizeof(*cpi->film_grain_table));
+ if (!cpi->film_grain_table) {
+ aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
+ "Error allocating grain table");
+ return -1;
+ }
+ memset(cpi->film_grain_table, 0, sizeof(*cpi->film_grain_table));
+ }
+ if (aom_denoise_and_model_run(cpi->denoise_and_model, sd,
+ &cm->film_grain_params)) {
+ if (cm->film_grain_params.apply_grain) {
+ aom_film_grain_table_append(cpi->film_grain_table, time_stamp, end_time,
+ &cm->film_grain_params);
+ }
+ }
+ return 0;
+}
+#endif
+
int av1_receive_raw_frame(AV1_COMP *cpi, aom_enc_frame_flags_t frame_flags,
YV12_BUFFER_CONFIG *sd, int64_t time_stamp,
int64_t end_time) {
@@ -5309,6 +5359,13 @@
aom_usec_timer_start(&timer);
+#if CONFIG_DENOISE
+ if (cpi->oxcf.noise_level > 0)
+ if (apply_denoise_2d(cpi, sd, cpi->oxcf.noise_block_size,
+ cpi->oxcf.noise_level, time_stamp, end_time) < 0)
+ res = -1;
+#endif // CONFIG_DENOISE
+
if (av1_lookahead_push(cpi->lookahead, sd, time_stamp, end_time,
use_highbitdepth, frame_flags))
res = -1;
@@ -6004,9 +6061,9 @@
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
cm->cur_frame->buf.buf_8bit_valid = 0;
- if (cm->film_grain_table) {
+ if (cpi->film_grain_table) {
cm->film_grain_params_present = aom_film_grain_table_lookup(
- cm->film_grain_table, *time_stamp, *time_end, 0 /* erase */,
+ cpi->film_grain_table, *time_stamp, *time_end, 0 /* =erase */,
&cm->film_grain_params);
}
cm->cur_frame->film_grain_params_present = cm->film_grain_params_present;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 7577a58..2b7ab71 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -41,6 +41,9 @@
#include "aom_dsp/ssim.h"
#endif
#include "aom_dsp/variance.h"
+#if CONFIG_DENOISE
+#include "aom_dsp/noise_model.h"
+#endif
#include "aom/internal/aom_codec_internal.h"
#include "aom_util/aom_thread.h"
@@ -301,6 +304,11 @@
int allow_warped_motion;
int enable_superres;
unsigned int save_as_annexb;
+
+#if CONFIG_DENOISE
+ float noise_level;
+ int noise_block_size;
+#endif
} AV1EncoderConfig;
static INLINE int is_lossless_requested(const AV1EncoderConfig *cfg) {
@@ -690,6 +698,11 @@
AV1LfSync lf_row_sync;
AV1LrSync lr_row_sync;
AV1LrStruct lr_ctxt;
+
+ aom_film_grain_table_t *film_grain_table;
+#if CONFIG_DENOISE
+ struct aom_denoise_and_model_t *denoise_and_model;
+#endif
} AV1_COMP;
void av1_initialize_enc(void);
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index c7252f0..19af5c4 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -76,6 +76,7 @@
set(CONFIG_ACCOUNTING 0 CACHE NUMBER "Enables bit accounting.")
set(CONFIG_ANALYZER 0 CACHE NUMBER "Enables bit stream analyzer.")
set(CONFIG_COEFFICIENT_RANGE_CHECKING 0 CACHE NUMBER "Coefficient range check.")
+set(CONFIG_DENOISE 0 CACHE NUMBER "Denoise/noise modeling support in encoder.")
set(CONFIG_FILEOPTIONS 1 CACHE NUMBER "Enables encoder config file support.")
set(CONFIG_INSPECTION 0 CACHE NUMBER "Enables bitstream inspection.")
set(CONFIG_INTERNAL_STATS 0 CACHE NUMBER "Enables internal encoder stats.")