15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_MP4_BOX_READER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_MP4_BOX_READER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_export.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_log.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/mp4/fourccs.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/mp4/rcheck.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mp4 {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BoxReader;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MEDIA_EXPORT Box {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Box();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Parse(BoxReader* reader) = 0;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual FourCC BoxType() const = 0;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT BufferReader {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferReader(const uint8* buf, const int size)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : buf_(buf), size_(size), pos_(0) {}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasBytes(int count) { return (pos() + count <= size()); }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read a value from the stream, perfoming endian correction, and advance the
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stream pointer.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read1(uint8* v)  WARN_UNUSED_RESULT;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read2(uint16* v) WARN_UNUSED_RESULT;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read2s(int16* v) WARN_UNUSED_RESULT;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read4(uint32* v) WARN_UNUSED_RESULT;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read4s(int32* v) WARN_UNUSED_RESULT;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read8(uint64* v) WARN_UNUSED_RESULT;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read8s(int64* v) WARN_UNUSED_RESULT;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadFourCC(FourCC* v) WARN_UNUSED_RESULT;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadVec(std::vector<uint8>* t, int count) WARN_UNUSED_RESULT;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These variants read a 4-byte integer of the corresponding signedness and
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // store it in the 8-byte return type.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read4Into8(uint64* v) WARN_UNUSED_RESULT;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Read4sInto8s(int64* v) WARN_UNUSED_RESULT;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance the stream by this many bytes.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SkipBytes(int nbytes) WARN_UNUSED_RESULT;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* data() const { return buf_; }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size() const { return size_; }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos() const { return pos_; }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* buf_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename T> bool Read(T* t) WARN_UNUSED_RESULT;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT BoxReader : public BufferReader {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~BoxReader();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a BoxReader from a buffer. Note that this function may return NULL
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if an intact, complete box was not available in the buffer. If |*err| is
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set, there was a stream-level error when creating the box; otherwise, NULL
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values are only expected when insufficient data is available.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |buf| is retained but not owned, and must outlive the BoxReader instance.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BoxReader* ReadTopLevelBox(const uint8* buf,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const int buf_size,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    const LogCB& log_cb,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool* err);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the box header from the current buffer. This function returns true if
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there is enough data to read the header and the header is sane; that is, it
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // does not check to ensure the entire box is in the buffer before returning
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true. The semantics of |*err| are the same as above.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |buf| is not retained.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool StartTopLevelBox(const uint8* buf,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const int buf_size,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const LogCB& log_cb,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FourCC* type,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int* box_size,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool* err) WARN_UNUSED_RESULT;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if |type| is recognized to be a top-level box, false
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise. This returns true for some boxes which we do not parse.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helpful in debugging misaligned appends.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static bool IsValidTopLevelBox(const FourCC& type,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const LogCB& log_cb);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scan through all boxes within the current box, starting at the current
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // buffer position. Must be called before any of the *Child functions work.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ScanChildren() WARN_UNUSED_RESULT;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read exactly one child box from the set of children. The type of the child
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be determined by the BoxType() method of |child|.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadChild(Box* child) WARN_UNUSED_RESULT;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read one child if available. Returns false on error, true on successful
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // read or on child absent.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool MaybeReadChild(Box* child) WARN_UNUSED_RESULT;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read at least one child. False means error or no such child present.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename T> bool ReadChildren(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<T>* children) WARN_UNUSED_RESULT;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read any number of children. False means error.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename T> bool MaybeReadChildren(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<T>* children) WARN_UNUSED_RESULT;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read all children, regardless of FourCC. This is used from exactly one box,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // corresponding to a rather significant inconsistency in the BMFF spec.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this method is mutually exclusive with ScanChildren().
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<typename T> bool ReadAllChildren(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<T>* children) WARN_UNUSED_RESULT;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate the values of 'version()' and 'flags()' from a full box header.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Many boxes, but not all, use these values. This call should happen after
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the box has been initialized, and does not re-read the main box header.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadFullBoxHeader() WARN_UNUSED_RESULT;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FourCC type() const   { return type_; }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 version() const { return version_; }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 flags() const  { return flags_; }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BoxReader(const uint8* buf, const int size, const LogCB& log_cb);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be called immediately after init. If the return is false, this
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indicates that the box header and its contents were not available in the
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stream or were nonsensical, and that the box must not be used further. In
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this case, if |*err| is false, the problem was simply a lack of data, and
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should only be an error condition if some higher-level component knows that
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no more data is coming (i.e. EOS or end of containing box). If |*err| is
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, the error is unrecoverable and the stream should be aborted.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadHeader(bool* err);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LogCB log_cb_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FourCC type_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 version_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 flags_;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::multimap<FourCC, BoxReader> ChildMap;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of child box FourCCs and their corresponding buffer readers. Only
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid if scanned_ is true.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChildMap children_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool scanned_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Template definitions
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> bool BoxReader::ReadChildren(std::vector<T>* children) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RCHECK(MaybeReadChildren(children) && !children->empty());
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T>
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BoxReader::MaybeReadChildren(std::vector<T>* children) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(scanned_);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(children->empty());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  children->resize(1);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FourCC child_type = (*children)[0].BoxType();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChildMap::iterator start_itr = children_.lower_bound(child_type);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChildMap::iterator end_itr = children_.upper_bound(child_type);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  children->resize(std::distance(start_itr, end_itr));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename std::vector<T>::iterator child_itr = children->begin();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ChildMap::iterator itr = start_itr; itr != end_itr; ++itr) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(child_itr->Parse(&itr->second));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++child_itr;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  children_.erase(start_itr, end_itr);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << "Found " << children->size() << " "
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << FourCCToString(child_type) << " boxes.";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T>
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BoxReader::ReadAllChildren(std::vector<T>* children) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!scanned_);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scanned_ = true;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool err = false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pos() < size()) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BoxReader child_reader(&buf_[pos_], size_ - pos_, log_cb_);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!child_reader.ReadHeader(&err)) break;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    T child;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(child.Parse(&child_reader));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    children->push_back(child);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos_ += child_reader.size();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !err;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mp4
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // MEDIA_MP4_BOX_READER_H_
215