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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 } | 68 } |
69 | 69 |
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 | 78 BoxReader::BoxReader(const uint8* buf, |
79 BoxReader::BoxReader(const uint8* buf, const int size, | 79 const int size, |
80 const LogCB& log_cb) | 80 const LogCB& log_cb, |
| 81 bool is_EOS) |
81 : BufferReader(buf, size), | 82 : BufferReader(buf, size), |
82 log_cb_(log_cb), | 83 log_cb_(log_cb), |
83 type_(FOURCC_NULL), | 84 type_(FOURCC_NULL), |
84 version_(0), | 85 version_(0), |
85 flags_(0), | 86 flags_(0), |
86 scanned_(false) { | 87 scanned_(false), |
| 88 is_EOS_(is_EOS) { |
87 } | 89 } |
88 | 90 |
89 BoxReader::~BoxReader() { | 91 BoxReader::~BoxReader() { |
90 if (scanned_ && !children_.empty()) { | 92 if (scanned_ && !children_.empty()) { |
91 for (ChildMap::iterator itr = children_.begin(); | 93 for (ChildMap::iterator itr = children_.begin(); |
92 itr != children_.end(); ++itr) { | 94 itr != children_.end(); ++itr) { |
93 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); | 95 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); |
94 } | 96 } |
95 } | 97 } |
96 } | 98 } |
97 | 99 |
98 // static | 100 // static |
99 BoxReader* BoxReader::ReadTopLevelBox(const uint8* buf, | 101 BoxReader* BoxReader::ReadTopLevelBox(const uint8* buf, |
100 const int buf_size, | 102 const int buf_size, |
101 const LogCB& log_cb, | 103 const LogCB& log_cb, |
102 bool* err) { | 104 bool* err) { |
103 scoped_ptr<BoxReader> reader(new BoxReader(buf, buf_size, log_cb)); | 105 scoped_ptr<BoxReader> reader( |
| 106 new BoxReader(buf, buf_size, log_cb, false)); |
104 if (!reader->ReadHeader(err)) | 107 if (!reader->ReadHeader(err)) |
105 return NULL; | 108 return NULL; |
106 | 109 |
107 if (!IsValidTopLevelBox(reader->type(), log_cb)) { | 110 if (!IsValidTopLevelBox(reader->type(), log_cb)) { |
108 *err = true; | 111 *err = true; |
109 return NULL; | 112 return NULL; |
110 } | 113 } |
111 | 114 |
112 if (reader->size() <= buf_size) | 115 if (reader->size() <= buf_size) |
113 return reader.release(); | 116 return reader.release(); |
114 | 117 |
115 return NULL; | 118 return NULL; |
116 } | 119 } |
117 | 120 |
118 // static | 121 // static |
119 bool BoxReader::StartTopLevelBox(const uint8* buf, | 122 bool BoxReader::StartTopLevelBox(const uint8* buf, |
120 const int buf_size, | 123 const int buf_size, |
121 const LogCB& log_cb, | 124 const LogCB& log_cb, |
122 FourCC* type, | 125 FourCC* type, |
123 int* box_size, | 126 int* box_size, |
124 bool* err) { | 127 bool* err) { |
125 BoxReader reader(buf, buf_size, log_cb); | 128 BoxReader reader(buf, buf_size, log_cb, false); |
126 if (!reader.ReadHeader(err)) return false; | 129 if (!reader.ReadHeader(err)) return false; |
127 if (!IsValidTopLevelBox(reader.type(), log_cb)) { | 130 if (!IsValidTopLevelBox(reader.type(), log_cb)) { |
128 *err = true; | 131 *err = true; |
129 return false; | 132 return false; |
130 } | 133 } |
131 *type = reader.type(); | 134 *type = reader.type(); |
132 *box_size = reader.size(); | 135 *box_size = reader.size(); |
133 return true; | 136 return true; |
134 } | 137 } |
135 | 138 |
136 // static | 139 // static |
| 140 BoxReader* BoxReader::ReadConcatentatedBoxes(const uint8* buf, |
| 141 const int buf_size) { |
| 142 return new BoxReader(buf, buf_size, LogCB(), true); |
| 143 } |
| 144 |
| 145 // static |
137 bool BoxReader::IsValidTopLevelBox(const FourCC& type, | 146 bool BoxReader::IsValidTopLevelBox(const FourCC& type, |
138 const LogCB& log_cb) { | 147 const LogCB& log_cb) { |
139 switch (type) { | 148 switch (type) { |
140 case FOURCC_FTYP: | 149 case FOURCC_FTYP: |
141 case FOURCC_PDIN: | 150 case FOURCC_PDIN: |
142 case FOURCC_BLOC: | 151 case FOURCC_BLOC: |
143 case FOURCC_MOOV: | 152 case FOURCC_MOOV: |
144 case FOURCC_MOOF: | 153 case FOURCC_MOOF: |
145 case FOURCC_MFRA: | 154 case FOURCC_MFRA: |
146 case FOURCC_MDAT: | 155 case FOURCC_MDAT: |
(...skipping 15 matching lines...) Expand all Loading... |
162 return false; | 171 return false; |
163 } | 172 } |
164 } | 173 } |
165 | 174 |
166 bool BoxReader::ScanChildren() { | 175 bool BoxReader::ScanChildren() { |
167 DCHECK(!scanned_); | 176 DCHECK(!scanned_); |
168 scanned_ = true; | 177 scanned_ = true; |
169 | 178 |
170 bool err = false; | 179 bool err = false; |
171 while (pos() < size()) { | 180 while (pos() < size()) { |
172 BoxReader child(&buf_[pos_], size_ - pos_, log_cb_); | 181 BoxReader child(&buf_[pos_], size_ - pos_, log_cb_, is_EOS_); |
173 if (!child.ReadHeader(&err)) break; | 182 if (!child.ReadHeader(&err)) break; |
174 | 183 |
175 children_.insert(std::pair<FourCC, BoxReader>(child.type(), child)); | 184 children_.insert(std::pair<FourCC, BoxReader>(child.type(), child)); |
176 pos_ += child.size(); | 185 pos_ += child.size(); |
177 } | 186 } |
178 | 187 |
179 DCHECK(!err); | 188 DCHECK(!err); |
180 return !err && pos() == size(); | 189 return !err && pos() == size(); |
181 } | 190 } |
182 | 191 |
(...skipping 25 matching lines...) Expand all Loading... |
208 RCHECK(Read4(&vflags)); | 217 RCHECK(Read4(&vflags)); |
209 version_ = vflags >> 24; | 218 version_ = vflags >> 24; |
210 flags_ = vflags & 0xffffff; | 219 flags_ = vflags & 0xffffff; |
211 return true; | 220 return true; |
212 } | 221 } |
213 | 222 |
214 bool BoxReader::ReadHeader(bool* err) { | 223 bool BoxReader::ReadHeader(bool* err) { |
215 uint64 size = 0; | 224 uint64 size = 0; |
216 *err = false; | 225 *err = false; |
217 | 226 |
218 if (!HasBytes(8)) return false; | 227 if (!HasBytes(8)) { |
| 228 // If EOS is known, then this is an error. If not, additional data may be |
| 229 // appended later, so this is a soft error. |
| 230 *err = is_EOS_; |
| 231 return false; |
| 232 } |
219 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); | 233 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); |
220 | 234 |
221 if (size == 0) { | 235 if (size == 0) { |
222 MEDIA_LOG(DEBUG, log_cb_) << "Media Source Extensions do not support ISO " | 236 if (is_EOS_) { |
223 "BMFF boxes that run to EOS"; | 237 // All the data bytes are expected to be provided. |
224 *err = true; | 238 size = size_; |
225 return false; | 239 } else { |
| 240 MEDIA_LOG(DEBUG, log_cb_) |
| 241 << "ISO BMFF boxes that run to EOS are not supported"; |
| 242 *err = true; |
| 243 return false; |
| 244 } |
226 } else if (size == 1) { | 245 } else if (size == 1) { |
227 if (!HasBytes(8)) return false; | 246 if (!HasBytes(8)) { |
| 247 // If EOS is known, then this is an error. If not, it's a soft error. |
| 248 *err = is_EOS_; |
| 249 return false; |
| 250 } |
228 CHECK(Read8(&size)); | 251 CHECK(Read8(&size)); |
229 } | 252 } |
230 | 253 |
231 // Implementation-specific: support for boxes larger than 2^31 has been | 254 // Implementation-specific: support for boxes larger than 2^31 has been |
232 // removed. | 255 // removed. |
233 if (size < static_cast<uint64>(pos_) || | 256 if (size < static_cast<uint64>(pos_) || |
234 size > static_cast<uint64>(kint32max)) { | 257 size > static_cast<uint64>(kint32max)) { |
235 *err = true; | 258 *err = true; |
236 return false; | 259 return false; |
237 } | 260 } |
238 | 261 |
| 262 // Make sure the buffer contains at least the expected number of bytes. |
| 263 // Since the data may be appended in pieces, this can only be checked if EOS. |
| 264 if (is_EOS_ && size > static_cast<uint64>(size_)) { |
| 265 *err = true; |
| 266 return false; |
| 267 } |
| 268 |
239 // Note that the pos_ head has advanced to the byte immediately after the | 269 // Note that the pos_ head has advanced to the byte immediately after the |
240 // header, which is where we want it. | 270 // header, which is where we want it. |
241 size_ = size; | 271 size_ = size; |
242 return true; | 272 return true; |
243 } | 273 } |
244 | 274 |
245 } // namespace mp4 | 275 } // namespace mp4 |
246 } // namespace media | 276 } // namespace media |
OLD | NEW |