h264_poc_unittest.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <stdint.h>
  5. #include "base/files/file_path.h"
  6. #include "base/files/memory_mapped_file.h"
  7. #include "media/base/test_data_util.h"
  8. #include "media/video/h264_parser.h"
  9. #include "media/video/h264_poc.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace media {
  12. class H264POCTest : public testing::Test {
  13. public:
  14. H264POCTest() : sps_(), slice_hdr_() {
  15. // Default every frame to be a reference frame.
  16. slice_hdr_.nal_ref_idc = 1;
  17. }
  18. H264POCTest(const H264POCTest&) = delete;
  19. H264POCTest& operator=(const H264POCTest&) = delete;
  20. protected:
  21. void ComputePOC() {
  22. poc_ = h264_poc_.ComputePicOrderCnt(&sps_, slice_hdr_);
  23. // Clear MMCO5.
  24. slice_hdr_.adaptive_ref_pic_marking_mode_flag = false;
  25. slice_hdr_.ref_pic_marking[0].memory_mgmnt_control_operation = 0;
  26. slice_hdr_.ref_pic_marking[1].memory_mgmnt_control_operation = 0;
  27. slice_hdr_.ref_pic_marking[2].memory_mgmnt_control_operation = 0;
  28. }
  29. // Also sets as a reference frame and unsets IDR, which is required for
  30. // memory management control operations to be parsed.
  31. void SetMMCO5() {
  32. slice_hdr_.nal_ref_idc = 1;
  33. slice_hdr_.idr_pic_flag = false;
  34. slice_hdr_.adaptive_ref_pic_marking_mode_flag = true;
  35. slice_hdr_.ref_pic_marking[0].memory_mgmnt_control_operation = 6;
  36. slice_hdr_.ref_pic_marking[1].memory_mgmnt_control_operation = 5;
  37. slice_hdr_.ref_pic_marking[2].memory_mgmnt_control_operation = 0;
  38. }
  39. absl::optional<int32_t> poc_;
  40. H264SPS sps_;
  41. H264SliceHeader slice_hdr_;
  42. H264POC h264_poc_;
  43. };
  44. TEST_F(H264POCTest, PicOrderCntType0) {
  45. sps_.pic_order_cnt_type = 0;
  46. sps_.log2_max_pic_order_cnt_lsb_minus4 = 0; // 16
  47. // Initial IDR with POC 0.
  48. slice_hdr_.idr_pic_flag = true;
  49. slice_hdr_.frame_num = 0;
  50. ComputePOC();
  51. ASSERT_TRUE(poc_.has_value());
  52. ASSERT_EQ(0, *poc_);
  53. // Ref frame with POC lsb 8.
  54. slice_hdr_.idr_pic_flag = false;
  55. slice_hdr_.frame_num = 1;
  56. slice_hdr_.pic_order_cnt_lsb = 8;
  57. ComputePOC();
  58. ASSERT_TRUE(poc_.has_value());
  59. ASSERT_EQ(8, *poc_);
  60. // Ref frame with POC lsb 0. This should be detected as wrapping, as the
  61. // (negative) gap is at least half the maximum.
  62. slice_hdr_.pic_order_cnt_lsb = 0;
  63. slice_hdr_.frame_num = 2;
  64. ComputePOC();
  65. ASSERT_TRUE(poc_.has_value());
  66. ASSERT_EQ(16, *poc_);
  67. // Ref frame with POC lsb 9. This should be detected as negative wrapping,
  68. // as the (positive) gap is more than half the maximum.
  69. slice_hdr_.pic_order_cnt_lsb = 9;
  70. slice_hdr_.frame_num = 3;
  71. ComputePOC();
  72. ASSERT_TRUE(poc_.has_value());
  73. ASSERT_EQ(9, *poc_);
  74. }
  75. TEST_F(H264POCTest, PicOrderCntType0_WithMMCO5) {
  76. sps_.pic_order_cnt_type = 0;
  77. sps_.log2_max_pic_order_cnt_lsb_minus4 = 0; // 16
  78. // Initial IDR with POC 0.
  79. slice_hdr_.idr_pic_flag = true;
  80. slice_hdr_.frame_num = 0;
  81. ComputePOC();
  82. ASSERT_TRUE(poc_.has_value());
  83. ASSERT_EQ(0, *poc_);
  84. // Skip ahead.
  85. slice_hdr_.idr_pic_flag = false;
  86. slice_hdr_.frame_num = 1;
  87. slice_hdr_.pic_order_cnt_lsb = 8;
  88. ComputePOC();
  89. ASSERT_TRUE(poc_.has_value());
  90. ASSERT_EQ(8, *poc_);
  91. slice_hdr_.frame_num = 2;
  92. slice_hdr_.pic_order_cnt_lsb = 0;
  93. ComputePOC();
  94. ASSERT_TRUE(poc_.has_value());
  95. ASSERT_EQ(16, *poc_);
  96. slice_hdr_.frame_num = 3;
  97. slice_hdr_.pic_order_cnt_lsb = 8;
  98. ComputePOC();
  99. ASSERT_TRUE(poc_.has_value());
  100. ASSERT_EQ(24, *poc_);
  101. // MMCO5 resets to 0.
  102. slice_hdr_.frame_num = 4;
  103. slice_hdr_.pic_order_cnt_lsb = 0;
  104. SetMMCO5();
  105. ComputePOC();
  106. ASSERT_TRUE(poc_.has_value());
  107. ASSERT_EQ(0, *poc_);
  108. // Still detected as positive wrapping.
  109. slice_hdr_.frame_num = 5;
  110. slice_hdr_.pic_order_cnt_lsb = 8;
  111. ComputePOC();
  112. ASSERT_TRUE(poc_.has_value());
  113. ASSERT_EQ(24, *poc_);
  114. }
  115. TEST_F(H264POCTest, PicOrderCntType1) {
  116. sps_.pic_order_cnt_type = 1;
  117. sps_.log2_max_frame_num_minus4 = 0; // 16
  118. sps_.num_ref_frames_in_pic_order_cnt_cycle = 2;
  119. sps_.expected_delta_per_pic_order_cnt_cycle = 3;
  120. sps_.offset_for_ref_frame[0] = 1;
  121. sps_.offset_for_ref_frame[1] = 2;
  122. // Initial IDR with POC 0.
  123. slice_hdr_.idr_pic_flag = true;
  124. slice_hdr_.frame_num = 0;
  125. ComputePOC();
  126. ASSERT_TRUE(poc_.has_value());
  127. ASSERT_EQ(0, *poc_);
  128. // Ref frame.
  129. slice_hdr_.idr_pic_flag = false;
  130. slice_hdr_.frame_num = 1;
  131. ComputePOC();
  132. ASSERT_TRUE(poc_.has_value());
  133. ASSERT_EQ(1, *poc_);
  134. // Ref frame.
  135. slice_hdr_.frame_num = 2;
  136. ComputePOC();
  137. ASSERT_TRUE(poc_.has_value());
  138. ASSERT_EQ(3, *poc_);
  139. // Ref frame.
  140. slice_hdr_.frame_num = 3;
  141. ComputePOC();
  142. ASSERT_TRUE(poc_.has_value());
  143. ASSERT_EQ(4, *poc_);
  144. // Ref frame.
  145. slice_hdr_.frame_num = 4;
  146. ComputePOC();
  147. ASSERT_TRUE(poc_.has_value());
  148. ASSERT_EQ(6, *poc_);
  149. // Ref frame, detected as wrapping (ie, this is frame 16).
  150. slice_hdr_.frame_num = 0;
  151. ComputePOC();
  152. ASSERT_TRUE(poc_.has_value());
  153. ASSERT_EQ(24, *poc_);
  154. }
  155. TEST_F(H264POCTest, PicOrderCntType1_WithMMCO5) {
  156. sps_.pic_order_cnt_type = 1;
  157. sps_.log2_max_frame_num_minus4 = 0; // 16
  158. sps_.num_ref_frames_in_pic_order_cnt_cycle = 2;
  159. sps_.expected_delta_per_pic_order_cnt_cycle = 3;
  160. sps_.offset_for_ref_frame[0] = 1;
  161. sps_.offset_for_ref_frame[1] = 2;
  162. // Initial IDR with POC 0.
  163. slice_hdr_.idr_pic_flag = true;
  164. slice_hdr_.frame_num = 0;
  165. ComputePOC();
  166. ASSERT_TRUE(poc_.has_value());
  167. ASSERT_EQ(0, *poc_);
  168. // Ref frame.
  169. slice_hdr_.idr_pic_flag = false;
  170. slice_hdr_.frame_num = 1;
  171. ComputePOC();
  172. ASSERT_TRUE(poc_.has_value());
  173. ASSERT_EQ(1, *poc_);
  174. // Ref frame, detected as wrapping.
  175. SetMMCO5();
  176. slice_hdr_.frame_num = 0;
  177. ComputePOC();
  178. ASSERT_TRUE(poc_.has_value());
  179. ASSERT_EQ(0, *poc_);
  180. // Ref frame, wrapping from before has been cleared.
  181. slice_hdr_.frame_num = 1;
  182. ComputePOC();
  183. ASSERT_TRUE(poc_.has_value());
  184. ASSERT_EQ(1, *poc_);
  185. }
  186. // |frame_num| values may be duplicated by non-reference frames.
  187. TEST_F(H264POCTest, PicOrderCntType1_DupFrameNum) {
  188. sps_.pic_order_cnt_type = 1;
  189. sps_.log2_max_frame_num_minus4 = 0; // 16
  190. sps_.num_ref_frames_in_pic_order_cnt_cycle = 2;
  191. sps_.expected_delta_per_pic_order_cnt_cycle = 3;
  192. sps_.offset_for_ref_frame[0] = 1;
  193. sps_.offset_for_ref_frame[1] = 2;
  194. // Initial IDR with POC 0.
  195. slice_hdr_.idr_pic_flag = true;
  196. slice_hdr_.frame_num = 0;
  197. ComputePOC();
  198. ASSERT_TRUE(poc_.has_value());
  199. ASSERT_EQ(0, *poc_);
  200. // Ref frame.
  201. slice_hdr_.idr_pic_flag = false;
  202. slice_hdr_.frame_num = 1;
  203. ComputePOC();
  204. ASSERT_TRUE(poc_.has_value());
  205. ASSERT_EQ(1, *poc_);
  206. // Duplicate |frame_num| frame.
  207. slice_hdr_.nal_ref_idc = 0;
  208. slice_hdr_.frame_num = 1;
  209. slice_hdr_.delta_pic_order_cnt0 = 2;
  210. ComputePOC();
  211. ASSERT_TRUE(poc_.has_value());
  212. ASSERT_EQ(2, *poc_);
  213. }
  214. TEST_F(H264POCTest, PicOrderCntType2) {
  215. sps_.pic_order_cnt_type = 2;
  216. // Initial IDR with POC 0.
  217. slice_hdr_.idr_pic_flag = true;
  218. slice_hdr_.frame_num = 0;
  219. ComputePOC();
  220. ASSERT_TRUE(poc_.has_value());
  221. ASSERT_EQ(0, *poc_);
  222. // Ref frame.
  223. slice_hdr_.idr_pic_flag = false;
  224. slice_hdr_.frame_num = 1;
  225. ComputePOC();
  226. ASSERT_TRUE(poc_.has_value());
  227. ASSERT_EQ(2, *poc_);
  228. // Ref frame.
  229. slice_hdr_.frame_num = 2;
  230. ComputePOC();
  231. ASSERT_TRUE(poc_.has_value());
  232. ASSERT_EQ(4, *poc_);
  233. // Ref frame.
  234. slice_hdr_.frame_num = 3;
  235. ComputePOC();
  236. ASSERT_TRUE(poc_.has_value());
  237. ASSERT_EQ(6, *poc_);
  238. // Ref frame.
  239. slice_hdr_.frame_num = 4;
  240. ComputePOC();
  241. ASSERT_TRUE(poc_.has_value());
  242. ASSERT_EQ(8, *poc_);
  243. // Ref frame, detected as wrapping (ie, this is frame 16).
  244. slice_hdr_.frame_num = 0;
  245. ComputePOC();
  246. ASSERT_TRUE(poc_.has_value());
  247. ASSERT_EQ(32, *poc_);
  248. }
  249. TEST_F(H264POCTest, PicOrderCntType2_WithMMCO5) {
  250. sps_.pic_order_cnt_type = 2;
  251. // Initial IDR with POC 0.
  252. slice_hdr_.idr_pic_flag = true;
  253. slice_hdr_.frame_num = 0;
  254. ComputePOC();
  255. ASSERT_TRUE(poc_.has_value());
  256. ASSERT_EQ(0, *poc_);
  257. // Ref frame.
  258. slice_hdr_.idr_pic_flag = false;
  259. slice_hdr_.frame_num = 1;
  260. ComputePOC();
  261. ASSERT_TRUE(poc_.has_value());
  262. ASSERT_EQ(2, *poc_);
  263. // Ref frame, detected as wrapping.
  264. SetMMCO5();
  265. slice_hdr_.frame_num = 0;
  266. ComputePOC();
  267. ASSERT_TRUE(poc_.has_value());
  268. ASSERT_EQ(0, *poc_);
  269. // Ref frame, wrapping from before has been cleared.
  270. slice_hdr_.frame_num = 1;
  271. ComputePOC();
  272. ASSERT_TRUE(poc_.has_value());
  273. ASSERT_EQ(2, *poc_);
  274. }
  275. } // namespace media