Commit 9c41143d authored by Stefan Holmer's avatar Stefan Holmer

Adds a motion compensated temporal denoiser to the encoder.

Some refactoring in rdopt.c and pickinter.c.

Change-Id: I4f50020eb3313c37f4d441d708fedcaf219d3038
parent c21f53a5
......@@ -47,6 +47,7 @@ Advanced options:
${toggle_small} favor smaller size over speed
${toggle_postproc_visualizer} macro block / block level visualizers
${toggle_multi_res_encoding} enable multiple-resolution encoding
${toggle_temporal_denoising} enable temporal denoising and disable the spatial denoiser
Codecs:
Codecs can be selectively enabled or disabled individually, or by family:
......@@ -165,6 +166,7 @@ enable md5
enable spatial_resampling
enable multithread
enable os_support
enable temporal_denoising
[ -d ${source_path}/../include ] && enable alt_tree_layout
for d in vp8; do
......@@ -263,6 +265,7 @@ CONFIG_LIST="
os_support
unit_tests
multi_res_encoding
temporal_denoising
"
CMDLINE_SELECT="
extra_warnings
......@@ -307,6 +310,7 @@ CMDLINE_SELECT="
postproc_visualizer
unit_tests
multi_res_encoding
temporal_denoising
"
process_cmdline() {
......
......@@ -37,7 +37,6 @@ static void update_mode_info_border(MODE_INFO *mi, int rows, int cols)
void vp8_de_alloc_frame_buffers(VP8_COMMON *oci)
{
int i;
for (i = 0; i < NUM_YV12_BUFFERS; i++)
vp8_yv12_de_alloc_frame_buffer(&oci->yv12_fb[i]);
......
......@@ -215,6 +215,12 @@ typedef struct macroblockd
MODE_INFO *mode_info_context;
int mode_info_stride;
#if CONFIG_TEMPORAL_DENOISING
MB_PREDICTION_MODE best_sse_inter_mode;
int_mv best_sse_mv;
unsigned char need_to_clamp_best_mvs;
#endif
FRAME_TYPE frame_type;
int up_available;
......
......@@ -362,6 +362,7 @@ void vp8_deblock(YV12_BUFFER_CONFIG *source,
vp8_post_proc_down_and_across(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
}
#if !(CONFIG_TEMPORAL_DENOISING)
void vp8_de_noise(YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *post,
int q,
......@@ -398,6 +399,7 @@ void vp8_de_noise(YV12_BUFFER_CONFIG *source,
source->uv_width - 4, ppl);
}
#endif
double vp8_gaussian(double sigma, double mu, double x)
{
......
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "denoising.h"
#include "vp8/common/reconinter.h"
#include "vpx/vpx_integer.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_rtcd.h"
const unsigned int NOISE_MOTION_THRESHOLD = 20*20;
const unsigned int NOISE_DIFF2_THRESHOLD = 75;
// SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming var(noise) ~= 100.
const unsigned int SSE_DIFF_THRESHOLD = 16*16*20;
const unsigned int SSE_THRESHOLD = 16*16*40;
static __inline uint8_t blend(uint8_t state, uint8_t sample, uint8_t factor_q8)
{
return (uint8_t)(
(((uint16_t)factor_q8 * ((uint16_t)state) + // Q8
(uint16_t)(256 - factor_q8) * ((uint16_t)sample)) + 128) // Q8
>> 8);
}
static unsigned int denoiser_motion_compensate(YV12_BUFFER_CONFIG* src,
YV12_BUFFER_CONFIG* dst,
MACROBLOCK* x,
unsigned int best_sse,
unsigned int zero_mv_sse,
int recon_yoffset,
int recon_uvoffset)
{
MACROBLOCKD filter_xd = x->e_mbd;
int mv_col;
int mv_row;
int sse_diff = zero_mv_sse - best_sse;
// Compensate the running average.
filter_xd.pre.y_buffer = src->y_buffer + recon_yoffset;
filter_xd.pre.u_buffer = src->u_buffer + recon_uvoffset;
filter_xd.pre.v_buffer = src->v_buffer + recon_uvoffset;
// Write the compensated running average to the destination buffer.
filter_xd.dst.y_buffer = dst->y_buffer + recon_yoffset;
filter_xd.dst.u_buffer = dst->u_buffer + recon_uvoffset;
filter_xd.dst.v_buffer = dst->v_buffer + recon_uvoffset;
// Use the best MV for the compensation.
filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
filter_xd.mode_info_context->mbmi.mode = filter_xd.best_sse_inter_mode;
filter_xd.mode_info_context->mbmi.mv = filter_xd.best_sse_mv;
filter_xd.mode_info_context->mbmi.need_to_clamp_mvs =
filter_xd.need_to_clamp_best_mvs;
mv_col = filter_xd.best_sse_mv.as_mv.col;
mv_row = filter_xd.best_sse_mv.as_mv.row;
if (filter_xd.mode_info_context->mbmi.mode <= B_PRED ||
(mv_row*mv_row + mv_col*mv_col <= NOISE_MOTION_THRESHOLD &&
sse_diff < SSE_DIFF_THRESHOLD))
{
// Handle intra blocks as referring to last frame with zero motion and
// let the absolute pixel difference affect the filter factor.
// Also consider small amount of motion as being random walk due to noise,
// if it doesn't mean that we get a much bigger error.
// Note that any changes to the mode info only affects the denoising.
filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
filter_xd.mode_info_context->mbmi.mode = ZEROMV;
filter_xd.mode_info_context->mbmi.mv.as_int = 0;
x->e_mbd.best_sse_inter_mode = ZEROMV;
x->e_mbd.best_sse_mv.as_int = 0;
best_sse = zero_mv_sse;
}
if (!x->skip)
{
vp8_build_inter_predictors_mb(&filter_xd);
}
else
{
vp8_build_inter16x16_predictors_mb(&filter_xd,
filter_xd.dst.y_buffer,
filter_xd.dst.u_buffer,
filter_xd.dst.v_buffer,
filter_xd.dst.y_stride,
filter_xd.dst.uv_stride);
}
return best_sse;
}
static void denoiser_filter(YV12_BUFFER_CONFIG* mc_running_avg,
YV12_BUFFER_CONFIG* running_avg,
MACROBLOCK* signal,
unsigned int motion_magnitude2,
int y_offset,
int uv_offset)
{
unsigned char* sig = signal->thismb;
int sig_stride = 16;
unsigned char* mc_running_avg_y = mc_running_avg->y_buffer + y_offset;
int mc_avg_y_stride = mc_running_avg->y_stride;
unsigned char* running_avg_y = running_avg->y_buffer + y_offset;
int avg_y_stride = running_avg->y_stride;
int r, c;
for (r = 0; r < 16; r++)
{
for (c = 0; c < 16; c++)
{
int diff;
int absdiff = 0;
unsigned int filter_coefficient;
absdiff = sig[c] - mc_running_avg_y[c];
absdiff = absdiff > 0 ? absdiff : -absdiff;
assert(absdiff >= 0 && absdiff < 256);
filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3));
// Allow some additional filtering of static blocks, or blocks with very
// small motion vectors.
filter_coefficient += filter_coefficient / (3 + (motion_magnitude2 >> 3));
filter_coefficient = filter_coefficient > 255 ? 255 : filter_coefficient;
running_avg_y[c] = blend(mc_running_avg_y[c], sig[c], filter_coefficient);
diff = sig[c] - running_avg_y[c];
if (diff * diff < NOISE_DIFF2_THRESHOLD)
{
// Replace with mean to suppress the noise.
sig[c] = running_avg_y[c];
}
else
{
// Replace the filter state with the signal since the change in this
// pixel isn't classified as noise.
running_avg_y[c] = sig[c];
}
}
sig += sig_stride;
mc_running_avg_y += mc_avg_y_stride;
running_avg_y += avg_y_stride;
}
}
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height)
{
assert(denoiser);
denoiser->yv12_running_avg.flags = 0;
if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg), width,
height, VP8BORDERINPIXELS) < 0)
{
vp8_denoiser_free(denoiser);
return 1;
}
denoiser->yv12_mc_running_avg.flags = 0;
if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
height, VP8BORDERINPIXELS) < 0)
{
vp8_denoiser_free(denoiser);
return 1;
}
vpx_memset(denoiser->yv12_running_avg.buffer_alloc, 0,
denoiser->yv12_running_avg.frame_size);
vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
denoiser->yv12_mc_running_avg.frame_size);
return 0;
}
void vp8_denoiser_free(VP8_DENOISER *denoiser)
{
assert(denoiser);
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg);
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
}
void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
MACROBLOCK *x,
unsigned int best_sse,
unsigned int zero_mv_sse,
int recon_yoffset,
int recon_uvoffset) {
int mv_row;
int mv_col;
unsigned int motion_magnitude2;
// Motion compensate the running average.
best_sse = denoiser_motion_compensate(&denoiser->yv12_running_avg,
&denoiser->yv12_mc_running_avg,
x,
best_sse,
zero_mv_sse,
recon_yoffset,
recon_uvoffset);
mv_row = x->e_mbd.best_sse_mv.as_mv.row;
mv_col = x->e_mbd.best_sse_mv.as_mv.col;
motion_magnitude2 = mv_row*mv_row + mv_col*mv_col;
if (best_sse > SSE_THRESHOLD ||
motion_magnitude2 > 8 * NOISE_MOTION_THRESHOLD)
{
// No filtering of this block since it differs too much from the predictor,
// or the motion vector magnitude is considered too big.
vp8_copy_mem16x16(x->thismb, 16,
denoiser->yv12_running_avg.y_buffer + recon_yoffset,
denoiser->yv12_running_avg.y_stride);
return;
}
// Filter.
denoiser_filter(&denoiser->yv12_mc_running_avg,
&denoiser->yv12_running_avg,
x,
motion_magnitude2,
recon_yoffset,
recon_uvoffset);
}
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VP8_ENCODER_DENOISING_H_
#define VP8_ENCODER_DENOISING_H_
#include "block.h"
typedef struct vp8_denoiser
{
YV12_BUFFER_CONFIG yv12_running_avg;
YV12_BUFFER_CONFIG yv12_mc_running_avg;
} VP8_DENOISER;
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height);
void vp8_denoiser_free(VP8_DENOISER *denoiser);
void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
MACROBLOCK *x,
unsigned int best_sse,
unsigned int zero_mv_sse,
int recon_yoffset,
int recon_uvoffset);
#endif // VP8_ENCODER_DENOISING_H_
......@@ -1179,6 +1179,13 @@ int vp8cx_encode_inter_macroblock
else
x->encode_breakout = cpi->oxcf.encode_breakout;
#if CONFIG_TEMPORAL_DENOISING
// Reset the best sse mode/mv for each macroblock.
x->e_mbd.best_sse_inter_mode = 0;
x->e_mbd.best_sse_mv.as_int = 0;
x->e_mbd.need_to_clamp_best_mvs = 0;
#endif
if (cpi->sf.RD)
{
int zbin_mode_boost_enabled = cpi->zbin_mode_boost_enabled;
......
......@@ -1680,6 +1680,17 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf)
cpi->alt_ref_source = NULL;
cpi->is_src_frame_alt_ref = 0;
#if CONFIG_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity)
{
if (!cpi->denoiser.yv12_mc_running_avg.buffer_alloc)
{
int width = (cpi->oxcf.Width + 15) & ~15;
int height = (cpi->oxcf.Height + 15) & ~15;
vp8_denoiser_allocate(&cpi->denoiser, width, height);
}
}
#endif
#if 0
// Experimental RD Code
......@@ -2314,6 +2325,9 @@ void vp8_remove_compressor(VP8_COMP **ptr)
vp8cx_remove_encoder_threads(cpi);
#endif
#if CONFIG_TEMPORAL_DENOISING
vp8_denoiser_free(&cpi->denoiser);
#endif
dealloc_compressor_data(cpi);
vpx_free(cpi->mb.ss);
vpx_free(cpi->tok);
......@@ -3133,7 +3147,12 @@ void vp8_loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
}
vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
#if CONFIG_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity)
{
vp8_yv12_extend_frame_borders(&cpi->denoiser.yv12_running_avg);
}
#endif
}
static void encode_frame_to_data_rate
......@@ -3589,7 +3608,7 @@ static void encode_frame_to_data_rate
scale_and_extend_source(cpi->un_scaled_source, cpi);
#if !(CONFIG_REALTIME_ONLY) && CONFIG_POSTPROC
#if !(CONFIG_REALTIME_ONLY) && CONFIG_POSTPROC && !(CONFIG_TEMPORAL_DENOISING)
if (cpi->oxcf.noise_sensitivity > 0)
{
......
......@@ -28,6 +28,9 @@
#include "mcomp.h"
#include "vp8/common/findnearmv.h"
#include "lookahead.h"
#if CONFIG_TEMPORAL_DENOISING
#include "vp8/encoder/denoising.h"
#endif
//#define SPEEDSTATS 1
#define MIN_GF_INTERVAL 4
......@@ -661,6 +664,10 @@ typedef struct VP8_COMP
int droppable;
#if CONFIG_TEMPORAL_DENOISING
VP8_DENOISER denoiser;
#endif
// Coding layer state variables
unsigned int current_layer;
LAYER_CONTEXT layer_context[MAX_LAYERS];
......
......@@ -24,6 +24,9 @@
#include "mcomp.h"
#include "rdopt.h"
#include "vpx_mem/vpx_mem.h"
#if CONFIG_TEMPORAL_DENOISING
#include "denoising.h"
#endif
extern int VP8_UVSSE(MACROBLOCK *x);
......@@ -450,6 +453,48 @@ void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd, int *dissim,
}
#endif
static void check_for_encode_breakout(unsigned int sse, MACROBLOCK* x)
{
if (sse < x->encode_breakout)
{
// Check u and v to make sure skip is ok
int sse2 = 0;
sse2 = VP8_UVSSE(x);
if (sse2 * 2 < x->encode_breakout)
x->skip = 1;
else
x->skip = 0;
}
}
static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, VP8_COMP *cpi, MACROBLOCK *x)
{
MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;
int this_rd;
/* Exit early and don't compute the distortion if this macroblock
* is marked inactive. */
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
{
*sse = 0;
*distortion2 = 0;
x->skip = 1;
return INT_MAX;
}
if((this_mode != NEWMV) ||
!(cpi->sf.half_pixel_search) || cpi->common.full_pixel==1)
*distortion2 = get_inter_mbpred_error(x,
&cpi->fn_ptr[BLOCK_16X16],
sse, mv);
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2);
check_for_encode_breakout(*sse, x);
return this_rd;
}
void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int recon_uvoffset, int *returnrate,
......@@ -476,7 +521,10 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int distortion2;
int bestsme = INT_MAX;
int best_mode_index = 0;
unsigned int sse = INT_MAX, best_sse = INT_MAX;
unsigned int sse = INT_MAX, best_rd_sse = INT_MAX;
#if CONFIG_TEMPORAL_DENOISING
unsigned int zero_mv_sse = 0, best_sse = INT_MAX;
#endif
int_mv mvp;
......@@ -488,9 +536,6 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int ref_frame_map[4];
int sign_bias = 0;
int have_subp_search = cpi->sf.half_pixel_search; /* In real-time mode,
when Speed >= 15, no sub-pixel search. */
#if CONFIG_MULTI_RES_ENCODING
int dissim = INT_MAX;
int parent_ref_frame = 0;
......@@ -657,7 +702,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
{
case B_PRED:
/* Pass best so far to pick_intra4x4mby_modes to use as breakout */
distortion2 = best_sse;
distortion2 = best_rd_sse;
pick_intra4x4mby_modes(x, &rate, &distortion2);
if (distortion2 == INT_MAX)
......@@ -905,43 +950,38 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
x->e_mbd.mode_info_context->mbmi.mv.as_int =
mode_mv[this_mode].as_int;
/* Exit early and don't compute the distortion if this macroblock
* is marked inactive. */
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
{
sse = 0;
distortion2 = 0;
x->skip = 1;
break;
}
if((this_mode != NEWMV) ||
!(have_subp_search) || cpi->common.full_pixel==1)
distortion2 = get_inter_mbpred_error(x,
&cpi->fn_ptr[BLOCK_16X16],
&sse, mode_mv[this_mode]);
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
if (sse < x->encode_breakout)
{
// Check u and v to make sure skip is ok
int sse2 = 0;
sse2 = VP8_UVSSE(x);
if (sse2 * 2 < x->encode_breakout)
x->skip = 1;
else
x->skip = 0;
}
this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
break;
default:
break;
}
#if CONFIG_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity)
{
// Store for later use by denoiser.
if (this_mode == ZEROMV &&
x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
{
zero_mv_sse = sse;
}
// Store the best NEWMV in x for later use in the denoiser.
// We are restricted to the LAST_FRAME since the denoiser only keeps
// one filter state.
if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV &&
x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
{
best_sse = sse;
x->e_mbd.best_sse_inter_mode = NEWMV;
x->e_mbd.best_sse_mv = x->e_mbd.mode_info_context->mbmi.mv;
x->e_mbd.need_to_clamp_best_mvs =
x->e_mbd.mode_info_context->mbmi.need_to_clamp_mvs;
}
}
#endif
if (this_rd < best_rd || x->skip)
{
// Note index of best mode
......@@ -949,7 +989,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
*returnrate = rate2;
*returndistortion = distortion2;
best_sse = sse;
best_rd_sse = sse;
best_rd = this_rd;
vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
sizeof(MB_MODE_INFO));
......@@ -1011,6 +1051,43 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
cpi->error_bins[this_rdbin] ++;
}
#if CONFIG_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity)
{
if (x->e_mbd.best_sse_inter_mode == DC_PRED) {
// No best MV found.
x->e_mbd.best_sse_inter_mode = best_mbmode.mode;
x->e_mbd.best_sse_mv = best_mbmode.mv;
x->e_mbd.need_to_clamp_best_mvs = best_mbmode.need_to_clamp_mvs;
best_sse = best_rd_sse;
}
vp8_denoiser_denoise_mb(&cpi->denoiser, x, best_sse, zero_mv_sse,
recon_yoffset, recon_uvoffset);
// Reevaluate ZEROMV after denoising.
if (best_mbmode.ref_frame == INTRA_FRAME)
{
int this_rd = 0;
rate2 = 0;
distortion2 = 0;
x->e_mbd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
rate2 += x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
this_mode = ZEROMV;
rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
x->e_mbd.mode_info_context->mbmi.mode = this_mode;
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
if (this_rd < best_rd || x->skip)
{
vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
sizeof(MB_MODE_INFO));
}
}
}
#endif
if (cpi->is_src_frame_alt_ref &&
(best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
{
......
This diff is collapsed.
......@@ -183,13 +183,19 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
#if CONFIG_TEMPORAL_DENOISING
RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 1);
#endif
#if !(CONFIG_REALTIME_ONLY)
RANGE_CHECK(vp8_cfg, encoding_mode, VP8_BEST_QUALITY_ENCODING, VP8_REAL_TIME_ENCODING);
#if !(CONFIG_TEMPORAL_DENOISING)
RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
#endif
#else
RANGE_CHECK(vp8_cfg, encoding_mode, VP8_REAL_TIME_ENCODING, VP8_REAL_TIME_ENCODING);
#if !(CONFIG_TEMPORAL_DENOISING)
RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0);
#endif
#endif
RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
......
......@@ -47,6 +47,8 @@ VP8_CX_SRCS-yes += encoder/firstpass.c
VP8_CX_SRCS-yes += encoder/block.h
VP8_CX_SRCS-yes += encoder/boolhuff.h
VP8_CX_SRCS-yes += encoder/bitstream.h
VP8_CX_SRCS-$(CONFIG_TEMPORAL_DENOISING) += encoder/denoising.h
VP8_CX_SRCS-$(CONFIG_TEMPORAL_DENOISING) += encoder/denoising.c
VP8_CX_SRCS-yes += encoder/encodeintra.h
VP8_CX_SRCS-yes += encoder/encodemb.h
VP8_CX_SRCS-yes += encoder/encodemv.h
......
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