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