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