]> granicus.if.org Git - libvpx/blob - test/simple_encode_test.cc
eddd1c59b617d17194c935ef30c1d96fc51d6de4
[libvpx] / test / simple_encode_test.cc
1 /*
2  *  Copyright (c) 2019 The WebM project authors. All Rights Reserved.
3  *
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.
9  */
10
11 #include <math.h>
12 #include <memory>
13 #include <vector>
14 #include "third_party/googletest/src/include/gtest/gtest.h"
15 #include "vp9/simple_encode.h"
16
17 namespace vp9 {
18 namespace {
19
20 // TODO(angirbid): Find a better way to construct encode info
21 const int w = 352;
22 const int h = 288;
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";
28
29 double GetBitrateInKbps(size_t bit_size, int num_frames, int frame_rate_num,
30                         int frame_rate_den) {
31   return static_cast<double>(bit_size) / num_frames * frame_rate_num /
32          frame_rate_den / 1000.0;
33 }
34
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; }
38
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
54     // frame stats
55     EXPECT_EQ(frame_stats[i][data_num - 1], 1);
56   }
57 }
58
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);
65 }
66
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();
83          ++group_index) {
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,
91                 frame_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;
98       ++frame_coding_index;
99     }
100     coded_show_frame_count += group_of_picture.show_frame_count;
101   }
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();
107 }
108
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();
123          ++group_index) {
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);
128       } else {
129         EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 0);
130       }
131     }
132     coded_show_frame_count += group_of_picture.show_frame_count;
133   }
134   simple_encode.EndEncode();
135 }
136
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);
149   }
150   simple_encode.EndEncode();
151 }
152
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;
158   {
159     // The first encode.
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);
172     }
173     simple_encode.EndEncode();
174   }
175   {
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]);
192     }
193     simple_encode.EndEncode();
194   }
195 }
196
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;
203   // The first encode.
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 *
209                                                  num_coding_frames);
210   std::vector<MotionVectorInfo> motion_vector_info_list(num_units_4x4 *
211                                                         num_coding_frames);
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];
221     }
222   }
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);
246
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]);
261     }
262   }
263   simple_encode_2.EndEncode();
264 }
265
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;
272   // The first encode.
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 *
278                                                  num_coding_frames);
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];
287     }
288   }
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);
313     }
314   }
315   simple_encode_2.EndEncode();
316 }
317
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);
328   {
329     // The first encode.
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();
334
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;
342       }
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();
346            ++group_index) {
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);
353       }
354       coded_show_frame_count += group_of_picture.show_frame_count;
355     }
356     simple_encode.EndEncode();
357   }
358   {
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]);
377     }
378     simple_encode.EndEncode();
379   }
380 }
381
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();
386
387   std::vector<int> gop_map(num_frames, 0);
388
389   // Should be the first gop group.
390   gop_map[0] = 0;
391
392   // Second gop group with an alt ref.
393   gop_map[5] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
394
395   // Third gop group without an alt ref.
396   gop_map[10] |= kGopMapFlagStart;
397
398   // Last gop group.
399   gop_map[14] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
400
401   simple_encode.SetExternalGroupOfPicturesMap(gop_map);
402
403   std::vector<int> observed_gop_map =
404       simple_encode.ObserveExternalGroupOfPicturesMap();
405
406   // First gop group.
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);
411
412   // Second gop group with an alt ref.
413   EXPECT_EQ(observed_gop_map[5], kGopMapFlagStart | kGopMapFlagUseAltRef);
414
415   // Third gop group without an alt ref.
416   EXPECT_EQ(observed_gop_map[10], kGopMapFlagStart);
417
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);
421
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 };
424   int gop_count = 0;
425
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();
438          ++group_index) {
439       EncodeFrameResult encode_frame_result;
440       simple_encode.EncodeFrame(&encode_frame_result);
441     }
442     coded_show_frame_count += group_of_picture.show_frame_count;
443     ++gop_count;
444   }
445   EXPECT_EQ(gop_count, 4);
446   simple_encode.EndEncode();
447 }
448
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);
463   }
464   simple_encode.EndEncode();
465 }
466
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));
472 }
473
474 }  // namespace
475 }  // namespace vp9