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(info_entry->crypt_byte_block == | |
426 track_encryption->default_crypt_byte_block); | |
427 RCHECK(info_entry->skip_byte_block == | |
428 track_encryption->default_skip_byte_block); | |
429 } | |
430 if (is_encrypted && !iv_size) { | |
431 const uint8_t constant_iv_size = | |
432 index == 0 ? track_encryption->default_constant_iv_size | |
433 : info_entry->constant_iv_size; | |
434 RCHECK(constant_iv_size != 0); | |
435 const uint8_t* constant_iv = | |
436 index == 0 ? track_encryption->default_constant_iv | |
437 : info_entry->constant_iv; | |
438 memcpy(entry.initialization_vector, constant_iv, constant_iv_size); | |
439 } | |
440 #endif | |
417 } | 441 } |
418 } | 442 } |
419 runs_.push_back(tri); | 443 runs_.push_back(tri); |
420 sample_count_sum += trun.sample_count; | 444 sample_count_sum += trun.sample_count; |
421 } | 445 } |
422 | 446 |
423 // We should have iterated through all samples in SampleToGroup Box. | 447 // We should have iterated through all samples in SampleToGroup Box. |
424 RCHECK(!sample_to_group_itr.IsValid()); | 448 RCHECK(!sample_to_group_itr.IsValid()); |
425 } | 449 } |
426 | 450 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 int64_t pos = 0; | 491 int64_t pos = 0; |
468 for (size_t i = 0; i < run_itr_->samples.size(); i++) { | 492 for (size_t i = 0; i < run_itr_->samples.size(); i++) { |
469 int info_size = run_itr_->aux_info_default_size; | 493 int info_size = run_itr_->aux_info_default_size; |
470 if (!info_size) | 494 if (!info_size) |
471 info_size = run_itr_->aux_info_sizes[i]; | 495 info_size = run_itr_->aux_info_sizes[i]; |
472 | 496 |
473 if (IsSampleEncrypted(i)) { | 497 if (IsSampleEncrypted(i)) { |
474 BufferReader reader(buf + pos, info_size); | 498 BufferReader reader(buf + pos, info_size); |
475 const uint8_t iv_size = GetIvSize(i); | 499 const uint8_t iv_size = GetIvSize(i); |
476 const bool has_subsamples = info_size > iv_size; | 500 const bool has_subsamples = info_size > iv_size; |
477 RCHECK( | 501 SampleEncryptionEntry& entry = sample_encryption_entries[i]; |
478 sample_encryption_entries[i].Parse(&reader, iv_size, has_subsamples)); | 502 RCHECK(entry.Parse(&reader, iv_size, has_subsamples)); |
503 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) | |
504 // if we don't have a per-sample IV, get the constant IV. | |
505 if (!iv_size) { | |
506 RCHECK(ApplyConstantIv(i, entry)); | |
507 } | |
508 #endif | |
479 } | 509 } |
480 pos += info_size; | 510 pos += info_size; |
481 } | 511 } |
482 | 512 |
483 return true; | 513 return true; |
484 } | 514 } |
485 | 515 |
486 bool TrackRunIterator::IsRunValid() const { | 516 bool TrackRunIterator::IsRunValid() const { |
487 return run_itr_ != runs_.end(); | 517 return run_itr_ != runs_.end(); |
488 } | 518 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 } | 615 } |
586 | 616 |
587 const TrackEncryption& TrackRunIterator::track_encryption() const { | 617 const TrackEncryption& TrackRunIterator::track_encryption() const { |
588 if (is_audio()) | 618 if (is_audio()) |
589 return audio_description().sinf.info.track_encryption; | 619 return audio_description().sinf.info.track_encryption; |
590 return video_description().sinf.info.track_encryption; | 620 return video_description().sinf.info.track_encryption; |
591 } | 621 } |
592 | 622 |
593 std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { | 623 std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { |
594 DCHECK(is_encrypted()); | 624 DCHECK(is_encrypted()); |
625 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); | |
626 const std::vector<uint8_t>& kid = GetKeyId(sample_idx); | |
595 | 627 |
596 if (run_itr_->sample_encryption_entries.empty()) { | 628 if (run_itr_->sample_encryption_entries.empty()) { |
597 DCHECK_EQ(0, aux_info_size()); | 629 DCHECK_EQ(0, aux_info_size()); |
630 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) | |
631 // The 'cbcs' scheme allows empty aux info when a constant IV is in use | |
632 // with full sample encryption. That case will fall through to here. | |
633 SampleEncryptionEntry sample_encryption_entry; | |
634 if (ApplyConstantIv(sample_idx, sample_encryption_entry)) { | |
635 return std::unique_ptr<DecryptConfig>(new DecryptConfig( | |
636 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), | |
637 std::string(reinterpret_cast<const char*>( | |
638 sample_encryption_entry.initialization_vector), | |
639 arraysize(sample_encryption_entry.initialization_vector)), | |
640 sample_encryption_entry.subsamples)); | |
641 } | |
642 #endif | |
598 MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available."; | 643 MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available."; |
599 return std::unique_ptr<DecryptConfig>(); | 644 return std::unique_ptr<DecryptConfig>(); |
600 } | 645 } |
601 | 646 |
602 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); | |
603 DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size()); | 647 DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size()); |
604 const SampleEncryptionEntry& sample_encryption_entry = | 648 const SampleEncryptionEntry& sample_encryption_entry = |
605 run_itr_->sample_encryption_entries[sample_idx]; | 649 run_itr_->sample_encryption_entries[sample_idx]; |
606 | 650 |
607 size_t total_size = 0; | 651 size_t total_size = 0; |
608 if (!sample_encryption_entry.subsamples.empty() && | 652 if (!sample_encryption_entry.subsamples.empty() && |
609 (!sample_encryption_entry.GetTotalSizeOfSubsamples(&total_size) || | 653 (!sample_encryption_entry.GetTotalSizeOfSubsamples(&total_size) || |
610 total_size != static_cast<size_t>(sample_size()))) { | 654 total_size != static_cast<size_t>(sample_size()))) { |
611 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; | 655 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; |
612 return std::unique_ptr<DecryptConfig>(); | 656 return std::unique_ptr<DecryptConfig>(); |
613 } | 657 } |
614 | 658 |
615 const std::vector<uint8_t>& kid = GetKeyId(sample_idx); | |
616 return std::unique_ptr<DecryptConfig>(new DecryptConfig( | 659 return std::unique_ptr<DecryptConfig>(new DecryptConfig( |
617 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), | 660 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), |
618 std::string(reinterpret_cast<const char*>( | 661 std::string(reinterpret_cast<const char*>( |
619 sample_encryption_entry.initialization_vector), | 662 sample_encryption_entry.initialization_vector), |
620 arraysize(sample_encryption_entry.initialization_vector)), | 663 arraysize(sample_encryption_entry.initialization_vector)), |
621 sample_encryption_entry.subsamples)); | 664 sample_encryption_entry.subsamples)); |
622 } | 665 } |
623 | 666 |
624 uint32_t TrackRunIterator::GetGroupDescriptionIndex( | 667 uint32_t TrackRunIterator::GetGroupDescriptionIndex( |
625 uint32_t sample_index) const { | 668 uint32_t sample_index) const { |
(...skipping 15 matching lines...) Expand all Loading... | |
641 return (index == 0) ? track_encryption().default_kid | 684 return (index == 0) ? track_encryption().default_kid |
642 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; | 685 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; |
643 } | 686 } |
644 | 687 |
645 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { | 688 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { |
646 uint32_t index = GetGroupDescriptionIndex(sample_index); | 689 uint32_t index = GetGroupDescriptionIndex(sample_index); |
647 return (index == 0) ? track_encryption().default_iv_size | 690 return (index == 0) ? track_encryption().default_iv_size |
648 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; | 691 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; |
649 } | 692 } |
650 | 693 |
694 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) | |
695 bool TrackRunIterator::ApplyConstantIv(size_t sample_index, | |
696 SampleEncryptionEntry& entry) const { | |
697 if (!IsSampleEncrypted(sample_index)) | |
698 return true; | |
699 uint32_t index = GetGroupDescriptionIndex(sample_index); | |
700 const uint8_t constant_iv_size = | |
701 index == 0 | |
702 ? track_encryption().default_constant_iv_size | |
703 : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv_size; | |
704 RCHECK(constant_iv_size != 0); | |
705 const uint8_t* constant_iv = | |
706 index == 0 ? track_encryption().default_constant_iv | |
707 : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv; | |
708 RCHECK(constant_iv != nullptr); | |
709 memcpy(entry.initialization_vector, constant_iv, constant_iv_size); | |
kqyang
2016/10/12 22:16:52
It is safer to do:
memcpy(entry.initialization_ve
| |
710 return true; | |
711 } | |
712 #endif | |
713 | |
651 } // namespace mp4 | 714 } // namespace mp4 |
652 } // namespace media | 715 } // namespace media |
OLD | NEW |