5#include <packager/media/formats/mp4/box_reader.h>
15#include <absl/log/check.h>
16#include <absl/log/log.h>
17#include <absl/strings/str_format.h>
19#include <packager/macros/logging.h>
20#include <packager/media/base/buffer_reader.h>
21#include <packager/media/base/fourccs.h>
22#include <packager/media/base/rcheck.h>
23#include <packager/media/formats/mp4/box.h>
29BoxReader::BoxReader(
const uint8_t* buf,
size_t size)
30 : BufferReader(buf, size), type_(FOURCC_NULL), scanned_(false) {
35BoxReader::~BoxReader() {
36 if (scanned_ && !children_.empty()) {
37 for (ChildMap::iterator itr = children_.begin(); itr != children_.end();
39 DVLOG(1) <<
"Skipping unknown box: " << FourCCToString(itr->first);
46 const size_t buf_size,
48 std::unique_ptr<BoxReader> reader(
new BoxReader(buf, buf_size));
49 if (!reader->ReadHeader(err))
53 if (reader->type() == FOURCC_mdat)
54 return reader.release();
56 if (reader->size() <= buf_size)
57 return reader.release();
63bool BoxReader::StartBox(
const uint8_t* buf,
64 const size_t buf_size,
69 if (!reader.ReadHeader(err))
71 *type = reader.type();
72 *box_size = reader.size();
76bool BoxReader::ScanChildren() {
80 while (pos() < size()) {
81 std::unique_ptr<BoxReader> child(
82 new BoxReader(&data()[pos()], size() - pos()));
84 if (!child->ReadHeader(&err))
87 FourCC box_type = child->type();
88 size_t box_size = child->size();
89 children_.insert(std::pair<FourCC, std::unique_ptr<BoxReader>>(
90 box_type, std::move(child)));
91 VLOG(2) <<
"Child " << FourCCToString(box_type) <<
" size 0x" << std::hex
92 << box_size << std::dec;
93 RCHECK(SkipBytes(box_size));
99bool BoxReader::ReadChild(
Box* child) {
101 FourCC child_type = child->
BoxType();
103 ChildMap::iterator itr = children_.find(child_type);
104 RCHECK(itr != children_.end());
105 DVLOG(2) <<
"Found a " << FourCCToString(child_type) <<
" box.";
106 RCHECK(child->
Parse(itr->second.get()));
107 children_.erase(itr);
111bool BoxReader::ChildExist(
Box* child) {
112 return children_.count(child->
BoxType()) > 0;
115bool BoxReader::TryReadChild(
Box* child) {
116 if (!children_.count(child->
BoxType()))
118 return ReadChild(child);
121bool BoxReader::ReadHeader(
bool* err) {
125 if (!ReadNBytesInto8(&size,
sizeof(uint32_t)) || !ReadFourCC(&type_))
130 NOTIMPLEMENTED() << absl::StrFormat(
"Box '%s' run to EOS.",
131 FourCCToString(type_).c_str());
134 }
else if (size == 1) {
141 LOG(ERROR) << absl::StrFormat(
"Box '%s' with size (%" PRIu64
143 FourCCToString(type_).c_str(), size);
149 if (size >
static_cast<uint64_t
>(std::numeric_limits<int32_t>::max()) &&
150 type_ != FOURCC_mdat) {
151 LOG(ERROR) << absl::StrFormat(
"Box '%s' size (%" PRIu64
") is too large.",
152 FourCCToString(type_).c_str(), size);
All the methods that are virtual are virtual for mocking.