Home | History | Annotate | Download | only in mp4
      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 {
     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 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