diff --git a/README.md b/README.md index 209b82a794..6295144a1f 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,14 @@ Demuxer demuxer(input_media_file); // Users may use WidevineKeySource to fetch keys from Widevine // common encryption server. -// A request signer is required to sign the common encryption request. -scoped_ptr signer( - RsaRequestSigner::CreateSigner(signer, pkcs1_rsa_private_key)); -if (!signer) { … } - scoped_ptr widevine_decryption_key_source( - new WidevineKeySource(key_server_url, signer.Pass())); + new WidevineKeySource(key_server_url)); + +// A request signer might be required to sign the common encryption request. +scoped_ptr signer( + RsaRequestSigner::CreateSigner(signer_name, pkcs1_rsa_private_key)); +if (!signer) { … } +widevine_decryption_key_source->set_signer(signer.Pass()); // Set encryption key source to demuxer. muxer->SetKeySource(widevine_decryption_key_source.Pass()); @@ -234,14 +235,15 @@ muxer_options.bandwidth = 0; // Users may use WidevineKeySource to fetch keys from Widevine // common encryption server. -// A request signer is required to sign the common encryption request. -scoped_ptr signer( - RsaRequestSigner::CreateSigner(signer, pkcs1_rsa_private_key)); -if (!signer) { … } - scoped_ptr widevine_encryption_key_source( new WidevineKeySource(key_server_url, signer.Pass())); +// A request signer might be required to sign the common encryption request. +scoped_ptr signer( + RsaRequestSigner::CreateSigner(signer_name, pkcs1_rsa_private_key)); +if (!signer) { … } +widevine_encryption_key_source->set_signer(signer.Pass()); + // Grab keys for the content. status = widevine_encryption_key_source->FetchKeys(content_id, policy)); if (!status.ok()) { … } diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 04acf761d4..62e1b55699 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -127,7 +127,13 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, if (stream_iter->input != previous_input) { // New remux job needed. Create demux and job thread. scoped_ptr demuxer(new Demuxer(stream_iter->input)); - demuxer->SetKeySource(CreateDecryptionKeySource()); + if (FLAGS_enable_widevine_decryption || + FLAGS_enable_fixed_key_decryption) { + scoped_ptr key_source(CreateDecryptionKeySource()); + if (!key_source) + return false; + demuxer->SetKeySource(key_source.Pass()); + } Status status = demuxer->Initialize(); if (!status.ok()) { LOG(ERROR) << "Demuxer failed to initialize: " << status.ToString(); diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 556bbf1ba4..8feedb08eb 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -66,23 +66,27 @@ scoped_ptr CreateSigner() { scoped_ptr CreateEncryptionKeySource() { scoped_ptr encryption_key_source; if (FLAGS_enable_widevine_encryption) { - scoped_ptr signer(CreateSigner()); + scoped_ptr widevine_key_source( + new WidevineKeySource(FLAGS_key_server_url)); + if (!FLAGS_signer.empty()) { + scoped_ptr request_signer(CreateSigner()); + if (!request_signer) + return scoped_ptr(); + widevine_key_source->set_signer(request_signer.Pass()); + } + std::vector content_id; if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) { LOG(ERROR) << "Invalid content_id hex string specified."; return scoped_ptr(); } - scoped_ptr widevine_encryption_key_source( - new WidevineKeySource(FLAGS_key_server_url, - signer.Pass())); - Status status = widevine_encryption_key_source->FetchKeys(content_id, - FLAGS_policy); + Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy); if (!status.ok()) { LOG(ERROR) << "Widevine encryption key source failed to fetch keys: " << status.ToString(); return scoped_ptr(); } - encryption_key_source = widevine_encryption_key_source.Pass(); + encryption_key_source = widevine_key_source.Pass(); } else if (FLAGS_enable_fixed_key_encryption) { encryption_key_source = KeySource::CreateFromHexStrings( FLAGS_key_id, FLAGS_key, FLAGS_pssh, ""); @@ -93,12 +97,19 @@ scoped_ptr CreateEncryptionKeySource() { scoped_ptr CreateDecryptionKeySource() { scoped_ptr decryption_key_source; if (FLAGS_enable_widevine_decryption) { - scoped_ptr signer(CreateSigner()); - decryption_key_source.reset(new WidevineKeySource(FLAGS_key_server_url, - signer.Pass())); + scoped_ptr widevine_key_source( + new WidevineKeySource(FLAGS_key_server_url)); + if (!FLAGS_signer.empty()) { + scoped_ptr request_signer(CreateSigner()); + if (!request_signer) + return scoped_ptr(); + widevine_key_source->set_signer(request_signer.Pass()); + } + + decryption_key_source = widevine_key_source.Pass(); } else if (FLAGS_enable_fixed_key_decryption) { - decryption_key_source = KeySource::CreateFromHexStrings( - FLAGS_key_id, FLAGS_key, "", ""); + decryption_key_source = + KeySource::CreateFromHexStrings(FLAGS_key_id, FLAGS_key, "", ""); } return decryption_key_source.Pass(); } diff --git a/packager/media/base/widevine_key_source.cc b/packager/media/base/widevine_key_source.cc index e6225c197a..5288953e86 100644 --- a/packager/media/base/widevine_key_source.cc +++ b/packager/media/base/widevine_key_source.cc @@ -136,14 +136,12 @@ class WidevineKeySource::RefCountedEncryptionKeyMap DISALLOW_COPY_AND_ASSIGN(RefCountedEncryptionKeyMap); }; -WidevineKeySource::WidevineKeySource(const std::string& server_url, - scoped_ptr signer) +WidevineKeySource::WidevineKeySource(const std::string& server_url) : key_production_thread_("KeyProductionThread", base::Bind(&WidevineKeySource::FetchKeysTask, base::Unretained(this))), key_fetcher_(new HttpKeyFetcher(kKeyFetchTimeoutInSeconds)), server_url_(server_url), - signer_(signer.Pass()), crypto_period_count_(kDefaultCryptoPeriodCount), key_production_started_(false), start_key_production_(false, false), @@ -248,8 +246,11 @@ Status WidevineKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index, return GetKeyInternal(crypto_period_index, track_type, key); } -void WidevineKeySource::set_key_fetcher( - scoped_ptr key_fetcher) { +void WidevineKeySource::set_signer(scoped_ptr signer) { + signer_ = signer.Pass(); +} + +void WidevineKeySource::set_key_fetcher(scoped_ptr key_fetcher) { key_fetcher_ = key_fetcher.Pass(); } diff --git a/packager/media/base/widevine_key_source.h b/packager/media/base/widevine_key_source.h index a777e88c30..090b951b79 100644 --- a/packager/media/base/widevine_key_source.h +++ b/packager/media/base/widevine_key_source.h @@ -26,9 +26,7 @@ template class ProducerConsumerQueue; class WidevineKeySource : public KeySource { public: /// @param server_url is the Widevine common encryption server url. - /// @param signer signs the request message. Can be NULL. - WidevineKeySource(const std::string& server_url, - scoped_ptr signer); + WidevineKeySource(const std::string& server_url); virtual ~WidevineKeySource(); @@ -47,6 +45,10 @@ class WidevineKeySource : public KeySource { EncryptionKey* key) OVERRIDE; /// @} + /// Set signer for the key source. + /// @param signer signs the request message. + void set_signer(scoped_ptr signer); + /// Inject an @b KeyFetcher object, mainly used for testing. /// @param key_fetcher points to the @b KeyFetcher object to be injected. void set_key_fetcher(scoped_ptr key_fetcher); diff --git a/packager/media/base/widevine_key_source_unittest.cc b/packager/media/base/widevine_key_source_unittest.cc index 97d5244ae9..45160a1498 100644 --- a/packager/media/base/widevine_key_source_unittest.cc +++ b/packager/media/base/widevine_key_source_unittest.cc @@ -156,9 +156,8 @@ class WidevineKeySourceTest : public ::testing::Test { } protected: - void CreateWidevineKeySource(scoped_ptr request_signer) { - widevine_key_source_.reset( - new WidevineKeySource(kServerUrl, request_signer.Pass())); + void CreateWidevineKeySource() { + widevine_key_source_.reset(new WidevineKeySource(kServerUrl)); widevine_key_source_->set_key_fetcher( mock_key_fetcher_.PassAs()); } @@ -203,7 +202,9 @@ TEST_F(WidevineKeySourceTest, GenerateSignatureFailure) { EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _)) .WillOnce(Return(false)); - CreateWidevineKeySource(mock_request_signer_.PassAs()); + CreateWidevineKeySource(); + widevine_key_source_->set_signer( + mock_request_signer_.PassAs()); ASSERT_EQ(Status(error::INTERNAL_ERROR, "Signature generation failed."), widevine_key_source_->FetchKeys(content_id_, kPolicy)); } @@ -226,7 +227,9 @@ TEST_F(WidevineKeySourceTest, HttpFetchFailure) { FetchKeys(StrEq(kServerUrl), expected_post_data, _)) .WillOnce(Return(kMockStatus)); - CreateWidevineKeySource(mock_request_signer_.PassAs()); + CreateWidevineKeySource(); + widevine_key_source_->set_signer( + mock_request_signer_.PassAs()); ASSERT_EQ(kMockStatus, widevine_key_source_->FetchKeys(content_id_, kPolicy)); } @@ -238,7 +241,7 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencOK) { EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy)); VerifyKeys(false); } @@ -251,7 +254,7 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencNotOK) { EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_EQ(error::SERVER_ERROR, widevine_key_source_->FetchKeys(content_id_, kPolicy) .error_code()); @@ -264,7 +267,7 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencWithPsshDataOK) { EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); std::vector pssh_data( reinterpret_cast(kRequestPsshData), reinterpret_cast(kRequestPsshData) + strlen(kContentId)); @@ -280,7 +283,7 @@ TEST_F(WidevineKeySourceTest, LicenseStatusClassicOK) { EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_OK(widevine_key_source_->FetchKeys(kClassicAssetId)); VerifyKeys(true); } @@ -294,7 +297,7 @@ TEST_F(WidevineKeySourceTest, RetryOnHttpTimeout) { .WillOnce(Return(Status(error::TIME_OUT, ""))) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy)); VerifyKeys(false); } @@ -314,7 +317,7 @@ TEST_F(WidevineKeySourceTest, RetryOnTransientError) { .WillOnce(DoAll(SetArgPointee<2>(expected_retried_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy)); VerifyKeys(false); } @@ -328,7 +331,7 @@ TEST_F(WidevineKeySourceTest, NoRetryOnUnknownError) { EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); - CreateWidevineKeySource(scoped_ptr()); + CreateWidevineKeySource(); ASSERT_EQ(error::SERVER_ERROR, widevine_key_source_->FetchKeys(content_id_, kPolicy).error_code()); } @@ -413,7 +416,9 @@ TEST_F(WidevineKeySourceTest, KeyRotationTest) { .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); } - CreateWidevineKeySource(mock_request_signer_.PassAs()); + CreateWidevineKeySource(); + widevine_key_source_->set_signer( + mock_request_signer_.PassAs()); ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy)); EncryptionKey encryption_key;