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.
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
;
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,
34 0x00, 0x00, 0x00, 0x08, 'f', 'r', 'e', 'e',
38 struct FreeBox
: Box
{
39 bool Parse(BoxReader
* reader
) override
{
42 FourCC
BoxType() const override
{ return FOURCC_FREE
; }
45 struct PsshBox
: Box
{
48 bool Parse(BoxReader
* reader
) override
{
49 return reader
->Read4(&val
);
51 FourCC
BoxType() const override
{ return FOURCC_PSSH
; }
54 struct SkipBox
: Box
{
60 std::vector
<PsshBox
> kids
;
63 bool Parse(BoxReader
* reader
) override
{
64 RCHECK(reader
->ReadFullBoxHeader() &&
69 reader
->Read4sInto8s(&e
));
70 return reader
->ScanChildren() &&
71 reader
->ReadChildren(&kids
) &&
72 reader
->MaybeReadChild(&mpty
);
74 FourCC
BoxType() const override
{ return FOURCC_SKIP
; }
81 SkipBox::~SkipBox() {}
83 class BoxReaderTest
: public testing::Test
{
85 BoxReaderTest() : media_log_(new StrictMock
<MockMediaLog
>()) {}
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
);
96 scoped_ptr
<BoxReader
> reader(
97 BoxReader::ReadTopLevelBox(&buf
[0], buf
.size(), media_log_
, &err
));
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();
111 scoped_ptr
<BoxReader
> reader(
112 BoxReader::ReadTopLevelBox(&buf
[0], buf
.size(), media_log_
, &err
));
114 EXPECT_TRUE(reader
.get());
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();
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
));
143 EXPECT_FALSE(r
.get());
146 TEST_F(BoxReaderTest
, InnerTooLongTest
) {
147 std::vector
<uint8
> buf
= GetBuf();
150 // Make an inner box too big for its outer box.
152 scoped_ptr
<BoxReader
> reader(
153 BoxReader::ReadTopLevelBox(&buf
[0], buf
.size(), media_log_
, &err
));
156 EXPECT_FALSE(box
.Parse(reader
.get()));
159 TEST_F(BoxReaderTest
, WrongFourCCTest
) {
160 std::vector
<uint8
> buf
= GetBuf();
163 // Set an unrecognized top-level FourCC.
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());
174 TEST_F(BoxReaderTest
, ScanChildrenTest
) {
175 std::vector
<uint8
> buf
= GetBuf();
177 scoped_ptr
<BoxReader
> reader(
178 BoxReader::ReadTopLevelBox(&buf
[0], buf
.size(), media_log_
, &err
));
180 EXPECT_TRUE(reader
->SkipBytes(16) && reader
->ScanChildren());
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());
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
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',
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
243 TestTopLevelBox(kData
, sizeof(kData
), FOURCC_UUID
);