OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/formats/mp4/box_reader.h" | 5 #include "media/formats/mp4/box_reader.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 bool BufferReader::Read4sInto8s(int64* v) { | 70 bool BufferReader::Read4sInto8s(int64* v) { |
71 // Beware of the need for sign extension. | 71 // Beware of the need for sign extension. |
72 int32 tmp; | 72 int32 tmp; |
73 RCHECK(Read4s(&tmp)); | 73 RCHECK(Read4s(&tmp)); |
74 *v = tmp; | 74 *v = tmp; |
75 return true; | 75 return true; |
76 } | 76 } |
77 | 77 |
78 BoxReader::BoxReader(const uint8* buf, | 78 BoxReader::BoxReader(const uint8* buf, |
79 const int size, | 79 const int size, |
80 const LogCB& log_cb, | 80 const scoped_refptr<MediaLog>& media_log, |
81 bool is_EOS) | 81 bool is_EOS) |
82 : BufferReader(buf, size), | 82 : BufferReader(buf, size), |
83 log_cb_(log_cb), | 83 media_log_(media_log), |
84 type_(FOURCC_NULL), | 84 type_(FOURCC_NULL), |
85 version_(0), | 85 version_(0), |
86 flags_(0), | 86 flags_(0), |
87 scanned_(false), | 87 scanned_(false), |
88 is_EOS_(is_EOS) { | 88 is_EOS_(is_EOS) { |
89 } | 89 } |
90 | 90 |
91 BoxReader::~BoxReader() { | 91 BoxReader::~BoxReader() { |
92 if (scanned_ && !children_.empty()) { | 92 if (scanned_ && !children_.empty()) { |
93 for (ChildMap::iterator itr = children_.begin(); | 93 for (ChildMap::iterator itr = children_.begin(); |
94 itr != children_.end(); ++itr) { | 94 itr != children_.end(); ++itr) { |
95 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); | 95 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); |
96 } | 96 } |
97 } | 97 } |
98 } | 98 } |
99 | 99 |
100 // static | 100 // static |
101 BoxReader* BoxReader::ReadTopLevelBox(const uint8* buf, | 101 BoxReader* BoxReader::ReadTopLevelBox(const uint8* buf, |
102 const int buf_size, | 102 const int buf_size, |
103 const LogCB& log_cb, | 103 const scoped_refptr<MediaLog>& media_log, |
104 bool* err) { | 104 bool* err) { |
105 scoped_ptr<BoxReader> reader( | 105 scoped_ptr<BoxReader> reader(new BoxReader(buf, buf_size, media_log, false)); |
106 new BoxReader(buf, buf_size, log_cb, false)); | |
107 if (!reader->ReadHeader(err)) | 106 if (!reader->ReadHeader(err)) |
108 return NULL; | 107 return NULL; |
109 | 108 |
110 if (!IsValidTopLevelBox(reader->type(), log_cb)) { | 109 if (!IsValidTopLevelBox(reader->type(), media_log)) { |
111 *err = true; | 110 *err = true; |
112 return NULL; | 111 return NULL; |
113 } | 112 } |
114 | 113 |
115 if (reader->size() <= buf_size) | 114 if (reader->size() <= buf_size) |
116 return reader.release(); | 115 return reader.release(); |
117 | 116 |
118 return NULL; | 117 return NULL; |
119 } | 118 } |
120 | 119 |
121 // static | 120 // static |
122 bool BoxReader::StartTopLevelBox(const uint8* buf, | 121 bool BoxReader::StartTopLevelBox(const uint8* buf, |
123 const int buf_size, | 122 const int buf_size, |
124 const LogCB& log_cb, | 123 const scoped_refptr<MediaLog>& media_log, |
125 FourCC* type, | 124 FourCC* type, |
126 int* box_size, | 125 int* box_size, |
127 bool* err) { | 126 bool* err) { |
128 BoxReader reader(buf, buf_size, log_cb, false); | 127 BoxReader reader(buf, buf_size, media_log, false); |
129 if (!reader.ReadHeader(err)) return false; | 128 if (!reader.ReadHeader(err)) return false; |
130 if (!IsValidTopLevelBox(reader.type(), log_cb)) { | 129 if (!IsValidTopLevelBox(reader.type(), media_log)) { |
131 *err = true; | 130 *err = true; |
132 return false; | 131 return false; |
133 } | 132 } |
134 *type = reader.type(); | 133 *type = reader.type(); |
135 *box_size = reader.size(); | 134 *box_size = reader.size(); |
136 return true; | 135 return true; |
137 } | 136 } |
138 | 137 |
139 // static | 138 // static |
140 BoxReader* BoxReader::ReadConcatentatedBoxes(const uint8* buf, | 139 BoxReader* BoxReader::ReadConcatentatedBoxes(const uint8* buf, |
141 const int buf_size) { | 140 const int buf_size) { |
142 return new BoxReader(buf, buf_size, LogCB(), true); | 141 return new BoxReader(buf, buf_size, new MediaLog(), true); |
143 } | 142 } |
144 | 143 |
145 // static | 144 // static |
146 bool BoxReader::IsValidTopLevelBox(const FourCC& type, | 145 bool BoxReader::IsValidTopLevelBox(const FourCC& type, |
147 const LogCB& log_cb) { | 146 const scoped_refptr<MediaLog>& media_log) { |
148 switch (type) { | 147 switch (type) { |
149 case FOURCC_FTYP: | 148 case FOURCC_FTYP: |
150 case FOURCC_PDIN: | 149 case FOURCC_PDIN: |
151 case FOURCC_BLOC: | 150 case FOURCC_BLOC: |
152 case FOURCC_MOOV: | 151 case FOURCC_MOOV: |
153 case FOURCC_MOOF: | 152 case FOURCC_MOOF: |
154 case FOURCC_MFRA: | 153 case FOURCC_MFRA: |
155 case FOURCC_MDAT: | 154 case FOURCC_MDAT: |
156 case FOURCC_FREE: | 155 case FOURCC_FREE: |
157 case FOURCC_SKIP: | 156 case FOURCC_SKIP: |
158 case FOURCC_META: | 157 case FOURCC_META: |
159 case FOURCC_MECO: | 158 case FOURCC_MECO: |
160 case FOURCC_STYP: | 159 case FOURCC_STYP: |
161 case FOURCC_SIDX: | 160 case FOURCC_SIDX: |
162 case FOURCC_SSIX: | 161 case FOURCC_SSIX: |
163 case FOURCC_PRFT: | 162 case FOURCC_PRFT: |
164 case FOURCC_UUID: | 163 case FOURCC_UUID: |
165 case FOURCC_EMSG: | 164 case FOURCC_EMSG: |
166 return true; | 165 return true; |
167 default: | 166 default: |
168 // Hex is used to show nonprintable characters and aid in debugging | 167 // Hex is used to show nonprintable characters and aid in debugging |
169 MEDIA_LOG(DEBUG, log_cb) << "Unrecognized top-level box type " | 168 MEDIA_LOG(DEBUG, media_log) << "Unrecognized top-level box type " |
170 << FourCCToString(type); | 169 << FourCCToString(type); |
171 return false; | 170 return false; |
172 } | 171 } |
173 } | 172 } |
174 | 173 |
175 bool BoxReader::ScanChildren() { | 174 bool BoxReader::ScanChildren() { |
176 DCHECK(!scanned_); | 175 DCHECK(!scanned_); |
177 scanned_ = true; | 176 scanned_ = true; |
178 | 177 |
179 bool err = false; | 178 bool err = false; |
180 while (pos() < size()) { | 179 while (pos() < size()) { |
181 BoxReader child(&buf_[pos_], size_ - pos_, log_cb_, is_EOS_); | 180 BoxReader child(&buf_[pos_], size_ - pos_, media_log_, is_EOS_); |
182 if (!child.ReadHeader(&err)) break; | 181 if (!child.ReadHeader(&err)) break; |
183 | 182 |
184 children_.insert(std::pair<FourCC, BoxReader>(child.type(), child)); | 183 children_.insert(std::pair<FourCC, BoxReader>(child.type(), child)); |
185 pos_ += child.size(); | 184 pos_ += child.size(); |
186 } | 185 } |
187 | 186 |
188 DCHECK(!err); | 187 DCHECK(!err); |
189 return !err && pos() == size(); | 188 return !err && pos() == size(); |
190 } | 189 } |
191 | 190 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 *err = is_EOS_; | 229 *err = is_EOS_; |
231 return false; | 230 return false; |
232 } | 231 } |
233 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); | 232 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); |
234 | 233 |
235 if (size == 0) { | 234 if (size == 0) { |
236 if (is_EOS_) { | 235 if (is_EOS_) { |
237 // All the data bytes are expected to be provided. | 236 // All the data bytes are expected to be provided. |
238 size = size_; | 237 size = size_; |
239 } else { | 238 } else { |
240 MEDIA_LOG(DEBUG, log_cb_) | 239 MEDIA_LOG(DEBUG, media_log_) |
241 << "ISO BMFF boxes that run to EOS are not supported"; | 240 << "ISO BMFF boxes that run to EOS are not supported"; |
242 *err = true; | 241 *err = true; |
243 return false; | 242 return false; |
244 } | 243 } |
245 } else if (size == 1) { | 244 } else if (size == 1) { |
246 if (!HasBytes(8)) { | 245 if (!HasBytes(8)) { |
247 // If EOS is known, then this is an error. If not, it's a soft error. | 246 // If EOS is known, then this is an error. If not, it's a soft error. |
248 *err = is_EOS_; | 247 *err = is_EOS_; |
249 return false; | 248 return false; |
250 } | 249 } |
(...skipping 16 matching lines...) Expand all Loading... |
267 } | 266 } |
268 | 267 |
269 // Note that the pos_ head has advanced to the byte immediately after the | 268 // Note that the pos_ head has advanced to the byte immediately after the |
270 // header, which is where we want it. | 269 // header, which is where we want it. |
271 size_ = size; | 270 size_ = size; |
272 return true; | 271 return true; |
273 } | 272 } |
274 | 273 |
275 } // namespace mp4 | 274 } // namespace mp4 |
276 } // namespace media | 275 } // namespace media |
OLD | NEW |