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

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: ddorwin more detailed comments Created 4 years, 2 months 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
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;
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698