| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "media/mp4/box_definitions.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "media/mp4/box_reader.h" |
| 9 #include "media/mp4/fourccs.h" |
| 10 #include "media/mp4/rcheck.h" |
| 11 |
| 12 namespace media { |
| 13 namespace mp4 { |
| 14 |
| 15 bool FileType::Parse(BoxReader* reader) { |
| 16 RCHECK(reader->ReadFourCC(&major_brand) && reader->Read4(&minor_version)); |
| 17 size_t num_brands = (reader->size() - reader->pos()) / sizeof(FourCC); |
| 18 return reader->SkipBytes(sizeof(FourCC) * num_brands); // compatible_brands |
| 19 } |
| 20 |
| 21 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {} |
| 22 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {} |
| 23 FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; } |
| 24 |
| 25 bool ProtectionSystemSpecificHeader::Parse(BoxReader* reader) { |
| 26 uint32 size; |
| 27 return reader->SkipBytes(4) && |
| 28 reader->ReadVec(&system_id, 16) && |
| 29 reader->Read4(&size) && |
| 30 reader->ReadVec(&data, size); |
| 31 } |
| 32 |
| 33 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {} |
| 34 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {} |
| 35 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; } |
| 36 |
| 37 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) { |
| 38 RCHECK(reader->ReadFullBoxHeader()); |
| 39 if (reader->flags() & 1) |
| 40 RCHECK(reader->SkipBytes(8)); |
| 41 |
| 42 uint32 count; |
| 43 RCHECK(reader->Read4(&count) && |
| 44 reader->HasBytes(count * (reader->version() == 1 ? 8 : 4))); |
| 45 offsets.resize(count); |
| 46 |
| 47 for (uint32 i = 0; i < count; i++) { |
| 48 if (reader->version() == 1) { |
| 49 RCHECK(reader->Read8(&offsets[i])); |
| 50 } else { |
| 51 RCHECK(reader->Read4Into8(&offsets[i])); |
| 52 } |
| 53 } |
| 54 return true; |
| 55 } |
| 56 |
| 57 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize() |
| 58 : default_sample_info_size(0), sample_count(0) { |
| 59 } |
| 60 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {} |
| 61 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; } |
| 62 |
| 63 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) { |
| 64 RCHECK(reader->ReadFullBoxHeader()); |
| 65 if (reader->flags() & 1) |
| 66 RCHECK(reader->SkipBytes(8)); |
| 67 |
| 68 RCHECK(reader->Read1(&default_sample_info_size) && |
| 69 reader->Read4(&sample_count)); |
| 70 if (default_sample_info_size == 0) |
| 71 return reader->ReadVec(&sample_info_sizes, sample_count); |
| 72 return true; |
| 73 } |
| 74 |
| 75 OriginalFormat::OriginalFormat() {} |
| 76 OriginalFormat::~OriginalFormat() {} |
| 77 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; } |
| 78 |
| 79 bool OriginalFormat::Parse(BoxReader* reader) { |
| 80 return reader->ReadFourCC(&format); |
| 81 } |
| 82 |
| 83 SchemeType::SchemeType() {} |
| 84 SchemeType::~SchemeType() {} |
| 85 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; } |
| 86 |
| 87 bool SchemeType::Parse(BoxReader* reader) { |
| 88 RCHECK(reader->SkipBytes(4) && |
| 89 reader->ReadFourCC(&type) && |
| 90 reader->Read4(&version)); |
| 91 RCHECK(type == FOURCC_CENC); |
| 92 return true; |
| 93 } |
| 94 |
| 95 TrackEncryption::TrackEncryption() |
| 96 : is_encrypted(false), default_iv_size(0) { |
| 97 } |
| 98 TrackEncryption::~TrackEncryption() {} |
| 99 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; } |
| 100 |
| 101 bool TrackEncryption::Parse(BoxReader* reader) { |
| 102 uint8 flag; |
| 103 RCHECK(reader->SkipBytes(2) && |
| 104 reader->Read1(&flag) && |
| 105 reader->Read1(&default_iv_size) && |
| 106 reader->ReadVec(&default_kid, 16)); |
| 107 is_encrypted = (flag != 0); |
| 108 if (is_encrypted) { |
| 109 RCHECK(default_iv_size == 8 || default_iv_size == 16); |
| 110 } else { |
| 111 RCHECK(default_iv_size == 0); |
| 112 } |
| 113 return true; |
| 114 } |
| 115 |
| 116 SchemeInfo::SchemeInfo() {} |
| 117 SchemeInfo::~SchemeInfo() {} |
| 118 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; } |
| 119 |
| 120 bool SchemeInfo::Parse(BoxReader* reader) { |
| 121 return reader->ScanChildren() && reader->ReadChild(&track_encryption); |
| 122 } |
| 123 |
| 124 ProtectionSchemeInfo::ProtectionSchemeInfo() {} |
| 125 ProtectionSchemeInfo::~ProtectionSchemeInfo() {} |
| 126 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; } |
| 127 |
| 128 bool ProtectionSchemeInfo::Parse(BoxReader* reader) { |
| 129 return reader->ScanChildren() && |
| 130 reader->ReadChild(&type) && |
| 131 reader->ReadChild(&info); |
| 132 } |
| 133 |
| 134 MovieHeader::MovieHeader() {} |
| 135 MovieHeader::~MovieHeader() {} |
| 136 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; } |
| 137 |
| 138 bool MovieHeader::Parse(BoxReader* reader) { |
| 139 RCHECK(reader->ReadFullBoxHeader()); |
| 140 |
| 141 if (reader->version() == 1) { |
| 142 RCHECK(reader->Read8(&creation_time) && |
| 143 reader->Read8(&modification_time) && |
| 144 reader->Read4(×cale) && |
| 145 reader->Read8(&duration)); |
| 146 } else { |
| 147 RCHECK(reader->Read4Into8(&creation_time) && |
| 148 reader->Read4Into8(&modification_time) && |
| 149 reader->Read4(×cale) && |
| 150 reader->Read4Into8(&duration)); |
| 151 } |
| 152 |
| 153 RCHECK(reader->Read4s(&rate) && |
| 154 reader->Read2s(&volume) && |
| 155 reader->SkipBytes(10) && // reserved |
| 156 reader->SkipBytes(36) && // matrix |
| 157 reader->SkipBytes(24) && // predefined zero |
| 158 reader->Read4(&next_track_id)); |
| 159 return true; |
| 160 } |
| 161 |
| 162 TrackHeader::TrackHeader() {} |
| 163 TrackHeader::~TrackHeader() {} |
| 164 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; } |
| 165 |
| 166 bool TrackHeader::Parse(BoxReader* reader) { |
| 167 RCHECK(reader->ReadFullBoxHeader()); |
| 168 if (reader->version() == 1) { |
| 169 RCHECK(reader->Read8(&creation_time) && |
| 170 reader->Read8(&modification_time) && |
| 171 reader->Read4(&track_id) && |
| 172 reader->SkipBytes(4) && // reserved |
| 173 reader->Read8(&duration)); |
| 174 } else { |
| 175 RCHECK(reader->Read4Into8(&creation_time) && |
| 176 reader->Read4Into8(&modification_time) && |
| 177 reader->Read4(&track_id) && |
| 178 reader->SkipBytes(4) && // reserved |
| 179 reader->Read4Into8(&duration)); |
| 180 } |
| 181 |
| 182 RCHECK(reader->SkipBytes(8) && // reserved |
| 183 reader->Read2s(&layer) && |
| 184 reader->Read2s(&alternate_group) && |
| 185 reader->Read2s(&volume) && |
| 186 reader->SkipBytes(2) && // reserved |
| 187 reader->SkipBytes(36) && // matrix |
| 188 reader->Read4(&width) && |
| 189 reader->Read4(&height)); |
| 190 width >>= 16; |
| 191 height >>= 16; |
| 192 return true; |
| 193 } |
| 194 |
| 195 SampleDescription::SampleDescription() {} |
| 196 SampleDescription::~SampleDescription() {} |
| 197 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; } |
| 198 |
| 199 bool SampleDescription::Parse(BoxReader* reader) { |
| 200 uint32 count; |
| 201 RCHECK(reader->SkipBytes(4) && |
| 202 reader->Read4(&count) && |
| 203 reader->ScanChildren()); |
| 204 video_entries.clear(); |
| 205 audio_entries.clear(); |
| 206 |
| 207 // Note: this value is preset before scanning begins. See comments in the |
| 208 // Parse(Media*) function. |
| 209 if (type == kVideo) { |
| 210 RCHECK(reader->ReadAllChildren(&video_entries)); |
| 211 } else if (type == kAudio) { |
| 212 RCHECK(reader->ReadAllChildren(&audio_entries)); |
| 213 } |
| 214 return true; |
| 215 } |
| 216 |
| 217 SampleTable::SampleTable() {} |
| 218 SampleTable::~SampleTable() {} |
| 219 FourCC SampleTable::BoxType() const { return FOURCC_STBL; } |
| 220 |
| 221 bool SampleTable::Parse(BoxReader* reader) { |
| 222 return reader->ScanChildren() && |
| 223 reader->ReadChild(&description); |
| 224 } |
| 225 |
| 226 EditList::EditList() {} |
| 227 EditList::~EditList() {} |
| 228 FourCC EditList::BoxType() const { return FOURCC_ELST; } |
| 229 |
| 230 bool EditList::Parse(BoxReader* reader) { |
| 231 uint32 count; |
| 232 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count)); |
| 233 |
| 234 if (reader->version() == 1) { |
| 235 RCHECK(reader->HasBytes(count * 20)); |
| 236 } else { |
| 237 RCHECK(reader->HasBytes(count * 12)); |
| 238 } |
| 239 edits.resize(count); |
| 240 |
| 241 for (std::vector<EditListEntry>::iterator edit = edits.begin(); |
| 242 edit != edits.end(); ++edit) { |
| 243 if (reader->version() == 1) { |
| 244 RCHECK(reader->Read8(&edit->segment_duration) && |
| 245 reader->Read8s(&edit->media_time)); |
| 246 } else { |
| 247 RCHECK(reader->Read4Into8(&edit->segment_duration) && |
| 248 reader->Read4sInto8s(&edit->media_time)); |
| 249 } |
| 250 RCHECK(reader->Read2s(&edit->media_rate_integer) && |
| 251 reader->Read2s(&edit->media_rate_fraction)); |
| 252 } |
| 253 return true; |
| 254 } |
| 255 |
| 256 Edit::Edit() {} |
| 257 Edit::~Edit() {} |
| 258 FourCC Edit::BoxType() const { return FOURCC_EDTS; } |
| 259 |
| 260 bool Edit::Parse(BoxReader* reader) { |
| 261 return reader->ScanChildren() && reader->ReadChild(&list); |
| 262 } |
| 263 |
| 264 HandlerReference::HandlerReference() {} |
| 265 HandlerReference::~HandlerReference() {} |
| 266 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; } |
| 267 |
| 268 bool HandlerReference::Parse(BoxReader* reader) { |
| 269 FourCC hdlr_type; |
| 270 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type)); |
| 271 // Note: remaining fields in box ignored |
| 272 if (hdlr_type == FOURCC_VIDE) { |
| 273 type = kVideo; |
| 274 } else if (hdlr_type == FOURCC_SOUN) { |
| 275 type = kAudio; |
| 276 } else { |
| 277 type = kInvalid; |
| 278 } |
| 279 return true; |
| 280 } |
| 281 |
| 282 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord() {} |
| 283 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {} |
| 284 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; } |
| 285 |
| 286 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) { |
| 287 RCHECK(reader->Read1(&version) && version == 1 && |
| 288 reader->Read1(&profile_indication) && |
| 289 reader->Read1(&profile_compatibility) && |
| 290 reader->Read1(&avc_level)); |
| 291 |
| 292 uint8 length_size_minus_one; |
| 293 RCHECK(reader->Read1(&length_size_minus_one) && |
| 294 (length_size_minus_one & 0xfc) == 0xfc); |
| 295 length_size = (length_size_minus_one & 0x3) + 1; |
| 296 |
| 297 uint8 num_sps; |
| 298 RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0); |
| 299 num_sps &= 0x1f; |
| 300 |
| 301 sps_list.resize(num_sps); |
| 302 for (int i = 0; i < num_sps; i++) { |
| 303 uint16 sps_length; |
| 304 RCHECK(reader->Read2(&sps_length) && |
| 305 reader->ReadVec(&sps_list[i], sps_length)); |
| 306 } |
| 307 |
| 308 uint8 num_pps; |
| 309 RCHECK(reader->Read1(&num_pps)); |
| 310 |
| 311 pps_list.resize(num_pps); |
| 312 for (int i = 0; i < num_pps; i++) { |
| 313 uint16 pps_length; |
| 314 RCHECK(reader->Read2(&pps_length) && |
| 315 reader->ReadVec(&pps_list[i], pps_length)); |
| 316 } |
| 317 |
| 318 return true; |
| 319 } |
| 320 |
| 321 VideoSampleEntry::VideoSampleEntry() {} |
| 322 VideoSampleEntry::~VideoSampleEntry() {} |
| 323 FourCC VideoSampleEntry::BoxType() const { |
| 324 DCHECK(false) << "VideoSampleEntry should be parsed according to the " |
| 325 << "handler type recovered in its Media ancestor."; |
| 326 return FOURCC_NULL; |
| 327 } |
| 328 |
| 329 bool VideoSampleEntry::Parse(BoxReader* reader) { |
| 330 format = reader->type(); |
| 331 RCHECK(reader->SkipBytes(6) && |
| 332 reader->Read2(&data_reference_index) && |
| 333 reader->SkipBytes(16) && |
| 334 reader->Read2(&width) && |
| 335 reader->Read2(&height) && |
| 336 reader->SkipBytes(50)); |
| 337 |
| 338 RCHECK(reader->ScanChildren()); |
| 339 if (format == FOURCC_ENCV) { |
| 340 RCHECK(reader->ReadChild(&sinf)); |
| 341 } |
| 342 |
| 343 // TODO(strobe): finalize format signaling for encrypted media |
| 344 // (http://crbug.com/132351) |
| 345 // |
| 346 // if (format == FOURCC_AVC1 || |
| 347 // (format == FOURCC_ENCV && |
| 348 // sinf.format.format == FOURCC_AVC1)) { |
| 349 RCHECK(reader->ReadChild(&avcc)); |
| 350 // } |
| 351 return true; |
| 352 } |
| 353 |
| 354 AudioSampleEntry::AudioSampleEntry() {} |
| 355 AudioSampleEntry::~AudioSampleEntry() {} |
| 356 FourCC AudioSampleEntry::BoxType() const { |
| 357 DCHECK(false) << "AudioSampleEntry should be parsed according to the " |
| 358 << "handler type recovered in its Media ancestor."; |
| 359 return FOURCC_NULL; |
| 360 } |
| 361 |
| 362 bool AudioSampleEntry::Parse(BoxReader* reader) { |
| 363 format = reader->type(); |
| 364 RCHECK(reader->SkipBytes(6) && |
| 365 reader->Read2(&data_reference_index) && |
| 366 reader->SkipBytes(8) && |
| 367 reader->Read2(&channelcount) && |
| 368 reader->Read2(&samplesize) && |
| 369 reader->SkipBytes(4) && |
| 370 reader->Read4(&samplerate)); |
| 371 // Convert from 16.16 fixed point to integer |
| 372 samplerate >>= 16; |
| 373 |
| 374 RCHECK(reader->ScanChildren()); |
| 375 if (format == FOURCC_ENCA) { |
| 376 RCHECK(reader->ReadChild(&sinf)); |
| 377 } |
| 378 return true; |
| 379 } |
| 380 |
| 381 MediaHeader::MediaHeader() {} |
| 382 MediaHeader::~MediaHeader() {} |
| 383 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; } |
| 384 |
| 385 bool MediaHeader::Parse(BoxReader* reader) { |
| 386 RCHECK(reader->ReadFullBoxHeader()); |
| 387 |
| 388 if (reader->version() == 1) { |
| 389 RCHECK(reader->Read8(&creation_time) && |
| 390 reader->Read8(&modification_time) && |
| 391 reader->Read4(×cale) && |
| 392 reader->Read8(&duration)); |
| 393 } else { |
| 394 RCHECK(reader->Read4Into8(&creation_time) && |
| 395 reader->Read4Into8(&modification_time) && |
| 396 reader->Read4(×cale) && |
| 397 reader->Read4Into8(&duration)); |
| 398 } |
| 399 // Skip language information |
| 400 return reader->SkipBytes(4); |
| 401 } |
| 402 |
| 403 MediaInformation::MediaInformation() {} |
| 404 MediaInformation::~MediaInformation() {} |
| 405 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; } |
| 406 |
| 407 bool MediaInformation::Parse(BoxReader* reader) { |
| 408 return reader->ScanChildren() && |
| 409 reader->ReadChild(&sample_table); |
| 410 } |
| 411 |
| 412 Media::Media() {} |
| 413 Media::~Media() {} |
| 414 FourCC Media::BoxType() const { return FOURCC_MDIA; } |
| 415 |
| 416 bool Media::Parse(BoxReader* reader) { |
| 417 RCHECK(reader->ScanChildren() && |
| 418 reader->ReadChild(&header) && |
| 419 reader->ReadChild(&handler)); |
| 420 |
| 421 // Maddeningly, the HandlerReference box specifies how to parse the |
| 422 // SampleDescription box, making the latter the only box (of those that we |
| 423 // support) which cannot be parsed correctly on its own (or even with |
| 424 // information from its strict ancestor tree). We thus copy the handler type |
| 425 // to the sample description box *before* parsing it to provide this |
| 426 // information while parsing. |
| 427 information.sample_table.description.type = handler.type; |
| 428 RCHECK(reader->ReadChild(&information)); |
| 429 return true; |
| 430 } |
| 431 |
| 432 Track::Track() {} |
| 433 Track::~Track() {} |
| 434 FourCC Track::BoxType() const { return FOURCC_TRAK; } |
| 435 |
| 436 bool Track::Parse(BoxReader* reader) { |
| 437 RCHECK(reader->ScanChildren() && |
| 438 reader->ReadChild(&header) && |
| 439 reader->ReadChild(&media) && |
| 440 reader->MaybeReadChild(&edit)); |
| 441 return true; |
| 442 } |
| 443 |
| 444 MovieExtendsHeader::MovieExtendsHeader() {} |
| 445 MovieExtendsHeader::~MovieExtendsHeader() {} |
| 446 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; } |
| 447 |
| 448 bool MovieExtendsHeader::Parse(BoxReader* reader) { |
| 449 RCHECK(reader->Read8(&fragment_duration)); |
| 450 return true; |
| 451 } |
| 452 |
| 453 TrackExtends::TrackExtends() {} |
| 454 TrackExtends::~TrackExtends() {} |
| 455 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; } |
| 456 |
| 457 bool TrackExtends::Parse(BoxReader* reader) { |
| 458 RCHECK(reader->ReadFullBoxHeader() && |
| 459 reader->Read4(&track_id) && |
| 460 reader->Read4(&default_sample_description_index) && |
| 461 reader->Read4(&default_sample_duration) && |
| 462 reader->Read4(&default_sample_size) && |
| 463 reader->Read4(&default_sample_flags)); |
| 464 return true; |
| 465 } |
| 466 |
| 467 MovieExtends::MovieExtends() {} |
| 468 MovieExtends::~MovieExtends() {} |
| 469 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; } |
| 470 |
| 471 bool MovieExtends::Parse(BoxReader* reader) { |
| 472 header.fragment_duration = 0; |
| 473 return reader->ScanChildren() && |
| 474 reader->MaybeReadChild(&header) && |
| 475 reader->ReadChildren(&tracks); |
| 476 } |
| 477 |
| 478 Movie::Movie() {} |
| 479 Movie::~Movie() {} |
| 480 FourCC Movie::BoxType() const { return FOURCC_MOOV; } |
| 481 |
| 482 bool Movie::Parse(BoxReader* reader) { |
| 483 return reader->ScanChildren() && |
| 484 reader->ReadChild(&header) && |
| 485 reader->ReadChildren(&tracks) && |
| 486 // Media Source specific: 'mvex' required |
| 487 reader->ReadChild(&extends) && |
| 488 reader->MaybeReadChildren(&pssh); |
| 489 } |
| 490 |
| 491 TrackFragmentDecodeTime::TrackFragmentDecodeTime() {} |
| 492 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {} |
| 493 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; } |
| 494 |
| 495 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) { |
| 496 RCHECK(reader->ReadFullBoxHeader()); |
| 497 if (reader->version() == 1) |
| 498 return reader->Read8(&decode_time); |
| 499 else |
| 500 return reader->Read4Into8(&decode_time); |
| 501 } |
| 502 |
| 503 MovieFragmentHeader::MovieFragmentHeader() {} |
| 504 MovieFragmentHeader::~MovieFragmentHeader() {} |
| 505 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; } |
| 506 |
| 507 bool MovieFragmentHeader::Parse(BoxReader* reader) { |
| 508 return reader->SkipBytes(4) && reader->Read4(&sequence_number); |
| 509 } |
| 510 |
| 511 TrackFragmentHeader::TrackFragmentHeader() {} |
| 512 TrackFragmentHeader::~TrackFragmentHeader() {} |
| 513 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; } |
| 514 |
| 515 bool TrackFragmentHeader::Parse(BoxReader* reader) { |
| 516 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id)); |
| 517 |
| 518 // Media Source specific: reject tracks that set 'base-data-offset-present'. |
| 519 // Although the Media Source requires that 'default-base-is-moof' (14496-12 |
| 520 // Amendment 2) be set, we omit this check as many otherwise-valid files in |
| 521 // the wild don't set it. |
| 522 // |
| 523 // RCHECK((flags & 0x020000) && !(flags & 0x1)); |
| 524 RCHECK(!(reader->flags() & 0x1)); |
| 525 |
| 526 if (reader->flags() & 0x2) |
| 527 RCHECK(reader->SkipBytes(4)); // sample_description_index |
| 528 |
| 529 if (reader->flags() & 0x8) { |
| 530 RCHECK(reader->Read4(&default_sample_duration)); |
| 531 } else { |
| 532 default_sample_duration = 0; |
| 533 } |
| 534 |
| 535 if (reader->flags() & 0x10) { |
| 536 RCHECK(reader->Read4(&default_sample_size)); |
| 537 } else { |
| 538 default_sample_size = 0; |
| 539 } |
| 540 |
| 541 if (reader->flags() & 0x20) { |
| 542 RCHECK(reader->Read4(&default_sample_flags)); |
| 543 has_default_sample_flags = true; |
| 544 } else { |
| 545 has_default_sample_flags = false; |
| 546 } |
| 547 |
| 548 return true; |
| 549 } |
| 550 |
| 551 TrackFragmentRun::TrackFragmentRun() {} |
| 552 TrackFragmentRun::~TrackFragmentRun() {} |
| 553 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; } |
| 554 |
| 555 bool TrackFragmentRun::Parse(BoxReader* reader) { |
| 556 RCHECK(reader->ReadFullBoxHeader() && |
| 557 reader->Read4(&sample_count)); |
| 558 const uint32 flags = reader->flags(); |
| 559 |
| 560 bool data_offset_present = (flags & 0x1) != 0; |
| 561 bool first_sample_flags_present = (flags & 0x4) != 0; |
| 562 bool sample_duration_present = (flags & 0x100) != 0; |
| 563 bool sample_size_present = (flags & 0x200) != 0; |
| 564 bool sample_flags_present = (flags & 0x400) != 0; |
| 565 bool sample_composition_time_offsets_present = (flags & 0x800) != 0; |
| 566 |
| 567 if (data_offset_present) { |
| 568 RCHECK(reader->Read4(&data_offset)); |
| 569 } else { |
| 570 data_offset = 0; |
| 571 } |
| 572 |
| 573 uint32 first_sample_flags; |
| 574 if (first_sample_flags_present) |
| 575 RCHECK(reader->Read4(&first_sample_flags)); |
| 576 |
| 577 int fields = sample_duration_present + sample_size_present + |
| 578 sample_flags_present + sample_composition_time_offsets_present; |
| 579 RCHECK(reader->HasBytes(fields * sample_count)); |
| 580 |
| 581 if (sample_duration_present) |
| 582 sample_durations.resize(sample_count); |
| 583 if (sample_size_present) |
| 584 sample_sizes.resize(sample_count); |
| 585 if (sample_flags_present) |
| 586 sample_flags.resize(sample_count); |
| 587 if (sample_composition_time_offsets_present) |
| 588 sample_composition_time_offsets.resize(sample_count); |
| 589 |
| 590 for (uint32 i = 0; i < sample_count; ++i) { |
| 591 if (sample_duration_present) |
| 592 RCHECK(reader->Read4(&sample_durations[i])); |
| 593 if (sample_size_present) |
| 594 RCHECK(reader->Read4(&sample_sizes[i])); |
| 595 if (sample_flags_present) |
| 596 RCHECK(reader->Read4(&sample_flags[i])); |
| 597 if (sample_composition_time_offsets_present) |
| 598 RCHECK(reader->Read4(&sample_composition_time_offsets[i])); |
| 599 } |
| 600 |
| 601 if (first_sample_flags_present) { |
| 602 if (sample_flags.size() == 0) { |
| 603 sample_flags.push_back(first_sample_flags); |
| 604 } else { |
| 605 sample_flags[0] = first_sample_flags; |
| 606 } |
| 607 } |
| 608 return true; |
| 609 } |
| 610 |
| 611 TrackFragment::TrackFragment() {} |
| 612 TrackFragment::~TrackFragment() {} |
| 613 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; } |
| 614 |
| 615 bool TrackFragment::Parse(BoxReader* reader) { |
| 616 return reader->ScanChildren() && |
| 617 reader->ReadChild(&header) && |
| 618 // Media Source specific: 'tfdt' required |
| 619 reader->ReadChild(&decode_time) && |
| 620 reader->MaybeReadChildren(&runs) && |
| 621 reader->MaybeReadChild(&auxiliary_offset) && |
| 622 reader->MaybeReadChild(&auxiliary_size); |
| 623 } |
| 624 |
| 625 MovieFragment::MovieFragment() {} |
| 626 MovieFragment::~MovieFragment() {} |
| 627 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; } |
| 628 |
| 629 bool MovieFragment::Parse(BoxReader* reader) { |
| 630 RCHECK(reader->ScanChildren() && |
| 631 reader->ReadChild(&header) && |
| 632 reader->ReadChildren(&tracks) && |
| 633 reader->MaybeReadChildren(&pssh)); |
| 634 return true; |
| 635 } |
| 636 |
| 637 } // namespace mp4 |
| 638 } // namespace media |
| OLD | NEW |