From f3e91301c2cc1ffece3edd0ea800aaee3d9ef3c2 Mon Sep 17 00:00:00 2001 From: Rintaro Kuroiwa Date: Tue, 4 Apr 2017 14:01:10 -0700 Subject: [PATCH] Widevine HLS new key format media event side - This change has the muxer listener side changes. - Also changed SetContentProtectionFields() to take vector for default_key_id so that MuxerListener subclasses don't need to convert it to string. Change-Id: I8832848a0c7e34b84e2b4e6baeba364861900ff1 --- .../media/event/hls_notify_muxer_listener.cc | 10 +++- .../media/event/hls_notify_muxer_listener.h | 1 + .../hls_notify_muxer_listener_unittest.cc | 55 +++++++++++++++++-- .../media/event/mpd_notify_muxer_listener.cc | 2 +- .../media/event/mpd_notify_muxer_listener.h | 2 +- .../media/event/muxer_listener_internal.cc | 11 ++-- .../media/event/muxer_listener_internal.h | 2 +- .../vod_media_info_dump_muxer_listener.cc | 2 +- .../vod_media_info_dump_muxer_listener.h | 2 +- 9 files changed, 68 insertions(+), 19 deletions(-) diff --git a/packager/media/event/hls_notify_muxer_listener.cc b/packager/media/event/hls_notify_muxer_listener.cc index a7b0d9bf7b..8aa6d08ae3 100644 --- a/packager/media/event/hls_notify_muxer_listener.cc +++ b/packager/media/event/hls_notify_muxer_listener.cc @@ -49,11 +49,12 @@ void HlsNotifyMuxerListener::OnEncryptionInfoReady( next_key_id_ = key_id; next_iv_ = iv; next_key_system_infos_ = key_system_infos; + protection_scheme_ = protection_scheme; return; } for (const ProtectionSystemSpecificInfo& info : key_system_infos) { const bool result = hls_notifier_->NotifyEncryptionUpdate( - stream_id_, key_id, info.system_id(), iv, info.pssh_data()); + stream_id_, key_id, info.system_id(), iv, info.CreateBox()); LOG_IF(WARNING, !result) << "Failed to add encryption info."; } } @@ -72,7 +73,7 @@ void HlsNotifyMuxerListener::OnEncryptionStart() { for (const ProtectionSystemSpecificInfo& info : next_key_system_infos_) { const bool result = hls_notifier_->NotifyEncryptionUpdate( stream_id_, next_key_id_, info.system_id(), next_iv_, - info.pssh_data()); + info.CreateBox()); LOG_IF(WARNING, !result) << "Failed to add encryption info"; } next_key_id_.clear(); @@ -91,6 +92,11 @@ void HlsNotifyMuxerListener::OnMediaStart(const MuxerOptions& muxer_options, LOG(ERROR) << "Failed to generate MediaInfo from input."; return; } + if (protection_scheme_ != FOURCC_NULL) { + internal::SetContentProtectionFields(protection_scheme_, next_key_id_, + next_key_system_infos_, &media_info); + } + const bool result = hls_notifier_->NotifyNewStream( media_info, playlist_name_, ext_x_media_name_, ext_x_media_group_id_, &stream_id_); diff --git a/packager/media/event/hls_notify_muxer_listener.h b/packager/media/event/hls_notify_muxer_listener.h index e1cb61e947..f2fac026bc 100644 --- a/packager/media/event/hls_notify_muxer_listener.h +++ b/packager/media/event/hls_notify_muxer_listener.h @@ -78,6 +78,7 @@ class HlsNotifyMuxerListener : public MuxerListener { std::vector next_key_id_; std::vector next_iv_; std::vector next_key_system_infos_; + FourCC protection_scheme_ = FOURCC_NULL; DISALLOW_COPY_AND_ASSIGN(HlsNotifyMuxerListener); }; diff --git a/packager/media/event/hls_notify_muxer_listener_unittest.cc b/packager/media/event/hls_notify_muxer_listener_unittest.cc index 11e6d9b734..134d912e9d 100644 --- a/packager/media/event/hls_notify_muxer_listener_unittest.cc +++ b/packager/media/event/hls_notify_muxer_listener_unittest.cc @@ -69,6 +69,17 @@ const char kDefaultPlaylistName[] = "default_playlist.m3u8"; const char kDefaultName[] = "DEFAULTNAME"; const char kDefaultGroupId[] = "DEFAULTGROUPID"; +MATCHER_P(HasEncryptionScheme, expected_scheme, "") { + *result_listener << "it has_protected_content: " + << arg.has_protected_content() << " has_protection_scheme: " + << arg.protected_content().has_protection_scheme() + << " protection_scheme: " + << arg.protected_content().protection_scheme(); + return arg.has_protected_content() && + arg.protected_content().has_protection_scheme() && + arg.protected_content().protection_scheme() == expected_scheme; +} + } // namespace class HlsNotifyMuxerListenerTest : public ::testing::Test { @@ -152,8 +163,8 @@ TEST_F(HlsNotifyMuxerListenerTest, OnEncryptionStart) { MuxerListener::kContainerMpeg2ts); ::testing::Mock::VerifyAndClearExpectations(&mock_notifier_); - EXPECT_CALL(mock_notifier_, - NotifyEncryptionUpdate(_, key_id, system_id, iv, pssh_data)) + EXPECT_CALL(mock_notifier_, NotifyEncryptionUpdate(_, key_id, system_id, iv, + info.CreateBox())) .WillOnce(Return(true)); listener_.OnEncryptionStart(); } @@ -190,8 +201,8 @@ TEST_F(HlsNotifyMuxerListenerTest, OnEncryptionStartBeforeMediaStart) { // It doesn't really matter when this is called, could be called right away in // OnEncryptionStart() if that is possible. Just matters that it is called by // the time OnMediaStart() returns. - EXPECT_CALL(mock_notifier_, - NotifyEncryptionUpdate(_, key_id, system_id, iv, pssh_data)) + EXPECT_CALL(mock_notifier_, NotifyEncryptionUpdate(_, key_id, system_id, iv, + info.CreateBox())) .WillOnce(Return(true)); listener_.OnEncryptionStart(); listener_.OnMediaStart(muxer_options, *video_stream_info, 90000, @@ -256,13 +267,45 @@ TEST_F(HlsNotifyMuxerListenerTest, OnEncryptionInfoReady) { std::vector iv(16, 0x54); - EXPECT_CALL(mock_notifier_, - NotifyEncryptionUpdate(_, key_id, system_id, iv, pssh_data)) + EXPECT_CALL(mock_notifier_, NotifyEncryptionUpdate(_, key_id, system_id, iv, + info.CreateBox())) .WillOnce(Return(true)); listener_.OnEncryptionInfoReady(kInitialEncryptionInfo, FOURCC_cbcs, key_id, iv, key_system_infos); } +// Verify that if protection scheme is specified in OnEncryptionInfoReady(), +// the information is copied to MediaInfo in OnMediaStart(). +TEST_F(HlsNotifyMuxerListenerTest, OnEncryptionInfoReadyWithProtectionScheme) { + ProtectionSystemSpecificInfo info; + std::vector system_id(kAnySystemId, + kAnySystemId + arraysize(kAnySystemId)); + info.set_system_id(system_id.data(), system_id.size()); + std::vector pssh_data(kAnyData, kAnyData + arraysize(kAnyData)); + info.set_pssh_data(pssh_data); + + std::vector key_id(16, 0x05); + std::vector key_system_infos; + key_system_infos.push_back(info); + + std::vector iv(16, 0x54); + + listener_.OnEncryptionInfoReady(kInitialEncryptionInfo, FOURCC_cenc, key_id, + iv, key_system_infos); + ::testing::Mock::VerifyAndClearExpectations(&mock_notifier_); + + ON_CALL(mock_notifier_, + NotifyNewStream(HasEncryptionScheme("cenc"), _, _, _, _)) + .WillByDefault(Return(true)); + VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); + std::shared_ptr video_stream_info = + CreateVideoStreamInfo(video_params); + MuxerOptions muxer_options; + + listener_.OnMediaStart(muxer_options, *video_stream_info, 90000, + MuxerListener::kContainerMpeg2ts); +} + // Make sure it doesn't crash. TEST_F(HlsNotifyMuxerListenerTest, OnSampleDurationReady) { listener_.OnSampleDurationReady(2340); diff --git a/packager/media/event/mpd_notify_muxer_listener.cc b/packager/media/event/mpd_notify_muxer_listener.cc index 6838372918..23806e832a 100644 --- a/packager/media/event/mpd_notify_muxer_listener.cc +++ b/packager/media/event/mpd_notify_muxer_listener.cc @@ -38,7 +38,7 @@ void MpdNotifyMuxerListener::OnEncryptionInfoReady( LOG_IF(WARNING, is_encrypted_) << "Updating initial encryption information."; protection_scheme_ = protection_scheme; - default_key_id_.assign(key_id.begin(), key_id.end()); + default_key_id_ = key_id; key_system_info_ = key_system_info; is_encrypted_ = true; return; diff --git a/packager/media/event/mpd_notify_muxer_listener.h b/packager/media/event/mpd_notify_muxer_listener.h index b119559bec..ed09ebb4a8 100644 --- a/packager/media/event/mpd_notify_muxer_listener.h +++ b/packager/media/event/mpd_notify_muxer_listener.h @@ -74,7 +74,7 @@ class MpdNotifyMuxerListener : public MuxerListener { bool is_encrypted_; // Storage for values passed to OnEncryptionInfoReady(). FourCC protection_scheme_; - std::string default_key_id_; + std::vector default_key_id_; std::vector key_system_info_; // Saves all the subsegment information for VOD. This should be used to call diff --git a/packager/media/event/muxer_listener_internal.cc b/packager/media/event/muxer_listener_internal.cc index 23f949befd..65faf21cae 100644 --- a/packager/media/event/muxer_listener_internal.cc +++ b/packager/media/event/muxer_listener_internal.cc @@ -241,19 +241,18 @@ bool SetVodInformation(bool has_init_range, void SetContentProtectionFields( FourCC protection_scheme, - const std::string& default_key_id, + const std::vector& default_key_id, const std::vector& key_system_info, MediaInfo* media_info) { DCHECK(media_info); MediaInfo::ProtectedContent* protected_content = media_info->mutable_protected_content(); - - DCHECK(protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cbc1 || - protection_scheme == FOURCC_cens || protection_scheme == FOURCC_cbcs); protected_content->set_protection_scheme(FourCCToString(protection_scheme)); - if (!default_key_id.empty()) - protected_content->set_default_key_id(default_key_id); + if (!default_key_id.empty()) { + protected_content->set_default_key_id(default_key_id.data(), + default_key_id.size()); + } for (const ProtectionSystemSpecificInfo& info : key_system_info) { MediaInfo::ProtectedContent::ContentProtectionEntry* entry = diff --git a/packager/media/event/muxer_listener_internal.h b/packager/media/event/muxer_listener_internal.h index 96695f4467..0a049c07e6 100644 --- a/packager/media/event/muxer_listener_internal.h +++ b/packager/media/event/muxer_listener_internal.h @@ -54,7 +54,7 @@ bool SetVodInformation(bool has_init_range, /// cannot be null. void SetContentProtectionFields( FourCC protection_scheme, - const std::string& default_key_id, + const std::vector& default_key_id, const std::vector& key_system_info, MediaInfo* media_info); diff --git a/packager/media/event/vod_media_info_dump_muxer_listener.cc b/packager/media/event/vod_media_info_dump_muxer_listener.cc index d3a07060c6..5488152756 100644 --- a/packager/media/event/vod_media_info_dump_muxer_listener.cc +++ b/packager/media/event/vod_media_info_dump_muxer_listener.cc @@ -35,7 +35,7 @@ void VodMediaInfoDumpMuxerListener::OnEncryptionInfoReady( << "Updating (non initial) encryption info is not supported by " "this module."; protection_scheme_ = protection_scheme; - default_key_id_.assign(default_key_id.begin(), default_key_id.end()); + default_key_id_ = default_key_id; key_system_info_ = key_system_info; is_encrypted_ = true; } diff --git a/packager/media/event/vod_media_info_dump_muxer_listener.h b/packager/media/event/vod_media_info_dump_muxer_listener.h index 6cee30073e..f35d58b640 100644 --- a/packager/media/event/vod_media_info_dump_muxer_listener.h +++ b/packager/media/event/vod_media_info_dump_muxer_listener.h @@ -74,7 +74,7 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener { bool is_encrypted_; // Storage for values passed to OnEncryptionInfoReady(). FourCC protection_scheme_; - std::string default_key_id_; + std::vector default_key_id_; std::vector key_system_info_; DISALLOW_COPY_AND_ASSIGN(VodMediaInfoDumpMuxerListener);