Chromium Code Reviews| 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/mp4_stream_parser.h" | 5 #include "media/formats/mp4/mp4_stream_parser.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 19 #include "media/base/audio_decoder_config.h" | 19 #include "media/base/audio_decoder_config.h" |
| 20 #include "media/base/encryption_scheme.h" | |
| 20 #include "media/base/media_tracks.h" | 21 #include "media/base/media_tracks.h" |
| 21 #include "media/base/media_util.h" | 22 #include "media/base/media_util.h" |
| 22 #include "media/base/stream_parser_buffer.h" | 23 #include "media/base/stream_parser_buffer.h" |
| 23 #include "media/base/text_track_config.h" | 24 #include "media/base/text_track_config.h" |
| 24 #include "media/base/timestamp_constants.h" | 25 #include "media/base/timestamp_constants.h" |
| 25 #include "media/base/video_decoder_config.h" | 26 #include "media/base/video_decoder_config.h" |
| 26 #include "media/base/video_util.h" | 27 #include "media/base/video_util.h" |
| 27 #include "media/formats/mp4/box_definitions.h" | 28 #include "media/formats/mp4/box_definitions.h" |
| 28 #include "media/formats/mp4/box_reader.h" | 29 #include "media/formats/mp4/box_reader.h" |
| 29 #include "media/formats/mp4/es_descriptor.h" | 30 #include "media/formats/mp4/es_descriptor.h" |
| 30 #include "media/formats/mp4/rcheck.h" | 31 #include "media/formats/mp4/rcheck.h" |
| 31 #include "media/formats/mpeg/adts_constants.h" | 32 #include "media/formats/mpeg/adts_constants.h" |
| 32 | 33 |
| 33 namespace media { | 34 namespace media { |
| 34 namespace mp4 { | 35 namespace mp4 { |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 const int kMaxEmptySampleLogs = 20; | 38 const int kMaxEmptySampleLogs = 20; |
| 39 | |
| 40 // Caller should be prepared to handle return of Unencrypted() in case of | |
| 41 // unsupported scheme. | |
| 42 EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) { | |
| 43 if (!sinf.HasSupportedScheme()) | |
| 44 return Unencrypted(); | |
| 45 FourCC fourCC = sinf.type.type; | |
|
kqyang
2016/10/12 22:16:52
s/fourCC/fourcc/
variable name should not be capi
dougsteed
2016/10/14 21:24:35
Done.
| |
| 46 EncryptionScheme::CipherMode mode = EncryptionScheme::CIPHER_MODE_UNENCRYPTED; | |
| 47 EncryptionScheme::Pattern pattern; | |
| 48 bool uses_pattern_encryption = false; | |
| 49 switch (fourCC) { | |
| 50 case FOURCC_CENC: | |
| 51 mode = EncryptionScheme::CIPHER_MODE_AES_CTR; | |
| 52 break; | |
| 53 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) | |
| 54 case FOURCC_CBCS: | |
| 55 mode = EncryptionScheme::CIPHER_MODE_AES_CBC; | |
| 56 uses_pattern_encryption = true; | |
| 57 break; | |
| 58 #endif | |
| 59 default: | |
| 60 NOTREACHED(); | |
| 61 break; | |
| 62 } | |
| 63 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) | |
| 64 if (uses_pattern_encryption) { | |
| 65 uint8_t crypt = sinf.info.track_encryption.default_crypt_byte_block; | |
| 66 uint8_t skip = sinf.info.track_encryption.default_skip_byte_block; | |
| 67 pattern = EncryptionScheme::Pattern(crypt, skip); | |
| 68 } | |
| 69 #endif | |
| 70 return EncryptionScheme(mode, pattern); | |
| 71 } | |
| 38 } // namespace | 72 } // namespace |
| 39 | 73 |
| 40 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, | 74 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, |
| 41 bool has_sbr) | 75 bool has_sbr) |
| 42 : state_(kWaitingForInit), | 76 : state_(kWaitingForInit), |
| 43 moof_head_(0), | 77 moof_head_(0), |
| 44 mdat_tail_(0), | 78 mdat_tail_(0), |
| 45 highest_end_offset_(0), | 79 highest_end_offset_(0), |
| 46 has_audio_(false), | 80 has_audio_(false), |
| 47 has_video_(false), | 81 has_video_(false), |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 | 344 |
| 311 uint32_t audio_track_id = track->header.track_id; | 345 uint32_t audio_track_id = track->header.track_id; |
| 312 if (audio_track_ids_.find(audio_track_id) != audio_track_ids_.end()) { | 346 if (audio_track_ids_.find(audio_track_id) != audio_track_ids_.end()) { |
| 313 MEDIA_LOG(ERROR, media_log_) | 347 MEDIA_LOG(ERROR, media_log_) |
| 314 << "Audio track with track_id=" << audio_track_id | 348 << "Audio track with track_id=" << audio_track_id |
| 315 << " already present."; | 349 << " already present."; |
| 316 return false; | 350 return false; |
| 317 } | 351 } |
| 318 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; | 352 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; |
| 319 is_track_encrypted_[audio_track_id] = is_track_encrypted; | 353 is_track_encrypted_[audio_track_id] = is_track_encrypted; |
| 320 audio_config.Initialize( | 354 EncryptionScheme scheme = Unencrypted(); |
| 321 codec, sample_format, channel_layout, sample_per_second, extra_data, | 355 if (is_track_encrypted) { |
| 322 is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted(), | 356 scheme = GetEncryptionScheme(entry.sinf); |
| 323 base::TimeDelta(), 0); | 357 if (!scheme.is_encrypted()) |
| 358 return false; | |
| 359 } | |
| 360 audio_config.Initialize(codec, sample_format, channel_layout, | |
| 361 sample_per_second, extra_data, scheme, | |
|
kqyang
2016/10/12 22:16:52
I don't think it is a good idea to pass encryption
dougsteed
2016/10/14 21:24:35
Let's discuss further. I'm not sure I agree that s
| |
| 362 base::TimeDelta(), 0); | |
| 324 DVLOG(1) << "audio_track_id=" << audio_track_id | 363 DVLOG(1) << "audio_track_id=" << audio_track_id |
| 325 << " config=" << audio_config.AsHumanReadableString(); | 364 << " config=" << audio_config.AsHumanReadableString(); |
| 326 if (!audio_config.IsValidConfig()) { | 365 if (!audio_config.IsValidConfig()) { |
| 327 MEDIA_LOG(ERROR, media_log_) << "Invalid audio decoder config: " | 366 MEDIA_LOG(ERROR, media_log_) << "Invalid audio decoder config: " |
| 328 << audio_config.AsHumanReadableString(); | 367 << audio_config.AsHumanReadableString(); |
| 329 return false; | 368 return false; |
| 330 } | 369 } |
| 331 has_audio_ = true; | 370 has_audio_ = true; |
| 332 audio_track_ids_.insert(audio_track_id); | 371 audio_track_ids_.insert(audio_track_id); |
| 333 const char* track_kind = (audio_track_ids_.size() == 1 ? "main" : ""); | 372 const char* track_kind = (audio_track_ids_.size() == 1 ? "main" : ""); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 | 410 |
| 372 uint32_t video_track_id = track->header.track_id; | 411 uint32_t video_track_id = track->header.track_id; |
| 373 if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) { | 412 if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) { |
| 374 MEDIA_LOG(ERROR, media_log_) | 413 MEDIA_LOG(ERROR, media_log_) |
| 375 << "Video track with track_id=" << video_track_id | 414 << "Video track with track_id=" << video_track_id |
| 376 << " already present."; | 415 << " already present."; |
| 377 return false; | 416 return false; |
| 378 } | 417 } |
| 379 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; | 418 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; |
| 380 is_track_encrypted_[video_track_id] = is_track_encrypted; | 419 is_track_encrypted_[video_track_id] = is_track_encrypted; |
| 381 video_config.Initialize( | 420 EncryptionScheme scheme = Unencrypted(); |
| 382 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, | 421 if (is_track_encrypted) { |
| 383 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, | 422 scheme = GetEncryptionScheme(entry.sinf); |
| 384 // No decoder-specific buffer needed for AVC; | 423 if (!scheme.is_encrypted()) |
| 385 // SPS/PPS are embedded in the video stream | 424 return false; |
| 386 EmptyExtraData(), | 425 } |
| 387 is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted()); | 426 video_config.Initialize(entry.video_codec, entry.video_codec_profile, |
| 427 PIXEL_FORMAT_YV12, COLOR_SPACE_HD_REC709, | |
| 428 coded_size, visible_rect, natural_size, | |
| 429 // No decoder-specific buffer needed for AVC; | |
| 430 // SPS/PPS are embedded in the video stream | |
| 431 EmptyExtraData(), scheme); | |
| 388 DVLOG(1) << "video_track_id=" << video_track_id | 432 DVLOG(1) << "video_track_id=" << video_track_id |
| 389 << " config=" << video_config.AsHumanReadableString(); | 433 << " config=" << video_config.AsHumanReadableString(); |
| 390 if (!video_config.IsValidConfig()) { | 434 if (!video_config.IsValidConfig()) { |
| 391 MEDIA_LOG(ERROR, media_log_) << "Invalid video decoder config: " | 435 MEDIA_LOG(ERROR, media_log_) << "Invalid video decoder config: " |
| 392 << video_config.AsHumanReadableString(); | 436 << video_config.AsHumanReadableString(); |
| 393 return false; | 437 return false; |
| 394 } | 438 } |
| 395 has_video_ = true; | 439 has_video_ = true; |
| 396 video_track_ids_.insert(video_track_id); | 440 video_track_ids_.insert(video_track_id); |
| 397 const char* track_kind = (video_track_ids_.size() == 1 ? "main" : ""); | 441 const char* track_kind = (video_track_ids_.size() == 1 ? "main" : ""); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 !PrepareAACBuffer(runs_->audio_description().esds.aac, | 659 !PrepareAACBuffer(runs_->audio_description().esds.aac, |
| 616 &frame_buf, &subsamples)) { | 660 &frame_buf, &subsamples)) { |
| 617 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; | 661 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; |
| 618 *err = true; | 662 *err = true; |
| 619 return false; | 663 return false; |
| 620 } | 664 } |
| 621 } | 665 } |
| 622 | 666 |
| 623 if (decrypt_config) { | 667 if (decrypt_config) { |
| 624 if (!subsamples.empty()) { | 668 if (!subsamples.empty()) { |
| 625 // Create a new config with the updated subsamples. | 669 // Create a new config with the updated subsamples. |
| 626 decrypt_config.reset(new DecryptConfig( | 670 decrypt_config.reset(new DecryptConfig(decrypt_config->key_id(), |
| 627 decrypt_config->key_id(), | 671 decrypt_config->iv(), subsamples)); |
| 628 decrypt_config->iv(), | |
| 629 subsamples)); | |
| 630 } | 672 } |
| 631 // else, use the existing config. | 673 // else, use the existing config. |
| 632 } else if (is_track_encrypted_[runs_->track_id()]) { | 674 } else if (is_track_encrypted_[runs_->track_id()]) { |
| 633 // The media pipeline requires a DecryptConfig with an empty |iv|. | 675 // The media pipeline requires a DecryptConfig with an empty |iv|. |
| 634 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); | 676 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); |
| 635 decrypt_config.reset( | 677 decrypt_config.reset( |
| 636 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); | 678 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); |
| 637 } | 679 } |
| 638 | 680 |
| 639 StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO : | 681 StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO : |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 runs.AdvanceSample(); | 773 runs.AdvanceSample(); |
| 732 } | 774 } |
| 733 runs.AdvanceRun(); | 775 runs.AdvanceRun(); |
| 734 } | 776 } |
| 735 | 777 |
| 736 return true; | 778 return true; |
| 737 } | 779 } |
| 738 | 780 |
| 739 } // namespace mp4 | 781 } // namespace mp4 |
| 740 } // namespace media | 782 } // namespace media |
| OLD | NEW |