diff --git a/app/packager_main.cc b/app/packager_main.cc index 95d5985ed8..1c24408f30 100644 --- a/app/packager_main.cc +++ b/app/packager_main.cc @@ -211,15 +211,8 @@ bool RunPackager(const std::string& input) { encryption_key_source = CreateEncryptionKeySource(); if (!encryption_key_source) return false; - EncryptionKeySource::TrackType track_type = - EncryptionKeySource::GetTrackTypeFromString(FLAGS_track_type); - if (track_type != EncryptionKeySource::TRACK_TYPE_SD && - track_type != EncryptionKeySource::TRACK_TYPE_HD) { - LOG(ERROR) << "FLAGS_track_type should be either 'SD' or 'HD'"; - return false; - } muxer->SetEncryptionKeySource(encryption_key_source.get(), - track_type, + FLAGS_max_sd_pixels, FLAGS_clear_lead, FLAGS_crypto_period_duration); } diff --git a/app/widevine_encryption_flags.h b/app/widevine_encryption_flags.h index 1c269bb983..d1bdd756e3 100644 --- a/app/widevine_encryption_flags.h +++ b/app/widevine_encryption_flags.h @@ -20,7 +20,10 @@ DEFINE_bool(enable_widevine_encryption, "--aes_signing_iv) or RSA signing key (--rsa_signing_key_path)."); DEFINE_string(server_url, "", "License server url."); DEFINE_string(content_id, "", "Content Id."); -DEFINE_string(track_type, "SD", "Track type: SD or HD."); +DEFINE_int32(max_sd_pixels, + 768 * 576, + "If the video track has more pixels per frame than max_sd_pixels, " + "it is considered as HD, SD otherwise. Default: 768 * 576."); DEFINE_string(signer, "", "The name of the signer."); DEFINE_string(aes_signing_key, "", @@ -43,6 +46,10 @@ static bool IsNotEmptyWithWidevineEncryption(const char* flag_name, return FLAGS_enable_widevine_encryption ? !flag_value.empty() : true; } +static bool IsPositive(const char* flag_name, int flag_value) { + return flag_value > 0; +} + static bool VerifyAesRsaKey(const char* flag_name, const std::string& flag_value) { if (!FLAGS_enable_widevine_encryption) @@ -78,8 +85,7 @@ static bool dummy_content_id_validator = google::RegisterFlagValidator(&FLAGS_content_id, &IsNotEmptyWithWidevineEncryption); static bool dummy_track_type_validator = - google::RegisterFlagValidator(&FLAGS_track_type, - &IsNotEmptyWithWidevineEncryption); + google::RegisterFlagValidator(&FLAGS_max_sd_pixels, &IsPositive); static bool dummy_signer_validator = google::RegisterFlagValidator(&FLAGS_signer, &IsNotEmptyWithWidevineEncryption); diff --git a/media/base/muxer.cc b/media/base/muxer.cc index 4f18f1add9..4edf50117c 100644 --- a/media/base/muxer.cc +++ b/media/base/muxer.cc @@ -6,7 +6,6 @@ #include "media/base/muxer.h" -#include "media/base/encryption_key_source.h" #include "media/base/media_sample.h" #include "media/base/media_stream.h" @@ -16,7 +15,7 @@ Muxer::Muxer(const MuxerOptions& options) : options_(options), initialized_(false), encryption_key_source_(NULL), - track_type_(EncryptionKeySource::TRACK_TYPE_SD), + max_sd_pixels_(0), clear_lead_in_seconds_(0), crypto_period_duration_in_seconds_(0), muxer_listener_(NULL), @@ -25,12 +24,12 @@ Muxer::Muxer(const MuxerOptions& options) Muxer::~Muxer() {} void Muxer::SetEncryptionKeySource(EncryptionKeySource* encryption_key_source, - EncryptionKeySource::TrackType track_type, + uint32 max_sd_pixels, double clear_lead_in_seconds, double crypto_period_duration_in_seconds) { DCHECK(encryption_key_source); encryption_key_source_ = encryption_key_source; - track_type_ = track_type; + max_sd_pixels_ = max_sd_pixels; clear_lead_in_seconds_ = clear_lead_in_seconds; crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds; } diff --git a/media/base/muxer.h b/media/base/muxer.h index 1a2093ecc0..fe46fb712a 100644 --- a/media/base/muxer.h +++ b/media/base/muxer.h @@ -13,7 +13,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "media/base/encryption_key_source.h" #include "media/base/muxer_options.h" #include "media/base/status.h" @@ -42,14 +41,15 @@ class Muxer { /// Set encryption key source. /// @param encryption_key_source points to the encryption key source to be /// injected. Should not be NULL. - /// @param track_type should be either SD or HD. It affects whether SD key or - /// HD key is used to encrypt the video content. + /// @param max_sd_pixels specifies the threshold to determine whether a video + /// track should be considered as SD or HD. If the track has more + /// pixels per frame than max_sd_pixels, it is HD, SD otherwise. /// @param clear_lead_in_seconds specifies clear lead duration in seconds. /// @param crypto_period_duration_in_seconds specifies crypto period duration /// in seconds. A positive value means key rotation is enabled, the /// key source must support key rotation in this case. void SetEncryptionKeySource(EncryptionKeySource* encryption_key_source, - EncryptionKeySource::TrackType track_type, + uint32 max_sd_pixels, double clear_lead_in_seconds, double crypto_period_duration_in_seconds); @@ -80,7 +80,7 @@ class Muxer { EncryptionKeySource* encryption_key_source() { return encryption_key_source_; } - EncryptionKeySource::TrackType track_type() const { return track_type_; } + uint32 max_sd_pixels() const { return max_sd_pixels_; } double clear_lead_in_seconds() const { return clear_lead_in_seconds_; } double crypto_period_duration_in_seconds() const { return crypto_period_duration_in_seconds_; @@ -109,7 +109,7 @@ class Muxer { bool initialized_; std::vector streams_; EncryptionKeySource* encryption_key_source_; - EncryptionKeySource::TrackType track_type_; + uint32 max_sd_pixels_; double clear_lead_in_seconds_; double crypto_period_duration_in_seconds_; diff --git a/media/formats/mp4/mp4_muxer.cc b/media/formats/mp4/mp4_muxer.cc index d0c2957dc9..e1b00e5586 100644 --- a/media/formats/mp4/mp4_muxer.cc +++ b/media/formats/mp4/mp4_muxer.cc @@ -101,7 +101,7 @@ Status MP4Muxer::Initialize() { Status segmenter_initialized = segmenter_->Initialize(streams(), encryption_key_source(), - track_type(), + max_sd_pixels(), clear_lead_in_seconds(), crypto_period_duration_in_seconds()); diff --git a/media/formats/mp4/segmenter.cc b/media/formats/mp4/segmenter.cc index 14f03be8c1..ae851b3e71 100644 --- a/media/formats/mp4/segmenter.cc +++ b/media/formats/mp4/segmenter.cc @@ -86,6 +86,27 @@ void GenerateEncryptedSampleEntryForKeyRotation( encryption_key, clear_lead_in_seconds, description); } +uint8 GetNaluLengthSize(const StreamInfo& stream_info) { + if (stream_info.stream_type() != kStreamVideo) + return 0; + const VideoStreamInfo& video_stream_info = + static_cast(stream_info); + return video_stream_info.nalu_length_size(); +} + +EncryptionKeySource::TrackType GetTrackTypeForEncryption( + const StreamInfo& stream_info, uint32 max_sd_pixels) { + if (stream_info.stream_type() == kStreamAudio) + return EncryptionKeySource::TRACK_TYPE_AUDIO; + + DCHECK_EQ(kStreamVideo, stream_info.stream_type()); + const VideoStreamInfo& video_stream_info = + static_cast(stream_info); + uint32 pixels = video_stream_info.width() * video_stream_info.height(); + return (pixels > max_sd_pixels) ? EncryptionKeySource::TRACK_TYPE_HD + : EncryptionKeySource::TRACK_TYPE_SD; +} + } // namespace Segmenter::Segmenter(const MuxerOptions& options, @@ -104,7 +125,7 @@ Segmenter::~Segmenter() { STLDeleteElements(&fragmenters_); } Status Segmenter::Initialize(const std::vector& streams, EncryptionKeySource* encryption_key_source, - EncryptionKeySource::TrackType track_type, + uint32 max_sd_pixels, double clear_lead_in_seconds, double crypto_period_duration_in_seconds) { DCHECK_LT(0u, streams.size()); @@ -116,29 +137,22 @@ Status Segmenter::Initialize(const std::vector& streams, for (uint32 i = 0; i < streams.size(); ++i) { stream_map_[streams[i]] = i; moof_->tracks[i].header.track_id = i + 1; - uint8 nalu_length_size = 0; if (streams[i]->info()->stream_type() == kStreamVideo) { - VideoStreamInfo* video = - static_cast(streams[i]->info().get()); - nalu_length_size = video->nalu_length_size(); - // We use the first video stream as the reference stream. + // Use the first video stream as the reference stream (which is 1-based). if (sidx_->reference_id == 0) sidx_->reference_id = i + 1; } - if (!encryption_key_source) { fragmenters_[i] = new Fragmenter( &moof_->tracks[i], options_.normalize_presentation_timestamp); continue; } - DCHECK(track_type == EncryptionKeySource::TRACK_TYPE_SD || - track_type == EncryptionKeySource::TRACK_TYPE_HD); + uint8 nalu_length_size = GetNaluLengthSize(*streams[i]->info()); + EncryptionKeySource::TrackType track_type = + GetTrackTypeForEncryption(*streams[i]->info(), max_sd_pixels); SampleDescription& description = moov_->tracks[i].media.information.sample_table.description; - EncryptionKeySource::TrackType cur_track_type = - description.type == kAudio ? EncryptionKeySource::TRACK_TYPE_AUDIO - : track_type; const bool key_rotation_enabled = crypto_period_duration_in_seconds != 0; if (key_rotation_enabled) { @@ -150,7 +164,7 @@ Status Segmenter::Initialize(const std::vector& streams, &moof_->tracks[i], options_.normalize_presentation_timestamp, encryption_key_source, - cur_track_type, + track_type, crypto_period_duration_in_seconds * streams[i]->info()->time_scale(), clear_lead_in_seconds * streams[i]->info()->time_scale(), nalu_length_size); @@ -159,7 +173,7 @@ Status Segmenter::Initialize(const std::vector& streams, scoped_ptr encryption_key(new EncryptionKey()); Status status = - encryption_key_source->GetKey(cur_track_type, encryption_key.get()); + encryption_key_source->GetKey(track_type, encryption_key.get()); if (!status.ok()) return status; diff --git a/media/formats/mp4/segmenter.h b/media/formats/mp4/segmenter.h index 57f69077fe..4fc23d3fcb 100644 --- a/media/formats/mp4/segmenter.h +++ b/media/formats/mp4/segmenter.h @@ -12,7 +12,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "media/base/encryption_key_source.h" #include "media/base/status.h" namespace media { @@ -53,14 +52,15 @@ class Segmenter { /// @param encryption_key_source points to the key source which contains /// the encryption keys. It can be NULL to indicate that no encryption /// is required. - /// @param track_type indicates whether SD key or HD key should be used to - /// encrypt the video content. + /// @param max_sd_pixels specifies the threshold to determine whether a video + /// track should be considered as SD or HD. If the track has more + /// pixels per frame than max_sd_pixels, it is HD, SD otherwise. /// @param clear_time specifies clear lead duration in seconds. /// @param crypto_period_duration specifies crypto period duration in seconds. /// @return OK on success, an error status otherwise. Status Initialize(const std::vector& streams, EncryptionKeySource* encryption_key_source, - EncryptionKeySource::TrackType track_type, + uint32 max_sd_pixels, double clear_lead_in_seconds, double crypto_period_duration_in_seconds);