 Chromium Code Reviews
 Chromium Code Reviews Issue 1998333002:
  MP4 support for Common Encryption 'cbcs' scheme.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1998333002:
  MP4 support for Common Encryption 'cbcs' scheme.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 | 
| 37 namespace { | |
| 38 | |
| 39 EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) { | |
| 40 if (!sinf.HasSupportedScheme()) | |
| 41 return Unencrypted(); | |
| 42 FourCC fourCC = sinf.type.type; | |
| 43 EncryptionScheme::CipherMode mode = EncryptionScheme::CIPHER_MODE_UNENCRYPTED; | |
| 44 EncryptionScheme::Pattern pattern; | |
| 45 bool pattern_encryption = false; | |
| 46 switch (fourCC) { | |
| 47 case FOURCC_CENC: | |
| 48 mode = EncryptionScheme::CIPHER_MODE_AES_CTR; | |
| 49 break; | |
| 50 #if BUILDFLAG(ENABLE_CENC_NEW_EDITIONS) | |
| 51 case FOURCC_CENS: | |
| 52 mode = EncryptionScheme::CIPHER_MODE_AES_CTR; | |
| 53 pattern_encryption = true; | |
| 54 break; | |
| 55 case FOURCC_CBC1: | |
| 56 mode = EncryptionScheme::CIPHER_MODE_AES_CBC; | |
| 57 break; | |
| 58 case FOURCC_CBCS: | |
| 59 mode = EncryptionScheme::CIPHER_MODE_AES_CBC; | |
| 60 pattern_encryption = true; | |
| 61 break; | |
| 62 #endif | |
| 63 default: | |
| 64 break; | |
| 
ddorwin
2016/05/24 23:25:03
Should this be a DLOG that we don't recognize the
 
dougsteed
2016/05/25 17:23:21
Done.
 | |
| 65 } | |
| 66 #if BUILDFLAG(ENABLE_CENC_NEW_EDITIONS) | |
| 67 if (pattern_encryption) { | |
| 68 uint8_t crypt = sinf.info.track_encryption.default_crypt_byte_block; | |
| 69 uint8_t skip = sinf.info.track_encryption.default_skip_byte_block; | |
| 70 pattern = EncryptionScheme::Pattern(crypt, skip); | |
| 71 } | |
| 72 #endif | |
| 73 return EncryptionScheme(mode, pattern); | |
| 74 } | |
| 75 } | |
| 
kqyang
2016/05/23 20:57:34
nit: }  // namespace
 
dougsteed
2016/05/25 17:23:21
Done.
 | |
| 76 | |
| 36 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, | 77 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, | 
| 37 bool has_sbr) | 78 bool has_sbr) | 
| 38 : state_(kWaitingForInit), | 79 : state_(kWaitingForInit), | 
| 39 moof_head_(0), | 80 moof_head_(0), | 
| 40 mdat_tail_(0), | 81 mdat_tail_(0), | 
| 41 highest_end_offset_(0), | 82 highest_end_offset_(0), | 
| 42 has_audio_(false), | 83 has_audio_(false), | 
| 43 has_video_(false), | 84 has_video_(false), | 
| 44 audio_track_id_(0), | 85 audio_track_id_(0), | 
| 45 video_track_id_(0), | 86 video_track_id_(0), | 
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 sample_format = kSampleFormatS32; | 350 sample_format = kSampleFormatS32; | 
| 310 } else { | 351 } else { | 
| 311 LOG(ERROR) << "Unsupported sample size."; | 352 LOG(ERROR) << "Unsupported sample size."; | 
| 312 return false; | 353 return false; | 
| 313 } | 354 } | 
| 314 | 355 | 
| 315 is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 356 is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 
| 316 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_; | 357 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_; | 
| 317 audio_config.Initialize( | 358 audio_config.Initialize( | 
| 318 codec, sample_format, channel_layout, sample_per_second, extra_data, | 359 codec, sample_format, channel_layout, sample_per_second, extra_data, | 
| 319 is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(), | 360 is_audio_track_encrypted_ ? GetEncryptionScheme(entry.sinf) | 
| 361 : Unencrypted(), | |
| 320 base::TimeDelta(), 0); | 362 base::TimeDelta(), 0); | 
| 321 has_audio_ = true; | 363 has_audio_ = true; | 
| 322 audio_track_id_ = track->header.track_id; | 364 audio_track_id_ = track->header.track_id; | 
| 323 media_tracks->AddAudioTrack( | 365 media_tracks->AddAudioTrack( | 
| 324 audio_config, base::UintToString(audio_track_id_), "main", | 366 audio_config, base::UintToString(audio_track_id_), "main", | 
| 325 track->media.handler.name, track->media.header.language()); | 367 track->media.handler.name, track->media.header.language()); | 
| 326 continue; | 368 continue; | 
| 327 } | 369 } | 
| 328 | 370 | 
| 329 if (track->media.handler.type == kVideo) { | 371 if (track->media.handler.type == kVideo) { | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 } | 403 } | 
| 362 | 404 | 
| 363 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 405 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 
| 364 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; | 406 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; | 
| 365 video_config.Initialize( | 407 video_config.Initialize( | 
| 366 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, | 408 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, | 
| 367 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, | 409 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, | 
| 368 // No decoder-specific buffer needed for AVC; | 410 // No decoder-specific buffer needed for AVC; | 
| 369 // SPS/PPS are embedded in the video stream | 411 // SPS/PPS are embedded in the video stream | 
| 370 EmptyExtraData(), | 412 EmptyExtraData(), | 
| 371 is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted()); | 413 is_video_track_encrypted_ ? GetEncryptionScheme(entry.sinf) | 
| 414 : Unencrypted()); | |
| 372 has_video_ = true; | 415 has_video_ = true; | 
| 373 video_track_id_ = track->header.track_id; | 416 video_track_id_ = track->header.track_id; | 
| 374 media_tracks->AddVideoTrack( | 417 media_tracks->AddVideoTrack( | 
| 375 video_config, base::UintToString(video_track_id_), "main", | 418 video_config, base::UintToString(video_track_id_), "main", | 
| 376 track->media.handler.name, track->media.header.language()); | 419 track->media.handler.name, track->media.header.language()); | 
| 377 continue; | 420 continue; | 
| 378 } | 421 } | 
| 379 | 422 | 
| 380 // TODO(wolenetz): Investigate support in MSE and Chrome MSE for CEA 608/708 | 423 // TODO(wolenetz): Investigate support in MSE and Chrome MSE for CEA 608/708 | 
| 381 // embedded caption data in video track. At time of init segment parsing, we | 424 // embedded caption data in video track. At time of init segment parsing, we | 
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 !PrepareAACBuffer(runs_->audio_description().esds.aac, | 610 !PrepareAACBuffer(runs_->audio_description().esds.aac, | 
| 568 &frame_buf, &subsamples)) { | 611 &frame_buf, &subsamples)) { | 
| 569 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; | 612 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; | 
| 570 *err = true; | 613 *err = true; | 
| 571 return false; | 614 return false; | 
| 572 } | 615 } | 
| 573 } | 616 } | 
| 574 | 617 | 
| 575 if (decrypt_config) { | 618 if (decrypt_config) { | 
| 576 if (!subsamples.empty()) { | 619 if (!subsamples.empty()) { | 
| 577 // Create a new config with the updated subsamples. | 620 // Create a new config with the updated subsamples. | 
| 578 decrypt_config.reset(new DecryptConfig( | 621 decrypt_config.reset(new DecryptConfig(decrypt_config->key_id(), | 
| 579 decrypt_config->key_id(), | 622 decrypt_config->iv(), subsamples)); | 
| 580 decrypt_config->iv(), | |
| 581 subsamples)); | |
| 582 } | 623 } | 
| 583 // else, use the existing config. | 624 // else, use the existing config. | 
| 584 } else if ((audio && is_audio_track_encrypted_) || | 625 } else if ((audio && is_audio_track_encrypted_) || | 
| 585 (video && is_video_track_encrypted_)) { | 626 (video && is_video_track_encrypted_)) { | 
| 586 // The media pipeline requires a DecryptConfig with an empty |iv|. | 627 // The media pipeline requires a DecryptConfig with an empty |iv|. | 
| 587 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); | 628 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); | 
| 588 decrypt_config.reset( | 629 decrypt_config.reset( | 
| 589 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); | 630 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); | 
| 590 } | 631 } | 
| 591 | 632 | 
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 698 runs.AdvanceSample(); | 739 runs.AdvanceSample(); | 
| 699 } | 740 } | 
| 700 runs.AdvanceRun(); | 741 runs.AdvanceRun(); | 
| 701 } | 742 } | 
| 702 | 743 | 
| 703 return true; | 744 return true; | 
| 704 } | 745 } | 
| 705 | 746 | 
| 706 } // namespace mp4 | 747 } // namespace mp4 | 
| 707 } // namespace media | 748 } // namespace media | 
| OLD | NEW |