• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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/mp4/box_reader.h"
11 #include "media/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 {
Parsemedia::mp4::FreeBox34   virtual bool Parse(BoxReader* reader) OVERRIDE {
35     return true;
36   }
BoxTypemedia::mp4::FreeBox37   virtual FourCC BoxType() const OVERRIDE { return FOURCC_FREE; }
38 };
39 
40 struct PsshBox : Box {
41   uint32 val;
42 
Parsemedia::mp4::PsshBox43   virtual bool Parse(BoxReader* reader) OVERRIDE {
44     return reader->Read4(&val);
45   }
BoxTypemedia::mp4::PsshBox46   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 
Parsemedia::mp4::SkipBox58   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   }
BoxTypemedia::mp4::SkipBox69   virtual FourCC BoxType() const OVERRIDE { return FOURCC_SKIP; }
70 
71   SkipBox();
72   virtual ~SkipBox();
73 };
74 
SkipBox()75 SkipBox::SkipBox() {}
~SkipBox()76 SkipBox::~SkipBox() {}
77 
78 class BoxReaderTest : public testing::Test {
79  protected:
GetBuf()80   std::vector<uint8> GetBuf() {
81     return std::vector<uint8>(kSkipBox, kSkipBox + sizeof(kSkipBox));
82   }
83 };
84 
TEST_F(BoxReaderTest,ExpectedOperationTest)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 
TEST_F(BoxReaderTest,OuterTooShortTest)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 
TEST_F(BoxReaderTest,InnerTooLongTest)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 
TEST_F(BoxReaderTest,WrongFourCCTest)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 
TEST_F(BoxReaderTest,ScanChildrenTest)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 
TEST_F(BoxReaderTest,ReadAllChildrenTest)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 
TEST_F(BoxReaderTest,SkippingBloc)184 TEST_F(BoxReaderTest, SkippingBloc) {
185   static const uint8 kData[] = {
186     0x00, 0x00, 0x00, 0x09,  'b',  'l',  'o',  'c', 0x00
187   };
188 
189   std::vector<uint8> buf(kData, kData + sizeof(kData));
190 
191   bool err;
192   scoped_ptr<BoxReader> reader(
193       BoxReader::ReadTopLevelBox(&buf[0], buf.size(), LogCB(), &err));
194 
195   EXPECT_FALSE(err);
196   EXPECT_TRUE(reader);
197   EXPECT_EQ(FOURCC_BLOC, reader->type());
198 }
199 
200 }  // namespace mp4
201 }  // namespace media
202