summaryrefslogtreecommitdiffstats
path: root/media/libvpx/libvpx/test/simple_encode_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/libvpx/libvpx/test/simple_encode_test.cc')
-rw-r--r--media/libvpx/libvpx/test/simple_encode_test.cc574
1 files changed, 574 insertions, 0 deletions
diff --git a/media/libvpx/libvpx/test/simple_encode_test.cc b/media/libvpx/libvpx/test/simple_encode_test.cc
new file mode 100644
index 0000000000..01fc258566
--- /dev/null
+++ b/media/libvpx/libvpx/test/simple_encode_test.cc
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2019 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 <math.h>
+#include <memory>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/video_source.h"
+#include "vp9/simple_encode.h"
+
+namespace vp9 {
+namespace {
+
+double GetBitrateInKbps(size_t bit_size, int num_frames, int frame_rate_num,
+ int frame_rate_den) {
+ return static_cast<double>(bit_size) / num_frames * frame_rate_num /
+ frame_rate_den / 1000.0;
+}
+
+// Returns the number of unit in size of 4.
+// For example, if size is 7, return 2.
+int GetNumUnit4x4(int size) { return (size + 3) >> 2; }
+
+class SimpleEncodeTest : public ::testing::Test {
+ protected:
+ const int width_ = 352;
+ const int height_ = 288;
+ const int frame_rate_num_ = 30;
+ const int frame_rate_den_ = 1;
+ const int target_bitrate_ = 1000;
+ const int num_frames_ = 17;
+ const int target_level_ = LEVEL_UNKNOWN;
+ const std::string in_file_path_str_ =
+ libvpx_test::GetDataPath() + "/bus_352x288_420_f20_b8.yuv";
+};
+
+TEST_F(SimpleEncodeTest, ComputeFirstPassStats) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<std::vector<double>> frame_stats =
+ simple_encode.ObserveFirstPassStats();
+ EXPECT_EQ(frame_stats.size(), static_cast<size_t>(num_frames_));
+ const size_t data_num = frame_stats[0].size();
+ // Read ObserveFirstPassStats before changing FIRSTPASS_STATS.
+ EXPECT_EQ(data_num, static_cast<size_t>(25));
+ for (size_t i = 0; i < frame_stats.size(); ++i) {
+ EXPECT_EQ(frame_stats[i].size(), data_num);
+ // FIRSTPASS_STATS's first element is frame
+ EXPECT_EQ(frame_stats[i][0], i);
+ // FIRSTPASS_STATS's last element is count, and the count is 1 for single
+ // frame stats
+ EXPECT_EQ(frame_stats[i][data_num - 1], 1);
+ }
+}
+
+TEST_F(SimpleEncodeTest, ObserveFirstPassMotionVectors) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<std::vector<MotionVectorInfo>> fps_motion_vectors =
+ simple_encode.ObserveFirstPassMotionVectors();
+ EXPECT_EQ(fps_motion_vectors.size(), static_cast<size_t>(num_frames_));
+ const size_t num_blocks = ((width_ + 15) >> 4) * ((height_ + 15) >> 4);
+ EXPECT_EQ(num_blocks, fps_motion_vectors[0].size());
+ for (size_t i = 0; i < fps_motion_vectors.size(); ++i) {
+ EXPECT_EQ(num_blocks, fps_motion_vectors[i].size());
+ for (size_t j = 0; j < num_blocks; ++j) {
+ const int mv_count = fps_motion_vectors[i][j].mv_count;
+ const int ref_count =
+ (fps_motion_vectors[i][j].ref_frame[0] != kRefFrameTypeNone) +
+ (fps_motion_vectors[i][j].ref_frame[1] != kRefFrameTypeNone);
+ EXPECT_EQ(mv_count, ref_count);
+ }
+ }
+}
+
+TEST_F(SimpleEncodeTest, GetCodingFrameNum) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(num_coding_frames, 19);
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrame) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_GE(num_coding_frames, num_frames_);
+ simple_encode.StartEncode();
+ size_t total_data_bit_size = 0;
+ int coded_show_frame_count = 0;
+ int frame_coding_index = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ EXPECT_EQ(encode_frame_result.show_idx,
+ encode_frame_list[group_index].show_idx);
+ EXPECT_EQ(encode_frame_result.frame_type,
+ encode_frame_list[group_index].frame_type);
+ EXPECT_EQ(encode_frame_list[group_index].coding_index,
+ frame_coding_index);
+ EXPECT_GE(encode_frame_result.psnr, 34)
+ << "The psnr is supposed to be greater than 34 given the "
+ "target_bitrate 1000 kbps";
+ EXPECT_EQ(encode_frame_result.ref_frame_info,
+ encode_frame_list[group_index].ref_frame_info);
+ total_data_bit_size += encode_frame_result.coding_data_bit_size;
+ ++frame_coding_index;
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ const double bitrate = GetBitrateInKbps(total_data_bit_size, num_frames_,
+ frame_rate_num_, frame_rate_den_);
+ const double off_target_threshold = 150;
+ EXPECT_LE(fabs(target_bitrate_ - bitrate), off_target_threshold);
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<int> key_frame_map = simple_encode.ObserveKeyFrameMap();
+ EXPECT_EQ(key_frame_map.size(), static_cast<size_t>(num_frames_));
+ simple_encode.StartEncode();
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ if (encode_frame_result.frame_type == kFrameTypeKey) {
+ EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 1);
+ } else {
+ EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 0);
+ }
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ 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;
+ switch (encode_frame_info.frame_type) {
+ case kFrameTypeInter: target_frame_bits = 20000; break;
+ case kFrameTypeKey:
+ case kFrameTypeAltRef:
+ case kFrameTypeGolden: target_frame_bits = 100000; break;
+ case kFrameTypeOverlay: target_frame_bits = 2000; break;
+ default: target_frame_bits = 20000;
+ }
+
+ double percent_diff = 15;
+ if (encode_frame_info.frame_type == kFrameTypeOverlay) {
+ percent_diff = 100;
+ }
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithTargetFrameBits(
+ &encode_frame_result, target_frame_bits, percent_diff);
+ 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);
+
+ const double diff = fabs((double)encode_frame_result.coding_data_bit_size -
+ target_frame_bits);
+ EXPECT_LE(diff * 100 / target_frame_bits, percent_diff);
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ 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) {
+ const int assigned_quantize_index = 100 + i;
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ assigned_quantize_index);
+ EXPECT_EQ(encode_frame_result.quantize_index, assigned_quantize_index);
+ }
+ simple_encode.EndEncode();
+}
+
+// This test encodes the video using EncodeFrame(), where quantize indexes
+// are selected by vp9 rate control.
+// Encode stats and the quantize_indexes are collected.
+// Then the test encodes the video again using EncodeFrameWithQuantizeIndex()
+// using the quantize indexes collected from the first run.
+// Then test whether the encode stats of the two encoding runs match.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest) {
+ std::vector<int> quantize_index_list;
+ std::vector<uint64_t> ref_sse_list;
+ std::vector<double> ref_psnr_list;
+ std::vector<size_t> ref_bit_size_list;
+ std::vector<FrameType> ref_frame_type_list;
+ std::vector<int> ref_show_idx_list;
+ {
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, 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) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ ref_sse_list.push_back(encode_frame_result.sse);
+ ref_psnr_list.push_back(encode_frame_result.psnr);
+ ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
+ ref_frame_type_list.push_back(encode_frame_result.frame_type);
+ ref_show_idx_list.push_back(encode_frame_result.show_idx);
+ }
+ simple_encode.EndEncode();
+ }
+ {
+ // The second encode with quantize index got from the first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(static_cast<size_t>(num_coding_frames),
+ quantize_index_list.size());
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
+ EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
+ EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
+ EXPECT_EQ(encode_frame_result.frame_type, ref_frame_type_list[i]);
+ EXPECT_EQ(encode_frame_result.show_idx, ref_show_idx_list[i]);
+ }
+ simple_encode.EndEncode();
+ }
+}
+
+// Test the information (partition info and motion vector info) stored in
+// encoder is the same between two encode runs.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest2) {
+ const int num_rows_4x4 = GetNumUnit4x4(width_);
+ const int num_cols_4x4 = GetNumUnit4x4(height_);
+ const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
+ num_coding_frames);
+ std::vector<MotionVectorInfo> motion_vector_info_list(num_units_4x4 *
+ num_coding_frames);
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ partition_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.partition_info[j];
+ motion_vector_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.motion_vector_info[j];
+ }
+ }
+ simple_encode.EndEncode();
+ // The second encode.
+ SimpleEncode simple_encode_2(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode_2.ComputeFirstPassStats();
+ const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
+ simple_encode_2.StartEncode();
+ for (int i = 0; i < num_coding_frames_2; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode_2.EncodeFrame(&encode_frame_result);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ EXPECT_EQ(encode_frame_result.partition_info[j].row,
+ partition_info_list[i * num_units_4x4 + j].row);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column,
+ partition_info_list[i * num_units_4x4 + j].column);
+ EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
+ partition_info_list[i * num_units_4x4 + j].row_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
+ partition_info_list[i * num_units_4x4 + j].column_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].width,
+ partition_info_list[i * num_units_4x4 + j].width);
+ EXPECT_EQ(encode_frame_result.partition_info[j].height,
+ partition_info_list[i * num_units_4x4 + j].height);
+
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_count,
+ motion_vector_info_list[i * num_units_4x4 + j].mv_count);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[0],
+ motion_vector_info_list[i * num_units_4x4 + j].ref_frame[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[1],
+ motion_vector_info_list[i * num_units_4x4 + j].ref_frame[1]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[0],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_row[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[0],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_column[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[1],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_row[1]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[1],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_column[1]);
+ }
+ }
+ simple_encode_2.EndEncode();
+}
+
+// Test the information stored in encoder is the same between two encode runs.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest3) {
+ std::vector<int> quantize_index_list;
+ const int num_rows_4x4 = GetNumUnit4x4(width_);
+ const int num_cols_4x4 = GetNumUnit4x4(height_);
+ const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
+ num_coding_frames);
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ partition_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.partition_info[j];
+ }
+ }
+ simple_encode.EndEncode();
+ // The second encode.
+ SimpleEncode simple_encode_2(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode_2.ComputeFirstPassStats();
+ const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
+ simple_encode_2.StartEncode();
+ for (int i = 0; i < num_coding_frames_2; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode_2.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ EXPECT_EQ(encode_frame_result.partition_info[j].row,
+ partition_info_list[i * num_units_4x4 + j].row);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column,
+ partition_info_list[i * num_units_4x4 + j].column);
+ EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
+ partition_info_list[i * num_units_4x4 + j].row_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
+ partition_info_list[i * num_units_4x4 + j].column_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].width,
+ partition_info_list[i * num_units_4x4 + j].width);
+ EXPECT_EQ(encode_frame_result.partition_info[j].height,
+ partition_info_list[i * num_units_4x4 + j].height);
+ }
+ }
+ simple_encode_2.EndEncode();
+}
+
+// Encode with default VP9 decision first.
+// Get QPs and arf locations from the first encode.
+// Set external arfs and QPs for the second encode.
+// Expect to get matched results.
+TEST_F(SimpleEncodeTest, EncodeConsistencySetExternalGroupOfPicturesMap) {
+ std::vector<int> quantize_index_list;
+ std::vector<uint64_t> ref_sse_list;
+ std::vector<double> ref_psnr_list;
+ std::vector<size_t> ref_bit_size_list;
+ std::vector<int> gop_map(num_frames_, 0);
+ {
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ simple_encode.StartEncode();
+
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ gop_map[coded_show_frame_count] |= kGopMapFlagStart;
+ if (group_of_picture.use_alt_ref) {
+ gop_map[coded_show_frame_count] |= kGopMapFlagUseAltRef;
+ }
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ ref_sse_list.push_back(encode_frame_result.sse);
+ ref_psnr_list.push_back(encode_frame_result.psnr);
+ ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ simple_encode.EndEncode();
+ }
+ {
+ // The second encode with quantize index got from the first encode.
+ // The external arfs are the same as the first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ simple_encode.SetExternalGroupOfPicturesMap(gop_map.data(), gop_map.size());
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(static_cast<size_t>(num_coding_frames),
+ quantize_index_list.size());
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
+ EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
+ EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
+ }
+ simple_encode.EndEncode();
+ }
+}
+
+TEST_F(SimpleEncodeTest, SetExternalGroupOfPicturesMap) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+
+ std::vector<int> gop_map(num_frames_, 0);
+
+ // Should be the first gop group.
+ gop_map[0] = 0;
+
+ // Second gop group with an alt ref.
+ gop_map[5] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
+
+ // Third gop group without an alt ref.
+ gop_map[10] |= kGopMapFlagStart;
+
+ // Last gop group.
+ gop_map[14] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
+
+ simple_encode.SetExternalGroupOfPicturesMap(gop_map.data(), gop_map.size());
+
+ std::vector<int> observed_gop_map =
+ simple_encode.ObserveExternalGroupOfPicturesMap();
+
+ // First gop group.
+ // There is always a key frame at show_idx 0 and key frame should always be
+ // the start of a gop. We expect ObserveExternalGroupOfPicturesMap() will
+ // insert an extra gop start here.
+ EXPECT_EQ(observed_gop_map[0], kGopMapFlagStart | kGopMapFlagUseAltRef);
+
+ // Second gop group with an alt ref.
+ EXPECT_EQ(observed_gop_map[5], kGopMapFlagStart | kGopMapFlagUseAltRef);
+
+ // Third gop group without an alt ref.
+ EXPECT_EQ(observed_gop_map[10], kGopMapFlagStart);
+
+ // Last gop group. The last gop is not supposed to use an alt ref. We expect
+ // ObserveExternalGroupOfPicturesMap() will remove the alt ref flag here.
+ EXPECT_EQ(observed_gop_map[14], kGopMapFlagStart);
+
+ int ref_gop_show_frame_count_list[4] = { 5, 5, 4, 3 };
+ size_t ref_gop_coded_frame_count_list[4] = { 6, 6, 4, 3 };
+ int gop_count = 0;
+
+ simple_encode.StartEncode();
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ EXPECT_EQ(encode_frame_list.size(),
+ ref_gop_coded_frame_count_list[gop_count]);
+ EXPECT_EQ(group_of_picture.show_frame_count,
+ ref_gop_show_frame_count_list[gop_count]);
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ ++gop_count;
+ }
+ EXPECT_EQ(gop_count, 4);
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, GetEncodeFrameInfo) {
+ // Makes sure that the encode_frame_info obtained from GetEncodeFrameInfo()
+ // matches the counterpart in encode_frame_result obtained from EncodeFrame()
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ 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();
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ EXPECT_EQ(encode_frame_info.show_idx, encode_frame_result.show_idx);
+ EXPECT_EQ(encode_frame_info.frame_type, encode_frame_result.frame_type);
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, GetFramePixelCount) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ EXPECT_EQ(simple_encode.GetFramePixelCount(),
+ static_cast<uint64_t>(width_ * height_ * 3 / 2));
+}
+
+} // namespace
+} // namespace vp9
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}