| 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 | 8 |
| 9 #include "media/base/buffers.h" | 9 #include "media/base/buffers.h" |
| 10 #include "media/formats/mp4/rcheck.h" | 10 #include "media/formats/mp4/rcheck.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us)); | 74 DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us)); |
| 75 return base::TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us); | 75 return base::TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us); |
| 76 } | 76 } |
| 77 | 77 |
| 78 DecodeTimestamp DecodeTimestampFromRational(int64 numer, int64 denom) { | 78 DecodeTimestamp DecodeTimestampFromRational(int64 numer, int64 denom) { |
| 79 return DecodeTimestamp::FromPresentationTime( | 79 return DecodeTimestamp::FromPresentationTime( |
| 80 TimeDeltaFromRational(numer, denom)); | 80 TimeDeltaFromRational(numer, denom)); |
| 81 } | 81 } |
| 82 | 82 |
| 83 TrackRunIterator::TrackRunIterator(const Movie* moov, | 83 TrackRunIterator::TrackRunIterator(const Movie* moov, |
| 84 const LogCB& log_cb) | 84 const scoped_refptr<MediaLog>& media_log) |
| 85 : moov_(moov), log_cb_(log_cb), sample_offset_(0) { | 85 : moov_(moov), media_log_(media_log), sample_offset_(0) { |
| 86 CHECK(moov); | 86 CHECK(moov); |
| 87 } | 87 } |
| 88 | 88 |
| 89 TrackRunIterator::~TrackRunIterator() {} | 89 TrackRunIterator::~TrackRunIterator() {} |
| 90 | 90 |
| 91 static bool PopulateSampleInfo(const TrackExtends& trex, | 91 static bool PopulateSampleInfo(const TrackExtends& trex, |
| 92 const TrackFragmentHeader& tfhd, | 92 const TrackFragmentHeader& tfhd, |
| 93 const TrackFragmentRun& trun, | 93 const TrackFragmentRun& trun, |
| 94 const int64 edit_list_offset, | 94 const int64 edit_list_offset, |
| 95 const uint32 i, | 95 const uint32 i, |
| 96 SampleInfo* sample_info, | 96 SampleInfo* sample_info, |
| 97 const SampleDependsOn sdtp_sample_depends_on, | 97 const SampleDependsOn sdtp_sample_depends_on, |
| 98 const LogCB& log_cb) { | 98 const scoped_refptr<MediaLog>& media_log) { |
| 99 if (i < trun.sample_sizes.size()) { | 99 if (i < trun.sample_sizes.size()) { |
| 100 sample_info->size = trun.sample_sizes[i]; | 100 sample_info->size = trun.sample_sizes[i]; |
| 101 } else if (tfhd.default_sample_size > 0) { | 101 } else if (tfhd.default_sample_size > 0) { |
| 102 sample_info->size = tfhd.default_sample_size; | 102 sample_info->size = tfhd.default_sample_size; |
| 103 } else { | 103 } else { |
| 104 sample_info->size = trex.default_sample_size; | 104 sample_info->size = trex.default_sample_size; |
| 105 } | 105 } |
| 106 | 106 |
| 107 if (i < trun.sample_durations.size()) { | 107 if (i < trun.sample_durations.size()) { |
| 108 sample_info->duration = trun.sample_durations[i]; | 108 sample_info->duration = trun.sample_durations[i]; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 | 150 |
| 151 case kSampleDependsOnOthers: | 151 case kSampleDependsOnOthers: |
| 152 sample_info->is_keyframe = false; | 152 sample_info->is_keyframe = false; |
| 153 break; | 153 break; |
| 154 | 154 |
| 155 case kSampleDependsOnNoOther: | 155 case kSampleDependsOnNoOther: |
| 156 sample_info->is_keyframe = true; | 156 sample_info->is_keyframe = true; |
| 157 break; | 157 break; |
| 158 | 158 |
| 159 case kSampleDependsOnReserved: | 159 case kSampleDependsOnReserved: |
| 160 MEDIA_LOG(ERROR, log_cb) << "Reserved value used in sample dependency" | 160 MEDIA_LOG(ERROR, media_log) << "Reserved value used in sample dependency" |
| 161 " info."; | 161 " info."; |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 return true; | 164 return true; |
| 165 } | 165 } |
| 166 | 166 |
| 167 // In well-structured encrypted media, each track run will be immediately | 167 // In well-structured encrypted media, each track run will be immediately |
| 168 // preceded by its auxiliary information; this is the only optimal storage | 168 // preceded by its auxiliary information; this is the only optimal storage |
| 169 // pattern in terms of minimum number of bytes from a serial stream needed to | 169 // pattern in terms of minimum number of bytes from a serial stream needed to |
| 170 // begin playback. It also allows us to optimize caching on memory-constrained | 170 // begin playback. It also allows us to optimize caching on memory-constrained |
| 171 // architectures, because we can cache the relatively small auxiliary | 171 // architectures, because we can cache the relatively small auxiliary |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 tri.aux_info_total_size += tri.aux_info_sizes[k]; | 297 tri.aux_info_total_size += tri.aux_info_sizes[k]; |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 } else { | 300 } else { |
| 301 tri.aux_info_start_offset = -1; | 301 tri.aux_info_start_offset = -1; |
| 302 tri.aux_info_total_size = 0; | 302 tri.aux_info_total_size = 0; |
| 303 } | 303 } |
| 304 | 304 |
| 305 tri.samples.resize(trun.sample_count); | 305 tri.samples.resize(trun.sample_count); |
| 306 for (size_t k = 0; k < trun.sample_count; k++) { | 306 for (size_t k = 0; k < trun.sample_count; k++) { |
| 307 if (!PopulateSampleInfo(*trex, traf.header, trun, edit_list_offset, | 307 if (!PopulateSampleInfo(*trex, traf.header, trun, edit_list_offset, k, |
| 308 k, &tri.samples[k], | 308 &tri.samples[k], traf.sdtp.sample_depends_on(k), |
| 309 traf.sdtp.sample_depends_on(k), | 309 media_log_)) { |
| 310 log_cb_)) { | |
| 311 return false; | 310 return false; |
| 312 } | 311 } |
| 313 | 312 |
| 314 run_start_dts += tri.samples[k].duration; | 313 run_start_dts += tri.samples[k].duration; |
| 315 | 314 |
| 316 if (!is_sample_to_group_valid) { | 315 if (!is_sample_to_group_valid) { |
| 317 // Set group description index to 0 to read encryption information | 316 // Set group description index to 0 to read encryption information |
| 318 // from TrackEncryption Box. | 317 // from TrackEncryption Box. |
| 319 tri.samples[k].cenc_group_description_index = 0; | 318 tri.samples[k].cenc_group_description_index = 0; |
| 320 continue; | 319 continue; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 if (is_audio()) | 511 if (is_audio()) |
| 513 return audio_description().sinf.info.track_encryption; | 512 return audio_description().sinf.info.track_encryption; |
| 514 return video_description().sinf.info.track_encryption; | 513 return video_description().sinf.info.track_encryption; |
| 515 } | 514 } |
| 516 | 515 |
| 517 scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { | 516 scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { |
| 518 DCHECK(is_encrypted()); | 517 DCHECK(is_encrypted()); |
| 519 | 518 |
| 520 if (cenc_info_.empty()) { | 519 if (cenc_info_.empty()) { |
| 521 DCHECK_EQ(0, aux_info_size()); | 520 DCHECK_EQ(0, aux_info_size()); |
| 522 MEDIA_LOG(ERROR, log_cb_) << "Aux Info is not available."; | 521 MEDIA_LOG(ERROR, media_log_) << "Aux Info is not available."; |
| 523 return scoped_ptr<DecryptConfig>(); | 522 return scoped_ptr<DecryptConfig>(); |
| 524 } | 523 } |
| 525 | 524 |
| 526 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); | 525 size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); |
| 527 DCHECK_LT(sample_idx, cenc_info_.size()); | 526 DCHECK_LT(sample_idx, cenc_info_.size()); |
| 528 const FrameCENCInfo& cenc_info = cenc_info_[sample_idx]; | 527 const FrameCENCInfo& cenc_info = cenc_info_[sample_idx]; |
| 529 | 528 |
| 530 size_t total_size = 0; | 529 size_t total_size = 0; |
| 531 if (!cenc_info.subsamples.empty() && | 530 if (!cenc_info.subsamples.empty() && |
| 532 (!cenc_info.GetTotalSizeOfSubsamples(&total_size) || | 531 (!cenc_info.GetTotalSizeOfSubsamples(&total_size) || |
| 533 total_size != static_cast<size_t>(sample_size()))) { | 532 total_size != static_cast<size_t>(sample_size()))) { |
| 534 MEDIA_LOG(ERROR, log_cb_) << "Incorrect CENC subsample size."; | 533 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; |
| 535 return scoped_ptr<DecryptConfig>(); | 534 return scoped_ptr<DecryptConfig>(); |
| 536 } | 535 } |
| 537 | 536 |
| 538 const std::vector<uint8>& kid = GetKeyId(sample_idx); | 537 const std::vector<uint8>& kid = GetKeyId(sample_idx); |
| 539 return scoped_ptr<DecryptConfig>(new DecryptConfig( | 538 return scoped_ptr<DecryptConfig>(new DecryptConfig( |
| 540 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), | 539 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), |
| 541 std::string(reinterpret_cast<const char*>(cenc_info.iv), | 540 std::string(reinterpret_cast<const char*>(cenc_info.iv), |
| 542 arraysize(cenc_info.iv)), | 541 arraysize(cenc_info.iv)), |
| 543 cenc_info.subsamples)); | 542 cenc_info.subsamples)); |
| 544 } | 543 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 573 } | 572 } |
| 574 | 573 |
| 575 uint8 TrackRunIterator::GetIvSize(size_t sample_index) const { | 574 uint8 TrackRunIterator::GetIvSize(size_t sample_index) const { |
| 576 uint32 index = GetGroupDescriptionIndex(sample_index); | 575 uint32 index = GetGroupDescriptionIndex(sample_index); |
| 577 return (index == 0) ? track_encryption().default_iv_size | 576 return (index == 0) ? track_encryption().default_iv_size |
| 578 : GetSampleEncryptionInfoEntry(index).iv_size; | 577 : GetSampleEncryptionInfoEntry(index).iv_size; |
| 579 } | 578 } |
| 580 | 579 |
| 581 } // namespace mp4 | 580 } // namespace mp4 |
| 582 } // namespace media | 581 } // namespace media |
| OLD | NEW |