summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorMarco <marpan@google.com>2017-07-10 17:38:03 -0700
committerMarco <marpan@google.com>2017-07-11 11:27:04 -0700
commit3818a3723b630252973ca85d9fc6b5dd7f8437dd (patch)
tree76ce0c3a69c05be4021f345fd1f976533467d1aa /vp9
parent4b78c6e6f70809cac27536b181ac9ff1f8759928 (diff)
downloadlibvpx-3818a3723b630252973ca85d9fc6b5dd7f8437dd.tar
libvpx-3818a3723b630252973ca85d9fc6b5dd7f8437dd.tar.gz
libvpx-3818a3723b630252973ca85d9fc6b5dd7f8437dd.tar.bz2
libvpx-3818a3723b630252973ca85d9fc6b5dd7f8437dd.zip
vp9: Fix to SVC and denoising for fixed pattern case.
For fixed pattern SVC: keep track of denoised last_frame buffer for base temporal layer, and if alt_ref is updated on middle/upper temporal layers, force an update to denoised last_frame buffer. This allows for improved denoising on top temporal layers. Change-Id: Icbd08566027d4d2eabc024d3b7a0d959d2f8c18b
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_denoiser.c45
-rw-r--r--vp9/encoder/vp9_denoiser.h13
-rw-r--r--vp9/encoder/vp9_encoder.c14
3 files changed, 55 insertions, 17 deletions
diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c
index e8356155f..a4da44408 100644
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -420,12 +420,23 @@ static void swap_frame_buffer(YV12_BUFFER_CONFIG *const dest,
src->y_buffer = tmp_buf;
}
-void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
- YV12_BUFFER_CONFIG src,
- FRAME_TYPE frame_type,
- int refresh_golden_frame,
- int refresh_last_frame, int resized,
- int svc_base_is_key) {
+void vp9_denoise_init_svc(VP9_COMP *cpi) {
+ // For fixed pattern SVC, on base temporal layer. Note we only denoise
+ // higher spatial layer for SVC.
+ if (cpi->svc.temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
+ cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1 &&
+ cpi->svc.temporal_layer_id == 0) {
+ VP9_DENOISER *denoiser = &cpi->denoiser;
+ copy_frame(&denoiser->running_avg_y[LAST_FRAME],
+ &denoiser->running_avg_y[GOLDEN_FRAME]);
+ }
+}
+
+void vp9_denoiser_update_frame_info(
+ VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type,
+ int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame,
+ int resized, int svc_base_is_key, int svc_fixed_pattern,
+ int temporal_layer_id) {
// Copy source into denoised reference buffers on KEY_FRAME or
// if the just encoded frame was resized. For SVC, copy source if the base
// spatial layer was key frame.
@@ -440,12 +451,15 @@ void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
}
// If more than one refresh occurs, must copy frame buffer.
- if (refresh_golden_frame + refresh_last_frame > 1) {
+ if (refresh_golden_frame + refresh_last_frame + refresh_alt_ref_frame > 1) {
if (refresh_golden_frame) {
copy_frame(&denoiser->running_avg_y[GOLDEN_FRAME],
&denoiser->running_avg_y[INTRA_FRAME]);
}
- if (refresh_last_frame) {
+ // For fixed pattern SVC: update denoised last_frame if alt_ref is
+ // refreshed, only for non-zero temporal layer.
+ if (refresh_last_frame ||
+ (refresh_alt_ref_frame && svc_fixed_pattern && temporal_layer_id > 0)) {
copy_frame(&denoiser->running_avg_y[LAST_FRAME],
&denoiser->running_avg_y[INTRA_FRAME]);
}
@@ -454,11 +468,24 @@ void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
swap_frame_buffer(&denoiser->running_avg_y[GOLDEN_FRAME],
&denoiser->running_avg_y[INTRA_FRAME]);
}
- if (refresh_last_frame) {
+ // For fixed pattern SVC: update denoised last_frame if alt_ref is
+ // refreshed, only for non-zero temporal layer.
+ if (refresh_last_frame ||
+ (refresh_alt_ref_frame && svc_fixed_pattern && temporal_layer_id > 0)) {
swap_frame_buffer(&denoiser->running_avg_y[LAST_FRAME],
&denoiser->running_avg_y[INTRA_FRAME]);
}
}
+ // For fixed pattern SVC we need to keep track of denoised last_frame for base
+ // temporal layer (since alt_ref refresh may update denoised last_frame on
+ // the upper/middle temporal layers).We do this by copying the current
+ // denoised last into the denoised golden_frame, for temporal_layer_id = 0.
+ // For the fixed pattern SVC golden is always spatial reference and is never
+ // used for denoising, so we can use it to keep track of denoised last_frame.
+ if (svc_fixed_pattern && temporal_layer_id == 0) {
+ copy_frame(&denoiser->running_avg_y[GOLDEN_FRAME],
+ &denoiser->running_avg_y[LAST_FRAME]);
+ }
}
void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) {
diff --git a/vp9/encoder/vp9_denoiser.h b/vp9/encoder/vp9_denoiser.h
index 727ce8538..7ed20856e 100644
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -62,12 +62,13 @@ typedef struct {
struct VP9_COMP;
-void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
- YV12_BUFFER_CONFIG src,
- FRAME_TYPE frame_type,
- int refresh_golden_frame,
- int refresh_last_frame, int resized,
- int svc_base_is_key);
+void vp9_denoise_init_svc(struct VP9_COMP *cpi);
+
+void vp9_denoiser_update_frame_info(
+ VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type,
+ int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame,
+ int resized, int svc_base_is_key, int svc_fixed_pattern,
+ int temporal_layer_id);
void vp9_denoiser_denoise(struct VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
int mi_col, BLOCK_SIZE bs, PICK_MODE_CONTEXT *ctx,
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index b7addd202..fc6d75590 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2806,17 +2806,21 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
cpi->denoiser.denoising_level > kDenLowLow) {
int svc_base_is_key = 0;
+ int svc_fixed_pattern = 0;
if (cpi->use_svc) {
int layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id,
cpi->svc.temporal_layer_id,
cpi->svc.number_temporal_layers);
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
svc_base_is_key = lc->is_key_frame;
+ svc_fixed_pattern = (cpi->svc.temporal_layering_mode !=
+ VP9E_TEMPORAL_LAYERING_MODE_BYPASS);
}
vp9_denoiser_update_frame_info(
&cpi->denoiser, *cpi->Source, cpi->common.frame_type,
- cpi->refresh_golden_frame, cpi->refresh_last_frame, cpi->resize_pending,
- svc_base_is_key);
+ cpi->refresh_alt_ref_frame, cpi->refresh_golden_frame,
+ cpi->refresh_last_frame, cpi->resize_pending, svc_base_is_key,
+ svc_fixed_pattern, cpi->svc.temporal_layer_id);
}
#endif
if (is_one_pass_cbr_svc(cpi)) {
@@ -3448,6 +3452,12 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size,
vp9_update_noise_estimate(cpi);
+#if CONFIG_VP9_TEMPORAL_DENOISING
+ if (cpi->oxcf.noise_sensitivity > 0 && cpi->use_svc &&
+ cpi->denoiser.denoising_level > kDenLowLow)
+ vp9_denoise_init_svc(cpi);
+#endif
+
// Scene detection is always used for VBR mode or screen-content case.
// For other cases (e.g., CBR mode) use it for 5 <= speed < 8 for now
// (need to check encoding time cost for doing this for speed 8).