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/track_run_iterator.h" | 5 #include "media/formats/mp4/track_run_iterator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <limits> | 9 #include <limits> |
10 #include <memory> | 10 #include <memory> |
11 | 11 |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "media/formats/mp4/rcheck.h" | 13 #include "media/formats/mp4/rcheck.h" |
14 #include "media/formats/mp4/sample_to_group_iterator.h" | 14 #include "media/formats/mp4/sample_to_group_iterator.h" |
| 15 #include "media/media_features.h" |
15 | 16 |
16 namespace media { | 17 namespace media { |
17 namespace mp4 { | 18 namespace mp4 { |
18 | 19 |
19 struct SampleInfo { | 20 struct SampleInfo { |
20 int size; | 21 int size; |
21 int duration; | 22 int duration; |
22 int cts_offset; | 23 int cts_offset; |
23 bool is_keyframe; | 24 bool is_keyframe; |
24 uint32_t cenc_group_description_index; | 25 uint32_t cenc_group_description_index; |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 TrackRunInfo tri; | 317 TrackRunInfo tri; |
317 tri.track_id = traf.header.track_id; | 318 tri.track_id = traf.header.track_id; |
318 tri.timescale = trak->media.header.timescale; | 319 tri.timescale = trak->media.header.timescale; |
319 tri.start_dts = run_start_dts; | 320 tri.start_dts = run_start_dts; |
320 tri.sample_start_offset = trun.data_offset; | 321 tri.sample_start_offset = trun.data_offset; |
321 tri.track_sample_encryption_group = | 322 tri.track_sample_encryption_group = |
322 &trak->media.information.sample_table.sample_group_description; | 323 &trak->media.information.sample_table.sample_group_description; |
323 tri.fragment_sample_encryption_info = | 324 tri.fragment_sample_encryption_info = |
324 traf.sample_group_description.entries; | 325 traf.sample_group_description.entries; |
325 | 326 |
326 uint8_t default_iv_size = 0; | 327 const TrackEncryption* track_encryption; |
327 tri.is_audio = (stsd.type == kAudio); | 328 tri.is_audio = (stsd.type == kAudio); |
328 if (tri.is_audio) { | 329 if (tri.is_audio) { |
329 RCHECK(!stsd.audio_entries.empty()); | 330 RCHECK(!stsd.audio_entries.empty()); |
330 if (desc_idx > stsd.audio_entries.size()) | 331 if (desc_idx > stsd.audio_entries.size()) |
331 desc_idx = 0; | 332 desc_idx = 0; |
332 tri.audio_description = &stsd.audio_entries[desc_idx]; | 333 tri.audio_description = &stsd.audio_entries[desc_idx]; |
333 default_iv_size = | 334 track_encryption = &tri.audio_description->sinf.info.track_encryption; |
334 tri.audio_description->sinf.info.track_encryption.default_iv_size; | |
335 } else { | 335 } else { |
336 RCHECK(!stsd.video_entries.empty()); | 336 RCHECK(!stsd.video_entries.empty()); |
337 if (desc_idx > stsd.video_entries.size()) | 337 if (desc_idx > stsd.video_entries.size()) |
338 desc_idx = 0; | 338 desc_idx = 0; |
339 tri.video_description = &stsd.video_entries[desc_idx]; | 339 tri.video_description = &stsd.video_entries[desc_idx]; |
340 default_iv_size = | 340 track_encryption = &tri.video_description->sinf.info.track_encryption; |
341 tri.video_description->sinf.info.track_encryption.default_iv_size; | |
342 } | 341 } |
343 | |
344 // Initialize aux_info variables only if no sample encryption entries. | 342 // Initialize aux_info variables only if no sample encryption entries. |
345 if (sample_encryption_entries_count == 0 && | 343 if (sample_encryption_entries_count == 0 && |
346 traf.auxiliary_offset.offsets.size() > j) { | 344 traf.auxiliary_offset.offsets.size() > j) { |
347 // Collect information from the auxiliary_offset entry with the same | 345 // Collect information from the auxiliary_offset entry with the same |
348 // index in the 'saiz' container as the current run's index in the | 346 // index in the 'saiz' container as the current run's index in the |
349 // 'trun' container, if it is present. | 347 // 'trun' container, if it is present. |
350 // There should be an auxiliary info entry corresponding to each sample | 348 // There should be an auxiliary info entry corresponding to each sample |
351 // in the auxiliary offset entry's corresponding track run. | 349 // in the auxiliary offset entry's corresponding track run. |
352 RCHECK(traf.auxiliary_size.sample_count >= | 350 RCHECK(traf.auxiliary_size.sample_count >= |
353 sample_count_sum + trun.sample_count); | 351 sample_count_sum + trun.sample_count); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 if (index != 0) | 399 if (index != 0) |
402 RCHECK(GetSampleEncryptionInfoEntry(tri, index)); | 400 RCHECK(GetSampleEncryptionInfoEntry(tri, index)); |
403 is_sample_to_group_valid = sample_to_group_itr.Advance(); | 401 is_sample_to_group_valid = sample_to_group_itr.Advance(); |
404 } | 402 } |
405 if (sample_encryption_entries_count > 0) { | 403 if (sample_encryption_entries_count > 0) { |
406 RCHECK(sample_encryption_entries_count >= | 404 RCHECK(sample_encryption_entries_count >= |
407 sample_count_sum + trun.sample_count); | 405 sample_count_sum + trun.sample_count); |
408 tri.sample_encryption_entries.resize(trun.sample_count); | 406 tri.sample_encryption_entries.resize(trun.sample_count); |
409 for (size_t k = 0; k < trun.sample_count; k++) { | 407 for (size_t k = 0; k < trun.sample_count; k++) { |
410 uint32_t index = tri.samples[k].cenc_group_description_index; | 408 uint32_t index = tri.samples[k].cenc_group_description_index; |
411 const uint8_t iv_size = | 409 const CencSampleEncryptionInfoEntry* info_entry = |
412 index == 0 ? default_iv_size | 410 index == 0 ? nullptr : GetSampleEncryptionInfoEntry(tri, index); |
413 : GetSampleEncryptionInfoEntry(tri, index)->iv_size; | 411 const uint8_t iv_size = index == 0 ? track_encryption->default_iv_size |
414 RCHECK(tri.sample_encryption_entries[k].Parse( | 412 : info_entry->iv_size; |
415 sample_encryption_reader.get(), iv_size, | 413 SampleEncryptionEntry& entry = tri.sample_encryption_entries[k]; |
416 traf.sample_encryption.use_subsample_encryption)); | 414 RCHECK(entry.Parse(sample_encryption_reader.get(), iv_size, |
| 415 traf.sample_encryption.use_subsample_encryption)); |
| 416 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| 417 // If we don't have a per-sample IV, get the constant IV. |
| 418 bool is_encrypted = index == 0 ? track_encryption->is_encrypted |
| 419 : info_entry->is_encrypted; |
| 420 // We only support setting the pattern values in the 'tenc' box for |
| 421 // the track (not varying on per sample group basis). |
| 422 // Thus we need to verify that the settings in the sample group match |
| 423 // those in the 'tenc'. |
| 424 if (is_encrypted && index != 0) { |
| 425 RCHECK_MEDIA_LOGGED(info_entry->crypt_byte_block == |
| 426 track_encryption->default_crypt_byte_block, |
| 427 media_log_, |
| 428 "Pattern value (crypt byte block) for the " |
| 429 "sample group does not match that in the tenc " |
| 430 "box . This is not currently supported."); |
| 431 RCHECK_MEDIA_LOGGED(info_entry->skip_byte_block == |
| 432 track_encryption->default_skip_byte_block, |
| 433 media_log_, |
| 434 "Pattern value (skip byte block) for the " |
| 435 "sample group does not match that in the tenc " |
| 436 "box . This is not currently supported."); |
| 437 } |
| 438 if (is_encrypted && !iv_size) { |
| 439 const uint8_t constant_iv_size = |
| 440 index == 0 ? track_encryption->default_constant_iv_size |
| 441 : info_entry->constant_iv_size; |
| 442 RCHECK(constant_iv_size != 0); |
| 443 const uint8_t* constant_iv = |
| 444 index == 0 ? track_encryption->default_constant_iv |
| 445 : info_entry->constant_iv; |
| 446 memcpy(entry.initialization_vector, constant_iv, constant_iv_size); |
| 447 } |
| 448 #endif |
417 } | 449 } |
418 } | 450 } |
419 runs_.push_back(tri); | 451 runs_.push_back(tri); |
420 sample_count_sum += trun.sample_count; | 452 sample_count_sum += trun.sample_count; |
421 } | 453 } |
422 | 454 |
423 // We should have iterated through all samples in SampleToGroup Box. | 455 // We should have iterated through all samples in SampleToGroup Box. |
424 RCHECK(!sample_to_group_itr.IsValid()); | 456 RCHECK(!sample_to_group_itr.IsValid()); |
425 } | 457 } |
426 | 458 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 int64_t pos = 0; | 499 int64_t pos = 0; |
468 for (size_t i = 0; i < run_itr_->samples.size(); i++) { | 500 for (size_t i = 0; i < run_itr_->samples.size(); i++) { |
469 int info_size = run_itr_->aux_info_default_size; | 501 int info_size = run_itr_->aux_info_default_size; |
470 if (!info_size) | 502 if (!info_size) |
471 info_size = run_itr_->aux_info_sizes[i]; | 503 info_size = run_itr_->aux_info_sizes[i]; |
472 | 504 |
473 if (IsSampleEncrypted(i)) { | 505 if (IsSampleEncrypted(i)) { |
474 BufferReader reader(buf + pos, info_size); | 506 BufferReader reader(buf + pos, info_size); |
475 const uint8_t iv_size = GetIvSize(i); | 507 const uint8_t iv_size = GetIvSize(i); |
476 const bool has_subsamples = info_size > iv_size; | 508 const bool has_subsamples = info_size > iv_size; |
477 RCHECK( | 509 SampleEncryptionEntry& entry = sample_encryption_entries[i]; |
478 sample_encryption_entries[i].Parse(&reader, iv_size, has_subsamples)); | 510 RCHECK(entry.Parse(&reader, iv_size, has_subsamples)); |
| 511 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| 512 // if we don't have a per-sample IV, get the constant IV. |
| 513 if (!iv_size) { |
| 514 RCHECK(ApplyConstantIv(i, &entry)); |
| 515 } |
| 516 #endif |
479 } | 517 } |
480 pos += info_size; | 518 pos += info_size; |
481 } | 519 } |
482 | 520 |
483 return true; | 521 return true; |
484 } | 522 } |
485 | 523 |
486 bool TrackRunIterator::IsRunValid() const { | 524 bool TrackRunIterator::IsRunValid() const { |
487 return run_itr_ != runs_.end(); | 525 return run_itr_ != runs_.end(); |
488 } | 526 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 } | 623 } |
586 | 624 |
587 const TrackEncryption& TrackRunIterator::track_encryption() const { | 625 const TrackEncryption& TrackRunIterator::track_encryption() const { |
588 if (is_audio()) | 626 if (is_audio()) |
589 return audio_description().sinf.info.track_encryption; | 627 return audio_description().sinf.info.track_encryption; |
590 return video_description().sinf.info.track_encryption; | 628 return video_description().sinf.info.track_encryption; |
591 } | 629 } |
592 | 630 |
593 std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { | 631 std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { |
594 DCHECK(is_encrypted()); | 632 DCHECK(is_encrypted()); |
| 633 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); |
| 634 const std::vector<uint8_t>& kid = GetKeyId(sample_idx); |
595 | 635 |
596 if (run_itr_->sample_encryption_entries.empty()) { | 636 if (run_itr_->sample_encryption_entries.empty()) { |
597 DCHECK_EQ(0, aux_info_size()); | 637 DCHECK_EQ(0, aux_info_size()); |
| 638 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| 639 // The 'cbcs' scheme allows empty aux info when a constant IV is in use |
| 640 // with full sample encryption. That case will fall through to here. |
| 641 SampleEncryptionEntry sample_encryption_entry; |
| 642 if (ApplyConstantIv(sample_idx, &sample_encryption_entry)) { |
| 643 return std::unique_ptr<DecryptConfig>(new DecryptConfig( |
| 644 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), |
| 645 std::string(reinterpret_cast<const char*>( |
| 646 sample_encryption_entry.initialization_vector), |
| 647 arraysize(sample_encryption_entry.initialization_vector)), |
| 648 sample_encryption_entry.subsamples)); |
| 649 } |
| 650 #endif |
598 MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available."; | 651 MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available."; |
599 return std::unique_ptr<DecryptConfig>(); | 652 return std::unique_ptr<DecryptConfig>(); |
600 } | 653 } |
601 | 654 |
602 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); | |
603 DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size()); | 655 DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size()); |
604 const SampleEncryptionEntry& sample_encryption_entry = | 656 const SampleEncryptionEntry& sample_encryption_entry = |
605 run_itr_->sample_encryption_entries[sample_idx]; | 657 run_itr_->sample_encryption_entries[sample_idx]; |
606 | 658 |
607 size_t total_size = 0; | 659 size_t total_size = 0; |
608 if (!sample_encryption_entry.subsamples.empty() && | 660 if (!sample_encryption_entry.subsamples.empty() && |
609 (!sample_encryption_entry.GetTotalSizeOfSubsamples(&total_size) || | 661 (!sample_encryption_entry.GetTotalSizeOfSubsamples(&total_size) || |
610 total_size != static_cast<size_t>(sample_size()))) { | 662 total_size != static_cast<size_t>(sample_size()))) { |
611 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; | 663 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; |
612 return std::unique_ptr<DecryptConfig>(); | 664 return std::unique_ptr<DecryptConfig>(); |
613 } | 665 } |
614 | 666 |
615 const std::vector<uint8_t>& kid = GetKeyId(sample_idx); | |
616 return std::unique_ptr<DecryptConfig>(new DecryptConfig( | 667 return std::unique_ptr<DecryptConfig>(new DecryptConfig( |
617 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), | 668 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), |
618 std::string(reinterpret_cast<const char*>( | 669 std::string(reinterpret_cast<const char*>( |
619 sample_encryption_entry.initialization_vector), | 670 sample_encryption_entry.initialization_vector), |
620 arraysize(sample_encryption_entry.initialization_vector)), | 671 arraysize(sample_encryption_entry.initialization_vector)), |
621 sample_encryption_entry.subsamples)); | 672 sample_encryption_entry.subsamples)); |
622 } | 673 } |
623 | 674 |
624 uint32_t TrackRunIterator::GetGroupDescriptionIndex( | 675 uint32_t TrackRunIterator::GetGroupDescriptionIndex( |
625 uint32_t sample_index) const { | 676 uint32_t sample_index) const { |
(...skipping 15 matching lines...) Expand all Loading... |
641 return (index == 0) ? track_encryption().default_kid | 692 return (index == 0) ? track_encryption().default_kid |
642 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; | 693 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; |
643 } | 694 } |
644 | 695 |
645 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { | 696 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { |
646 uint32_t index = GetGroupDescriptionIndex(sample_index); | 697 uint32_t index = GetGroupDescriptionIndex(sample_index); |
647 return (index == 0) ? track_encryption().default_iv_size | 698 return (index == 0) ? track_encryption().default_iv_size |
648 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; | 699 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; |
649 } | 700 } |
650 | 701 |
| 702 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| 703 bool TrackRunIterator::ApplyConstantIv(size_t sample_index, |
| 704 SampleEncryptionEntry* entry) const { |
| 705 DCHECK(IsSampleEncrypted(sample_index)); |
| 706 uint32_t index = GetGroupDescriptionIndex(sample_index); |
| 707 const uint8_t constant_iv_size = |
| 708 index == 0 |
| 709 ? track_encryption().default_constant_iv_size |
| 710 : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv_size; |
| 711 RCHECK(constant_iv_size != 0); |
| 712 const uint8_t* constant_iv = |
| 713 index == 0 ? track_encryption().default_constant_iv |
| 714 : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv; |
| 715 RCHECK(constant_iv != nullptr); |
| 716 memcpy(entry->initialization_vector, constant_iv, kInitializationVectorSize); |
| 717 return true; |
| 718 } |
| 719 #endif |
| 720 |
651 } // namespace mp4 | 721 } // namespace mp4 |
652 } // namespace media | 722 } // namespace media |
OLD | NEW |