box_reader_unittest.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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 "media/formats/mp4/box_reader.h"
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include <memory>
  8. #include "base/logging.h"
  9. #include "media/base/mock_media_log.h"
  10. #include "media/formats/mp4/box_definitions.h"
  11. #include "media/formats/mp4/parse_result.h"
  12. #include "media/formats/mp4/rcheck.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. using ::testing::HasSubstr;
  16. using ::testing::StrictMock;
  17. namespace media {
  18. namespace mp4 {
  19. static const uint8_t kSkipBox[] = {
  20. // Top-level test box containing three children
  21. 0x00, 0x00, 0x00, 0x40, 's', 'k', 'i', 'p', 0x01, 0x02, 0x03, 0x04, 0x05,
  22. 0x06, 0x07, 0x08, 0xf9, 0x0a, 0x0b, 0x0c, 0xfd, 0x0e, 0x0f, 0x10,
  23. // Ordinary (8-byte header) child box
  24. 0x00, 0x00, 0x00, 0x0c, 'p', 's', 's', 'h', 0xde, 0xad, 0xbe, 0xef,
  25. // Extended-size header child box
  26. 0x00, 0x00, 0x00, 0x01, 'p', 's', 's', 'h', 0x00, 0x00, 0x00, 0x00, 0x00,
  27. 0x00, 0x00, 0x14, 0xfa, 0xce, 0xca, 0xfe,
  28. // Empty free box
  29. 0x00, 0x00, 0x00, 0x08, 'f', 'r', 'e', 'e',
  30. // Trailing garbage
  31. 0x00};
  32. struct FreeBox : Box {
  33. bool Parse(BoxReader* reader) override {
  34. return true;
  35. }
  36. FourCC BoxType() const override { return FOURCC_FREE; }
  37. };
  38. struct PsshBox : Box {
  39. uint32_t val;
  40. bool Parse(BoxReader* reader) override {
  41. return reader->Read4(&val);
  42. }
  43. FourCC BoxType() const override { return FOURCC_PSSH; }
  44. };
  45. struct SkipBox : Box {
  46. uint8_t a, b;
  47. uint16_t c;
  48. int32_t d;
  49. int64_t e;
  50. std::vector<PsshBox> kids;
  51. FreeBox mpty;
  52. bool Parse(BoxReader* reader) override {
  53. RCHECK(reader->ReadFullBoxHeader() &&
  54. reader->Read1(&a) &&
  55. reader->Read1(&b) &&
  56. reader->Read2(&c) &&
  57. reader->Read4s(&d) &&
  58. reader->Read4sInto8s(&e));
  59. return reader->ScanChildren() &&
  60. reader->ReadChildren(&kids) &&
  61. reader->MaybeReadChild(&mpty);
  62. }
  63. FourCC BoxType() const override { return FOURCC_SKIP; }
  64. SkipBox();
  65. ~SkipBox() override;
  66. };
  67. SkipBox::SkipBox() = default;
  68. SkipBox::~SkipBox() = default;
  69. class BoxReaderTest : public testing::Test {
  70. public:
  71. BoxReaderTest() = default;
  72. protected:
  73. std::vector<uint8_t> GetBuf() {
  74. return std::vector<uint8_t>(kSkipBox, kSkipBox + sizeof(kSkipBox));
  75. }
  76. void TestTopLevelBox(const uint8_t* data, size_t data_size, uint32_t fourCC) {
  77. std::vector<uint8_t> buf(data, data + data_size);
  78. std::unique_ptr<BoxReader> reader;
  79. ParseResult result =
  80. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  81. EXPECT_EQ(result, ParseResult::kOk);
  82. EXPECT_TRUE(reader);
  83. EXPECT_EQ(fourCC, static_cast<uint32_t>(reader->type()));
  84. EXPECT_EQ(reader->box_size(), data_size);
  85. }
  86. template <typename ChildType>
  87. void TestParsing32bitOverflow(const uint8_t* buffer,
  88. size_t size,
  89. const std::string& overflow_error) {
  90. // Wrap whatever we're passed in a dummy EMSG so we can satisfy requirements
  91. // for ReadTopLevelBox and to kick off parsing.
  92. std::vector<uint8_t> buffer_wrapper = {
  93. 0x00, 0x00, 0x00, 0x00, // dummy size
  94. 'e', 'm', 's', 'g', // fourcc
  95. };
  96. buffer_wrapper.insert(buffer_wrapper.end(), buffer, buffer + size);
  97. // Basic check of the nested buffer size. If box_size > buffer size the test
  98. // will exit early (waiting for more bytes to be appended).
  99. ASSERT_TRUE(base::IsValueInRangeForNumericType<uint8_t>(size));
  100. ASSERT_LE(buffer[3], size);
  101. // Update the size (keep it simple).
  102. ASSERT_TRUE(
  103. base::IsValueInRangeForNumericType<uint8_t>(buffer_wrapper.size()));
  104. buffer_wrapper[3] = buffer_wrapper.size();
  105. std::unique_ptr<BoxReader> reader;
  106. ParseResult result = BoxReader::ReadTopLevelBox(
  107. &buffer_wrapper[0], buffer_wrapper.size(), &media_log_, &reader);
  108. EXPECT_EQ(result, ParseResult::kOk);
  109. EXPECT_TRUE(reader);
  110. EXPECT_EQ(FOURCC_EMSG, reader->type());
  111. // Overflow is only triggered/caught on 32-bit systems. 64-bit systems will
  112. // instead fail parsing because tests are written such that |buffer| never
  113. // contains enough bytes for parsing to succeed.
  114. #if defined(ARCH_CPU_32_BITS)
  115. const int kOverflowLogCount = 1;
  116. #else
  117. const int kOverflowLogCount = 0;
  118. #endif
  119. if (!overflow_error.empty())
  120. EXPECT_MEDIA_LOG(HasSubstr(overflow_error)).Times(kOverflowLogCount);
  121. std::vector<ChildType> children;
  122. EXPECT_FALSE(reader->ReadAllChildrenAndCheckFourCC(&children));
  123. }
  124. StrictMock<MockMediaLog> media_log_;
  125. };
  126. TEST_F(BoxReaderTest, ExpectedOperationTest) {
  127. std::vector<uint8_t> buf = GetBuf();
  128. std::unique_ptr<BoxReader> reader;
  129. ParseResult result =
  130. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  131. EXPECT_EQ(result, ParseResult::kOk);
  132. EXPECT_TRUE(reader);
  133. SkipBox box;
  134. EXPECT_TRUE(box.Parse(reader.get()));
  135. EXPECT_EQ(0x01, reader->version());
  136. EXPECT_EQ(0x020304u, reader->flags());
  137. EXPECT_EQ(0x05, box.a);
  138. EXPECT_EQ(0x06, box.b);
  139. EXPECT_EQ(0x0708, box.c);
  140. EXPECT_EQ(static_cast<int32_t>(0xf90a0b0c), box.d);
  141. EXPECT_EQ(static_cast<int32_t>(0xfd0e0f10), box.e);
  142. EXPECT_EQ(2u, box.kids.size());
  143. EXPECT_EQ(0xdeadbeef, box.kids[0].val);
  144. EXPECT_EQ(0xfacecafe, box.kids[1].val);
  145. // Accounting for the extra byte outside of the box above
  146. EXPECT_EQ(buf.size(), static_cast<uint64_t>(reader->box_size() + 1));
  147. }
  148. TEST_F(BoxReaderTest, OuterTooShortTest) {
  149. std::vector<uint8_t> buf = GetBuf();
  150. // Create a soft failure by truncating the outer box.
  151. std::unique_ptr<BoxReader> r;
  152. ParseResult result =
  153. BoxReader::ReadTopLevelBox(&buf[0], buf.size() - 2, &media_log_, &r);
  154. EXPECT_EQ(result, ParseResult::kNeedMoreData);
  155. EXPECT_FALSE(r);
  156. }
  157. TEST_F(BoxReaderTest, InnerTooLongTest) {
  158. std::vector<uint8_t> buf = GetBuf();
  159. // Make an inner box too big for its outer box.
  160. buf[25] = 1;
  161. std::unique_ptr<BoxReader> reader;
  162. ParseResult result =
  163. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  164. EXPECT_EQ(result, ParseResult::kOk);
  165. SkipBox box;
  166. EXPECT_FALSE(box.Parse(reader.get()));
  167. }
  168. TEST_F(BoxReaderTest, WrongFourCCTest) {
  169. std::vector<uint8_t> buf = GetBuf();
  170. // Set an unrecognized top-level FourCC.
  171. buf[4] = 0x44;
  172. buf[5] = 0x41;
  173. buf[6] = 0x4c;
  174. buf[7] = 0x45;
  175. // Also, tests that the offending FourCC is emitted only in a debug media log.
  176. EXPECT_MEDIA_LOG(
  177. AllOf(HasSubstr("error"),
  178. HasSubstr("Invalid top-level ISO BMFF box type DALE")));
  179. std::unique_ptr<BoxReader> reader;
  180. ParseResult result =
  181. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  182. EXPECT_FALSE(reader);
  183. EXPECT_EQ(result, ParseResult::kError);
  184. }
  185. TEST_F(BoxReaderTest, ScanChildrenTest) {
  186. std::vector<uint8_t> buf = GetBuf();
  187. std::unique_ptr<BoxReader> reader;
  188. ParseResult result =
  189. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  190. EXPECT_EQ(result, ParseResult::kOk);
  191. EXPECT_TRUE(reader->SkipBytes(16) && reader->ScanChildren());
  192. FreeBox free;
  193. EXPECT_TRUE(reader->ReadChild(&free));
  194. EXPECT_FALSE(reader->ReadChild(&free));
  195. EXPECT_TRUE(reader->MaybeReadChild(&free));
  196. std::vector<PsshBox> kids;
  197. EXPECT_TRUE(reader->ReadChildren(&kids));
  198. EXPECT_EQ(2u, kids.size());
  199. kids.clear();
  200. EXPECT_FALSE(reader->ReadChildren(&kids));
  201. EXPECT_TRUE(reader->MaybeReadChildren(&kids));
  202. }
  203. TEST_F(BoxReaderTest, ReadAllChildrenTest) {
  204. std::vector<uint8_t> buf = GetBuf();
  205. // Modify buffer to exclude its last 'free' box
  206. buf[3] = 0x38;
  207. std::unique_ptr<BoxReader> reader;
  208. ParseResult result =
  209. BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
  210. EXPECT_EQ(result, ParseResult::kOk);
  211. std::vector<PsshBox> kids;
  212. EXPECT_TRUE(reader->SkipBytes(16) && reader->ReadAllChildren(&kids));
  213. EXPECT_EQ(2u, kids.size());
  214. EXPECT_EQ(kids[0].val, 0xdeadbeef); // Ensure order is preserved
  215. }
  216. TEST_F(BoxReaderTest, SkippingBloc) {
  217. static const uint8_t kData[] = {0x00, 0x00, 0x00, 0x09, 'b',
  218. 'l', 'o', 'c', 0x00};
  219. TestTopLevelBox(kData, sizeof(kData), FOURCC_BLOC);
  220. }
  221. TEST_F(BoxReaderTest, SkippingEmsg) {
  222. static const uint8_t kData[] = {
  223. 0x00, 0x00, 0x00, 0x24, 'e', 'm', 's', 'g',
  224. 0x00, // version = 0
  225. 0x00, 0x00, 0x00, // flags = 0
  226. 0x61, 0x00, // scheme_id_uri = "a"
  227. 0x61, 0x00, // value = "a"
  228. 0x00, 0x00, 0x00, 0x01, // timescale = 1
  229. 0x00, 0x00, 0x00, 0x02, // presentation_time_delta = 2
  230. 0x00, 0x00, 0x00, 0x03, // event_duration = 3
  231. 0x00, 0x00, 0x00, 0x04, // id = 4
  232. 0x05, 0x06, 0x07, 0x08, // message_data[4] = 0x05060708
  233. };
  234. TestTopLevelBox(kData, sizeof(kData), FOURCC_EMSG);
  235. }
  236. TEST_F(BoxReaderTest, SkippingUuid) {
  237. static const uint8_t kData[] = {
  238. 0x00, 0x00, 0x00, 0x19, 'u', 'u', 'i', 'd',
  239. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  240. 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, // usertype
  241. 0x00,
  242. };
  243. TestTopLevelBox(kData, sizeof(kData), FOURCC_UUID);
  244. }
  245. TEST_F(BoxReaderTest, NestedBoxWithHugeSize) {
  246. // This data is not a valid 'emsg' box. It is just used as a top-level box
  247. // as ReadTopLevelBox() has a restricted set of boxes it allows. |kData|
  248. // contains all the bytes as specified by the 'emsg' header size.
  249. // The nested box ('junk') has a large size that was chosen to catch
  250. // integer overflows. The nested box should not specify more than the
  251. // number of remaining bytes in the enclosing box.
  252. static const uint8_t kData[] = {
  253. 0x00, 0x00, 0x00, 0x24, 'e', 'm', 's', 'g', // outer box
  254. 0x7f, 0xff, 0xff, 0xff, 'j', 'u', 'n', 'k', // nested box
  255. 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x3b, 0x03, // random data for rest
  256. 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08};
  257. std::unique_ptr<BoxReader> reader;
  258. ParseResult result =
  259. BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
  260. EXPECT_EQ(result, ParseResult::kOk);
  261. EXPECT_TRUE(reader);
  262. EXPECT_EQ(FOURCC_EMSG, reader->type());
  263. EXPECT_FALSE(reader->ScanChildren());
  264. }
  265. TEST_F(BoxReaderTest, ScanChildrenWithInvalidChild) {
  266. // This data is not a valid 'emsg' box. It is just used as a top-level box
  267. // as ReadTopLevelBox() has a restricted set of boxes it allows.
  268. // The nested 'elst' box is used as it includes a count of EditListEntry's.
  269. // The sample specifies a large number of EditListEntry's, but only 1 is
  270. // actually included in the box. This test verifies that the code checks
  271. // properly that the buffer contains the specified number of EditListEntry's
  272. static const uint8_t kData[] = {
  273. 0x00, 0x00, 0x00, 0x2c, 'e', 'm', 's', 'g', // outer box
  274. 0x00, 0x00, 0x00, 0x24, 'e', 'l', 's', 't', // nested box
  275. 0x01, 0x00, 0x00, 0x00, // version = 1, flags = 0
  276. 0x00, 0x00, 0x00, 0x0a, // count = 10, but only 1 actually included
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  278. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  279. std::unique_ptr<BoxReader> reader;
  280. ParseResult result =
  281. BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
  282. EXPECT_EQ(result, ParseResult::kOk);
  283. EXPECT_TRUE(reader);
  284. EXPECT_EQ(FOURCC_EMSG, reader->type());
  285. EXPECT_TRUE(reader->ScanChildren());
  286. // 'elst' specifies lots of EditListEntry's but only includes 1. Thus
  287. // parsing it should fail.
  288. EditList child;
  289. EXPECT_FALSE(reader->ReadChild(&child));
  290. }
  291. TEST_F(BoxReaderTest, ReadAllChildrenWithChildLargerThanParent) {
  292. static const uint8_t kData[] = {
  293. 0x00, 0x00, 0x00, 0x10, 's', 'k', 'i', 'p', // outer box
  294. 0x00, 0x00, 0x00, 0x10, 'p', 's', 's', 'h', // nested box
  295. };
  296. std::unique_ptr<BoxReader> reader;
  297. ParseResult result =
  298. BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
  299. EXPECT_EQ(result, ParseResult::kOk);
  300. EXPECT_TRUE(reader);
  301. EXPECT_EQ(FOURCC_SKIP, reader->type());
  302. std::vector<PsshBox> tmp;
  303. EXPECT_FALSE(reader->ReadAllChildren(&tmp));
  304. }
  305. TEST_F(BoxReaderTest, TrunSampleCount32bitOverflow) {
  306. // This 'trun' box specifies an unusually high sample count, though only one
  307. // sample is included in the bytes below. The values for "sample_count" and
  308. // "flags" are chosen such that the needed number of bytes will overflow 32
  309. // bits to yield a very small number (4), potentially passing the
  310. // internal check for HasBytes(). http://crbug.com/679640
  311. static const uint8_t kData[] = {
  312. 0x00, 0x00, 0x00, 0x18, 't', 'r', 'u', 'n', // header
  313. 0x00, 0x00, // version = 0
  314. 0x03, 0x00, // flags = 2 fields present (sample duration and sample size)
  315. 0x80, 0x00, 0x00, 0x02, // sample count = 2147483650
  316. 0x00, 0x00, 0x00, 0x00, // only one sample present
  317. 0x00, 0x00, 0x00, 0x00};
  318. // Verify we catch the overflow to avoid OOB reads/writes.
  319. TestParsing32bitOverflow<TrackFragmentRun>(
  320. kData, sizeof(kData),
  321. "Extreme TRUN sample count exceeds implementation limit.");
  322. }
  323. TEST_F(BoxReaderTest, SaioCount32bitOverflow) {
  324. // This 'saio' box specifies an unusually high number of offset counts, though
  325. // only one offset is included in the bytes below. The values for "count" and
  326. // "version" are chosen such that the needed number of bytes will overflow 32
  327. // bits to yield a very small number (4), potentially passing the internal
  328. // check for HasBytes(). http://crbug.com/679641
  329. static const uint8_t kData[] = {
  330. 0x00, 0x00, 0x00, 0x14, 's', 'a', 'i', 'o', // header
  331. 0x00, 0x00, // version = 0 (4 bytes per offset entry)
  332. 0x00, 0x00, // flags = 0
  333. 0x40, 0x00, 0x00, 0x01, // offsets count = 1073741825
  334. 0x00, 0x00, 0x00, 0x00, // single offset entry
  335. };
  336. // Verify we catch the overflow to avoid OOB reads/writes.
  337. TestParsing32bitOverflow<SampleAuxiliaryInformationOffset>(
  338. kData, sizeof(kData), "Extreme SAIO count exceeds implementation limit.");
  339. }
  340. TEST_F(BoxReaderTest, ElstCount32bitOverflow) {
  341. // This 'elst' box specifies an unusually high number of edit counts, though
  342. // only one edit is included in the bytes below. The values for "count" and
  343. // "version" are chosen such that the needed number of bytes will overflow 32
  344. // bits to yield a very small number (12), potentially passing the internal
  345. // check for HasBytes(). http://crbug.com/679645
  346. static const uint8_t kData[] = {
  347. 0x00, 0x00, 0x00, 0x1c, 'e', 'l', 's', 't', // header
  348. 0x00, 0x00, // version = 0 (12 bytes per edit entry)
  349. 0x00, 0x00, // flags = 0
  350. 0x80, 0x00, 0x00, 0x01, // edits count = 2147483649
  351. 0x00, 0x00, 0x00, 0x00, // single edit entry
  352. 0x00, 0x00, 0x00, 0x00, // ...
  353. 0x00, 0x00, 0x00, 0x00,
  354. };
  355. // Verify we catch the overflow to avoid OOB reads/writes.
  356. TestParsing32bitOverflow<EditList>(
  357. kData, sizeof(kData), "Extreme ELST count exceeds implementation limit.");
  358. }
  359. TEST_F(BoxReaderTest, SbgpCount32bitOverflow) {
  360. // This 'sbgp' box specifies an unusually high count of entries, though only
  361. // one partial entry is included in the bytes below. The value for "count" is
  362. // chosen such that we could overflow attempting to allocate the vector for
  363. // parsed entries. http://crbug.com/679646
  364. static const uint8_t kData[] = {
  365. 0x00, 0x00, 0x00, 0x1c, 's', 'b', 'g', 'p', // header
  366. 0x00, 0x00, 0x00, 0x00, // version = 0, flags = 0
  367. 's', 'e', 'i', 'g', // required grouping "type"
  368. 0xff, 0xff, 0xff, 0xff, // count = 4294967295
  369. 0x00, 0x00, 0x00, 0x00, // partial entry
  370. 0x00, 0x00, 0x00, 0x00,
  371. };
  372. // Verify we catch the overflow to avoid OOB reads/writes.
  373. TestParsing32bitOverflow<SampleToGroup>(
  374. kData, sizeof(kData), "Extreme SBGP count exceeds implementation limit.");
  375. }
  376. TEST_F(BoxReaderTest, SgpdCount32bitOverflow) {
  377. // This 'sgpd' box specifies an unusually high count of entries, though only
  378. // one partial entry is included in the bytes below. The value for "count" is
  379. // chosen such that we could overflow attempting to allocate the vector for
  380. // parsed entries. http://crbug.com/679647
  381. static const uint8_t kData[] = {
  382. 0x00, 0x00, 0x00, 0x1c, 's', 'g', 'p', 'd', // header
  383. 0x00, 0x00, 0x00, 0x00, // version = 0, flags = 0
  384. 's', 'e', 'i', 'g', // required grouping "type"
  385. 0xff, 0xff, 0xff, 0xff, // count = 4294967295
  386. 0x00, 0x00, 0x00, 0x00, // partial entry
  387. 0x00, 0x00, 0x00, 0x00,
  388. };
  389. // Verify we catch the overflow to avoid OOB reads/writes.
  390. TestParsing32bitOverflow<SampleGroupDescription>(
  391. kData, sizeof(kData), "Extreme SGPD count exceeds implementation limit.");
  392. }
  393. TEST_F(BoxReaderTest, OutsideOfBoxRead) {
  394. static const uint8_t kData[] = {
  395. 0x00, 0x00, 0x00, 0x0c, 'f', 'r', 'e', 'e', // header
  396. 0x01, 0x02, 0x03, 0x04, // box contents
  397. 0x05, 0x06, 0x07, 0x08, // buffer padding
  398. };
  399. std::unique_ptr<BoxReader> reader;
  400. ParseResult result =
  401. BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
  402. EXPECT_EQ(result, ParseResult::kOk);
  403. EXPECT_TRUE(reader);
  404. uint32_t value;
  405. EXPECT_TRUE(reader->Read4(&value));
  406. EXPECT_EQ(value, 0x01020304u);
  407. EXPECT_FALSE(reader->Read4(&value));
  408. }
  409. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  410. TEST_F(BoxReaderTest, AVCDecoderConfigurationRecordTakenFromMp4) {
  411. std::vector<uint8_t> test_data{
  412. 0x1, // configurationVersion
  413. 0x64, // AVCProfileIndication
  414. 0x0, // profile_compatibility
  415. 0xc, // AVCLevelIndication
  416. 0xff, // lengthSizeMinusOne
  417. 0xe1, // numOfSequenceParameterSets = 1
  418. 0x0, 0x19, // sequenceParameterSetLength = 25
  419. // sequenceParameterSet
  420. 0x67, 0x64, 0x0, 0xc, 0xac, 0xd9, 0x41, 0x41, 0xfb, 0x1, 0x10, 0x0, 0x0,
  421. 0x3, 0x0, 0x10, 0x0, 0x0, 0x3, 0x1, 0x40, 0xf1, 0x42, 0x99, 0x60,
  422. 0x1, // numOfPictureParameterSets
  423. 0x0, 0x6, // pictureParameterSetLength = 6
  424. 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
  425. // Profile specific params are not supported yet, skip last bytes
  426. // 0xfd, 0xf8, 0xf8, 0x0
  427. };
  428. AVCDecoderConfigurationRecord record;
  429. EXPECT_TRUE(record.Parse(test_data.data(), test_data.size()));
  430. EXPECT_EQ(record.version, 1);
  431. EXPECT_EQ(record.profile_indication, 0x64);
  432. EXPECT_EQ(record.profile_compatibility, 0);
  433. EXPECT_EQ(record.avc_level, 0xc);
  434. EXPECT_EQ(record.length_size, 4);
  435. EXPECT_EQ(record.sps_list.size(), 1ull);
  436. EXPECT_EQ(record.sps_list[0].size(), 25ull);
  437. EXPECT_EQ(record.pps_list.size(), 1ull);
  438. EXPECT_EQ(record.pps_list[0].size(), 6ull);
  439. std::vector<uint8_t> output;
  440. EXPECT_TRUE(record.Serialize(output));
  441. EXPECT_EQ(output.size(), test_data.size());
  442. ASSERT_THAT(output, testing::ElementsAreArray(test_data));
  443. }
  444. TEST_F(BoxReaderTest, AVCDecoderConfigurationRecordTakenFromStream) {
  445. std::vector<uint8_t> test_data{
  446. 0x01, 0x4D, 0x00, 0x15, 0xff, 0xe1, 0x00, 0x2F, 0x67, 0x4D, 0x40,
  447. 0x15, 0x96, 0x52, 0x02, 0x83, 0xF6, 0x02, 0xA1, 0x00, 0x00, 0x03,
  448. 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x28, 0xE0, 0x60, 0x03, 0x0D,
  449. 0x40, 0x00, 0x49, 0x3E, 0x7F, 0x18, 0xE3, 0x03, 0x00, 0x18, 0x6A,
  450. 0x00, 0x02, 0x49, 0xF3, 0xF8, 0xC7, 0x0E, 0xD0, 0xB1, 0x68, 0x90,
  451. 0x01, 0x00, 0x04, 0x68, 0xEB, 0x73, 0x52};
  452. AVCDecoderConfigurationRecord record;
  453. EXPECT_TRUE(record.Parse(test_data.data(), test_data.size()));
  454. std::vector<uint8_t> output;
  455. EXPECT_TRUE(record.Serialize(output));
  456. ASSERT_THAT(output, testing::ElementsAreArray(test_data));
  457. }
  458. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  459. } // namespace mp4
  460. } // namespace media