summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorHui Su <huisu@google.com>2017-08-10 15:05:20 -0700
committerHui Su <huisu@google.com>2017-09-14 16:20:29 +0000
commitc3a6943c16f701f5f344692e1a1af3a90f23d791 (patch)
treecaa73d84dcce1e200b1c7345c935e101900fffb2 /vp9
parentd49a1a5329ea43968faaf295f7da5f72b28f971e (diff)
downloadlibvpx-c3a6943c16f701f5f344692e1a1af3a90f23d791.tar
libvpx-c3a6943c16f701f5f344692e1a1af3a90f23d791.tar.gz
libvpx-c3a6943c16f701f5f344692e1a1af3a90f23d791.tar.bz2
libvpx-c3a6943c16f701f5f344692e1a1af3a90f23d791.zip
VP9 level targeting: add a new AUTO mode
In the new AUTO mode, restrict the minimum alt-ref interval and max column tiles adaptively based on picture size, while not applying any rate control constraints. This mode aims to produce encodings that fit into levels corresponding to the source picture size, with minimum compression quality lost. However, the bitstream is not guaranteed to be level compatible, e.g., the average bitrate may exceed level limit. BUG=b/64451920 Change-Id: I02080b169cbbef4ab2e08c0df4697ce894aad83c
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_encoder.c8
-rw-r--r--vp9/encoder/vp9_encoder.h13
-rw-r--r--vp9/encoder/vp9_ethread.c7
-rw-r--r--vp9/encoder/vp9_ratectrl.c17
-rw-r--r--vp9/vp9_cx_iface.c2
5 files changed, 46 insertions, 1 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 870ba9fce..27bc0188e 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1209,6 +1209,14 @@ static void set_tile_limits(VP9_COMP *cpi) {
clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
cm->log2_tile_rows = cpi->oxcf.tile_rows;
}
+
+ if (cpi->oxcf.target_level == LEVEL_AUTO) {
+ const uint32_t pic_size = cpi->common.width * cpi->common.height;
+ const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size);
+ if (cm->log2_tile_cols > level_tile_cols) {
+ cm->log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
+ }
+ }
}
static void update_frame_size(VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index d735fe08b..34a175a74 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -360,6 +360,7 @@ typedef struct IMAGE_STAT {
typedef enum {
LEVEL_UNKNOWN = 0,
+ LEVEL_AUTO = 1,
LEVEL_1 = 10,
LEVEL_1_1 = 11,
LEVEL_2 = 20,
@@ -913,6 +914,18 @@ static INLINE int get_level_index(VP9_LEVEL level) {
return -1;
}
+// Return the log2 value of max column tiles corresponding to the level that
+// the picture size fits into.
+static INLINE int log_tile_cols_from_picsize_level(uint32_t pic_size) {
+ int i;
+ for (i = LEVEL_1; i < LEVEL_MAX; ++i) {
+ if (vp9_level_defs[i].max_luma_picture_size > pic_size) {
+ return get_msb(vp9_level_defs[i].max_col_tiles);
+ }
+ }
+ return INT_MAX;
+}
+
VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec);
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
diff --git a/vp9/encoder/vp9_ethread.c b/vp9/encoder/vp9_ethread.c
index 5028eef0f..d182ec765 100644
--- a/vp9/encoder/vp9_ethread.c
+++ b/vp9/encoder/vp9_ethread.c
@@ -64,6 +64,13 @@ static int get_max_tile_cols(VP9_COMP *cpi) {
vp9_get_tile_n_bits(mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
log2_tile_cols =
clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
+ if (cpi->oxcf.target_level == LEVEL_AUTO) {
+ const uint32_t pic_size = cpi->common.width * cpi->common.height;
+ const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size);
+ if (log2_tile_cols > level_tile_cols) {
+ log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
+ }
+ }
return (1 << log2_tile_cols);
}
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 82e4b1df1..93de41e86 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1851,6 +1851,23 @@ void vp9_rc_set_gf_interval_range(const VP9_COMP *const cpi,
// Clamp min to max
rc->min_gf_interval = VPXMIN(rc->min_gf_interval, rc->max_gf_interval);
+
+ if (oxcf->target_level == LEVEL_AUTO) {
+ const uint32_t pic_size = cpi->common.width * cpi->common.height;
+ int i;
+ for (i = LEVEL_1; i < LEVEL_MAX; ++i) {
+ if (vp9_level_defs[i].max_luma_picture_size > pic_size) {
+ if (rc->min_gf_interval <=
+ (int)vp9_level_defs[i].min_altref_distance) {
+ rc->min_gf_interval =
+ (int)vp9_level_defs[i].min_altref_distance + 1;
+ rc->max_gf_interval =
+ VPXMAX(rc->max_gf_interval, rc->min_gf_interval);
+ }
+ break;
+ }
+ }
+ }
}
}
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 7b6aa4bf5..db18862c7 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -213,7 +213,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
level != LEVEL_4 && level != LEVEL_4_1 && level != LEVEL_5 &&
level != LEVEL_5_1 && level != LEVEL_5_2 && level != LEVEL_6 &&
level != LEVEL_6_1 && level != LEVEL_6_2 && level != LEVEL_UNKNOWN &&
- level != LEVEL_MAX)
+ level != LEVEL_AUTO && level != LEVEL_MAX)
ERROR("target_level is invalid");
}