| /* |
| * 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 "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 std::string in_file_path_str_ = "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_, |
| 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_, |
| 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] > 0) + |
| (fps_motion_vectors[i][j].ref_frame[1] > 0); |
| 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_, |
| 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_, |
| 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_, |
| 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, EncodeFrameWithQuantizeIndex) { |
| 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) { |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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_, |
| 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(); |
| } |