Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / formats / mp4 / box_reader_unittest.cc
blobfb97c075ec131b8a8940a08f11be698e24cc9fbf
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.
5 #include <string.h>
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "media/base/mock_media_log.h"
11 #include "media/formats/mp4/box_reader.h"
12 #include "media/formats/mp4/rcheck.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using ::testing::HasSubstr;
17 using ::testing::StrictMock;
19 namespace media {
20 namespace mp4 {
22 static const uint8 kSkipBox[] = {
23 // Top-level test box containing three children
24 0x00, 0x00, 0x00, 0x40, 's', 'k', 'i', 'p',
25 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
26 0xf9, 0x0a, 0x0b, 0x0c, 0xfd, 0x0e, 0x0f, 0x10,
27 // Ordinary (8-byte header) child box
28 0x00, 0x00, 0x00, 0x0c, 'p', 's', 's', 'h', 0xde, 0xad, 0xbe, 0xef,
29 // Extended-size header child box
30 0x00, 0x00, 0x00, 0x01, 'p', 's', 's', 'h',
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
32 0xfa, 0xce, 0xca, 0xfe,
33 // Empty free box
34 0x00, 0x00, 0x00, 0x08, 'f', 'r', 'e', 'e',
35 // Trailing garbage
36 0x00 };
38 struct FreeBox : Box {
39 bool Parse(BoxReader* reader) override {
40 return true;
42 FourCC BoxType() const override { return FOURCC_FREE; }
45 struct PsshBox : Box {
46 uint32 val;
48 bool Parse(BoxReader* reader) override {
49 return reader->Read4(&val);
51 FourCC BoxType() const override { return FOURCC_PSSH; }
54 struct SkipBox : Box {
55 uint8 a, b;
56 uint16 c;
57 int32 d;
58 int64 e;
60 std::vector<PsshBox> kids;
61 FreeBox mpty;
63 bool Parse(BoxReader* reader) override {
64 RCHECK(reader->ReadFullBoxHeader() &&
65 reader->Read1(&a) &&
66 reader->Read1(&b) &&
67 reader->Read2(&c) &&
68 reader->Read4s(&d) &&
69 reader->Read4sInto8s(&e));
70 return reader->ScanChildren() &&
71 reader->ReadChildren(&kids) &&
72 reader->MaybeReadChild(&mpty);
74 FourCC BoxType() const override { return FOURCC_SKIP; }
76 SkipBox();
77 ~SkipBox() override;
80 SkipBox::SkipBox() {}
81 SkipBox::~SkipBox() {}
83 class BoxReaderTest : public testing::Test {
84 public:
85 BoxReaderTest() : media_log_(new StrictMock<MockMediaLog>()) {}
87 protected:
88 std::vector<uint8> GetBuf() {
89 return std::vector<uint8>(kSkipBox, kSkipBox + sizeof(kSkipBox));
92 void TestTopLevelBox(const uint8* data, int size, uint32 fourCC) {
93 std::vector<uint8> buf(data, data + size);
95 bool err;
96 scoped_ptr<BoxReader> reader(
97 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
99 EXPECT_FALSE(err);
100 EXPECT_TRUE(reader);
101 EXPECT_EQ(fourCC, reader->type());
102 EXPECT_EQ(reader->size(), size);
105 scoped_refptr<StrictMock<MockMediaLog>> media_log_;
108 TEST_F(BoxReaderTest, ExpectedOperationTest) {
109 std::vector<uint8> buf = GetBuf();
110 bool err;
111 scoped_ptr<BoxReader> reader(
112 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
113 EXPECT_FALSE(err);
114 EXPECT_TRUE(reader.get());
116 SkipBox box;
117 EXPECT_TRUE(box.Parse(reader.get()));
118 EXPECT_EQ(0x01, reader->version());
119 EXPECT_EQ(0x020304u, reader->flags());
120 EXPECT_EQ(0x05, box.a);
121 EXPECT_EQ(0x06, box.b);
122 EXPECT_EQ(0x0708, box.c);
123 EXPECT_EQ(static_cast<int32>(0xf90a0b0c), box.d);
124 EXPECT_EQ(static_cast<int32>(0xfd0e0f10), box.e);
126 EXPECT_EQ(2u, box.kids.size());
127 EXPECT_EQ(0xdeadbeef, box.kids[0].val);
128 EXPECT_EQ(0xfacecafe, box.kids[1].val);
130 // Accounting for the extra byte outside of the box above
131 EXPECT_EQ(buf.size(), static_cast<uint64>(reader->size() + 1));
134 TEST_F(BoxReaderTest, OuterTooShortTest) {
135 std::vector<uint8> buf = GetBuf();
136 bool err;
138 // Create a soft failure by truncating the outer box.
139 scoped_ptr<BoxReader> r(
140 BoxReader::ReadTopLevelBox(&buf[0], buf.size() - 2, media_log_, &err));
142 EXPECT_FALSE(err);
143 EXPECT_FALSE(r.get());
146 TEST_F(BoxReaderTest, InnerTooLongTest) {
147 std::vector<uint8> buf = GetBuf();
148 bool err;
150 // Make an inner box too big for its outer box.
151 buf[25] = 1;
152 scoped_ptr<BoxReader> reader(
153 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
155 SkipBox box;
156 EXPECT_FALSE(box.Parse(reader.get()));
159 TEST_F(BoxReaderTest, WrongFourCCTest) {
160 std::vector<uint8> buf = GetBuf();
161 bool err;
163 // Set an unrecognized top-level FourCC.
164 buf[5] = 1;
166 EXPECT_MEDIA_LOG(HasSubstr("Unrecognized top-level box type s\\u0001ip"));
168 scoped_ptr<BoxReader> reader(
169 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
170 EXPECT_FALSE(reader.get());
171 EXPECT_TRUE(err);
174 TEST_F(BoxReaderTest, ScanChildrenTest) {
175 std::vector<uint8> buf = GetBuf();
176 bool err;
177 scoped_ptr<BoxReader> reader(
178 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
180 EXPECT_TRUE(reader->SkipBytes(16) && reader->ScanChildren());
182 FreeBox free;
183 EXPECT_TRUE(reader->ReadChild(&free));
184 EXPECT_FALSE(reader->ReadChild(&free));
185 EXPECT_TRUE(reader->MaybeReadChild(&free));
187 std::vector<PsshBox> kids;
189 EXPECT_TRUE(reader->ReadChildren(&kids));
190 EXPECT_EQ(2u, kids.size());
191 kids.clear();
192 EXPECT_FALSE(reader->ReadChildren(&kids));
193 EXPECT_TRUE(reader->MaybeReadChildren(&kids));
196 TEST_F(BoxReaderTest, ReadAllChildrenTest) {
197 std::vector<uint8> buf = GetBuf();
198 // Modify buffer to exclude its last 'free' box
199 buf[3] = 0x38;
200 bool err;
201 scoped_ptr<BoxReader> reader(
202 BoxReader::ReadTopLevelBox(&buf[0], buf.size(), media_log_, &err));
204 std::vector<PsshBox> kids;
205 EXPECT_TRUE(reader->SkipBytes(16) && reader->ReadAllChildren(&kids));
206 EXPECT_EQ(2u, kids.size());
207 EXPECT_EQ(kids[0].val, 0xdeadbeef); // Ensure order is preserved
210 TEST_F(BoxReaderTest, SkippingBloc) {
211 static const uint8 kData[] = {
212 0x00, 0x00, 0x00, 0x09, 'b', 'l', 'o', 'c', 0x00
215 TestTopLevelBox(kData, sizeof(kData), FOURCC_BLOC);
218 TEST_F(BoxReaderTest, SkippingEmsg) {
219 static const uint8 kData[] = {
220 0x00, 0x00, 0x00, 0x24, 'e', 'm', 's', 'g',
221 0x00, // version = 0
222 0x00, 0x00, 0x00, // flags = 0
223 0x61, 0x00, // scheme_id_uri = "a"
224 0x61, 0x00, // value = "a"
225 0x00, 0x00, 0x00, 0x01, // timescale = 1
226 0x00, 0x00, 0x00, 0x02, // presentation_time_delta = 2
227 0x00, 0x00, 0x00, 0x03, // event_duration = 3
228 0x00, 0x00, 0x00, 0x04, // id = 4
229 0x05, 0x06, 0x07, 0x08, // message_data[4] = 0x05060708
232 TestTopLevelBox(kData, sizeof(kData), FOURCC_EMSG);
235 TEST_F(BoxReaderTest, SkippingUuid) {
236 static const uint8 kData[] = {
237 0x00, 0x00, 0x00, 0x19, 'u', 'u', 'i', 'd',
238 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
239 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, // usertype
240 0x00,
243 TestTopLevelBox(kData, sizeof(kData), FOURCC_UUID);
246 } // namespace mp4
247 } // namespace media