Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: media/formats/mp4/mp4_stream_parser.cc

Issue 1998333002: MP4 support for Common Encryption 'cbcs' scheme. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: another ddorwin comment Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/formats/mp4/fourccs.h ('k') | media/formats/mp4/track_run_iterator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
46 EncryptionScheme::CipherMode mode = EncryptionScheme::CIPHER_MODE_UNENCRYPTED;
47 EncryptionScheme::Pattern pattern;
48 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
49 bool uses_pattern_encryption = false;
50 #endif
51 switch (fourcc) {
52 case FOURCC_CENC:
53 mode = EncryptionScheme::CIPHER_MODE_AES_CTR;
54 break;
55 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
56 case FOURCC_CBCS:
57 mode = EncryptionScheme::CIPHER_MODE_AES_CBC;
58 uses_pattern_encryption = true;
59 break;
60 #endif
61 default:
62 NOTREACHED();
63 break;
64 }
65 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
66 if (uses_pattern_encryption) {
67 uint8_t crypt = sinf.info.track_encryption.default_crypt_byte_block;
68 uint8_t skip = sinf.info.track_encryption.default_skip_byte_block;
69 pattern = EncryptionScheme::Pattern(crypt, skip);
70 }
71 #endif
72 return EncryptionScheme(mode, pattern);
73 }
38 } // namespace 74 } // namespace
39 75
40 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, 76 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
41 bool has_sbr) 77 bool has_sbr)
42 : state_(kWaitingForInit), 78 : state_(kWaitingForInit),
43 moof_head_(0), 79 moof_head_(0),
44 mdat_tail_(0), 80 mdat_tail_(0),
45 highest_end_offset_(0), 81 highest_end_offset_(0),
46 has_audio_(false), 82 has_audio_(false),
47 has_video_(false), 83 has_video_(false),
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 346
311 uint32_t audio_track_id = track->header.track_id; 347 uint32_t audio_track_id = track->header.track_id;
312 if (audio_track_ids_.find(audio_track_id) != audio_track_ids_.end()) { 348 if (audio_track_ids_.find(audio_track_id) != audio_track_ids_.end()) {
313 MEDIA_LOG(ERROR, media_log_) 349 MEDIA_LOG(ERROR, media_log_)
314 << "Audio track with track_id=" << audio_track_id 350 << "Audio track with track_id=" << audio_track_id
315 << " already present."; 351 << " already present.";
316 return false; 352 return false;
317 } 353 }
318 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; 354 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
319 is_track_encrypted_[audio_track_id] = is_track_encrypted; 355 is_track_encrypted_[audio_track_id] = is_track_encrypted;
320 audio_config.Initialize( 356 EncryptionScheme scheme = Unencrypted();
321 codec, sample_format, channel_layout, sample_per_second, extra_data, 357 if (is_track_encrypted) {
322 is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted(), 358 scheme = GetEncryptionScheme(entry.sinf);
323 base::TimeDelta(), 0); 359 if (!scheme.is_encrypted())
360 return false;
361 }
362 audio_config.Initialize(codec, sample_format, channel_layout,
363 sample_per_second, extra_data, scheme,
364 base::TimeDelta(), 0);
324 DVLOG(1) << "audio_track_id=" << audio_track_id 365 DVLOG(1) << "audio_track_id=" << audio_track_id
325 << " config=" << audio_config.AsHumanReadableString(); 366 << " config=" << audio_config.AsHumanReadableString();
326 if (!audio_config.IsValidConfig()) { 367 if (!audio_config.IsValidConfig()) {
327 MEDIA_LOG(ERROR, media_log_) << "Invalid audio decoder config: " 368 MEDIA_LOG(ERROR, media_log_) << "Invalid audio decoder config: "
328 << audio_config.AsHumanReadableString(); 369 << audio_config.AsHumanReadableString();
329 return false; 370 return false;
330 } 371 }
331 has_audio_ = true; 372 has_audio_ = true;
332 audio_track_ids_.insert(audio_track_id); 373 audio_track_ids_.insert(audio_track_id);
333 const char* track_kind = (audio_track_ids_.size() == 1 ? "main" : ""); 374 const char* track_kind = (audio_track_ids_.size() == 1 ? "main" : "");
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 412
372 uint32_t video_track_id = track->header.track_id; 413 uint32_t video_track_id = track->header.track_id;
373 if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) { 414 if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) {
374 MEDIA_LOG(ERROR, media_log_) 415 MEDIA_LOG(ERROR, media_log_)
375 << "Video track with track_id=" << video_track_id 416 << "Video track with track_id=" << video_track_id
376 << " already present."; 417 << " already present.";
377 return false; 418 return false;
378 } 419 }
379 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; 420 bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
380 is_track_encrypted_[video_track_id] = is_track_encrypted; 421 is_track_encrypted_[video_track_id] = is_track_encrypted;
381 video_config.Initialize( 422 EncryptionScheme scheme = Unencrypted();
382 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, 423 if (is_track_encrypted) {
383 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, 424 scheme = GetEncryptionScheme(entry.sinf);
384 // No decoder-specific buffer needed for AVC; 425 if (!scheme.is_encrypted())
385 // SPS/PPS are embedded in the video stream 426 return false;
386 EmptyExtraData(), 427 }
387 is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted()); 428 video_config.Initialize(entry.video_codec, entry.video_codec_profile,
429 PIXEL_FORMAT_YV12, COLOR_SPACE_HD_REC709,
430 coded_size, visible_rect, natural_size,
431 // No decoder-specific buffer needed for AVC;
432 // SPS/PPS are embedded in the video stream
433 EmptyExtraData(), scheme);
388 DVLOG(1) << "video_track_id=" << video_track_id 434 DVLOG(1) << "video_track_id=" << video_track_id
389 << " config=" << video_config.AsHumanReadableString(); 435 << " config=" << video_config.AsHumanReadableString();
390 if (!video_config.IsValidConfig()) { 436 if (!video_config.IsValidConfig()) {
391 MEDIA_LOG(ERROR, media_log_) << "Invalid video decoder config: " 437 MEDIA_LOG(ERROR, media_log_) << "Invalid video decoder config: "
392 << video_config.AsHumanReadableString(); 438 << video_config.AsHumanReadableString();
393 return false; 439 return false;
394 } 440 }
395 has_video_ = true; 441 has_video_ = true;
396 video_track_ids_.insert(video_track_id); 442 video_track_ids_.insert(video_track_id);
397 const char* track_kind = (video_track_ids_.size() == 1 ? "main" : ""); 443 const char* track_kind = (video_track_ids_.size() == 1 ? "main" : "");
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 !PrepareAACBuffer(runs_->audio_description().esds.aac, 661 !PrepareAACBuffer(runs_->audio_description().esds.aac,
616 &frame_buf, &subsamples)) { 662 &frame_buf, &subsamples)) {
617 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; 663 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode";
618 *err = true; 664 *err = true;
619 return false; 665 return false;
620 } 666 }
621 } 667 }
622 668
623 if (decrypt_config) { 669 if (decrypt_config) {
624 if (!subsamples.empty()) { 670 if (!subsamples.empty()) {
625 // Create a new config with the updated subsamples. 671 // Create a new config with the updated subsamples.
626 decrypt_config.reset(new DecryptConfig( 672 decrypt_config.reset(new DecryptConfig(decrypt_config->key_id(),
627 decrypt_config->key_id(), 673 decrypt_config->iv(), subsamples));
628 decrypt_config->iv(),
629 subsamples));
630 } 674 }
631 // else, use the existing config. 675 // else, use the existing config.
632 } else if (is_track_encrypted_[runs_->track_id()]) { 676 } else if (is_track_encrypted_[runs_->track_id()]) {
633 // The media pipeline requires a DecryptConfig with an empty |iv|. 677 // The media pipeline requires a DecryptConfig with an empty |iv|.
634 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); 678 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1");
635 decrypt_config.reset( 679 decrypt_config.reset(
636 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); 680 new DecryptConfig("1", "", std::vector<SubsampleEntry>()));
637 } 681 }
638 682
639 StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO : 683 StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO :
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 runs.AdvanceSample(); 775 runs.AdvanceSample();
732 } 776 }
733 runs.AdvanceRun(); 777 runs.AdvanceRun();
734 } 778 }
735 779
736 return true; 780 return true;
737 } 781 }
738 782
739 } // namespace mp4 783 } // namespace mp4
740 } // namespace media 784 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/mp4/fourccs.h ('k') | media/formats/mp4/track_run_iterator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698