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 |