From: Debargha Mukherjee Date: Wed, 16 Dec 2015 23:34:07 +0000 (-0800) Subject: Adding an aq mode for 360 videos X-Git-Tag: v1.6.0~440^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=02345be98674f5ae57dc9508f95aba312ad6b633;p=libvpx Adding an aq mode for 360 videos Different quality levels are used for different regions in the frame depending on how far they are vertically from the center. Specifically, three segments are used based on the mi_row index with respect number to the number of mi_rows in the frame. Change-Id: Ifc8b777bc58ea8521dffc4640360c67d99f8d381 --- diff --git a/vp9/encoder/vp9_aq_360.c b/vp9/encoder/vp9_aq_360.c new file mode 100644 index 000000000..7f937344d --- /dev/null +++ b/vp9/encoder/vp9_aq_360.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 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 + +#include "vpx_ports/mem.h" +#include "vpx_ports/system_state.h" + +#include "vp9/encoder/vp9_aq_variance.h" + +#include "vp9/common/vp9_seg_common.h" + +#include "vp9/encoder/vp9_ratectrl.h" +#include "vp9/encoder/vp9_rd.h" +#include "vp9/encoder/vp9_segmentation.h" + +#define ENERGY_MIN (-4) +#define ENERGY_MAX (1) +#define ENERGY_SPAN (ENERGY_MAX - ENERGY_MIN + 1) +#define ENERGY_IN_BOUNDS(energy)\ + assert((energy) >= ENERGY_MIN && (energy) <= ENERGY_MAX) + +static const double rate_ratio[MAX_SEGMENTS] = + {1.0, 0.75, 0.6, 0.5, 0.4, 0.3, 0.25}; + +// Sets segment id 0 for the equatorial region, 1 for temperate region +// and 2 for the polar regions +unsigned int vp9_360aq_segment_id(int mi_row, int mi_rows) { + if (mi_row < mi_rows / 8 || mi_row > mi_rows - mi_rows / 8) + return 2; + else if (mi_row < mi_rows / 4 || mi_row > mi_rows - mi_rows / 4) + return 1; + else + return 0; +} + +void vp9_360aq_frame_setup(VP9_COMP *cpi) { + VP9_COMMON *cm = &cpi->common; + struct segmentation *seg = &cm->seg; + int i; + + if (frame_is_intra_only(cm) || cm->error_resilient_mode) { + vp9_enable_segmentation(seg); + vp9_clearall_segfeatures(seg); + + seg->abs_delta = SEGMENT_DELTADATA; + + vpx_clear_system_state(); + + for (i = 0; i < MAX_SEGMENTS; ++i) { + int qindex_delta = + vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, cm->base_qindex, + rate_ratio[i], cm->bit_depth); + + // We don't allow qindex 0 in a segment if the base value is not 0. + // Q index 0 (lossless) implies 4x4 encoding only and in AQ mode a segment + // Q delta is sometimes applied without going back around the rd loop. + // This could lead to an illegal combination of partition size and q. + if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) { + qindex_delta = -cm->base_qindex + 1; + } + + // No need to enable SEG_LVL_ALT_Q for this segment. + if (rate_ratio[i] == 1.0) { + continue; + } + + vp9_set_segdata(seg, i, SEG_LVL_ALT_Q, qindex_delta); + vp9_enable_segfeature(seg, i, SEG_LVL_ALT_Q); + } + } +} diff --git a/vp9/encoder/vp9_aq_360.h b/vp9/encoder/vp9_aq_360.h new file mode 100644 index 000000000..fb861cb05 --- /dev/null +++ b/vp9/encoder/vp9_aq_360.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 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 VP9_ENCODER_VP9_AQ_360_H_ +#define VP9_ENCODER_VP9_AQ_360_H_ + +#include "vp9/encoder/vp9_encoder.h" + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned int vp9_360aq_segment_id(int mi_row, int mi_rows); +void vp9_360aq_frame_setup(VP9_COMP *cpi); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VP9_ENCODER_VP9_AQ_VARIANCE_H_ diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index c07eee969..6e999ca5e 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -33,6 +33,7 @@ #include "vp9/common/vp9_seg_common.h" #include "vp9/common/vp9_tile_common.h" +#include "vp9/encoder/vp9_aq_360.h" #include "vp9/encoder/vp9_aq_complexity.h" #include "vp9/encoder/vp9_aq_cyclicrefresh.h" #include "vp9/encoder/vp9_aq_variance.h" @@ -221,7 +222,8 @@ static void set_offsets(VP9_COMP *cpi, const TileInfo *const tile, // Setup segment ID. if (seg->enabled) { - if (cpi->oxcf.aq_mode != VARIANCE_AQ) { + if (cpi->oxcf.aq_mode != VARIANCE_AQ && + cpi->oxcf.aq_mode != EQUATOR360_AQ) { const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); @@ -1263,6 +1265,15 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); } x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id); + } else if (aq_mode == EQUATOR360_AQ) { + if (cm->frame_type == KEY_FRAME) { + mbmi->segment_id = vp9_360aq_segment_id(mi_row, cm->mi_rows); + } else { + const uint8_t *const map = cm->seg.update_map ? cpi->segmentation_map + : cm->last_frame_seg_map; + mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); + } + x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id); } else if (aq_mode == COMPLEXITY_AQ) { x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id); } else if (aq_mode == CYCLIC_REFRESH_AQ) { @@ -1719,7 +1730,8 @@ static void update_state_rt(VP9_COMP *cpi, ThreadData *td, // For in frame complexity AQ or variance AQ, copy segment_id from // segmentation_map. if (cpi->oxcf.aq_mode == COMPLEXITY_AQ || - cpi->oxcf.aq_mode == VARIANCE_AQ ) { + cpi->oxcf.aq_mode == VARIANCE_AQ || + cpi->oxcf.aq_mode == EQUATOR360_AQ) { const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e4681f601..609344dcd 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -36,6 +36,7 @@ #include "vp9/common/vp9_reconintra.h" #include "vp9/common/vp9_tile_common.h" +#include "vp9/encoder/vp9_aq_360.h" #include "vp9/encoder/vp9_aq_complexity.h" #include "vp9/encoder/vp9_aq_cyclicrefresh.h" #include "vp9/encoder/vp9_aq_variance.h" @@ -3334,6 +3335,8 @@ static void encode_without_recode_loop(VP9_COMP *cpi, // exclusive. if (cpi->oxcf.aq_mode == VARIANCE_AQ) { vp9_vaq_frame_setup(cpi); + } else if (cpi->oxcf.aq_mode == EQUATOR360_AQ) { + vp9_360aq_frame_setup(cpi); } else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) { vp9_setup_in_frame_q_adj(cpi); } else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) { @@ -3464,6 +3467,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // exclusive. if (cpi->oxcf.aq_mode == VARIANCE_AQ) { vp9_vaq_frame_setup(cpi); + } else if (cpi->oxcf.aq_mode == EQUATOR360_AQ) { + vp9_360aq_frame_setup(cpi); } else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) { vp9_setup_in_frame_q_adj(cpi); } diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index f6d8931fe..76c36f4e5 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -112,6 +112,7 @@ typedef enum { VARIANCE_AQ = 1, COMPLEXITY_AQ = 2, CYCLIC_REFRESH_AQ = 3, + EQUATOR360_AQ = 4, AQ_MODE_COUNT // This should always be the last member of the enum } AQ_MODE; diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk index de688bf48..c7a334d86 100644 --- a/vp9/vp9cx.mk +++ b/vp9/vp9cx.mk @@ -75,6 +75,8 @@ VP9_CX_SRCS-yes += encoder/vp9_tokenize.c VP9_CX_SRCS-yes += encoder/vp9_treewriter.c VP9_CX_SRCS-yes += encoder/vp9_aq_variance.c VP9_CX_SRCS-yes += encoder/vp9_aq_variance.h +VP9_CX_SRCS-yes += encoder/vp9_aq_360.c +VP9_CX_SRCS-yes += encoder/vp9_aq_360.h VP9_CX_SRCS-yes += encoder/vp9_aq_cyclicrefresh.c VP9_CX_SRCS-yes += encoder/vp9_aq_cyclicrefresh.h VP9_CX_SRCS-yes += encoder/vp9_aq_complexity.c diff --git a/vpxenc.c b/vpxenc.c index afbaeac31..db8fcafa1 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -388,7 +388,7 @@ static const arg_def_t frame_parallel_decoding = ARG_DEF( static const arg_def_t aq_mode = ARG_DEF( NULL, "aq-mode", 1, "Adaptive quantization mode (0: off (default), 1: variance 2: complexity, " - "3: cyclic refresh)"); + "3: cyclic refresh, 4: equator360)"); static const arg_def_t frame_periodic_boost = ARG_DEF( NULL, "frame-boost", 1, "Enable frame periodic boost (0: off (default), 1: on)");