| 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 |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "media/formats/mp4/box_definitions.h" | 12 #include "media/formats/mp4/box_definitions.h" |
| 13 | 13 |
| 14 namespace media { | 14 namespace media { |
| 15 namespace mp4 { | 15 namespace mp4 { |
| 16 | 16 |
| 17 Box::~Box() {} | 17 Box::~Box() {} |
| 18 | 18 |
| 19 bool BufferReader::Read1(uint8* v) { | 19 bool BufferReader::Read1(uint8_t* v) { |
| 20 RCHECK(HasBytes(1)); | 20 RCHECK(HasBytes(1)); |
| 21 *v = buf_[pos_++]; | 21 *v = buf_[pos_++]; |
| 22 return true; | 22 return true; |
| 23 } | 23 } |
| 24 | 24 |
| 25 // Internal implementation of multi-byte reads | 25 // Internal implementation of multi-byte reads |
| 26 template<typename T> bool BufferReader::Read(T* v) { | 26 template<typename T> bool BufferReader::Read(T* v) { |
| 27 RCHECK(HasBytes(sizeof(T))); | 27 RCHECK(HasBytes(sizeof(T))); |
| 28 | 28 |
| 29 T tmp = 0; | 29 T tmp = 0; |
| 30 for (size_t i = 0; i < sizeof(T); i++) { | 30 for (size_t i = 0; i < sizeof(T); i++) { |
| 31 tmp <<= 8; | 31 tmp <<= 8; |
| 32 tmp += buf_[pos_++]; | 32 tmp += buf_[pos_++]; |
| 33 } | 33 } |
| 34 *v = tmp; | 34 *v = tmp; |
| 35 return true; | 35 return true; |
| 36 } | 36 } |
| 37 | 37 |
| 38 bool BufferReader::Read2(uint16* v) { return Read(v); } | 38 bool BufferReader::Read2(uint16_t* v) { |
| 39 bool BufferReader::Read2s(int16* v) { return Read(v); } | 39 return Read(v); |
| 40 bool BufferReader::Read4(uint32* v) { return Read(v); } | 40 } |
| 41 bool BufferReader::Read4s(int32* v) { return Read(v); } | 41 bool BufferReader::Read2s(int16_t* v) { |
| 42 bool BufferReader::Read8(uint64* v) { return Read(v); } | 42 return Read(v); |
| 43 bool BufferReader::Read8s(int64* v) { return Read(v); } | 43 } |
| 44 bool BufferReader::Read4(uint32_t* v) { |
| 45 return Read(v); |
| 46 } |
| 47 bool BufferReader::Read4s(int32_t* v) { |
| 48 return Read(v); |
| 49 } |
| 50 bool BufferReader::Read8(uint64_t* v) { |
| 51 return Read(v); |
| 52 } |
| 53 bool BufferReader::Read8s(int64_t* v) { |
| 54 return Read(v); |
| 55 } |
| 44 | 56 |
| 45 bool BufferReader::ReadFourCC(FourCC* v) { | 57 bool BufferReader::ReadFourCC(FourCC* v) { |
| 46 return Read4(reinterpret_cast<uint32*>(v)); | 58 return Read4(reinterpret_cast<uint32_t*>(v)); |
| 47 } | 59 } |
| 48 | 60 |
| 49 bool BufferReader::ReadVec(std::vector<uint8>* vec, uint64 count) { | 61 bool BufferReader::ReadVec(std::vector<uint8_t>* vec, uint64_t count) { |
| 50 RCHECK(HasBytes(count)); | 62 RCHECK(HasBytes(count)); |
| 51 vec->clear(); | 63 vec->clear(); |
| 52 vec->insert(vec->end(), buf_ + pos_, buf_ + pos_ + count); | 64 vec->insert(vec->end(), buf_ + pos_, buf_ + pos_ + count); |
| 53 pos_ += count; | 65 pos_ += count; |
| 54 return true; | 66 return true; |
| 55 } | 67 } |
| 56 | 68 |
| 57 bool BufferReader::SkipBytes(uint64 bytes) { | 69 bool BufferReader::SkipBytes(uint64_t bytes) { |
| 58 RCHECK(HasBytes(bytes)); | 70 RCHECK(HasBytes(bytes)); |
| 59 pos_ += bytes; | 71 pos_ += bytes; |
| 60 return true; | 72 return true; |
| 61 } | 73 } |
| 62 | 74 |
| 63 bool BufferReader::Read4Into8(uint64* v) { | 75 bool BufferReader::Read4Into8(uint64_t* v) { |
| 64 uint32 tmp; | 76 uint32_t tmp; |
| 65 RCHECK(Read4(&tmp)); | 77 RCHECK(Read4(&tmp)); |
| 66 *v = tmp; | 78 *v = tmp; |
| 67 return true; | 79 return true; |
| 68 } | 80 } |
| 69 | 81 |
| 70 bool BufferReader::Read4sInto8s(int64* v) { | 82 bool BufferReader::Read4sInto8s(int64_t* v) { |
| 71 // Beware of the need for sign extension. | 83 // Beware of the need for sign extension. |
| 72 int32 tmp; | 84 int32_t tmp; |
| 73 RCHECK(Read4s(&tmp)); | 85 RCHECK(Read4s(&tmp)); |
| 74 *v = tmp; | 86 *v = tmp; |
| 75 return true; | 87 return true; |
| 76 } | 88 } |
| 77 | 89 |
| 78 BoxReader::BoxReader(const uint8* buf, | 90 BoxReader::BoxReader(const uint8_t* buf, |
| 79 const int size, | 91 const int size, |
| 80 const scoped_refptr<MediaLog>& media_log, | 92 const scoped_refptr<MediaLog>& media_log, |
| 81 bool is_EOS) | 93 bool is_EOS) |
| 82 : BufferReader(buf, size), | 94 : BufferReader(buf, size), |
| 83 media_log_(media_log), | 95 media_log_(media_log), |
| 84 type_(FOURCC_NULL), | 96 type_(FOURCC_NULL), |
| 85 version_(0), | 97 version_(0), |
| 86 flags_(0), | 98 flags_(0), |
| 87 scanned_(false), | 99 scanned_(false), |
| 88 is_EOS_(is_EOS) { | 100 is_EOS_(is_EOS) {} |
| 89 } | |
| 90 | 101 |
| 91 BoxReader::~BoxReader() { | 102 BoxReader::~BoxReader() { |
| 92 if (scanned_ && !children_.empty()) { | 103 if (scanned_ && !children_.empty()) { |
| 93 for (ChildMap::iterator itr = children_.begin(); | 104 for (ChildMap::iterator itr = children_.begin(); |
| 94 itr != children_.end(); ++itr) { | 105 itr != children_.end(); ++itr) { |
| 95 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); | 106 DVLOG(1) << "Skipping unknown box: " << FourCCToString(itr->first); |
| 96 } | 107 } |
| 97 } | 108 } |
| 98 } | 109 } |
| 99 | 110 |
| 100 // static | 111 // static |
| 101 BoxReader* BoxReader::ReadTopLevelBox(const uint8* buf, | 112 BoxReader* BoxReader::ReadTopLevelBox(const uint8_t* buf, |
| 102 const int buf_size, | 113 const int buf_size, |
| 103 const scoped_refptr<MediaLog>& media_log, | 114 const scoped_refptr<MediaLog>& media_log, |
| 104 bool* err) { | 115 bool* err) { |
| 105 scoped_ptr<BoxReader> reader(new BoxReader(buf, buf_size, media_log, false)); | 116 scoped_ptr<BoxReader> reader(new BoxReader(buf, buf_size, media_log, false)); |
| 106 if (!reader->ReadHeader(err)) | 117 if (!reader->ReadHeader(err)) |
| 107 return NULL; | 118 return NULL; |
| 108 | 119 |
| 109 if (!IsValidTopLevelBox(reader->type(), media_log)) { | 120 if (!IsValidTopLevelBox(reader->type(), media_log)) { |
| 110 *err = true; | 121 *err = true; |
| 111 return NULL; | 122 return NULL; |
| 112 } | 123 } |
| 113 | 124 |
| 114 if (reader->size() <= static_cast<uint64>(buf_size)) | 125 if (reader->size() <= static_cast<uint64_t>(buf_size)) |
| 115 return reader.release(); | 126 return reader.release(); |
| 116 | 127 |
| 117 return NULL; | 128 return NULL; |
| 118 } | 129 } |
| 119 | 130 |
| 120 // static | 131 // static |
| 121 bool BoxReader::StartTopLevelBox(const uint8* buf, | 132 bool BoxReader::StartTopLevelBox(const uint8_t* buf, |
| 122 const int buf_size, | 133 const int buf_size, |
| 123 const scoped_refptr<MediaLog>& media_log, | 134 const scoped_refptr<MediaLog>& media_log, |
| 124 FourCC* type, | 135 FourCC* type, |
| 125 int* box_size, | 136 int* box_size, |
| 126 bool* err) { | 137 bool* err) { |
| 127 BoxReader reader(buf, buf_size, media_log, false); | 138 BoxReader reader(buf, buf_size, media_log, false); |
| 128 if (!reader.ReadHeader(err)) return false; | 139 if (!reader.ReadHeader(err)) return false; |
| 129 if (!IsValidTopLevelBox(reader.type(), media_log)) { | 140 if (!IsValidTopLevelBox(reader.type(), media_log)) { |
| 130 *err = true; | 141 *err = true; |
| 131 return false; | 142 return false; |
| 132 } | 143 } |
| 133 *type = reader.type(); | 144 *type = reader.type(); |
| 134 *box_size = reader.size(); | 145 *box_size = reader.size(); |
| 135 return true; | 146 return true; |
| 136 } | 147 } |
| 137 | 148 |
| 138 // static | 149 // static |
| 139 BoxReader* BoxReader::ReadConcatentatedBoxes(const uint8* buf, | 150 BoxReader* BoxReader::ReadConcatentatedBoxes(const uint8_t* buf, |
| 140 const int buf_size) { | 151 const int buf_size) { |
| 141 return new BoxReader(buf, buf_size, new MediaLog(), true); | 152 return new BoxReader(buf, buf_size, new MediaLog(), true); |
| 142 } | 153 } |
| 143 | 154 |
| 144 // static | 155 // static |
| 145 bool BoxReader::IsValidTopLevelBox(const FourCC& type, | 156 bool BoxReader::IsValidTopLevelBox(const FourCC& type, |
| 146 const scoped_refptr<MediaLog>& media_log) { | 157 const scoped_refptr<MediaLog>& media_log) { |
| 147 switch (type) { | 158 switch (type) { |
| 148 case FOURCC_FTYP: | 159 case FOURCC_FTYP: |
| 149 case FOURCC_PDIN: | 160 case FOURCC_PDIN: |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 children_.erase(itr); | 216 children_.erase(itr); |
| 206 return true; | 217 return true; |
| 207 } | 218 } |
| 208 | 219 |
| 209 bool BoxReader::MaybeReadChild(Box* child) { | 220 bool BoxReader::MaybeReadChild(Box* child) { |
| 210 if (!children_.count(child->BoxType())) return true; | 221 if (!children_.count(child->BoxType())) return true; |
| 211 return ReadChild(child); | 222 return ReadChild(child); |
| 212 } | 223 } |
| 213 | 224 |
| 214 bool BoxReader::ReadFullBoxHeader() { | 225 bool BoxReader::ReadFullBoxHeader() { |
| 215 uint32 vflags; | 226 uint32_t vflags; |
| 216 RCHECK(Read4(&vflags)); | 227 RCHECK(Read4(&vflags)); |
| 217 version_ = vflags >> 24; | 228 version_ = vflags >> 24; |
| 218 flags_ = vflags & 0xffffff; | 229 flags_ = vflags & 0xffffff; |
| 219 return true; | 230 return true; |
| 220 } | 231 } |
| 221 | 232 |
| 222 bool BoxReader::ReadHeader(bool* err) { | 233 bool BoxReader::ReadHeader(bool* err) { |
| 223 uint64 size = 0; | 234 uint64_t size = 0; |
| 224 *err = false; | 235 *err = false; |
| 225 | 236 |
| 226 if (!HasBytes(8)) { | 237 if (!HasBytes(8)) { |
| 227 // If EOS is known, then this is an error. If not, additional data may be | 238 // If EOS is known, then this is an error. If not, additional data may be |
| 228 // appended later, so this is a soft error. | 239 // appended later, so this is a soft error. |
| 229 *err = is_EOS_; | 240 *err = is_EOS_; |
| 230 return false; | 241 return false; |
| 231 } | 242 } |
| 232 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); | 243 CHECK(Read4Into8(&size) && ReadFourCC(&type_)); |
| 233 | 244 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 245 if (!HasBytes(8)) { | 256 if (!HasBytes(8)) { |
| 246 // If EOS is known, then this is an error. If not, it's a soft error. | 257 // If EOS is known, then this is an error. If not, it's a soft error. |
| 247 *err = is_EOS_; | 258 *err = is_EOS_; |
| 248 return false; | 259 return false; |
| 249 } | 260 } |
| 250 CHECK(Read8(&size)); | 261 CHECK(Read8(&size)); |
| 251 } | 262 } |
| 252 | 263 |
| 253 // Implementation-specific: support for boxes larger than 2^31 has been | 264 // Implementation-specific: support for boxes larger than 2^31 has been |
| 254 // removed. | 265 // removed. |
| 255 if (size < static_cast<uint64>(pos_) || | 266 if (size < static_cast<uint64_t>(pos_) || |
| 256 size > static_cast<uint64>(kint32max)) { | 267 size > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) { |
| 257 *err = true; | 268 *err = true; |
| 258 return false; | 269 return false; |
| 259 } | 270 } |
| 260 | 271 |
| 261 // Make sure the buffer contains at least the expected number of bytes. | 272 // Make sure the buffer contains at least the expected number of bytes. |
| 262 // Since the data may be appended in pieces, this can only be checked if EOS. | 273 // Since the data may be appended in pieces, this can only be checked if EOS. |
| 263 if (is_EOS_ && size > size_) { | 274 if (is_EOS_ && size > size_) { |
| 264 *err = true; | 275 *err = true; |
| 265 return false; | 276 return false; |
| 266 } | 277 } |
| 267 | 278 |
| 268 // Note that the pos_ head has advanced to the byte immediately after the | 279 // Note that the pos_ head has advanced to the byte immediately after the |
| 269 // header, which is where we want it. | 280 // header, which is where we want it. |
| 270 size_ = size; | 281 size_ = size; |
| 271 return true; | 282 return true; |
| 272 } | 283 } |
| 273 | 284 |
| 274 } // namespace mp4 | 285 } // namespace mp4 |
| 275 } // namespace media | 286 } // namespace media |
| OLD | NEW |