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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 continue; | 276 continue; |
276 } | 277 } |
277 size_t desc_idx = traf.header.sample_description_index; | 278 size_t desc_idx = traf.header.sample_description_index; |
278 if (!desc_idx) desc_idx = trex->default_sample_description_index; | 279 if (!desc_idx) desc_idx = trex->default_sample_description_index; |
279 RCHECK(desc_idx > 0); // Descriptions are one-indexed in the file | 280 RCHECK(desc_idx > 0); // Descriptions are one-indexed in the file |
280 desc_idx -= 1; | 281 desc_idx -= 1; |
281 | 282 |
282 const std::vector<uint8_t>& sample_encryption_data = | 283 const std::vector<uint8_t>& sample_encryption_data = |
283 traf.sample_encryption.sample_encryption_data; | 284 traf.sample_encryption.sample_encryption_data; |
284 std::unique_ptr<BufferReader> sample_encryption_reader; | 285 std::unique_ptr<BufferReader> sample_encryption_reader; |
285 uint32_t sample_encrytion_entries_count = 0; | 286 uint32_t sample_encryption_entries_count = 0; |
286 if (!sample_encryption_data.empty()) { | 287 if (!sample_encryption_data.empty()) { |
287 sample_encryption_reader.reset(new BufferReader( | 288 sample_encryption_reader.reset(new BufferReader( |
288 sample_encryption_data.data(), sample_encryption_data.size())); | 289 sample_encryption_data.data(), sample_encryption_data.size())); |
289 RCHECK(sample_encryption_reader->Read4(&sample_encrytion_entries_count)); | 290 RCHECK(sample_encryption_reader->Read4(&sample_encryption_entries_count)); |
290 } | 291 } |
291 | 292 |
292 // Process edit list to remove CTS offset introduced in the presence of | 293 // Process edit list to remove CTS offset introduced in the presence of |
293 // B-frames (those that contain a single edit with a nonnegative media | 294 // B-frames (those that contain a single edit with a nonnegative media |
294 // time). Other uses of edit lists are not supported, as they are | 295 // time). Other uses of edit lists are not supported, as they are |
295 // both uncommon and better served by higher-level protocols. | 296 // both uncommon and better served by higher-level protocols. |
296 int64_t edit_list_offset = 0; | 297 int64_t edit_list_offset = 0; |
297 const std::vector<EditListEntry>& edits = trak->edit.list.edits; | 298 const std::vector<EditListEntry>& edits = trak->edit.list.edits; |
298 if (!edits.empty()) { | 299 if (!edits.empty()) { |
299 if (edits.size() > 1) | 300 if (edits.size() > 1) |
(...skipping 16 matching lines...) Expand all 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_encrytion_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); |
354 tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j]; | 352 tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j]; |
355 tri.aux_info_default_size = | 353 tri.aux_info_default_size = |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 tri.samples[k].cenc_group_description_index = 0; | 393 tri.samples[k].cenc_group_description_index = 0; |
396 continue; | 394 continue; |
397 } | 395 } |
398 | 396 |
399 uint32_t index = sample_to_group_itr.group_description_index(); | 397 uint32_t index = sample_to_group_itr.group_description_index(); |
400 tri.samples[k].cenc_group_description_index = index; | 398 tri.samples[k].cenc_group_description_index = index; |
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_encrytion_entries_count > 0) { | 403 if (sample_encryption_entries_count > 0) { |
406 RCHECK(sample_encrytion_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 if (!iv_size) { | |
419 const uint8_t constant_iv_size = | |
420 index == 0 ? track_encryption->default_constant_iv_size | |
421 : info_entry->constant_iv_size; | |
422 RCHECK(constant_iv_size != 0); | |
423 const uint8_t* constant_iv = | |
424 index == 0 ? track_encryption->default_constant_iv | |
425 : info_entry->constant_iv; | |
426 memcpy(entry.initialization_vector, constant_iv, constant_iv_size); | |
427 } | |
428 // We only support setting the pattern values in the 'tenc' box for | |
429 // the track (not varying on per sample group basis). | |
430 // Thus we need to verify that the settings in the sample group match | |
431 // those in the 'tenc'. | |
432 if (index != 0) { | |
433 RCHECK(info_entry->crypt_byte_block == | |
434 track_encryption->default_crypt_byte_block); | |
435 RCHECK(info_entry->skip_byte_block == | |
436 track_encryption->default_skip_byte_block); | |
437 } | |
438 #endif | |
kqyang
2016/05/26 17:34:50
Consider add a new unittest in track_run_iterator_
dougsteed
2016/06/09 22:38:27
Done.
| |
417 } | 439 } |
418 } | 440 } |
kqyang
2016/05/27 17:45:58
The implementation here only supports the case whe
dougsteed
2016/06/09 22:38:27
Done. I added code to cover the other cases.
| |
419 runs_.push_back(tri); | 441 runs_.push_back(tri); |
420 sample_count_sum += trun.sample_count; | 442 sample_count_sum += trun.sample_count; |
421 } | 443 } |
422 | 444 |
423 // We should have iterated through all samples in SampleToGroup Box. | 445 // We should have iterated through all samples in SampleToGroup Box. |
424 RCHECK(!sample_to_group_itr.IsValid()); | 446 RCHECK(!sample_to_group_itr.IsValid()); |
425 } | 447 } |
426 | 448 |
427 std::sort(runs_.begin(), runs_.end(), CompareMinTrackRunDataOffset()); | 449 std::sort(runs_.begin(), runs_.end(), CompareMinTrackRunDataOffset()); |
428 run_itr_ = runs_.begin(); | 450 run_itr_ = runs_.begin(); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 } | 665 } |
644 | 666 |
645 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { | 667 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { |
646 uint32_t index = GetGroupDescriptionIndex(sample_index); | 668 uint32_t index = GetGroupDescriptionIndex(sample_index); |
647 return (index == 0) ? track_encryption().default_iv_size | 669 return (index == 0) ? track_encryption().default_iv_size |
648 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; | 670 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; |
649 } | 671 } |
650 | 672 |
651 } // namespace mp4 | 673 } // namespace mp4 |
652 } // namespace media | 674 } // namespace media |
OLD | NEW |