h265_nalu_parser_unittest.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright 2015 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 <memory>
  5. #include <string>
  6. #include "base/files/file_path.h"
  7. #include "base/files/memory_mapped_file.h"
  8. #include "base/logging.h"
  9. #include "media/base/subsample_entry.h"
  10. #include "media/base/test_data_util.h"
  11. #include "media/video/h265_nalu_parser.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. namespace media {
  14. namespace {
  15. struct HevcTestData {
  16. std::string file_name;
  17. // Number of NALUs in the test stream to be parsed.
  18. int num_nalus;
  19. };
  20. } // namespace
  21. class H265NaluParserTest : public ::testing::Test {
  22. protected:
  23. void LoadParserFile(std::string file_name) {
  24. parser_.Reset();
  25. base::FilePath file_path = GetTestDataFilePath(file_name);
  26. stream_ = std::make_unique<base::MemoryMappedFile>();
  27. ASSERT_TRUE(stream_->Initialize(file_path))
  28. << "Couldn't open stream file: " << file_path.MaybeAsASCII();
  29. parser_.SetStream(stream_->data(), stream_->length());
  30. }
  31. bool ParseNalusUntilNut(H265NALU* target_nalu, H265NALU::Type nalu_type) {
  32. while (true) {
  33. H265NaluParser::Result res = parser_.AdvanceToNextNALU(target_nalu);
  34. if (res == H265NaluParser::kEOStream) {
  35. return false;
  36. }
  37. EXPECT_EQ(res, H265NaluParser::kOk);
  38. if (target_nalu->nal_unit_type == nalu_type)
  39. return true;
  40. }
  41. }
  42. H265NaluParser parser_;
  43. std::unique_ptr<base::MemoryMappedFile> stream_;
  44. };
  45. TEST_F(H265NaluParserTest, RawHevcStreamFileParsing) {
  46. HevcTestData test_data[] = {
  47. {"bear.hevc", 35},
  48. {"bbb.hevc", 64},
  49. };
  50. for (const auto& data : test_data) {
  51. LoadParserFile(data.file_name);
  52. // Parse until the end of stream/unsupported stream/error in stream is
  53. // found.
  54. int num_parsed_nalus = 0;
  55. while (true) {
  56. H265NALU nalu;
  57. H265NaluParser::Result res = parser_.AdvanceToNextNALU(&nalu);
  58. if (res == H265NaluParser::kEOStream) {
  59. DVLOG(1) << "Number of successfully parsed NALUs before EOS: "
  60. << num_parsed_nalus;
  61. EXPECT_EQ(data.num_nalus, num_parsed_nalus);
  62. break;
  63. }
  64. EXPECT_EQ(res, H265NaluParser::kOk);
  65. ++num_parsed_nalus;
  66. DVLOG(4) << "Found NALU " << nalu.nal_unit_type;
  67. EXPECT_EQ(res, H265NaluParser::kOk);
  68. }
  69. }
  70. }
  71. // Verify that GetCurrentSubsamples works.
  72. TEST_F(H265NaluParserTest, GetCurrentSubsamplesNormal) {
  73. constexpr uint8_t kStream[] = {
  74. // First NALU.
  75. // Clear bytes = 5.
  76. 0x00, 0x00, 0x01, // start code.
  77. 0x28, 0x00, // Nalu type = 20, IDR slice.
  78. // Below is bogus data.
  79. // Encrypted bytes = 15.
  80. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03,
  81. 0x04, 0x05, 0x06,
  82. // Clear bytes = 5.
  83. 0x07, 0x00, 0x01, 0x02, 0x03,
  84. // Encrypted until next NALU. Encrypted bytes = 20.
  85. 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  86. // Note that this is still in the encrypted region but looks like a start
  87. // code.
  88. 0x00, 0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07,
  89. // Second NALU. Completely clear.
  90. // Clear bytes = 11.
  91. 0x00, 0x00, 0x01, // start code.
  92. 0x42, 0x00, // nalu type = 33, SPS.
  93. // Bogus data.
  94. 0xff, 0xfe, 0xfd, 0xee, 0x12, 0x33,
  95. };
  96. std::vector<SubsampleEntry> subsamples;
  97. subsamples.emplace_back(5u, 15u);
  98. subsamples.emplace_back(5u, 20u);
  99. subsamples.emplace_back(11u, 0u);
  100. H265NaluParser parser;
  101. parser.SetEncryptedStream(kStream, std::size(kStream), subsamples);
  102. H265NALU nalu;
  103. EXPECT_EQ(H265NaluParser::kOk, parser.AdvanceToNextNALU(&nalu));
  104. EXPECT_EQ(H265NALU::IDR_N_LP, nalu.nal_unit_type);
  105. auto nalu_subsamples = parser.GetCurrentSubsamples();
  106. EXPECT_EQ(2u, nalu_subsamples.size());
  107. // Note that nalu->data starts from the NALU header, i.e. does not include
  108. // the start code.
  109. EXPECT_EQ(2u, nalu_subsamples[0].clear_bytes);
  110. EXPECT_EQ(15u, nalu_subsamples[0].cypher_bytes);
  111. EXPECT_EQ(5u, nalu_subsamples[1].clear_bytes);
  112. EXPECT_EQ(20u, nalu_subsamples[1].cypher_bytes);
  113. // Make sure that it reached the next NALU.
  114. EXPECT_EQ(H265NaluParser::kOk, parser.AdvanceToNextNALU(&nalu));
  115. EXPECT_EQ(H265NALU::SPS_NUT, nalu.nal_unit_type);
  116. nalu_subsamples = parser.GetCurrentSubsamples();
  117. EXPECT_EQ(1u, nalu_subsamples.size());
  118. EXPECT_EQ(8u, nalu_subsamples[0].clear_bytes);
  119. EXPECT_EQ(0u, nalu_subsamples[0].cypher_bytes);
  120. }
  121. // Verify that subsamples starting at non-NALU boundary also works.
  122. TEST_F(H265NaluParserTest,
  123. GetCurrentSubsamplesSubsampleNotStartingAtNaluBoundary) {
  124. constexpr uint8_t kStream[] = {
  125. // First NALU.
  126. // Clear bytes = 5.
  127. 0x00, 0x00, 0x01, // start code.
  128. 0x28, 0x00, // Nalu type = 20, IDR slice.
  129. // Below is bogus data.
  130. // Encrypted bytes = 24.
  131. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03,
  132. 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  133. // Clear bytes = 19. The rest is in the clear. Note that this is not at
  134. // a NALU boundary and a NALU starts below.
  135. 0xaa, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  136. // Second NALU. Completely clear.
  137. 0x00, 0x00, 0x01, // start code.
  138. 0x42, 0x00, // nalu type = 33, SPS.
  139. // Bogus data.
  140. 0xff, 0xfe, 0xfd, 0xee, 0x12, 0x33,
  141. };
  142. std::vector<SubsampleEntry> subsamples;
  143. subsamples.emplace_back(5u, 24u);
  144. subsamples.emplace_back(19u, 0u);
  145. H265NaluParser parser;
  146. parser.SetEncryptedStream(kStream, std::size(kStream), subsamples);
  147. H265NALU nalu;
  148. EXPECT_EQ(H265NaluParser::kOk, parser.AdvanceToNextNALU(&nalu));
  149. EXPECT_EQ(H265NALU::IDR_N_LP, nalu.nal_unit_type);
  150. auto nalu_subsamples = parser.GetCurrentSubsamples();
  151. EXPECT_EQ(2u, nalu_subsamples.size());
  152. // Note that nalu->data starts from the NALU header, i.e. does not include
  153. // the start code.
  154. EXPECT_EQ(2u, nalu_subsamples[0].clear_bytes);
  155. EXPECT_EQ(24u, nalu_subsamples[0].cypher_bytes);
  156. // The nalu ends with 8 more clear bytes. The last 10 bytes should be
  157. // associated with the next nalu.
  158. EXPECT_EQ(8u, nalu_subsamples[1].clear_bytes);
  159. EXPECT_EQ(0u, nalu_subsamples[1].cypher_bytes);
  160. EXPECT_EQ(H265NaluParser::kOk, parser.AdvanceToNextNALU(&nalu));
  161. EXPECT_EQ(H265NALU::SPS_NUT, nalu.nal_unit_type);
  162. nalu_subsamples = parser.GetCurrentSubsamples();
  163. EXPECT_EQ(1u, nalu_subsamples.size());
  164. // Although the input had 10 more bytes, since nalu->data starts from the nalu
  165. // header, there's only 7 more bytes left.
  166. EXPECT_EQ(8u, nalu_subsamples[0].clear_bytes);
  167. EXPECT_EQ(0u, nalu_subsamples[0].cypher_bytes);
  168. }
  169. } // namespace media