123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/formats/mp4/box_reader.h"
- #include <stdint.h>
- #include <string.h>
- #include <memory>
- #include "base/logging.h"
- #include "media/base/mock_media_log.h"
- #include "media/formats/mp4/box_definitions.h"
- #include "media/formats/mp4/parse_result.h"
- #include "media/formats/mp4/rcheck.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::HasSubstr;
- using ::testing::StrictMock;
- namespace media {
- namespace mp4 {
- static const uint8_t kSkipBox[] = {
- // Top-level test box containing three children
- 0x00, 0x00, 0x00, 0x40, 's', 'k', 'i', 'p', 0x01, 0x02, 0x03, 0x04, 0x05,
- 0x06, 0x07, 0x08, 0xf9, 0x0a, 0x0b, 0x0c, 0xfd, 0x0e, 0x0f, 0x10,
- // Ordinary (8-byte header) child box
- 0x00, 0x00, 0x00, 0x0c, 'p', 's', 's', 'h', 0xde, 0xad, 0xbe, 0xef,
- // Extended-size header child box
- 0x00, 0x00, 0x00, 0x01, 'p', 's', 's', 'h', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x14, 0xfa, 0xce, 0xca, 0xfe,
- // Empty free box
- 0x00, 0x00, 0x00, 0x08, 'f', 'r', 'e', 'e',
- // Trailing garbage
- 0x00};
- struct FreeBox : Box {
- bool Parse(BoxReader* reader) override {
- return true;
- }
- FourCC BoxType() const override { return FOURCC_FREE; }
- };
- struct PsshBox : Box {
- uint32_t val;
- bool Parse(BoxReader* reader) override {
- return reader->Read4(&val);
- }
- FourCC BoxType() const override { return FOURCC_PSSH; }
- };
- struct SkipBox : Box {
- uint8_t a, b;
- uint16_t c;
- int32_t d;
- int64_t e;
- std::vector<PsshBox> kids;
- FreeBox mpty;
- bool Parse(BoxReader* reader) override {
- RCHECK(reader->ReadFullBoxHeader() &&
- reader->Read1(&a) &&
- reader->Read1(&b) &&
- reader->Read2(&c) &&
- reader->Read4s(&d) &&
- reader->Read4sInto8s(&e));
- return reader->ScanChildren() &&
- reader->ReadChildren(&kids) &&
- reader->MaybeReadChild(&mpty);
- }
- FourCC BoxType() const override { return FOURCC_SKIP; }
- SkipBox();
- ~SkipBox() override;
- };
- SkipBox::SkipBox() = default;
- SkipBox::~SkipBox() = default;
- class BoxReaderTest : public testing::Test {
- public:
- BoxReaderTest() = default;
- protected:
- std::vector<uint8_t> GetBuf() {
- return std::vector<uint8_t>(kSkipBox, kSkipBox + sizeof(kSkipBox));
- }
- void TestTopLevelBox(const uint8_t* data, size_t data_size, uint32_t fourCC) {
- std::vector<uint8_t> buf(data, data + data_size);
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- EXPECT_EQ(fourCC, static_cast<uint32_t>(reader->type()));
- EXPECT_EQ(reader->box_size(), data_size);
- }
- template <typename ChildType>
- void TestParsing32bitOverflow(const uint8_t* buffer,
- size_t size,
- const std::string& overflow_error) {
- // Wrap whatever we're passed in a dummy EMSG so we can satisfy requirements
- // for ReadTopLevelBox and to kick off parsing.
- std::vector<uint8_t> buffer_wrapper = {
- 0x00, 0x00, 0x00, 0x00, // dummy size
- 'e', 'm', 's', 'g', // fourcc
- };
- buffer_wrapper.insert(buffer_wrapper.end(), buffer, buffer + size);
- // Basic check of the nested buffer size. If box_size > buffer size the test
- // will exit early (waiting for more bytes to be appended).
- ASSERT_TRUE(base::IsValueInRangeForNumericType<uint8_t>(size));
- ASSERT_LE(buffer[3], size);
- // Update the size (keep it simple).
- ASSERT_TRUE(
- base::IsValueInRangeForNumericType<uint8_t>(buffer_wrapper.size()));
- buffer_wrapper[3] = buffer_wrapper.size();
- std::unique_ptr<BoxReader> reader;
- ParseResult result = BoxReader::ReadTopLevelBox(
- &buffer_wrapper[0], buffer_wrapper.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- EXPECT_EQ(FOURCC_EMSG, reader->type());
- // Overflow is only triggered/caught on 32-bit systems. 64-bit systems will
- // instead fail parsing because tests are written such that |buffer| never
- // contains enough bytes for parsing to succeed.
- #if defined(ARCH_CPU_32_BITS)
- const int kOverflowLogCount = 1;
- #else
- const int kOverflowLogCount = 0;
- #endif
- if (!overflow_error.empty())
- EXPECT_MEDIA_LOG(HasSubstr(overflow_error)).Times(kOverflowLogCount);
- std::vector<ChildType> children;
- EXPECT_FALSE(reader->ReadAllChildrenAndCheckFourCC(&children));
- }
- StrictMock<MockMediaLog> media_log_;
- };
- TEST_F(BoxReaderTest, ExpectedOperationTest) {
- std::vector<uint8_t> buf = GetBuf();
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- SkipBox box;
- EXPECT_TRUE(box.Parse(reader.get()));
- EXPECT_EQ(0x01, reader->version());
- EXPECT_EQ(0x020304u, reader->flags());
- EXPECT_EQ(0x05, box.a);
- EXPECT_EQ(0x06, box.b);
- EXPECT_EQ(0x0708, box.c);
- EXPECT_EQ(static_cast<int32_t>(0xf90a0b0c), box.d);
- EXPECT_EQ(static_cast<int32_t>(0xfd0e0f10), box.e);
- EXPECT_EQ(2u, box.kids.size());
- EXPECT_EQ(0xdeadbeef, box.kids[0].val);
- EXPECT_EQ(0xfacecafe, box.kids[1].val);
- // Accounting for the extra byte outside of the box above
- EXPECT_EQ(buf.size(), static_cast<uint64_t>(reader->box_size() + 1));
- }
- TEST_F(BoxReaderTest, OuterTooShortTest) {
- std::vector<uint8_t> buf = GetBuf();
- // Create a soft failure by truncating the outer box.
- std::unique_ptr<BoxReader> r;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size() - 2, &media_log_, &r);
- EXPECT_EQ(result, ParseResult::kNeedMoreData);
- EXPECT_FALSE(r);
- }
- TEST_F(BoxReaderTest, InnerTooLongTest) {
- std::vector<uint8_t> buf = GetBuf();
- // Make an inner box too big for its outer box.
- buf[25] = 1;
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- SkipBox box;
- EXPECT_FALSE(box.Parse(reader.get()));
- }
- TEST_F(BoxReaderTest, WrongFourCCTest) {
- std::vector<uint8_t> buf = GetBuf();
- // Set an unrecognized top-level FourCC.
- buf[4] = 0x44;
- buf[5] = 0x41;
- buf[6] = 0x4c;
- buf[7] = 0x45;
- // Also, tests that the offending FourCC is emitted only in a debug media log.
- EXPECT_MEDIA_LOG(
- AllOf(HasSubstr("error"),
- HasSubstr("Invalid top-level ISO BMFF box type DALE")));
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_FALSE(reader);
- EXPECT_EQ(result, ParseResult::kError);
- }
- TEST_F(BoxReaderTest, ScanChildrenTest) {
- std::vector<uint8_t> buf = GetBuf();
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader->SkipBytes(16) && reader->ScanChildren());
- FreeBox free;
- EXPECT_TRUE(reader->ReadChild(&free));
- EXPECT_FALSE(reader->ReadChild(&free));
- EXPECT_TRUE(reader->MaybeReadChild(&free));
- std::vector<PsshBox> kids;
- EXPECT_TRUE(reader->ReadChildren(&kids));
- EXPECT_EQ(2u, kids.size());
- kids.clear();
- EXPECT_FALSE(reader->ReadChildren(&kids));
- EXPECT_TRUE(reader->MaybeReadChildren(&kids));
- }
- TEST_F(BoxReaderTest, ReadAllChildrenTest) {
- std::vector<uint8_t> buf = GetBuf();
- // Modify buffer to exclude its last 'free' box
- buf[3] = 0x38;
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- std::vector<PsshBox> kids;
- EXPECT_TRUE(reader->SkipBytes(16) && reader->ReadAllChildren(&kids));
- EXPECT_EQ(2u, kids.size());
- EXPECT_EQ(kids[0].val, 0xdeadbeef); // Ensure order is preserved
- }
- TEST_F(BoxReaderTest, SkippingBloc) {
- static const uint8_t kData[] = {0x00, 0x00, 0x00, 0x09, 'b',
- 'l', 'o', 'c', 0x00};
- TestTopLevelBox(kData, sizeof(kData), FOURCC_BLOC);
- }
- TEST_F(BoxReaderTest, SkippingEmsg) {
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x24, 'e', 'm', 's', 'g',
- 0x00, // version = 0
- 0x00, 0x00, 0x00, // flags = 0
- 0x61, 0x00, // scheme_id_uri = "a"
- 0x61, 0x00, // value = "a"
- 0x00, 0x00, 0x00, 0x01, // timescale = 1
- 0x00, 0x00, 0x00, 0x02, // presentation_time_delta = 2
- 0x00, 0x00, 0x00, 0x03, // event_duration = 3
- 0x00, 0x00, 0x00, 0x04, // id = 4
- 0x05, 0x06, 0x07, 0x08, // message_data[4] = 0x05060708
- };
- TestTopLevelBox(kData, sizeof(kData), FOURCC_EMSG);
- }
- TEST_F(BoxReaderTest, SkippingUuid) {
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x19, 'u', 'u', 'i', 'd',
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, // usertype
- 0x00,
- };
- TestTopLevelBox(kData, sizeof(kData), FOURCC_UUID);
- }
- TEST_F(BoxReaderTest, NestedBoxWithHugeSize) {
- // This data is not a valid 'emsg' box. It is just used as a top-level box
- // as ReadTopLevelBox() has a restricted set of boxes it allows. |kData|
- // contains all the bytes as specified by the 'emsg' header size.
- // The nested box ('junk') has a large size that was chosen to catch
- // integer overflows. The nested box should not specify more than the
- // number of remaining bytes in the enclosing box.
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x24, 'e', 'm', 's', 'g', // outer box
- 0x7f, 0xff, 0xff, 0xff, 'j', 'u', 'n', 'k', // nested box
- 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x3b, 0x03, // random data for rest
- 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08};
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- EXPECT_EQ(FOURCC_EMSG, reader->type());
- EXPECT_FALSE(reader->ScanChildren());
- }
- TEST_F(BoxReaderTest, ScanChildrenWithInvalidChild) {
- // This data is not a valid 'emsg' box. It is just used as a top-level box
- // as ReadTopLevelBox() has a restricted set of boxes it allows.
- // The nested 'elst' box is used as it includes a count of EditListEntry's.
- // The sample specifies a large number of EditListEntry's, but only 1 is
- // actually included in the box. This test verifies that the code checks
- // properly that the buffer contains the specified number of EditListEntry's
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x2c, 'e', 'm', 's', 'g', // outer box
- 0x00, 0x00, 0x00, 0x24, 'e', 'l', 's', 't', // nested box
- 0x01, 0x00, 0x00, 0x00, // version = 1, flags = 0
- 0x00, 0x00, 0x00, 0x0a, // count = 10, but only 1 actually included
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- EXPECT_EQ(FOURCC_EMSG, reader->type());
- EXPECT_TRUE(reader->ScanChildren());
- // 'elst' specifies lots of EditListEntry's but only includes 1. Thus
- // parsing it should fail.
- EditList child;
- EXPECT_FALSE(reader->ReadChild(&child));
- }
- TEST_F(BoxReaderTest, ReadAllChildrenWithChildLargerThanParent) {
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x10, 's', 'k', 'i', 'p', // outer box
- 0x00, 0x00, 0x00, 0x10, 'p', 's', 's', 'h', // nested box
- };
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- EXPECT_EQ(FOURCC_SKIP, reader->type());
- std::vector<PsshBox> tmp;
- EXPECT_FALSE(reader->ReadAllChildren(&tmp));
- }
- TEST_F(BoxReaderTest, TrunSampleCount32bitOverflow) {
- // This 'trun' box specifies an unusually high sample count, though only one
- // sample is included in the bytes below. The values for "sample_count" and
- // "flags" are chosen such that the needed number of bytes will overflow 32
- // bits to yield a very small number (4), potentially passing the
- // internal check for HasBytes(). http://crbug.com/679640
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x18, 't', 'r', 'u', 'n', // header
- 0x00, 0x00, // version = 0
- 0x03, 0x00, // flags = 2 fields present (sample duration and sample size)
- 0x80, 0x00, 0x00, 0x02, // sample count = 2147483650
- 0x00, 0x00, 0x00, 0x00, // only one sample present
- 0x00, 0x00, 0x00, 0x00};
- // Verify we catch the overflow to avoid OOB reads/writes.
- TestParsing32bitOverflow<TrackFragmentRun>(
- kData, sizeof(kData),
- "Extreme TRUN sample count exceeds implementation limit.");
- }
- TEST_F(BoxReaderTest, SaioCount32bitOverflow) {
- // This 'saio' box specifies an unusually high number of offset counts, though
- // only one offset is included in the bytes below. The values for "count" and
- // "version" are chosen such that the needed number of bytes will overflow 32
- // bits to yield a very small number (4), potentially passing the internal
- // check for HasBytes(). http://crbug.com/679641
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x14, 's', 'a', 'i', 'o', // header
- 0x00, 0x00, // version = 0 (4 bytes per offset entry)
- 0x00, 0x00, // flags = 0
- 0x40, 0x00, 0x00, 0x01, // offsets count = 1073741825
- 0x00, 0x00, 0x00, 0x00, // single offset entry
- };
- // Verify we catch the overflow to avoid OOB reads/writes.
- TestParsing32bitOverflow<SampleAuxiliaryInformationOffset>(
- kData, sizeof(kData), "Extreme SAIO count exceeds implementation limit.");
- }
- TEST_F(BoxReaderTest, ElstCount32bitOverflow) {
- // This 'elst' box specifies an unusually high number of edit counts, though
- // only one edit is included in the bytes below. The values for "count" and
- // "version" are chosen such that the needed number of bytes will overflow 32
- // bits to yield a very small number (12), potentially passing the internal
- // check for HasBytes(). http://crbug.com/679645
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x1c, 'e', 'l', 's', 't', // header
- 0x00, 0x00, // version = 0 (12 bytes per edit entry)
- 0x00, 0x00, // flags = 0
- 0x80, 0x00, 0x00, 0x01, // edits count = 2147483649
- 0x00, 0x00, 0x00, 0x00, // single edit entry
- 0x00, 0x00, 0x00, 0x00, // ...
- 0x00, 0x00, 0x00, 0x00,
- };
- // Verify we catch the overflow to avoid OOB reads/writes.
- TestParsing32bitOverflow<EditList>(
- kData, sizeof(kData), "Extreme ELST count exceeds implementation limit.");
- }
- TEST_F(BoxReaderTest, SbgpCount32bitOverflow) {
- // This 'sbgp' box specifies an unusually high count of entries, though only
- // one partial entry is included in the bytes below. The value for "count" is
- // chosen such that we could overflow attempting to allocate the vector for
- // parsed entries. http://crbug.com/679646
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x1c, 's', 'b', 'g', 'p', // header
- 0x00, 0x00, 0x00, 0x00, // version = 0, flags = 0
- 's', 'e', 'i', 'g', // required grouping "type"
- 0xff, 0xff, 0xff, 0xff, // count = 4294967295
- 0x00, 0x00, 0x00, 0x00, // partial entry
- 0x00, 0x00, 0x00, 0x00,
- };
- // Verify we catch the overflow to avoid OOB reads/writes.
- TestParsing32bitOverflow<SampleToGroup>(
- kData, sizeof(kData), "Extreme SBGP count exceeds implementation limit.");
- }
- TEST_F(BoxReaderTest, SgpdCount32bitOverflow) {
- // This 'sgpd' box specifies an unusually high count of entries, though only
- // one partial entry is included in the bytes below. The value for "count" is
- // chosen such that we could overflow attempting to allocate the vector for
- // parsed entries. http://crbug.com/679647
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x1c, 's', 'g', 'p', 'd', // header
- 0x00, 0x00, 0x00, 0x00, // version = 0, flags = 0
- 's', 'e', 'i', 'g', // required grouping "type"
- 0xff, 0xff, 0xff, 0xff, // count = 4294967295
- 0x00, 0x00, 0x00, 0x00, // partial entry
- 0x00, 0x00, 0x00, 0x00,
- };
- // Verify we catch the overflow to avoid OOB reads/writes.
- TestParsing32bitOverflow<SampleGroupDescription>(
- kData, sizeof(kData), "Extreme SGPD count exceeds implementation limit.");
- }
- TEST_F(BoxReaderTest, OutsideOfBoxRead) {
- static const uint8_t kData[] = {
- 0x00, 0x00, 0x00, 0x0c, 'f', 'r', 'e', 'e', // header
- 0x01, 0x02, 0x03, 0x04, // box contents
- 0x05, 0x06, 0x07, 0x08, // buffer padding
- };
- std::unique_ptr<BoxReader> reader;
- ParseResult result =
- BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
- EXPECT_EQ(result, ParseResult::kOk);
- EXPECT_TRUE(reader);
- uint32_t value;
- EXPECT_TRUE(reader->Read4(&value));
- EXPECT_EQ(value, 0x01020304u);
- EXPECT_FALSE(reader->Read4(&value));
- }
- #if BUILDFLAG(USE_PROPRIETARY_CODECS)
- TEST_F(BoxReaderTest, AVCDecoderConfigurationRecordTakenFromMp4) {
- std::vector<uint8_t> test_data{
- 0x1, // configurationVersion
- 0x64, // AVCProfileIndication
- 0x0, // profile_compatibility
- 0xc, // AVCLevelIndication
- 0xff, // lengthSizeMinusOne
- 0xe1, // numOfSequenceParameterSets = 1
- 0x0, 0x19, // sequenceParameterSetLength = 25
- // sequenceParameterSet
- 0x67, 0x64, 0x0, 0xc, 0xac, 0xd9, 0x41, 0x41, 0xfb, 0x1, 0x10, 0x0, 0x0,
- 0x3, 0x0, 0x10, 0x0, 0x0, 0x3, 0x1, 0x40, 0xf1, 0x42, 0x99, 0x60,
- 0x1, // numOfPictureParameterSets
- 0x0, 0x6, // pictureParameterSetLength = 6
- 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
- // Profile specific params are not supported yet, skip last bytes
- // 0xfd, 0xf8, 0xf8, 0x0
- };
- AVCDecoderConfigurationRecord record;
- EXPECT_TRUE(record.Parse(test_data.data(), test_data.size()));
- EXPECT_EQ(record.version, 1);
- EXPECT_EQ(record.profile_indication, 0x64);
- EXPECT_EQ(record.profile_compatibility, 0);
- EXPECT_EQ(record.avc_level, 0xc);
- EXPECT_EQ(record.length_size, 4);
- EXPECT_EQ(record.sps_list.size(), 1ull);
- EXPECT_EQ(record.sps_list[0].size(), 25ull);
- EXPECT_EQ(record.pps_list.size(), 1ull);
- EXPECT_EQ(record.pps_list[0].size(), 6ull);
- std::vector<uint8_t> output;
- EXPECT_TRUE(record.Serialize(output));
- EXPECT_EQ(output.size(), test_data.size());
- ASSERT_THAT(output, testing::ElementsAreArray(test_data));
- }
- TEST_F(BoxReaderTest, AVCDecoderConfigurationRecordTakenFromStream) {
- std::vector<uint8_t> test_data{
- 0x01, 0x4D, 0x00, 0x15, 0xff, 0xe1, 0x00, 0x2F, 0x67, 0x4D, 0x40,
- 0x15, 0x96, 0x52, 0x02, 0x83, 0xF6, 0x02, 0xA1, 0x00, 0x00, 0x03,
- 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x28, 0xE0, 0x60, 0x03, 0x0D,
- 0x40, 0x00, 0x49, 0x3E, 0x7F, 0x18, 0xE3, 0x03, 0x00, 0x18, 0x6A,
- 0x00, 0x02, 0x49, 0xF3, 0xF8, 0xC7, 0x0E, 0xD0, 0xB1, 0x68, 0x90,
- 0x01, 0x00, 0x04, 0x68, 0xEB, 0x73, 0x52};
- AVCDecoderConfigurationRecord record;
- EXPECT_TRUE(record.Parse(test_data.data(), test_data.size()));
- std::vector<uint8_t> output;
- EXPECT_TRUE(record.Serialize(output));
- ASSERT_THAT(output, testing::ElementsAreArray(test_data));
- }
- #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- } // namespace mp4
- } // namespace media
|