Index: source/libvpx/vp9/encoder/vp9_svc_layercontext.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_svc_layercontext.c (revision 292608) |
+++ source/libvpx/vp9/encoder/vp9_svc_layercontext.c (working copy) |
@@ -14,6 +14,8 @@ |
#include "vp9/encoder/vp9_svc_layercontext.h" |
#include "vp9/encoder/vp9_extend.h" |
+#define SMALL_FRAME_FB_IDX 7 |
+ |
void vp9_init_layer_context(VP9_COMP *const cpi) { |
SVC *const svc = &cpi->svc; |
const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
@@ -28,6 +30,25 @@ |
layer_end = svc->number_temporal_layers; |
} else { |
layer_end = svc->number_spatial_layers; |
+ |
+ if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) { |
+ if (vp9_realloc_frame_buffer(&cpi->svc.empty_frame.img, |
+ cpi->common.width, cpi->common.height, |
+ cpi->common.subsampling_x, |
+ cpi->common.subsampling_y, |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ cpi->common.use_highbitdepth, |
+#endif |
+ VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL)) |
+ vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, |
+ "Failed to allocate empty frame for multiple frame " |
+ "contexts"); |
+ |
+ vpx_memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80, |
+ cpi->svc.empty_frame.img.buffer_alloc_sz); |
+ cpi->svc.empty_frame_width = cpi->common.width; |
+ cpi->svc.empty_frame_height = cpi->common.height; |
+ } |
} |
for (layer = 0; layer < layer_end; ++layer) { |
@@ -310,6 +331,47 @@ |
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height, |
lc->scaling_factor_num, lc->scaling_factor_den, |
&width, &height); |
+ |
+ // Workaround for multiple frame contexts. In some frames we can't use prev_mi |
+ // since its previous frame could be changed during decoding time. The idea is |
+ // we put a empty invisible frame in front of them, then we will not use |
+ // prev_mi when encoding these frames. |
+ if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 && |
+ cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE) { |
+ if ((cpi->svc.number_temporal_layers > 1 && |
+ cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) || |
+ (cpi->svc.number_spatial_layers > 1 && |
+ cpi->svc.spatial_layer_id == 0)) { |
+ struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead, 0); |
+ |
+ if (buf != NULL) { |
+ cpi->svc.empty_frame.ts_start = buf->ts_start; |
+ cpi->svc.empty_frame.ts_end = buf->ts_end; |
+ cpi->svc.encode_empty_frame_state = ENCODING; |
+ cpi->common.show_frame = 0; |
+ cpi->ref_frame_flags = 0; |
+ cpi->common.frame_type = INTER_FRAME; |
+ cpi->lst_fb_idx = |
+ cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX; |
+ |
+ // Gradually make the empty frame smaller to save bits. Make it half of |
+ // its previous size because of the scaling factor restriction. |
+ cpi->svc.empty_frame_width >>= 1; |
+ cpi->svc.empty_frame_width = (cpi->svc.empty_frame_width + 1) & ~1; |
+ if (cpi->svc.empty_frame_width < 16) |
+ cpi->svc.empty_frame_width = 16; |
+ |
+ cpi->svc.empty_frame_height >>= 1; |
+ cpi->svc.empty_frame_height = (cpi->svc.empty_frame_height + 1) & ~1; |
+ if (cpi->svc.empty_frame_height < 16) |
+ cpi->svc.empty_frame_height = 16; |
+ |
+ width = cpi->svc.empty_frame_width; |
+ height = cpi->svc.empty_frame_height; |
+ } |
+ } |
+ } |
+ |
if (vp9_set_size_literal(cpi, width, height) != 0) |
return VPX_CODEC_INVALID_PARAM; |
@@ -317,7 +379,6 @@ |
cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q); |
vp9_change_config(cpi, &cpi->oxcf); |
- |
vp9_set_high_precision_mv(cpi, 1); |
cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source; |