Merge "vp8_change_config: fix unsigned/signed comparison"
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index 3941e16..2f1db9c 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -90,7 +90,7 @@
<< pkt->data.frame.pts;
}
- const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+ const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
// Subtract from the buffer the bits associated with a played back frame.
bits_in_buffer_model_ -= frame_size_in_bits;
diff --git a/test/level_test.cc b/test/level_test.cc
index 5b9ce41..62d0247 100644
--- a/test/level_test.cc
+++ b/test/level_test.cc
@@ -22,7 +22,9 @@
: EncoderTest(GET_PARAM(0)),
encoding_mode_(GET_PARAM(1)),
cpu_used_(GET_PARAM(2)),
- target_level_(0) {}
+ min_gf_internal_(24),
+ target_level_(0),
+ level_(0) {}
virtual ~LevelTest() {}
virtual void SetUp() {
@@ -47,6 +49,7 @@
if (video->frame() == 0) {
encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
encoder->Control(VP9E_SET_TARGET_LEVEL, target_level_);
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_gf_internal_);
if (encoding_mode_ != ::libvpx_test::kRealTime) {
encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
@@ -54,20 +57,33 @@
encoder->Control(VP8E_SET_ARNR_TYPE, 3);
}
}
+ encoder->Control(VP9E_GET_LEVEL, &level_);
+ ASSERT_LE(level_, 51);
+ ASSERT_GE(level_, 0);
}
::libvpx_test::TestMode encoding_mode_;
int cpu_used_;
+ int min_gf_internal_;
int target_level_;
+ int level_;
};
+// Test for keeping level stats only
TEST_P(LevelTest, TestTargetLevel0) {
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
- 30);
+ 40);
target_level_ = 0;
+ min_gf_internal_ = 4;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_EQ(11, level_);
+
+ cfg_.rc_target_bitrate = 1600;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_EQ(20, level_);
}
+// Test for level control being turned off
TEST_P(LevelTest, TestTargetLevel255) {
::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
30);
@@ -98,7 +114,6 @@
VP9_INSTANTIATE_TEST_CASE(LevelTest,
::testing::Values(::libvpx_test::kTwoPassGood,
- ::libvpx_test::kOnePassGood,
- ::libvpx_test::kRealTime),
+ ::libvpx_test::kOnePassGood),
::testing::Range(0, 9));
} // namespace
diff --git a/vp8/encoder/denoising.c b/vp8/encoder/denoising.c
index cff99c0..26ce120 100644
--- a/vp8/encoder/denoising.c
+++ b/vp8/encoder/denoising.c
@@ -529,7 +529,7 @@
// Bias on zero motion vector sse.
const int zero_bias = denoiser->denoise_pars.denoise_mv_bias;
zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100);
- sse_diff = zero_mv_sse - best_sse;
+ sse_diff = (int)zero_mv_sse - (int)best_sse;
saved_mbmi = *mbmi;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 1a30993..d5a0fff 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -5220,7 +5220,7 @@
vp8_second_pass(cpi);
encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
- cpi->twopass.bits_left -= 8 * *size;
+ cpi->twopass.bits_left -= 8 * (int)(*size);
if (!cpi->common.refresh_alt_ref_frame)
{
diff --git a/vp9/common/vp9_common.h b/vp9/common/vp9_common.h
index 2aff132..908fa80 100644
--- a/vp9/common/vp9_common.h
+++ b/vp9/common/vp9_common.h
@@ -67,25 +67,6 @@
#define VP9_FRAME_MARKER 0x2
-typedef enum {
- LEVEL_UNKNOWN = 0,
- LEVEL_1 = 10,
- LEVEL_1_1 = 11,
- LEVEL_2 = 20,
- LEVEL_2_1 = 21,
- LEVEL_3 = 30,
- LEVEL_3_1 = 31,
- LEVEL_4 = 40,
- LEVEL_4_1 = 41,
- LEVEL_5 = 50,
- LEVEL_5_1 = 51,
- LEVEL_5_2 = 52,
- LEVEL_6 = 60,
- LEVEL_6_1 = 61,
- LEVEL_6_2 = 62,
- LEVEL_NOT_CARE = 255,
-} VP9_LEVEL;
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 1df6f08..3fd935e 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -168,8 +168,6 @@
int allow_high_precision_mv;
- int keep_level_stats;
-
// Flag signaling that the frame context should be reset to default values.
// 0 or 1 implies don't reset, 2 reset just the context specified in the
// frame header, 3 reset all contexts.
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 61cca39..73a2db0 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -891,7 +891,7 @@
vpx_wb_write_bit(wb, cm->log2_tile_rows != 1);
}
-static int get_refresh_mask(VP9_COMP *cpi) {
+int vp9_get_refresh_mask(VP9_COMP *cpi) {
if (vp9_preserve_existing_gf(cpi)) {
// We have decided to preserve the previously existing golden frame as our
// new ARF frame. However, in the short term we leave it in the GF slot and,
@@ -1107,11 +1107,11 @@
write_bitdepth_colorspace_sampling(cm, wb);
}
- vpx_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
+ vpx_wb_write_literal(wb, vp9_get_refresh_mask(cpi), REF_FRAMES);
write_frame_size(cm, wb);
} else {
MV_REFERENCE_FRAME ref_frame;
- vpx_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
+ vpx_wb_write_literal(wb, vp9_get_refresh_mask(cpi), REF_FRAMES);
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX);
vpx_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame),
diff --git a/vp9/encoder/vp9_bitstream.h b/vp9/encoder/vp9_bitstream.h
index da6b414..f24d20f 100644
--- a/vp9/encoder/vp9_bitstream.h
+++ b/vp9/encoder/vp9_bitstream.h
@@ -18,6 +18,8 @@
#include "vp9/encoder/vp9_encoder.h"
+int vp9_get_refresh_mask(VP9_COMP *cpi);
+
void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size);
static INLINE int vp9_preserve_existing_gf(VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index d8bfb9d..6af0c0b 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -796,7 +796,7 @@
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
const YV12_BUFFER_CONFIG *yv12_g = NULL;
- unsigned int y_sad, y_sad_g;
+ unsigned int y_sad, y_sad_g, y_sad_thr;
const BLOCK_SIZE bsize = BLOCK_32X32
+ (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
@@ -829,7 +829,10 @@
mi->interp_filter = BILINEAR;
y_sad = vp9_int_pro_motion_estimation(cpi, x, bsize, mi_row, mi_col);
- if (y_sad_g < y_sad) {
+ // Pick ref frame for partitioning, bias last frame when y_sad_g and y_sad
+ // are close if short_circuit_low_temp_var is on.
+ y_sad_thr = cpi->sf.short_circuit_low_temp_var ? (y_sad * 7) >> 3 : y_sad;
+ if (y_sad_g < y_sad_thr) {
vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
&cm->frame_refs[GOLDEN_FRAME - 1].sf);
mi->ref_frame[0] = GOLDEN_FRAME;
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 8201794..9bae1d3 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -86,6 +86,25 @@
FILE *keyfile;
#endif
+static const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = {
+ {LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8},
+ {LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8},
+ {LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8},
+ {LEVEL_2_1, 9216000, 245760, 3600, 2800, 2, 2, 4, 8},
+ {LEVEL_3, 20736000, 552960, 7200, 6000, 2, 4, 4, 8},
+ {LEVEL_3_1, 36864000, 983040, 12000, 10000, 2, 4, 4, 8},
+ {LEVEL_4, 83558400, 2228224, 18000, 16000, 4, 4, 4, 8},
+ {LEVEL_4_1, 160432128, 2228224, 30000, 18000, 4, 4, 5, 6},
+ {LEVEL_5, 311951360, 8912896, 60000, 36000, 6, 8, 6, 4},
+ {LEVEL_5_1, 588251136, 8912896, 120000, 46000, 8, 8, 10, 4},
+ // TODO(huisu): update max_cpb_size for level 5_2 ~ 6_2 when
+ // they are finalized (currently TBD).
+ {LEVEL_5_2, 1176502272, 8912896, 180000, 0, 8, 8, 10, 4},
+ {LEVEL_6, 1176502272, 35651584, 180000, 0, 8, 16, 10, 4},
+ {LEVEL_6_1, 2353004544u, 35651584, 240000, 0, 8, 16, 10, 4},
+ {LEVEL_6_2, 4706009088u, 35651584, 480000, 0, 8, 16, 10, 4},
+};
+
static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) {
switch (mode) {
case NORMAL:
@@ -159,6 +178,39 @@
}
}
+static void init_level_info(Vp9LevelInfo *level_info) {
+ Vp9LevelStats *const level_stats = &level_info->level_stats;
+ Vp9LevelSpec *const level_spec = &level_info->level_spec;
+
+ memset(level_stats, 0, sizeof(*level_stats));
+ memset(level_spec, 0, sizeof(*level_spec));
+ level_spec->level = LEVEL_UNKNOWN;
+ level_spec->min_altref_distance = INT_MAX;
+}
+
+VP9_LEVEL vp9_get_level(const Vp9LevelSpec * const level_spec) {
+ int i;
+ const Vp9LevelSpec *this_level;
+
+ vpx_clear_system_state();
+
+ for (i = 0; i < VP9_LEVELS; ++i) {
+ this_level = &vp9_level_defs[i];
+ if ((double)level_spec->max_luma_sample_rate * (1 + SAMPLE_RATE_GRACE_P) >
+ (double)this_level->max_luma_sample_rate ||
+ level_spec->max_luma_picture_size > this_level->max_luma_picture_size ||
+ level_spec->average_bitrate > this_level->average_bitrate ||
+ level_spec->max_cpb_size > this_level->max_cpb_size ||
+ level_spec->compression_ratio < this_level->compression_ratio ||
+ level_spec->max_col_tiles > this_level->max_col_tiles ||
+ level_spec->min_altref_distance < this_level->min_altref_distance ||
+ level_spec->max_ref_frame_buffers > this_level->max_ref_frame_buffers)
+ continue;
+ break;
+ }
+ return (i == VP9_LEVELS) ? LEVEL_UNKNOWN : vp9_level_defs[i].level;
+}
+
int vp9_set_active_map(VP9_COMP* cpi,
unsigned char* new_map_16x16,
int rows,
@@ -783,7 +835,7 @@
cm->color_range = oxcf->color_range;
cpi->target_level = oxcf->target_level;
- cm->keep_level_stats = oxcf->target_level != LEVEL_NOT_CARE;
+ cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX;
cm->width = oxcf->width;
cm->height = oxcf->height;
@@ -1476,7 +1528,7 @@
cm->color_range = oxcf->color_range;
cpi->target_level = oxcf->target_level;
- cm->keep_level_stats = oxcf->target_level != LEVEL_NOT_CARE;
+ cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX;
if (cm->profile <= PROFILE_1)
assert(cm->bit_depth == VPX_BITS_8);
@@ -1660,7 +1712,6 @@
} while (++i <= MV_MAX);
}
-
VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf,
BufferPool *const pool) {
unsigned int i;
@@ -1749,6 +1800,9 @@
cpi->multi_arf_last_grp_enabled = 0;
cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
+
+ init_level_info(&cpi->level_info);
+
#if CONFIG_INTERNAL_STATS
cpi->b_calculate_ssimg = 0;
cpi->b_calculate_blockiness = 1;
@@ -2798,7 +2852,7 @@
} else if (vp9_preserve_existing_gf(cpi)) {
// We have decided to preserve the previously existing golden frame as our
// new ARF frame. However, in the short term in function
- // vp9_bitstream.c::get_refresh_mask() we left it in the GF slot and, if
+ // vp9_get_refresh_mask() we left it in the GF slot and, if
// we're updating the GF with the current decoded frame, we save it to the
// ARF slot instead.
// We now have to update the ARF with the current frame and swap gld_fb_idx
@@ -4420,6 +4474,124 @@
}
#endif // CONFIG_INTERNAL_STATS
+static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) {
+ VP9_COMMON *const cm = &cpi->common;
+ Vp9LevelInfo *const level_info = &cpi->level_info;
+ Vp9LevelSpec *const level_spec = &level_info->level_spec;
+ Vp9LevelStats *const level_stats = &level_info->level_stats;
+ int i, idx;
+ uint64_t luma_samples, dur_end;
+ const uint32_t luma_pic_size = cm->width * cm->height;
+ double cpb_data_size;
+
+ vpx_clear_system_state();
+
+ // update level_stats
+ level_stats->total_compressed_size += *size;
+ if (cm->show_frame) {
+ level_stats->total_uncompressed_size +=
+ luma_pic_size +
+ 2 * (luma_pic_size >> (cm->subsampling_x + cm->subsampling_y));
+ level_stats->time_encoded =
+ (cpi->last_end_time_stamp_seen - cpi->first_time_stamp_ever) /
+ (double)TICKS_PER_SEC;
+ }
+
+ if (arf_src_index > 0) {
+ if (!level_stats->seen_first_altref) {
+ level_stats->seen_first_altref = 1;
+ } else if (level_stats->frames_since_last_altref <
+ level_spec->min_altref_distance) {
+ level_spec->min_altref_distance = level_stats->frames_since_last_altref;
+ }
+ level_stats->frames_since_last_altref = 0;
+ } else {
+ ++level_stats->frames_since_last_altref;
+ }
+
+ if (level_stats->frame_window_buffer.len < FRAME_WINDOW_SIZE - 1) {
+ idx = (level_stats->frame_window_buffer.start +
+ level_stats->frame_window_buffer.len++) % FRAME_WINDOW_SIZE;
+ } else {
+ idx = level_stats->frame_window_buffer.start;
+ level_stats->frame_window_buffer.start = (idx + 1) % FRAME_WINDOW_SIZE;
+ }
+ level_stats->frame_window_buffer.buf[idx].ts = cpi->last_time_stamp_seen;
+ level_stats->frame_window_buffer.buf[idx].size = (uint32_t)(*size);
+ level_stats->frame_window_buffer.buf[idx].luma_samples = luma_pic_size;
+
+ if (cm->frame_type == KEY_FRAME) {
+ level_stats->ref_refresh_map = 0;
+ } else {
+ int count = 0;
+ level_stats->ref_refresh_map |= vp9_get_refresh_mask(cpi);
+ // Also need to consider the case where the encoder refers to a buffer
+ // that has been implicitly refreshed after encoding a keyframe.
+ if (!cm->intra_only) {
+ level_stats->ref_refresh_map |= (1 << cpi->lst_fb_idx);
+ level_stats->ref_refresh_map |= (1 << cpi->gld_fb_idx);
+ level_stats->ref_refresh_map |= (1 << cpi->alt_fb_idx);
+ }
+ for (i = 0; i < REF_FRAMES; ++i) {
+ count += (level_stats->ref_refresh_map >> i) & 1;
+ }
+ if (count > level_spec->max_ref_frame_buffers) {
+ level_spec->max_ref_frame_buffers = count;
+ }
+ }
+
+ // update average_bitrate
+ level_spec->average_bitrate =
+ (double)level_stats->total_compressed_size / 125.0 /
+ level_stats->time_encoded;
+
+ // update max_luma_sample_rate
+ luma_samples = 0;
+ for (i = 0; i < level_stats->frame_window_buffer.len; ++i) {
+ idx = (level_stats->frame_window_buffer.start +
+ level_stats->frame_window_buffer.len - 1 - i) % FRAME_WINDOW_SIZE;
+ if (i == 0) {
+ dur_end = level_stats->frame_window_buffer.buf[idx].ts;
+ }
+ if (dur_end - level_stats->frame_window_buffer.buf[idx].ts >=
+ TICKS_PER_SEC) {
+ break;
+ }
+ luma_samples += level_stats->frame_window_buffer.buf[idx].luma_samples;
+ }
+ if (luma_samples > level_spec->max_luma_sample_rate) {
+ level_spec->max_luma_sample_rate = luma_samples;
+ }
+
+ // update max_cpb_size
+ cpb_data_size = 0;
+ for (i = 0; i < CPB_WINDOW_SIZE; ++i) {
+ if (i >= level_stats->frame_window_buffer.len) break;
+ idx = (level_stats->frame_window_buffer.start +
+ level_stats->frame_window_buffer.len - 1 - i) % FRAME_WINDOW_SIZE;
+ cpb_data_size += level_stats->frame_window_buffer.buf[idx].size;
+ }
+ cpb_data_size = cpb_data_size / 125.0;
+ if (cpb_data_size > level_spec->max_cpb_size) {
+ level_spec->max_cpb_size = cpb_data_size;
+ }
+
+ // update max_luma_picture_size
+ if (luma_pic_size > level_spec->max_luma_picture_size) {
+ level_spec->max_luma_picture_size = luma_pic_size;
+ }
+
+ // update compression_ratio
+ level_spec->compression_ratio =
+ (double)level_stats->total_uncompressed_size * cm->bit_depth /
+ level_stats->total_compressed_size / 8.0;
+
+ // update max_col_tiles
+ if (level_spec->max_col_tiles < (1 << cm->log2_tile_cols)) {
+ level_spec->max_col_tiles = (1 << cm->log2_tile_cols);
+ }
+}
+
int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest,
int64_t *time_stamp, int64_t *time_end, int flush) {
@@ -4690,6 +4862,9 @@
if (cpi->b_calculate_psnr && oxcf->pass != 1 && cm->show_frame)
generate_psnr_packet(cpi);
+ if (cpi->keep_level_stats && oxcf->pass != 1)
+ update_level_info(cpi, size, arf_src_index);
+
#if CONFIG_INTERNAL_STATS
if (oxcf->pass != 1) {
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 6be61ac..b65dfa8 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -20,6 +20,7 @@
#include "vpx_dsp/ssim.h"
#endif
#include "vpx_dsp/variance.h"
+#include "vpx_ports/system_state.h"
#include "vpx_util/vpx_thread.h"
#include "vp9/common/vp9_alloccommon.h"
@@ -51,6 +52,9 @@
extern "C" {
#endif
+// vp9 uses 10,000,000 ticks/second as time stamp
+#define TICKS_PER_SEC 10000000
+
typedef struct {
int nmvjointcost[MV_JOINTS];
int nmvcosts[2][MV_VALS];
@@ -297,6 +301,69 @@
double worst;
} ImageStat;
+#define CPB_WINDOW_SIZE 4
+#define FRAME_WINDOW_SIZE 128
+#define SAMPLE_RATE_GRACE_P 0.015
+#define VP9_LEVELS 14
+
+typedef enum {
+ LEVEL_UNKNOWN = 0,
+ LEVEL_1 = 10,
+ LEVEL_1_1 = 11,
+ LEVEL_2 = 20,
+ LEVEL_2_1 = 21,
+ LEVEL_3 = 30,
+ LEVEL_3_1 = 31,
+ LEVEL_4 = 40,
+ LEVEL_4_1 = 41,
+ LEVEL_5 = 50,
+ LEVEL_5_1 = 51,
+ LEVEL_5_2 = 52,
+ LEVEL_6 = 60,
+ LEVEL_6_1 = 61,
+ LEVEL_6_2 = 62,
+ LEVEL_MAX = 255
+} VP9_LEVEL;
+
+typedef struct {
+ VP9_LEVEL level;
+ uint64_t max_luma_sample_rate;
+ uint32_t max_luma_picture_size;
+ double average_bitrate; // in kilobits per second
+ double max_cpb_size; // in kilobits
+ double compression_ratio;
+ uint8_t max_col_tiles;
+ uint32_t min_altref_distance;
+ uint8_t max_ref_frame_buffers;
+} Vp9LevelSpec;
+
+typedef struct {
+ int64_t ts; // timestamp
+ uint32_t luma_samples;
+ uint32_t size; // in bytes
+} FrameRecord;
+
+typedef struct {
+ FrameRecord buf[FRAME_WINDOW_SIZE];
+ uint8_t start;
+ uint8_t len;
+} FrameWindowBuffer;
+
+typedef struct {
+ uint8_t seen_first_altref;
+ uint32_t frames_since_last_altref;
+ uint64_t total_compressed_size;
+ uint64_t total_uncompressed_size;
+ double time_encoded; // in seconds
+ FrameWindowBuffer frame_window_buffer;
+ int ref_refresh_map;
+} Vp9LevelStats;
+
+typedef struct {
+ Vp9LevelStats level_stats;
+ Vp9LevelSpec level_spec;
+} Vp9LevelInfo;
+
typedef struct VP9_COMP {
QUANTS quants;
ThreadData td;
@@ -519,6 +586,9 @@
VPxWorker *workers;
struct EncWorkerData *tile_thr_data;
VP9LfSync lf_row_sync;
+
+ int keep_level_stats;
+ Vp9LevelInfo level_info;
} VP9_COMP;
void vp9_initialize_enc(void);
@@ -674,6 +744,8 @@
return cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL;
}
+VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec);
+
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
#define LAYER_IDS_TO_IDX(sl, tl, num_tl) ((sl) * (num_tl) + (tl))
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index e40e59b..130fc2b 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -590,20 +590,21 @@
}
#if CONFIG_VP9_HIGHBITDEPTH
-static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, int *rate, int64_t *dist,
+static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
int *skippable, int64_t *sse, BLOCK_SIZE bsize,
TX_SIZE tx_size) {
MACROBLOCKD *xd = &x->e_mbd;
unsigned int var_y, sse_y;
(void)tx_size;
- model_rd_for_sb_y(cpi, bsize, x, xd, rate, dist, &var_y, &sse_y);
+ model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc->rate, &this_rdc->dist, &var_y,
+ &sse_y);
*sse = INT_MAX;
*skippable = 0;
return;
}
#else
-static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, int *rate, int64_t *dist,
+static void block_yrd(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *this_rdc,
int *skippable, int64_t *sse, BLOCK_SIZE bsize,
TX_SIZE tx_size) {
MACROBLOCKD *xd = &x->e_mbd;
@@ -677,17 +678,17 @@
}
}
- *rate = 0;
+ this_rdc->rate = 0;
if (*sse < INT64_MAX) {
*sse = (*sse << 6) >> 2;
if (*skippable) {
- *dist = *sse;
+ this_rdc->dist = *sse;
return;
}
}
block = 0;
- *dist = 0;
+ this_rdc->dist = 0;
for (r = 0; r < max_blocks_high; r += block_step) {
for (c = 0; c < num_4x4_w; c += block_step) {
if (c < max_blocks_wide) {
@@ -697,25 +698,26 @@
uint16_t *const eob = &p->eobs[block];
if (*eob == 1)
- *rate += (int)abs(qcoeff[0]);
+ this_rdc->rate += (int)abs(qcoeff[0]);
else if (*eob > 1)
- *rate += vpx_satd((const int16_t *)qcoeff, step << 4);
+ this_rdc->rate += vpx_satd((const int16_t *)qcoeff, step << 4);
- *dist += vp9_block_error_fp(coeff, dqcoeff, step << 4) >> 2;
+ this_rdc->dist +=
+ vp9_block_error_fp(coeff, dqcoeff, step << 4) >> 2;
}
block += step;
}
}
// If skippable is set, rate gets clobbered later.
- *rate <<= (2 + VP9_PROB_COST_SHIFT);
- *rate += (eob_cost << VP9_PROB_COST_SHIFT);
+ this_rdc->rate <<= (2 + VP9_PROB_COST_SHIFT);
+ this_rdc->rate += (eob_cost << VP9_PROB_COST_SHIFT);
}
#endif
static void model_rd_for_sb_uv(VP9_COMP *cpi, BLOCK_SIZE plane_bsize,
MACROBLOCK *x, MACROBLOCKD *xd,
- int *out_rate_sum, int64_t *out_dist_sum,
+ RD_COST *this_rdc,
unsigned int *var_y, unsigned int *sse_y,
int start_plane, int stop_plane) {
// Note our transform coeffs are 8 times an orthogonal transform.
@@ -726,8 +728,8 @@
int64_t dist;
int i;
- *out_rate_sum = 0;
- *out_dist_sum = 0;
+ this_rdc->rate = 0;
+ this_rdc->dist = 0;
for (i = start_plane; i <= stop_plane; ++i) {
struct macroblock_plane *const p = &x->plane[i];
@@ -758,8 +760,8 @@
dc_quant >> 3, &rate, &dist);
#endif // CONFIG_VP9_HIGHBITDEPTH
- *out_rate_sum += rate >> 1;
- *out_dist_sum += dist << 3;
+ this_rdc->rate += rate >> 1;
+ this_rdc->dist += dist << 3;
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
@@ -774,8 +776,8 @@
ac_quant >> 3, &rate, &dist);
#endif // CONFIG_VP9_HIGHBITDEPTH
- *out_rate_sum += rate;
- *out_dist_sum += dist << 4;
+ this_rdc->rate += rate;
+ this_rdc->dist += dist << 4;
}
}
@@ -912,8 +914,7 @@
MACROBLOCK *x;
PREDICTION_MODE mode;
int skippable;
- int rate;
- int64_t dist;
+ RD_COST *rdc;
};
static void estimate_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
@@ -930,8 +931,7 @@
const int src_stride = p->src.stride;
const int dst_stride = pd->dst.stride;
int i, j;
- int rate;
- int64_t dist;
+ RD_COST this_rdc;
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
@@ -948,19 +948,19 @@
if (plane == 0) {
int64_t this_sse = INT64_MAX;
// TODO(jingning): This needs further refactoring.
- block_yrd(cpi, x, &rate, &dist, &args->skippable, &this_sse, bsize_tx,
+ block_yrd(cpi, x, &this_rdc, &args->skippable, &this_sse, bsize_tx,
VPXMIN(tx_size, TX_16X16));
} else {
unsigned int var = 0;
unsigned int sse = 0;
- model_rd_for_sb_uv(cpi, plane_bsize, x, xd, &rate, &dist, &var, &sse,
- plane, plane);
+ model_rd_for_sb_uv(cpi, plane_bsize, x, xd, &this_rdc, &var, &sse, plane,
+ plane);
}
p->src.buf = src_buf_base;
pd->dst.buf = dst_buf_base;
- args->rate += rate;
- args->dist += dist;
+ args->rdc->rate += this_rdc.rate;
+ args->rdc->dist += this_rdc.dist;
}
static const THR_MODES mode_idx[MAX_REF_FRAMES - 1][4] = {
@@ -1013,7 +1013,7 @@
MODE_INFO *const mi = xd->mi[0];
RD_COST this_rdc, best_rdc;
PREDICTION_MODE this_mode;
- struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0, 0 };
+ struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 };
const TX_SIZE intra_tx_size =
VPXMIN(max_txsize_lookup[bsize],
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
@@ -1037,22 +1037,20 @@
// Change the limit of this loop to add other intra prediction
// mode tests.
for (this_mode = DC_PRED; this_mode <= H_PRED; ++this_mode) {
+ this_rdc.rate = this_rdc.dist = 0;
args.mode = this_mode;
args.skippable = 1;
- args.rate = 0;
- args.dist = 0;
+ args.rdc = &this_rdc;
mi->tx_size = intra_tx_size;
vp9_foreach_transformed_block_in_plane(xd, bsize, 0,
estimate_block_intra, &args);
if (args.skippable) {
x->skip_txfm[0] = SKIP_TXFM_AC_DC;
- args.rate = vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 1);
+ this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 1);
} else {
x->skip_txfm[0] = SKIP_TXFM_NONE;
- args.rate += vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 0);
+ this_rdc.rate += vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 0);
}
- this_rdc.rate = args.rate;
- this_rdc.dist = args.dist;
this_rdc.rate += bmode_costs[this_mode];
this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv,
this_rdc.rate, this_rdc.dist);
@@ -1667,8 +1665,9 @@
if ((this_mode == NEWMV || filter_ref == SWITCHABLE) && pred_filter_search
&& (ref_frame == LAST_FRAME ||
- (ref_frame == GOLDEN_FRAME && cpi->use_svc))
- && (((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07) != 0)) {
+ (ref_frame == GOLDEN_FRAME &&
+ (cpi->use_svc || cpi->oxcf.rc_mode == VPX_VBR))) &&
+ (((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07) != 0)) {
int pf_rate[3];
int64_t pf_dist[3];
unsigned int pf_var[3];
@@ -1723,7 +1722,7 @@
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
// For large partition blocks, extra testing is done.
- if (bsize > BLOCK_32X32 &&
+ if (cpi->oxcf.rc_mode == VPX_CBR && bsize > BLOCK_32X32 &&
!cyclic_refresh_segment_id_boosted(xd->mi[0]->segment_id) &&
cm->base_qindex) {
model_rd_for_sb_y_large(cpi, bsize, x, xd, &this_rdc.rate,
@@ -1737,8 +1736,8 @@
if (!this_early_term) {
this_sse = (int64_t)sse_y;
- block_yrd(cpi, x, &this_rdc.rate, &this_rdc.dist, &is_skippable,
- &this_sse, bsize, VPXMIN(mi->tx_size, TX_16X16));
+ block_yrd(cpi, x, &this_rdc, &is_skippable, &this_sse, bsize,
+ VPXMIN(mi->tx_size, TX_16X16));
x->skip_txfm[0] = is_skippable;
if (is_skippable) {
this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
@@ -1764,17 +1763,15 @@
}
if (x->color_sensitivity[0] || x->color_sensitivity[1]) {
- int uv_rate = 0;
- int64_t uv_dist = 0;
+ RD_COST rdc_uv;
const BLOCK_SIZE uv_bsize = get_plane_block_size(bsize, &xd->plane[1]);
if (x->color_sensitivity[0])
vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 1);
if (x->color_sensitivity[1])
vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 2);
- model_rd_for_sb_uv(cpi, uv_bsize, x, xd, &uv_rate, &uv_dist,
- &var_y, &sse_y, 1, 2);
- this_rdc.rate += uv_rate;
- this_rdc.dist += uv_dist;
+ model_rd_for_sb_uv(cpi, uv_bsize, x, xd, &rdc_uv, &var_y, &sse_y, 1, 2);
+ this_rdc.rate += rdc_uv.rate;
+ this_rdc.dist += rdc_uv.dist;
}
this_rdc.rate += rate_mv;
@@ -1875,7 +1872,7 @@
(best_rdc.rdcost == INT64_MAX ||
(!x->skip && best_rdc.rdcost > inter_mode_thresh &&
bsize <= cpi->sf.max_intra_bsize))) {
- struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0, 0 };
+ struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 };
int i;
TX_SIZE best_intra_tx_size = TX_SIZES;
TX_SIZE intra_tx_size =
@@ -1924,10 +1921,10 @@
mi->mode = this_mode;
mi->ref_frame[0] = INTRA_FRAME;
+ this_rdc.rate = this_rdc.dist = 0;
args.mode = this_mode;
args.skippable = 1;
- args.rate = 0;
- args.dist = 0;
+ args.rdc = &this_rdc;
mi->tx_size = intra_tx_size;
vp9_foreach_transformed_block_in_plane(xd, bsize, 0,
estimate_block_intra, &args);
@@ -1935,10 +1932,10 @@
// mirrors the behavior used by inter
if (args.skippable) {
x->skip_txfm[0] = SKIP_TXFM_AC_DC;
- args.rate = vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 1);
+ this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 1);
} else {
x->skip_txfm[0] = SKIP_TXFM_NONE;
- args.rate += vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 0);
+ this_rdc.rate += vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 0);
}
// Inter and intra RD will mismatch in scale for non-screen content.
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
@@ -1949,8 +1946,6 @@
vp9_foreach_transformed_block_in_plane(xd, bsize, 2,
estimate_block_intra, &args);
}
- this_rdc.rate = args.rate;
- this_rdc.dist = args.dist;
this_rdc.rate += cpi->mbmode_cost[this_mode];
this_rdc.rate += ref_frame_cost[INTRA_FRAME];
this_rdc.rate += intra_cost_penalty;
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index 9766c05..d68b684 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -94,7 +94,7 @@
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int64_t tmp = abs_coeff + round_ptr[rc != 0];
- const uint32_t abs_qcoeff = (uint32_t)((tmp * quant_ptr[rc != 0]) >> 16);
+ const int abs_qcoeff = (int)((tmp * quant_ptr[rc != 0]) >> 16);
qcoeff_ptr[rc] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0];
if (abs_qcoeff)
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 1a11a6d..73a089b 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -205,7 +205,7 @@
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_NOT_CARE)
+ level != LEVEL_UNKNOWN && level != LEVEL_MAX)
ERROR("target_level is invalid");
}
@@ -807,6 +807,13 @@
return update_extra_cfg(ctx, &extra_cfg);
}
+static vpx_codec_err_t ctrl_get_level(vpx_codec_alg_priv_t *ctx, va_list args) {
+ int *const arg = va_arg(args, int *);
+ if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
+ *arg = (int)vp9_get_level(&ctx->cpi->level_info.level_spec);
+ return VPX_CODEC_OK;
+}
+
static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
vpx_codec_priv_enc_mr_cfg_t *data) {
vpx_codec_err_t res = VPX_CODEC_OK;
@@ -964,9 +971,6 @@
return index_sz;
}
-// vp9 uses 10,000,000 ticks/second as time stamp
-#define TICKS_PER_SEC 10000000LL
-
static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
int64_t n) {
return n * TICKS_PER_SEC * timebase->num / timebase->den;
@@ -974,7 +978,7 @@
static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
int64_t n) {
- const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
+ const int64_t round = (int64_t)TICKS_PER_SEC * timebase->num / 2 - 1;
return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
}
@@ -1547,6 +1551,7 @@
{VP9_GET_REFERENCE, ctrl_get_reference},
{VP9E_GET_SVC_LAYER_ID, ctrl_get_svc_layer_id},
{VP9E_GET_ACTIVEMAP, ctrl_get_active_map},
+ {VP9E_GET_LEVEL, ctrl_get_level},
{ -1, NULL},
};
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index b059d47..2752a86 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -562,7 +562,13 @@
*
* Supported in codecs: VP9
*/
- VP9E_SET_TARGET_LEVEL
+ VP9E_SET_TARGET_LEVEL,
+
+ /*!\brief Codec control function to get bitstream level.
+ *
+ * Supported in codecs: VP9
+ */
+ VP9E_GET_LEVEL
};
/*!\brief vpx 1-D scaling mode
@@ -821,6 +827,9 @@
VPX_CTRL_USE_TYPE(VP9E_SET_TARGET_LEVEL, unsigned int)
#define VPX_CTRL_VP9E_SET_TARGET_LEVEL
+VPX_CTRL_USE_TYPE(VP9E_GET_LEVEL, int *)
+#define VPX_CTRL_VP9E_GET_LEVEL
+
/*!\endcond */
/*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus
diff --git a/vpx_dsp/quantize.c b/vpx_dsp/quantize.c
index 6426ccc..80fcd66 100644
--- a/vpx_dsp/quantize.c
+++ b/vpx_dsp/quantize.c
@@ -53,7 +53,7 @@
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int64_t tmp = abs_coeff + round_ptr[0];
- const uint32_t abs_qcoeff = (uint32_t)((tmp * quant) >> 16);
+ const int abs_qcoeff = (int)((tmp * quant) >> 16);
qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant_ptr;
if (abs_qcoeff)
@@ -109,7 +109,7 @@
const int coeff_sign = (coeff >> 31);
const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
const int64_t tmp = abs_coeff + ROUND_POWER_OF_TWO(round_ptr[0], 1);
- const uint32_t abs_qcoeff = (uint32_t)((tmp * quant) >> 15);
+ const int abs_qcoeff = (int)((tmp * quant) >> 15);
qcoeff_ptr[0] = (tran_low_t)((abs_qcoeff ^ coeff_sign) - coeff_sign);
dqcoeff_ptr[0] = qcoeff_ptr[0] * dequant_ptr / 2;
if (abs_qcoeff)
diff --git a/vpx_dsp/variance.c b/vpx_dsp/variance.c
index e8bddb0..cdec0db 100644
--- a/vpx_dsp/variance.c
+++ b/vpx_dsp/variance.c
@@ -275,7 +275,7 @@
#if CONFIG_VP9_HIGHBITDEPTH
static void highbd_variance64(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride,
- int w, int h, uint64_t *sse, uint64_t *sum) {
+ int w, int h, uint64_t *sse, int64_t *sum) {
int i, j;
uint16_t *a = CONVERT_TO_SHORTPTR(a8);
@@ -298,7 +298,7 @@
const uint8_t *b8, int b_stride,
int w, int h, uint32_t *sse, int *sum) {
uint64_t sse_long = 0;
- uint64_t sum_long = 0;
+ int64_t sum_long = 0;
highbd_variance64(a8, a_stride, b8, b_stride, w, h, &sse_long, &sum_long);
*sse = (uint32_t)sse_long;
*sum = (int)sum_long;
@@ -308,7 +308,7 @@
const uint8_t *b8, int b_stride,
int w, int h, uint32_t *sse, int *sum) {
uint64_t sse_long = 0;
- uint64_t sum_long = 0;
+ int64_t sum_long = 0;
highbd_variance64(a8, a_stride, b8, b_stride, w, h, &sse_long, &sum_long);
*sse = (uint32_t)ROUND_POWER_OF_TWO(sse_long, 4);
*sum = (int)ROUND_POWER_OF_TWO(sum_long, 2);
@@ -318,7 +318,7 @@
const uint8_t *b8, int b_stride,
int w, int h, uint32_t *sse, int *sum) {
uint64_t sse_long = 0;
- uint64_t sum_long = 0;
+ int64_t sum_long = 0;
highbd_variance64(a8, a_stride, b8, b_stride, w, h, &sse_long, &sum_long);
*sse = (uint32_t)ROUND_POWER_OF_TWO(sse_long, 8);
*sum = (int)ROUND_POWER_OF_TWO(sum_long, 4);