simple_encode.EndEncode();
}
+TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo();
+ int target_frame_bits = 20000;
+ if (encode_frame_info.frame_type == kFrameTypeKey ||
+ encode_frame_info.frame_type == kFrameTypeAltRef ||
+ encode_frame_info.frame_type == kFrameTypeGolden) {
+ target_frame_bits = 100000;
+ }
+ if (encode_frame_info.frame_type == kFrameTypeOverlay) {
+ target_frame_bits = 2000;
+ }
+
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithTargetFrameBits(&encode_frame_result,
+ target_frame_bits);
+ const int recode_count = encode_frame_result.recode_count;
+ // TODO(angiebird): Replace 7 by RATE_CTRL_MAX_RECODE_NUM
+ EXPECT_LE(recode_count, 7);
+ EXPECT_GE(recode_count, 1);
+
+ double diff = fabs((double)encode_frame_result.coding_data_bit_size -
+ target_frame_bits);
+ EXPECT_LE(diff * 100 / target_frame_bits, 15);
+ }
+ simple_encode.EndEncode();
+}
+
TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) {
SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
target_bitrate_, num_frames_,
}
#if CONFIG_RATE_CTRL
-#define RATE_CTRL_MAX_RECODE_NUM 7
-
-typedef struct RATE_QINDEX_HISTORY {
- int recode_count;
- int q_index_history[RATE_CTRL_MAX_RECODE_NUM];
- int rate_history[RATE_CTRL_MAX_RECODE_NUM];
- int q_index_high;
- int q_index_low;
-} RATE_QINDEX_HISTORY;
-
static void init_rq_history(RATE_QINDEX_HISTORY *rq_history) {
rq_history->recode_count = 0;
rq_history->q_index_high = 255;
}
#endif // CONFIG_RATE_CTRL
-static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
- uint8_t *dest) {
+static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
+#if CONFIG_RATE_CTRL
+ ,
+ RATE_QINDEX_HISTORY *rq_history
+#endif // CONFIG_RATE_CTRL
+) {
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index];
const ENCODE_FRAME_TYPE frame_type = get_encode_frame_type(update_type);
RATE_QSTEP_MODEL *rq_model = &cpi->rq_model[frame_type];
- RATE_QINDEX_HISTORY rq_history;
- init_rq_history(&rq_history);
+ init_rq_history(rq_history);
#endif // CONFIG_RATE_CTRL
if (cm->show_existing_frame) {
#if CONFIG_RATE_CTRL
if (cpi->encode_command.use_external_target_frame_bits) {
- q = rq_model_predict_q_index(rq_model, &rq_history,
- rc->this_frame_target);
+ q = rq_model_predict_q_index(rq_model, rq_history, rc->this_frame_target);
}
#endif // CONFIG_RATE_CTRL
// Decide frame size bounds first time through.
if (cpi->encode_command.use_external_target_frame_bits) {
const double percent_diff = get_bits_percent_diff(
rc->this_frame_target, rc->projected_frame_size);
- update_rq_history(&rq_history, rc->this_frame_target,
+ update_rq_history(rq_history, rc->this_frame_target,
rc->projected_frame_size, q);
loop_count += 1;
- rq_model_update(&rq_history, rc->this_frame_target, rq_model);
+ rq_model_update(rq_history, rc->this_frame_target, rq_model);
// Check if we hit the target bitrate.
if (percent_diff <= 15 ||
- rq_history.recode_count >= RATE_CTRL_MAX_RECODE_NUM ||
- rq_history.q_index_low >= rq_history.q_index_high) {
+ rq_history->recode_count >= RATE_CTRL_MAX_RECODE_NUM ||
+ rq_history->q_index_low >= rq_history->q_index_high) {
break;
}
if (!encode_without_recode_loop(cpi, size, dest)) return;
} else {
#if !CONFIG_REALTIME_ONLY
+#if CONFIG_RATE_CTRL
+ encode_with_recode_loop(cpi, size, dest, &encode_frame_result->rq_history);
+#else // CONFIG_RATE_CTRL
encode_with_recode_loop(cpi, size, dest);
-#endif
+#endif // CONFIG_RATE_CTRL
+#endif // !CONFIG_REALTIME_ONLY
}
// TODO(jingning): When using show existing frame mode, we assume that the
encode_frame_result->frame_coding_index = -1;
vp9_zero(encode_frame_result->coded_frame);
encode_frame_result->coded_frame.allocated = 0;
+ init_rq_history(&encode_frame_result->rq_history);
#endif // CONFIG_RATE_CTRL
}
int plane_height[3];
uint8_t *plane_buffer[3];
} IMAGE_BUFFER;
+
+#define RATE_CTRL_MAX_RECODE_NUM 7
+
+typedef struct RATE_QINDEX_HISTORY {
+ int recode_count;
+ int q_index_history[RATE_CTRL_MAX_RECODE_NUM];
+ int rate_history[RATE_CTRL_MAX_RECODE_NUM];
+ int q_index_high;
+ int q_index_low;
+} RATE_QINDEX_HISTORY;
+
#endif // CONFIG_RATE_CTRL
typedef struct ENCODE_FRAME_RESULT {
const PARTITION_INFO *partition_info;
const MOTION_VECTOR_INFO *motion_vector_info;
IMAGE_BUFFER coded_frame;
+ RATE_QINDEX_HISTORY rq_history;
#endif // CONFIG_RATE_CTRL
int quantize_index;
} ENCODE_FRAME_RESULT;
frame_height, img_fmt);
}
+static void encode_frame_result_update_rq_history(
+ const RATE_QINDEX_HISTORY *rq_history,
+ EncodeFrameResult *encode_frame_result) {
+ encode_frame_result->recode_count = rq_history->recode_count;
+ for (int i = 0; i < encode_frame_result->recode_count; ++i) {
+ const int q_index = rq_history->q_index_history[i];
+ const int rate = rq_history->rate_history[i];
+ encode_frame_result->q_index_history.push_back(q_index);
+ encode_frame_result->rate_history.push_back(rate);
+ }
+}
+
static void update_encode_frame_result(
EncodeFrameResult *encode_frame_result,
const ENCODE_FRAME_RESULT *encode_frame_info) {
&encode_frame_result->motion_vector_info[0]);
update_frame_counts(&encode_frame_info->frame_counts,
&encode_frame_result->frame_counts);
+ encode_frame_result_update_rq_history(&encode_frame_info->rq_history,
+ encode_frame_result);
}
static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) {
// share the same motion vector information.
std::vector<MotionVectorInfo> motion_vector_info;
ImageBuffer coded_frame;
+
+ // recode_count, q_index_history and rate_history are only available when
+ // EncodeFrameWithTargetFrameBits() is used.
+ int recode_count;
+ std::vector<int> q_index_history;
+ std::vector<int> rate_history;
};
struct GroupOfPicture {