2 * Copyright (c) 2019 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 #include "third_party/googletest/src/include/gtest/gtest.h"
15 #include "vp9/simple_encode.h"
20 // TODO(angirbid): Find a better way to construct encode info
23 const int frame_rate_num = 30;
24 const int frame_rate_den = 1;
25 const int target_bitrate = 1000;
26 const int num_frames = 17;
27 const char infile_path[] = "bus_352x288_420_f20_b8.yuv";
29 double GetBitrateInKbps(size_t bit_size, int num_frames, int frame_rate_num,
31 return static_cast<double>(bit_size) / num_frames * frame_rate_num /
32 frame_rate_den / 1000.0;
35 // Returns the number of unit in size of 4.
36 // For example, if size is 7, return 2.
37 int GetNumUnit4x4(int size) { return (size + 3) >> 2; }
39 TEST(SimpleEncode, ComputeFirstPassStats) {
40 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
41 target_bitrate, num_frames, infile_path);
42 simple_encode.ComputeFirstPassStats();
43 std::vector<std::vector<double>> frame_stats =
44 simple_encode.ObserveFirstPassStats();
45 EXPECT_EQ(frame_stats.size(), static_cast<size_t>(num_frames));
46 size_t data_num = frame_stats[0].size();
47 // Read ObserveFirstPassStats before changing FIRSTPASS_STATS.
48 EXPECT_EQ(data_num, static_cast<size_t>(25));
49 for (size_t i = 0; i < frame_stats.size(); ++i) {
50 EXPECT_EQ(frame_stats[i].size(), data_num);
51 // FIRSTPASS_STATS's first element is frame
52 EXPECT_EQ(frame_stats[i][0], i);
53 // FIRSTPASS_STATS's last element is count, and the count is 1 for single
55 EXPECT_EQ(frame_stats[i][data_num - 1], 1);
59 TEST(SimpleEncode, GetCodingFrameNum) {
60 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
61 target_bitrate, num_frames, infile_path);
62 simple_encode.ComputeFirstPassStats();
63 int num_coding_frames = simple_encode.GetCodingFrameNum();
64 EXPECT_EQ(num_coding_frames, 19);
67 TEST(SimpleEncode, EncodeFrame) {
68 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
69 target_bitrate, num_frames, infile_path);
70 simple_encode.ComputeFirstPassStats();
71 int num_coding_frames = simple_encode.GetCodingFrameNum();
72 EXPECT_GE(num_coding_frames, num_frames);
73 simple_encode.StartEncode();
74 size_t total_data_bit_size = 0;
75 int coded_show_frame_count = 0;
76 int frame_coding_index = 0;
77 while (coded_show_frame_count < num_frames) {
78 const GroupOfPicture group_of_picture =
79 simple_encode.ObserveGroupOfPicture();
80 const std::vector<EncodeFrameInfo> &encode_frame_list =
81 group_of_picture.encode_frame_list;
82 for (size_t group_index = 0; group_index < encode_frame_list.size();
84 EncodeFrameResult encode_frame_result;
85 simple_encode.EncodeFrame(&encode_frame_result);
86 EXPECT_EQ(encode_frame_result.show_idx,
87 encode_frame_list[group_index].show_idx);
88 EXPECT_EQ(encode_frame_result.frame_type,
89 encode_frame_list[group_index].frame_type);
90 EXPECT_EQ(encode_frame_list[group_index].coding_index,
92 EXPECT_GE(encode_frame_result.psnr, 34)
93 << "The psnr is supposed to be greater than 34 given the "
94 "target_bitrate 1000 kbps";
95 EXPECT_EQ(encode_frame_result.ref_frame_info,
96 encode_frame_list[group_index].ref_frame_info);
97 total_data_bit_size += encode_frame_result.coding_data_bit_size;
100 coded_show_frame_count += group_of_picture.show_frame_count;
102 const double bitrate = GetBitrateInKbps(total_data_bit_size, num_frames,
103 frame_rate_num, frame_rate_den);
104 const double off_target_threshold = 150;
105 EXPECT_LE(fabs(target_bitrate - bitrate), off_target_threshold);
106 simple_encode.EndEncode();
109 TEST(SimpleEncode, ObserveKeyFrameMap) {
110 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
111 target_bitrate, num_frames, infile_path);
112 simple_encode.ComputeFirstPassStats();
113 std::vector<int> key_frame_map = simple_encode.ObserveKeyFrameMap();
114 EXPECT_EQ(key_frame_map.size(), static_cast<size_t>(num_frames));
115 simple_encode.StartEncode();
116 int coded_show_frame_count = 0;
117 while (coded_show_frame_count < num_frames) {
118 const GroupOfPicture group_of_picture =
119 simple_encode.ObserveGroupOfPicture();
120 const std::vector<EncodeFrameInfo> &encode_frame_list =
121 group_of_picture.encode_frame_list;
122 for (size_t group_index = 0; group_index < encode_frame_list.size();
124 EncodeFrameResult encode_frame_result;
125 simple_encode.EncodeFrame(&encode_frame_result);
126 if (encode_frame_result.frame_type == kFrameTypeKey) {
127 EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 1);
129 EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 0);
132 coded_show_frame_count += group_of_picture.show_frame_count;
134 simple_encode.EndEncode();
137 TEST(SimpleEncode, EncodeFrameWithQuantizeIndex) {
138 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
139 target_bitrate, num_frames, infile_path);
140 simple_encode.ComputeFirstPassStats();
141 int num_coding_frames = simple_encode.GetCodingFrameNum();
142 simple_encode.StartEncode();
143 for (int i = 0; i < num_coding_frames; ++i) {
144 const int assigned_quantize_index = 100 + i;
145 EncodeFrameResult encode_frame_result;
146 simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
147 assigned_quantize_index);
148 EXPECT_EQ(encode_frame_result.quantize_index, assigned_quantize_index);
150 simple_encode.EndEncode();
153 TEST(SimpleEncode, EncodeConsistencyTest) {
154 std::vector<int> quantize_index_list;
155 std::vector<uint64_t> ref_sse_list;
156 std::vector<double> ref_psnr_list;
157 std::vector<size_t> ref_bit_size_list;
160 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
161 target_bitrate, num_frames, infile_path);
162 simple_encode.ComputeFirstPassStats();
163 const int num_coding_frames = simple_encode.GetCodingFrameNum();
164 simple_encode.StartEncode();
165 for (int i = 0; i < num_coding_frames; ++i) {
166 EncodeFrameResult encode_frame_result;
167 simple_encode.EncodeFrame(&encode_frame_result);
168 quantize_index_list.push_back(encode_frame_result.quantize_index);
169 ref_sse_list.push_back(encode_frame_result.sse);
170 ref_psnr_list.push_back(encode_frame_result.psnr);
171 ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
173 simple_encode.EndEncode();
176 // The second encode with quantize index got from the first encode.
177 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
178 target_bitrate, num_frames, infile_path);
179 simple_encode.ComputeFirstPassStats();
180 const int num_coding_frames = simple_encode.GetCodingFrameNum();
181 EXPECT_EQ(static_cast<size_t>(num_coding_frames),
182 quantize_index_list.size());
183 simple_encode.StartEncode();
184 for (int i = 0; i < num_coding_frames; ++i) {
185 EncodeFrameResult encode_frame_result;
186 simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
187 quantize_index_list[i]);
188 EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
189 EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
190 EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
191 EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
193 simple_encode.EndEncode();
197 // Test the information (partition info and motion vector info) stored in
198 // encoder is the same between two encode runs.
199 TEST(SimpleEncode, EncodeConsistencyTest2) {
200 const int num_rows_4x4 = GetNumUnit4x4(w);
201 const int num_cols_4x4 = GetNumUnit4x4(h);
202 const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
204 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
205 target_bitrate, num_frames, infile_path);
206 simple_encode.ComputeFirstPassStats();
207 const int num_coding_frames = simple_encode.GetCodingFrameNum();
208 std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
210 std::vector<MotionVectorInfo> motion_vector_info_list(num_units_4x4 *
212 simple_encode.StartEncode();
213 for (int i = 0; i < num_coding_frames; ++i) {
214 EncodeFrameResult encode_frame_result;
215 simple_encode.EncodeFrame(&encode_frame_result);
216 for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
217 partition_info_list[i * num_units_4x4 + j] =
218 encode_frame_result.partition_info[j];
219 motion_vector_info_list[i * num_units_4x4 + j] =
220 encode_frame_result.motion_vector_info[j];
223 simple_encode.EndEncode();
224 // The second encode.
225 SimpleEncode simple_encode_2(w, h, frame_rate_num, frame_rate_den,
226 target_bitrate, num_frames, infile_path);
227 simple_encode_2.ComputeFirstPassStats();
228 const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
229 simple_encode_2.StartEncode();
230 for (int i = 0; i < num_coding_frames_2; ++i) {
231 EncodeFrameResult encode_frame_result;
232 simple_encode_2.EncodeFrame(&encode_frame_result);
233 for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
234 EXPECT_EQ(encode_frame_result.partition_info[j].row,
235 partition_info_list[i * num_units_4x4 + j].row);
236 EXPECT_EQ(encode_frame_result.partition_info[j].column,
237 partition_info_list[i * num_units_4x4 + j].column);
238 EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
239 partition_info_list[i * num_units_4x4 + j].row_start);
240 EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
241 partition_info_list[i * num_units_4x4 + j].column_start);
242 EXPECT_EQ(encode_frame_result.partition_info[j].width,
243 partition_info_list[i * num_units_4x4 + j].width);
244 EXPECT_EQ(encode_frame_result.partition_info[j].height,
245 partition_info_list[i * num_units_4x4 + j].height);
247 EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_count,
248 motion_vector_info_list[i * num_units_4x4 + j].mv_count);
249 EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[0],
250 motion_vector_info_list[i * num_units_4x4 + j].ref_frame[0]);
251 EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[1],
252 motion_vector_info_list[i * num_units_4x4 + j].ref_frame[1]);
253 EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[0],
254 motion_vector_info_list[i * num_units_4x4 + j].mv_row[0]);
255 EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[0],
256 motion_vector_info_list[i * num_units_4x4 + j].mv_column[0]);
257 EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[1],
258 motion_vector_info_list[i * num_units_4x4 + j].mv_row[1]);
259 EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[1],
260 motion_vector_info_list[i * num_units_4x4 + j].mv_column[1]);
263 simple_encode_2.EndEncode();
266 // Test the information stored in encoder is the same between two encode runs.
267 TEST(SimpleEncode, EncodeConsistencyTest3) {
268 std::vector<int> quantize_index_list;
269 const int num_rows_4x4 = GetNumUnit4x4(w);
270 const int num_cols_4x4 = GetNumUnit4x4(h);
271 const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
273 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
274 target_bitrate, num_frames, infile_path);
275 simple_encode.ComputeFirstPassStats();
276 const int num_coding_frames = simple_encode.GetCodingFrameNum();
277 std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
279 simple_encode.StartEncode();
280 for (int i = 0; i < num_coding_frames; ++i) {
281 EncodeFrameResult encode_frame_result;
282 simple_encode.EncodeFrame(&encode_frame_result);
283 quantize_index_list.push_back(encode_frame_result.quantize_index);
284 for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
285 partition_info_list[i * num_units_4x4 + j] =
286 encode_frame_result.partition_info[j];
289 simple_encode.EndEncode();
290 // The second encode.
291 SimpleEncode simple_encode_2(w, h, frame_rate_num, frame_rate_den,
292 target_bitrate, num_frames, infile_path);
293 simple_encode_2.ComputeFirstPassStats();
294 const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
295 simple_encode_2.StartEncode();
296 for (int i = 0; i < num_coding_frames_2; ++i) {
297 EncodeFrameResult encode_frame_result;
298 simple_encode_2.EncodeFrameWithQuantizeIndex(&encode_frame_result,
299 quantize_index_list[i]);
300 for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
301 EXPECT_EQ(encode_frame_result.partition_info[j].row,
302 partition_info_list[i * num_units_4x4 + j].row);
303 EXPECT_EQ(encode_frame_result.partition_info[j].column,
304 partition_info_list[i * num_units_4x4 + j].column);
305 EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
306 partition_info_list[i * num_units_4x4 + j].row_start);
307 EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
308 partition_info_list[i * num_units_4x4 + j].column_start);
309 EXPECT_EQ(encode_frame_result.partition_info[j].width,
310 partition_info_list[i * num_units_4x4 + j].width);
311 EXPECT_EQ(encode_frame_result.partition_info[j].height,
312 partition_info_list[i * num_units_4x4 + j].height);
315 simple_encode_2.EndEncode();
318 // Encode with default VP9 decision first.
319 // Get QPs and arf locations from the first encode.
320 // Set external arfs and QPs for the second encode.
321 // Expect to get matched results.
322 TEST(SimpleEncode, EncodeConsistencySetExternalGroupOfPicturesMap) {
323 std::vector<int> quantize_index_list;
324 std::vector<uint64_t> ref_sse_list;
325 std::vector<double> ref_psnr_list;
326 std::vector<size_t> ref_bit_size_list;
327 std::vector<int> gop_map(num_frames, 0);
330 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
331 target_bitrate, num_frames, infile_path);
332 simple_encode.ComputeFirstPassStats();
333 simple_encode.StartEncode();
335 int coded_show_frame_count = 0;
336 while (coded_show_frame_count < num_frames) {
337 const GroupOfPicture group_of_picture =
338 simple_encode.ObserveGroupOfPicture();
339 gop_map[coded_show_frame_count] |= kGopMapFlagStart;
340 if (group_of_picture.use_alt_ref) {
341 gop_map[coded_show_frame_count] |= kGopMapFlagUseAltRef;
343 const std::vector<EncodeFrameInfo> &encode_frame_list =
344 group_of_picture.encode_frame_list;
345 for (size_t group_index = 0; group_index < encode_frame_list.size();
347 EncodeFrameResult encode_frame_result;
348 simple_encode.EncodeFrame(&encode_frame_result);
349 quantize_index_list.push_back(encode_frame_result.quantize_index);
350 ref_sse_list.push_back(encode_frame_result.sse);
351 ref_psnr_list.push_back(encode_frame_result.psnr);
352 ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
354 coded_show_frame_count += group_of_picture.show_frame_count;
356 simple_encode.EndEncode();
359 // The second encode with quantize index got from the first encode.
360 // The external arfs are the same as the first encode.
361 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
362 target_bitrate, num_frames, infile_path);
363 simple_encode.ComputeFirstPassStats();
364 simple_encode.SetExternalGroupOfPicturesMap(gop_map);
365 const int num_coding_frames = simple_encode.GetCodingFrameNum();
366 EXPECT_EQ(static_cast<size_t>(num_coding_frames),
367 quantize_index_list.size());
368 simple_encode.StartEncode();
369 for (int i = 0; i < num_coding_frames; ++i) {
370 EncodeFrameResult encode_frame_result;
371 simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
372 quantize_index_list[i]);
373 EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
374 EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
375 EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
376 EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
378 simple_encode.EndEncode();
382 TEST(SimpleEncode, SetExternalGroupOfPicturesMap) {
383 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
384 target_bitrate, num_frames, infile_path);
385 simple_encode.ComputeFirstPassStats();
387 std::vector<int> gop_map(num_frames, 0);
389 // Should be the first gop group.
392 // Second gop group with an alt ref.
393 gop_map[5] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
395 // Third gop group without an alt ref.
396 gop_map[10] |= kGopMapFlagStart;
399 gop_map[14] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
401 simple_encode.SetExternalGroupOfPicturesMap(gop_map);
403 std::vector<int> observed_gop_map =
404 simple_encode.ObserveExternalGroupOfPicturesMap();
407 // There is always a key frame at show_idx 0 and key frame should always be
408 // the start of a gop. We expect ObserveExternalGroupOfPicturesMap() will
409 // insert an extra gop start here.
410 EXPECT_EQ(observed_gop_map[0], kGopMapFlagStart | kGopMapFlagUseAltRef);
412 // Second gop group with an alt ref.
413 EXPECT_EQ(observed_gop_map[5], kGopMapFlagStart | kGopMapFlagUseAltRef);
415 // Third gop group without an alt ref.
416 EXPECT_EQ(observed_gop_map[10], kGopMapFlagStart);
418 // Last gop group. The last gop is not supposed to use an alt ref. We expect
419 // ObserveExternalGroupOfPicturesMap() will remove the alt ref flag here.
420 EXPECT_EQ(observed_gop_map[14], kGopMapFlagStart);
422 int ref_gop_show_frame_count_list[4] = { 5, 5, 4, 3 };
423 size_t ref_gop_coded_frame_count_list[4] = { 6, 6, 4, 3 };
426 simple_encode.StartEncode();
427 int coded_show_frame_count = 0;
428 while (coded_show_frame_count < num_frames) {
429 const GroupOfPicture group_of_picture =
430 simple_encode.ObserveGroupOfPicture();
431 const std::vector<EncodeFrameInfo> &encode_frame_list =
432 group_of_picture.encode_frame_list;
433 EXPECT_EQ(encode_frame_list.size(),
434 ref_gop_coded_frame_count_list[gop_count]);
435 EXPECT_EQ(group_of_picture.show_frame_count,
436 ref_gop_show_frame_count_list[gop_count]);
437 for (size_t group_index = 0; group_index < encode_frame_list.size();
439 EncodeFrameResult encode_frame_result;
440 simple_encode.EncodeFrame(&encode_frame_result);
442 coded_show_frame_count += group_of_picture.show_frame_count;
445 EXPECT_EQ(gop_count, 4);
446 simple_encode.EndEncode();
449 TEST(SimpleEncode, GetEncodeFrameInfo) {
450 // Makes sure that the encode_frame_info obtained from GetEncodeFrameInfo()
451 // matches the counterpart in encode_frame_result obtained from EncodeFrame()
452 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
453 target_bitrate, num_frames, infile_path);
454 simple_encode.ComputeFirstPassStats();
455 const int num_coding_frames = simple_encode.GetCodingFrameNum();
456 simple_encode.StartEncode();
457 for (int i = 0; i < num_coding_frames; ++i) {
458 EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo();
459 EncodeFrameResult encode_frame_result;
460 simple_encode.EncodeFrame(&encode_frame_result);
461 EXPECT_EQ(encode_frame_info.show_idx, encode_frame_result.show_idx);
462 EXPECT_EQ(encode_frame_info.frame_type, encode_frame_result.frame_type);
464 simple_encode.EndEncode();
467 TEST(SimpleEncode, GetFramePixelCount) {
468 SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
469 target_bitrate, num_frames, infile_path);
470 EXPECT_EQ(simple_encode.GetFramePixelCount(),
471 static_cast<uint64_t>(w * h * 3 / 2));