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

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: handle comments Created 4 years, 6 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
37 namespace {
38
39 EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) {
40 if (!sinf.HasSupportedScheme())
41 return Unencrypted();
ddorwin 2016/06/17 23:32:41 Is that the best way to handle this? We know it is
dougsteed 2016/10/10 18:18:01 Done.
42 FourCC fourCC = sinf.type.type;
43 EncryptionScheme::CipherMode mode = EncryptionScheme::CIPHER_MODE_UNENCRYPTED;
44 EncryptionScheme::Pattern pattern;
45 bool pattern_encryption = false;
ddorwin 2016/06/17 23:32:41 nit: is_/uses_...
dougsteed 2016/10/10 18:18:02 Done.
46 switch (fourCC) {
47 case FOURCC_CENC:
48 mode = EncryptionScheme::CIPHER_MODE_AES_CTR;
49 break;
50 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
51 case FOURCC_CBCS:
52 mode = EncryptionScheme::CIPHER_MODE_AES_CBC;
53 pattern_encryption = true;
54 break;
55 #endif
56 default:
57 DLOG(WARNING) << "Unsupported encryption scheme: " << fourCC;
ddorwin 2016/06/17 23:32:40 Should this be a DCHECK based on line 40?
dougsteed 2016/10/10 18:18:02 Done.
58 break;
59 }
60 #if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
61 if (pattern_encryption) {
62 uint8_t crypt = sinf.info.track_encryption.default_crypt_byte_block;
ddorwin 2016/06/17 23:32:40 ditto on "crypt"
dougsteed 2016/10/10 18:18:01 as mentioned above, this is the term used in the s
63 uint8_t skip = sinf.info.track_encryption.default_skip_byte_block;
64 pattern = EncryptionScheme::Pattern(crypt, skip);
65 }
66 #endif
67 return EncryptionScheme(mode, pattern);
68 }
69
70 } // namespace
71
36 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, 72 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
37 bool has_sbr) 73 bool has_sbr)
38 : state_(kWaitingForInit), 74 : state_(kWaitingForInit),
39 moof_head_(0), 75 moof_head_(0),
40 mdat_tail_(0), 76 mdat_tail_(0),
41 highest_end_offset_(0), 77 highest_end_offset_(0),
42 has_audio_(false), 78 has_audio_(false),
43 has_video_(false), 79 has_video_(false),
44 audio_track_id_(0), 80 audio_track_id_(0),
45 video_track_id_(0), 81 video_track_id_(0),
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 sample_format = kSampleFormatS32; 345 sample_format = kSampleFormatS32;
310 } else { 346 } else {
311 LOG(ERROR) << "Unsupported sample size."; 347 LOG(ERROR) << "Unsupported sample size.";
312 return false; 348 return false;
313 } 349 }
314 350
315 is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; 351 is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
316 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_; 352 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_;
317 audio_config.Initialize( 353 audio_config.Initialize(
318 codec, sample_format, channel_layout, sample_per_second, extra_data, 354 codec, sample_format, channel_layout, sample_per_second, extra_data,
319 is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(), 355 is_audio_track_encrypted_ ? GetEncryptionScheme(entry.sinf)
ddorwin 2016/06/17 23:32:40 Continuing from line 41, we know it's encrypted, b
dougsteed 2016/10/10 18:18:01 Done.
356 : Unencrypted(),
320 base::TimeDelta(), 0); 357 base::TimeDelta(), 0);
321 has_audio_ = true; 358 has_audio_ = true;
322 audio_track_id_ = track->header.track_id; 359 audio_track_id_ = track->header.track_id;
323 media_tracks->AddAudioTrack( 360 media_tracks->AddAudioTrack(
324 audio_config, base::UintToString(audio_track_id_), "main", 361 audio_config, base::UintToString(audio_track_id_), "main",
325 track->media.handler.name, track->media.header.language()); 362 track->media.handler.name, track->media.header.language());
326 continue; 363 continue;
327 } 364 }
328 365
329 if (track->media.handler.type == kVideo) { 366 if (track->media.handler.type == kVideo) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 } 398 }
362 399
363 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; 400 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
364 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; 401 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
365 video_config.Initialize( 402 video_config.Initialize(
366 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, 403 entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12,
367 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, 404 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size,
368 // No decoder-specific buffer needed for AVC; 405 // No decoder-specific buffer needed for AVC;
369 // SPS/PPS are embedded in the video stream 406 // SPS/PPS are embedded in the video stream
370 EmptyExtraData(), 407 EmptyExtraData(),
371 is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted()); 408 is_video_track_encrypted_ ? GetEncryptionScheme(entry.sinf)
409 : Unencrypted());
372 has_video_ = true; 410 has_video_ = true;
373 video_track_id_ = track->header.track_id; 411 video_track_id_ = track->header.track_id;
374 media_tracks->AddVideoTrack( 412 media_tracks->AddVideoTrack(
375 video_config, base::UintToString(video_track_id_), "main", 413 video_config, base::UintToString(video_track_id_), "main",
376 track->media.handler.name, track->media.header.language()); 414 track->media.handler.name, track->media.header.language());
377 continue; 415 continue;
378 } 416 }
379 417
380 // TODO(wolenetz): Investigate support in MSE and Chrome MSE for CEA 608/708 418 // 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 419 // 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
567 !PrepareAACBuffer(runs_->audio_description().esds.aac, 605 !PrepareAACBuffer(runs_->audio_description().esds.aac,
568 &frame_buf, &subsamples)) { 606 &frame_buf, &subsamples)) {
569 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode"; 607 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode";
570 *err = true; 608 *err = true;
571 return false; 609 return false;
572 } 610 }
573 } 611 }
574 612
575 if (decrypt_config) { 613 if (decrypt_config) {
576 if (!subsamples.empty()) { 614 if (!subsamples.empty()) {
577 // Create a new config with the updated subsamples. 615 // Create a new config with the updated subsamples.
578 decrypt_config.reset(new DecryptConfig( 616 decrypt_config.reset(new DecryptConfig(decrypt_config->key_id(),
579 decrypt_config->key_id(), 617 decrypt_config->iv(), subsamples));
580 decrypt_config->iv(),
581 subsamples));
582 } 618 }
583 // else, use the existing config. 619 // else, use the existing config.
584 } else if ((audio && is_audio_track_encrypted_) || 620 } else if ((audio && is_audio_track_encrypted_) ||
585 (video && is_video_track_encrypted_)) { 621 (video && is_video_track_encrypted_)) {
586 // The media pipeline requires a DecryptConfig with an empty |iv|. 622 // The media pipeline requires a DecryptConfig with an empty |iv|.
587 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); 623 // TODO(ddorwin): Refactor so we do not need a fake key ID ("1");
588 decrypt_config.reset( 624 decrypt_config.reset(
589 new DecryptConfig("1", "", std::vector<SubsampleEntry>())); 625 new DecryptConfig("1", "", std::vector<SubsampleEntry>()));
590 } 626 }
591 627
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 runs.AdvanceSample(); 734 runs.AdvanceSample();
699 } 735 }
700 runs.AdvanceRun(); 736 runs.AdvanceRun();
701 } 737 }
702 738
703 return true; 739 return true;
704 } 740 }
705 741
706 } // namespace mp4 742 } // namespace mp4
707 } // namespace media 743 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698