box_definitions.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 3// found in the LICENSE file. 4 5#include "media/formats/mp4/box_definitions.h" 6 7#include "base/logging.h" 8#include "media/formats/mp4/es_descriptor.h" 9#include "media/formats/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 248SyncSample::SyncSample() : is_present(false) {} 249SyncSample::~SyncSample() {} 250FourCC SyncSample::BoxType() const { return FOURCC_STSS; } 251 252bool SyncSample::Parse(BoxReader* reader) { 253 uint32 entry_count; 254 RCHECK(reader->ReadFullBoxHeader() && 255 reader->Read4(&entry_count)); 256 257 is_present = true; 258 259 if (entry_count == 0) 260 return true; 261 262 // Skip over the entries since we don't actually care about 263 // them right now. In most fragmented files with an stss, there 264 // aren't any entries anyways because the random access point info 265 // is signalled in the fragments. 266 int64 skip_size = 4 * entry_count; 267 if (skip_size > INT_MAX) 268 return false; 269 270 RCHECK(reader->SkipBytes(skip_size)); 271 272 return true; 273} 274 275SampleTable::SampleTable() {} 276SampleTable::~SampleTable() {} 277FourCC SampleTable::BoxType() const { return FOURCC_STBL; } 278 279bool SampleTable::Parse(BoxReader* reader) { 280 return reader->ScanChildren() && 281 reader->ReadChild(&description) && 282 reader->MaybeReadChild(&sync_sample); 283} 284 285EditList::EditList() {} 286EditList::~EditList() {} 287FourCC EditList::BoxType() const { return FOURCC_ELST; } 288 289bool EditList::Parse(BoxReader* reader) { 290 uint32 count; 291 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count)); 292 293 if (reader->version() == 1) { 294 RCHECK(reader->HasBytes(count * 20)); 295 } else { 296 RCHECK(reader->HasBytes(count * 12)); 297 } 298 edits.resize(count); 299 300 for (std::vector<EditListEntry>::iterator edit = edits.begin(); 301 edit != edits.end(); ++edit) { 302 if (reader->version() == 1) { 303 RCHECK(reader->Read8(&edit->segment_duration) && 304 reader->Read8s(&edit->media_time)); 305 } else { 306 RCHECK(reader->Read4Into8(&edit->segment_duration) && 307 reader->Read4sInto8s(&edit->media_time)); 308 } 309 RCHECK(reader->Read2s(&edit->media_rate_integer) && 310 reader->Read2s(&edit->media_rate_fraction)); 311 } 312 return true; 313} 314 315Edit::Edit() {} 316Edit::~Edit() {} 317FourCC Edit::BoxType() const { return FOURCC_EDTS; } 318 319bool Edit::Parse(BoxReader* reader) { 320 return reader->ScanChildren() && reader->ReadChild(&list); 321} 322 323HandlerReference::HandlerReference() : type(kInvalid) {} 324HandlerReference::~HandlerReference() {} 325FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; } 326 327bool HandlerReference::Parse(BoxReader* reader) { 328 FourCC hdlr_type; 329 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type)); 330 // Note: remaining fields in box ignored 331 if (hdlr_type == FOURCC_VIDE) { 332 type = kVideo; 333 } else if (hdlr_type == FOURCC_SOUN) { 334 type = kAudio; 335 } else { 336 type = kInvalid; 337 } 338 return true; 339} 340 341AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord() 342 : version(0), 343 profile_indication(0), 344 profile_compatibility(0), 345 avc_level(0), 346 length_size(0) {} 347 348AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {} 349FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; } 350 351bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) { 352 RCHECK(reader->Read1(&version) && version == 1 && 353 reader->Read1(&profile_indication) && 354 reader->Read1(&profile_compatibility) && 355 reader->Read1(&avc_level)); 356 357 uint8 length_size_minus_one; 358 RCHECK(reader->Read1(&length_size_minus_one) && 359 (length_size_minus_one & 0xfc) == 0xfc); 360 length_size = (length_size_minus_one & 0x3) + 1; 361 362 uint8 num_sps; 363 RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0); 364 num_sps &= 0x1f; 365 366 sps_list.resize(num_sps); 367 for (int i = 0; i < num_sps; i++) { 368 uint16 sps_length; 369 RCHECK(reader->Read2(&sps_length) && 370 reader->ReadVec(&sps_list[i], sps_length)); 371 } 372 373 uint8 num_pps; 374 RCHECK(reader->Read1(&num_pps)); 375 376 pps_list.resize(num_pps); 377 for (int i = 0; i < num_pps; i++) { 378 uint16 pps_length; 379 RCHECK(reader->Read2(&pps_length) && 380 reader->ReadVec(&pps_list[i], pps_length)); 381 } 382 383 return true; 384} 385 386PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {} 387PixelAspectRatioBox::~PixelAspectRatioBox() {} 388FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; } 389 390bool PixelAspectRatioBox::Parse(BoxReader* reader) { 391 RCHECK(reader->Read4(&h_spacing) && 392 reader->Read4(&v_spacing)); 393 return true; 394} 395 396VideoSampleEntry::VideoSampleEntry() 397 : format(FOURCC_NULL), 398 data_reference_index(0), 399 width(0), 400 height(0) {} 401 402VideoSampleEntry::~VideoSampleEntry() {} 403FourCC VideoSampleEntry::BoxType() const { 404 DCHECK(false) << "VideoSampleEntry should be parsed according to the " 405 << "handler type recovered in its Media ancestor."; 406 return FOURCC_NULL; 407} 408 409bool VideoSampleEntry::Parse(BoxReader* reader) { 410 format = reader->type(); 411 RCHECK(reader->SkipBytes(6) && 412 reader->Read2(&data_reference_index) && 413 reader->SkipBytes(16) && 414 reader->Read2(&width) && 415 reader->Read2(&height) && 416 reader->SkipBytes(50)); 417 418 RCHECK(reader->ScanChildren() && 419 reader->MaybeReadChild(&pixel_aspect)); 420 421 if (format == FOURCC_ENCV) { 422 // Continue scanning until a recognized protection scheme is found, or until 423 // we run out of protection schemes. 424 while (sinf.type.type != FOURCC_CENC) { 425 if (!reader->ReadChild(&sinf)) 426 return false; 427 } 428 } 429 430 if (IsFormatValid()) 431 RCHECK(reader->ReadChild(&avcc)); 432 433 return true; 434} 435 436bool VideoSampleEntry::IsFormatValid() const { 437 return format == FOURCC_AVC1 || format == FOURCC_AVC3 || 438 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 || 439 sinf.format.format == FOURCC_AVC3)); 440} 441 442ElementaryStreamDescriptor::ElementaryStreamDescriptor() 443 : object_type(kForbidden) {} 444 445ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {} 446 447FourCC ElementaryStreamDescriptor::BoxType() const { 448 return FOURCC_ESDS; 449} 450 451bool ElementaryStreamDescriptor::Parse(BoxReader* reader) { 452 std::vector<uint8> data; 453 ESDescriptor es_desc; 454 455 RCHECK(reader->ReadFullBoxHeader()); 456 RCHECK(reader->ReadVec(&data, reader->size() - reader->pos())); 457 RCHECK(es_desc.Parse(data)); 458 459 object_type = es_desc.object_type(); 460 461 RCHECK(aac.Parse(es_desc.decoder_specific_info())); 462 463 return true; 464} 465 466AudioSampleEntry::AudioSampleEntry() 467 : format(FOURCC_NULL), 468 data_reference_index(0), 469 channelcount(0), 470 samplesize(0), 471 samplerate(0) {} 472 473AudioSampleEntry::~AudioSampleEntry() {} 474 475FourCC AudioSampleEntry::BoxType() const { 476 DCHECK(false) << "AudioSampleEntry should be parsed according to the " 477 << "handler type recovered in its Media ancestor."; 478 return FOURCC_NULL; 479} 480 481bool AudioSampleEntry::Parse(BoxReader* reader) { 482 format = reader->type(); 483 RCHECK(reader->SkipBytes(6) && 484 reader->Read2(&data_reference_index) && 485 reader->SkipBytes(8) && 486 reader->Read2(&channelcount) && 487 reader->Read2(&samplesize) && 488 reader->SkipBytes(4) && 489 reader->Read4(&samplerate)); 490 // Convert from 16.16 fixed point to integer 491 samplerate >>= 16; 492 493 RCHECK(reader->ScanChildren()); 494 if (format == FOURCC_ENCA) { 495 // Continue scanning until a recognized protection scheme is found, or until 496 // we run out of protection schemes. 497 while (sinf.type.type != FOURCC_CENC) { 498 if (!reader->ReadChild(&sinf)) 499 return false; 500 } 501 } 502 503 // ESDS is not valid in case of EAC3. 504 RCHECK(reader->MaybeReadChild(&esds)); 505 return true; 506} 507 508MediaHeader::MediaHeader() 509 : creation_time(0), 510 modification_time(0), 511 timescale(0), 512 duration(0) {} 513MediaHeader::~MediaHeader() {} 514FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; } 515 516bool MediaHeader::Parse(BoxReader* reader) { 517 RCHECK(reader->ReadFullBoxHeader()); 518 519 if (reader->version() == 1) { 520 RCHECK(reader->Read8(&creation_time) && 521 reader->Read8(&modification_time) && 522 reader->Read4(×cale) && 523 reader->Read8(&duration)); 524 } else { 525 RCHECK(reader->Read4Into8(&creation_time) && 526 reader->Read4Into8(&modification_time) && 527 reader->Read4(×cale) && 528 reader->Read4Into8(&duration)); 529 } 530 // Skip language information 531 return reader->SkipBytes(4); 532} 533 534MediaInformation::MediaInformation() {} 535MediaInformation::~MediaInformation() {} 536FourCC MediaInformation::BoxType() const { return FOURCC_MINF; } 537 538bool MediaInformation::Parse(BoxReader* reader) { 539 return reader->ScanChildren() && 540 reader->ReadChild(&sample_table); 541} 542 543Media::Media() {} 544Media::~Media() {} 545FourCC Media::BoxType() const { return FOURCC_MDIA; } 546 547bool Media::Parse(BoxReader* reader) { 548 RCHECK(reader->ScanChildren() && 549 reader->ReadChild(&header) && 550 reader->ReadChild(&handler)); 551 552 // Maddeningly, the HandlerReference box specifies how to parse the 553 // SampleDescription box, making the latter the only box (of those that we 554 // support) which cannot be parsed correctly on its own (or even with 555 // information from its strict ancestor tree). We thus copy the handler type 556 // to the sample description box *before* parsing it to provide this 557 // information while parsing. 558 information.sample_table.description.type = handler.type; 559 RCHECK(reader->ReadChild(&information)); 560 return true; 561} 562 563Track::Track() {} 564Track::~Track() {} 565FourCC Track::BoxType() const { return FOURCC_TRAK; } 566 567bool Track::Parse(BoxReader* reader) { 568 RCHECK(reader->ScanChildren() && 569 reader->ReadChild(&header) && 570 reader->ReadChild(&media) && 571 reader->MaybeReadChild(&edit)); 572 return true; 573} 574 575MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {} 576MovieExtendsHeader::~MovieExtendsHeader() {} 577FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; } 578 579bool MovieExtendsHeader::Parse(BoxReader* reader) { 580 RCHECK(reader->ReadFullBoxHeader()); 581 if (reader->version() == 1) { 582 RCHECK(reader->Read8(&fragment_duration)); 583 } else { 584 RCHECK(reader->Read4Into8(&fragment_duration)); 585 } 586 return true; 587} 588 589TrackExtends::TrackExtends() 590 : track_id(0), 591 default_sample_description_index(0), 592 default_sample_duration(0), 593 default_sample_size(0), 594 default_sample_flags(0) {} 595TrackExtends::~TrackExtends() {} 596FourCC TrackExtends::BoxType() const { return FOURCC_TREX; } 597 598bool TrackExtends::Parse(BoxReader* reader) { 599 RCHECK(reader->ReadFullBoxHeader() && 600 reader->Read4(&track_id) && 601 reader->Read4(&default_sample_description_index) && 602 reader->Read4(&default_sample_duration) && 603 reader->Read4(&default_sample_size) && 604 reader->Read4(&default_sample_flags)); 605 return true; 606} 607 608MovieExtends::MovieExtends() {} 609MovieExtends::~MovieExtends() {} 610FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; } 611 612bool MovieExtends::Parse(BoxReader* reader) { 613 header.fragment_duration = 0; 614 return reader->ScanChildren() && 615 reader->MaybeReadChild(&header) && 616 reader->ReadChildren(&tracks); 617} 618 619Movie::Movie() : fragmented(false) {} 620Movie::~Movie() {} 621FourCC Movie::BoxType() const { return FOURCC_MOOV; } 622 623bool Movie::Parse(BoxReader* reader) { 624 return reader->ScanChildren() && 625 reader->ReadChild(&header) && 626 reader->ReadChildren(&tracks) && 627 // Media Source specific: 'mvex' required 628 reader->ReadChild(&extends) && 629 reader->MaybeReadChildren(&pssh); 630} 631 632TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {} 633TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {} 634FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; } 635 636bool TrackFragmentDecodeTime::Parse(BoxReader* reader) { 637 RCHECK(reader->ReadFullBoxHeader()); 638 if (reader->version() == 1) 639 return reader->Read8(&decode_time); 640 else 641 return reader->Read4Into8(&decode_time); 642} 643 644MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {} 645MovieFragmentHeader::~MovieFragmentHeader() {} 646FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; } 647 648bool MovieFragmentHeader::Parse(BoxReader* reader) { 649 return reader->SkipBytes(4) && reader->Read4(&sequence_number); 650} 651 652TrackFragmentHeader::TrackFragmentHeader() 653 : track_id(0), 654 sample_description_index(0), 655 default_sample_duration(0), 656 default_sample_size(0), 657 default_sample_flags(0), 658 has_default_sample_flags(false) {} 659 660TrackFragmentHeader::~TrackFragmentHeader() {} 661FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; } 662 663bool TrackFragmentHeader::Parse(BoxReader* reader) { 664 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id)); 665 666 // Media Source specific: reject tracks that set 'base-data-offset-present'. 667 // Although the Media Source requires that 'default-base-is-moof' (14496-12 668 // Amendment 2) be set, we omit this check as many otherwise-valid files in 669 // the wild don't set it. 670 // 671 // RCHECK((flags & 0x020000) && !(flags & 0x1)); 672 RCHECK(!(reader->flags() & 0x1)); 673 674 if (reader->flags() & 0x2) { 675 RCHECK(reader->Read4(&sample_description_index)); 676 } else { 677 sample_description_index = 0; 678 } 679 680 if (reader->flags() & 0x8) { 681 RCHECK(reader->Read4(&default_sample_duration)); 682 } else { 683 default_sample_duration = 0; 684 } 685 686 if (reader->flags() & 0x10) { 687 RCHECK(reader->Read4(&default_sample_size)); 688 } else { 689 default_sample_size = 0; 690 } 691 692 if (reader->flags() & 0x20) { 693 RCHECK(reader->Read4(&default_sample_flags)); 694 has_default_sample_flags = true; 695 } else { 696 has_default_sample_flags = false; 697 } 698 699 return true; 700} 701 702TrackFragmentRun::TrackFragmentRun() 703 : sample_count(0), data_offset(0) {} 704TrackFragmentRun::~TrackFragmentRun() {} 705FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; } 706 707bool TrackFragmentRun::Parse(BoxReader* reader) { 708 RCHECK(reader->ReadFullBoxHeader() && 709 reader->Read4(&sample_count)); 710 const uint32 flags = reader->flags(); 711 712 bool data_offset_present = (flags & 0x1) != 0; 713 bool first_sample_flags_present = (flags & 0x4) != 0; 714 bool sample_duration_present = (flags & 0x100) != 0; 715 bool sample_size_present = (flags & 0x200) != 0; 716 bool sample_flags_present = (flags & 0x400) != 0; 717 bool sample_composition_time_offsets_present = (flags & 0x800) != 0; 718 719 if (data_offset_present) { 720 RCHECK(reader->Read4(&data_offset)); 721 } else { 722 data_offset = 0; 723 } 724 725 uint32 first_sample_flags; 726 if (first_sample_flags_present) 727 RCHECK(reader->Read4(&first_sample_flags)); 728 729 int fields = sample_duration_present + sample_size_present + 730 sample_flags_present + sample_composition_time_offsets_present; 731 RCHECK(reader->HasBytes(fields * sample_count)); 732 733 if (sample_duration_present) 734 sample_durations.resize(sample_count); 735 if (sample_size_present) 736 sample_sizes.resize(sample_count); 737 if (sample_flags_present) 738 sample_flags.resize(sample_count); 739 if (sample_composition_time_offsets_present) 740 sample_composition_time_offsets.resize(sample_count); 741 742 for (uint32 i = 0; i < sample_count; ++i) { 743 if (sample_duration_present) 744 RCHECK(reader->Read4(&sample_durations[i])); 745 if (sample_size_present) 746 RCHECK(reader->Read4(&sample_sizes[i])); 747 if (sample_flags_present) 748 RCHECK(reader->Read4(&sample_flags[i])); 749 if (sample_composition_time_offsets_present) 750 RCHECK(reader->Read4s(&sample_composition_time_offsets[i])); 751 } 752 753 if (first_sample_flags_present) { 754 if (sample_flags.size() == 0) { 755 sample_flags.push_back(first_sample_flags); 756 } else { 757 sample_flags[0] = first_sample_flags; 758 } 759 } 760 return true; 761} 762 763TrackFragment::TrackFragment() {} 764TrackFragment::~TrackFragment() {} 765FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; } 766 767bool TrackFragment::Parse(BoxReader* reader) { 768 return reader->ScanChildren() && 769 reader->ReadChild(&header) && 770 // Media Source specific: 'tfdt' required 771 reader->ReadChild(&decode_time) && 772 reader->MaybeReadChildren(&runs) && 773 reader->MaybeReadChild(&auxiliary_offset) && 774 reader->MaybeReadChild(&auxiliary_size) && 775 reader->MaybeReadChild(&sdtp); 776} 777 778MovieFragment::MovieFragment() {} 779MovieFragment::~MovieFragment() {} 780FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; } 781 782bool MovieFragment::Parse(BoxReader* reader) { 783 RCHECK(reader->ScanChildren() && 784 reader->ReadChild(&header) && 785 reader->ReadChildren(&tracks) && 786 reader->MaybeReadChildren(&pssh)); 787 return true; 788} 789 790IndependentAndDisposableSamples::IndependentAndDisposableSamples() {} 791IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {} 792FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; } 793 794bool IndependentAndDisposableSamples::Parse(BoxReader* reader) { 795 RCHECK(reader->ReadFullBoxHeader()); 796 RCHECK(reader->version() == 0); 797 RCHECK(reader->flags() == 0); 798 799 int sample_count = reader->size() - reader->pos(); 800 sample_depends_on_.resize(sample_count); 801 for (int i = 0; i < sample_count; ++i) { 802 uint8 sample_info; 803 RCHECK(reader->Read1(&sample_info)); 804 RCHECK((sample_info >> 6) == 0); // reserved. 805 806 sample_depends_on_[i] = 807 static_cast<SampleDependsOn>((sample_info >> 4) & 0x3); 808 809 RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved); 810 } 811 812 return true; 813} 814 815SampleDependsOn IndependentAndDisposableSamples::sample_depends_on( 816 size_t i) const { 817 if (i >= sample_depends_on_.size()) 818 return kSampleDependsOnUnknown; 819 820 return sample_depends_on_[i]; 821} 822 823} // namespace mp4 824} // namespace media 825