Add --hls_key_uri to allow setting fairplay/identity key uri
Change-Id: I52e0f56cd10390faf515170f407ea488a6b3c9fc
This commit is contained in:
parent
61e36d7d21
commit
5cf2b17ade
|
@ -11,6 +11,11 @@ HLS options
|
||||||
The base URL for the Media Playlists and media files listed in the
|
The base URL for the Media Playlists and media files listed in the
|
||||||
playlists. This is the prefix for the files.
|
playlists. This is the prefix for the files.
|
||||||
|
|
||||||
|
--hls_key_uri <uri>
|
||||||
|
|
||||||
|
The key uri for 'identity' and 'com.apple.streamingkeydelivery' key formats.
|
||||||
|
Ignored if the playlist is not encrypted or not using the above key formats.
|
||||||
|
|
||||||
--hls_playlist_type <type>
|
--hls_playlist_type <type>
|
||||||
|
|
||||||
VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in the HLS
|
VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in the HLS
|
||||||
|
|
|
@ -14,6 +14,11 @@ DEFINE_string(hls_base_url,
|
||||||
"",
|
"",
|
||||||
"The base URL for the Media Playlists and media files listed in "
|
"The base URL for the Media Playlists and media files listed in "
|
||||||
"the playlists. This is the prefix for the files.");
|
"the playlists. This is the prefix for the files.");
|
||||||
|
DEFINE_string(hls_key_uri,
|
||||||
|
"",
|
||||||
|
"The key uri for 'identity' and 'com.apple.streamingkeydelivery' "
|
||||||
|
"key formats. Ignored if the playlist is not encrypted or not "
|
||||||
|
"using the above key formats.");
|
||||||
DEFINE_string(hls_playlist_type,
|
DEFINE_string(hls_playlist_type,
|
||||||
"VOD",
|
"VOD",
|
||||||
"VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in "
|
"VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in "
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
DECLARE_string(hls_master_playlist_output);
|
DECLARE_string(hls_master_playlist_output);
|
||||||
DECLARE_string(hls_base_url);
|
DECLARE_string(hls_base_url);
|
||||||
|
DECLARE_string(hls_key_uri);
|
||||||
DECLARE_string(hls_playlist_type);
|
DECLARE_string(hls_playlist_type);
|
||||||
|
|
||||||
#endif // PACKAGER_APP_HLS_FLAGS_H_
|
#endif // PACKAGER_APP_HLS_FLAGS_H_
|
||||||
|
|
|
@ -356,6 +356,7 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
||||||
}
|
}
|
||||||
hls_params.master_playlist_output = FLAGS_hls_master_playlist_output;
|
hls_params.master_playlist_output = FLAGS_hls_master_playlist_output;
|
||||||
hls_params.base_url = FLAGS_hls_base_url;
|
hls_params.base_url = FLAGS_hls_base_url;
|
||||||
|
hls_params.key_uri = FLAGS_hls_key_uri;
|
||||||
hls_params.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
|
hls_params.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
|
||||||
|
|
||||||
TestParams& test_params = packaging_params.test_params;
|
TestParams& test_params = packaging_params.test_params;
|
||||||
|
|
|
@ -122,6 +122,7 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
def _GetFlags(self,
|
def _GetFlags(self,
|
||||||
strip_parameter_set_nalus=True,
|
strip_parameter_set_nalus=True,
|
||||||
encryption=False,
|
encryption=False,
|
||||||
|
fairplay=False,
|
||||||
clear_lead=1,
|
clear_lead=1,
|
||||||
protection_scheme=None,
|
protection_scheme=None,
|
||||||
vp9_subsample_encryption=True,
|
vp9_subsample_encryption=True,
|
||||||
|
@ -160,6 +161,15 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
|
|
||||||
if not random_iv:
|
if not random_iv:
|
||||||
flags.append('--iv=' + self.encryption_iv)
|
flags.append('--iv=' + self.encryption_iv)
|
||||||
|
|
||||||
|
if fairplay:
|
||||||
|
fairplay_pssh = ('000000207073736800000000'
|
||||||
|
'29701FE43CC74A348C5BAE90C7439A4700000000')
|
||||||
|
fairplay_key_uri = ('skd://www.license.com/'
|
||||||
|
'getkey?KeyId=31323334-3536-3738-3930-313233343536')
|
||||||
|
flags += [
|
||||||
|
'--pssh=' + fairplay_pssh, '--hls_key_uri=' + fairplay_key_uri
|
||||||
|
]
|
||||||
if protection_scheme:
|
if protection_scheme:
|
||||||
flags += ['--protection_scheme', protection_scheme]
|
flags += ['--protection_scheme', protection_scheme]
|
||||||
if not vp9_subsample_encryption:
|
if not vp9_subsample_encryption:
|
||||||
|
@ -771,6 +781,31 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
os.path.join(self.tmp_dir, 'video.m3u8'),
|
os.path.join(self.tmp_dir, 'video.m3u8'),
|
||||||
'bear-640x360-v-enc-golden.m3u8')
|
'bear-640x360-v-enc-golden.m3u8')
|
||||||
|
|
||||||
|
def testPackageAvcTsWithEncryptionAndFairplay(self):
|
||||||
|
# Currently we only support live packaging for ts.
|
||||||
|
self.assertPackageSuccess(
|
||||||
|
self._GetStreams(
|
||||||
|
['audio', 'video'],
|
||||||
|
output_format='ts',
|
||||||
|
live=True,
|
||||||
|
hls=True,
|
||||||
|
test_files=['bear-640x360.ts']),
|
||||||
|
self._GetFlags(encryption=True, output_hls=True, fairplay=True))
|
||||||
|
self._DiffLiveGold(self.output[0],
|
||||||
|
'bear-640x360-a-enc-golden',
|
||||||
|
output_format='ts')
|
||||||
|
self._DiffLiveGold(self.output[1],
|
||||||
|
'bear-640x360-v-enc-golden',
|
||||||
|
output_format='ts')
|
||||||
|
self._DiffGold(self.hls_master_playlist_output,
|
||||||
|
'bear-640x360-av-master-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'audio.m3u8'),
|
||||||
|
'bear-640x360-a-fairplay-enc-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'video.m3u8'),
|
||||||
|
'bear-640x360-v-fairplay-enc-golden.m3u8')
|
||||||
|
|
||||||
def testPackageAvcTsWithEncryptionExerciseEmulationPrevention(self):
|
def testPackageAvcTsWithEncryptionExerciseEmulationPrevention(self):
|
||||||
self.encryption_key = 'ad7e9786def9159db6724be06dfcde7a'
|
self.encryption_key = 'ad7e9786def9159db6724be06dfcde7a'
|
||||||
# Currently we only support live packaging for ts.
|
# Currently we only support live packaging for ts.
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXTINF:0.975,
|
||||||
|
output_audio-1.ts
|
||||||
|
#EXTINF:0.998,
|
||||||
|
output_audio-2.ts
|
||||||
|
#EXT-X-DISCONTINUITY
|
||||||
|
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="skd://www.license.com/getkey?KeyId=31323334-3536-3738-3930-313233343536",KEYFORMATVERSIONS="1",KEYFORMAT="com.apple.streamingkeydelivery"
|
||||||
|
#EXTINF:0.789,
|
||||||
|
output_audio-3.ts
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -0,0 +1,14 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXTINF:1.001,
|
||||||
|
output_video-1.ts
|
||||||
|
#EXT-X-DISCONTINUITY
|
||||||
|
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="skd://www.license.com/getkey?KeyId=31323334-3536-3738-3930-313233343536",KEYFORMATVERSIONS="1",KEYFORMAT="com.apple.streamingkeydelivery"
|
||||||
|
#EXTINF:1.001,
|
||||||
|
output_video-2.ts
|
||||||
|
#EXTINF:0.734,
|
||||||
|
output_video-3.ts
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -250,11 +250,13 @@ std::unique_ptr<MediaPlaylist> MediaPlaylistFactory::Create(
|
||||||
SimpleHlsNotifier::SimpleHlsNotifier(HlsPlaylistType playlist_type,
|
SimpleHlsNotifier::SimpleHlsNotifier(HlsPlaylistType playlist_type,
|
||||||
double time_shift_buffer_depth,
|
double time_shift_buffer_depth,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
|
const std::string& key_uri,
|
||||||
const std::string& output_dir,
|
const std::string& output_dir,
|
||||||
const std::string& master_playlist_name)
|
const std::string& master_playlist_name)
|
||||||
: HlsNotifier(playlist_type),
|
: HlsNotifier(playlist_type),
|
||||||
time_shift_buffer_depth_(time_shift_buffer_depth),
|
time_shift_buffer_depth_(time_shift_buffer_depth),
|
||||||
prefix_(prefix),
|
prefix_(prefix),
|
||||||
|
key_uri_(key_uri),
|
||||||
output_dir_(output_dir),
|
output_dir_(output_dir),
|
||||||
media_playlist_factory_(new MediaPlaylistFactory()),
|
media_playlist_factory_(new MediaPlaylistFactory()),
|
||||||
master_playlist_(new MasterPlaylist(master_playlist_name)) {}
|
master_playlist_(new MasterPlaylist(master_playlist_name)) {}
|
||||||
|
@ -389,31 +391,39 @@ bool SimpleHlsNotifier::NotifyEncryptionUpdate(
|
||||||
key_id, iv, protection_system_specific_data,
|
key_id, iv, protection_system_specific_data,
|
||||||
media_playlist.get());
|
media_playlist.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key Id does not need to be specified with "identity" and "sdk".
|
||||||
|
const std::vector<uint8_t> empty_key_id;
|
||||||
|
|
||||||
if (IsCommonSystemId(system_id)) {
|
if (IsCommonSystemId(system_id)) {
|
||||||
// Use key_id as the key_uri. The player needs to have custom logic to
|
std::string key_uri;
|
||||||
// convert it to the actual key url.
|
if (!key_uri_.empty()) {
|
||||||
std::string key_uri_data = VectorToString(key_id);
|
key_uri = key_uri_;
|
||||||
std::string key_uri_data_base64 =
|
} else {
|
||||||
Base64EncodeData(kUriBase64Prefix, key_uri_data);
|
// Use key_id as the key_uri. The player needs to have custom logic to
|
||||||
NotifyEncryptionToMediaPlaylist(encryption_method,
|
// convert it to the actual key uri.
|
||||||
key_uri_data_base64, std::vector<uint8_t>(),
|
std::string key_uri_data = VectorToString(key_id);
|
||||||
|
key_uri = Base64EncodeData(kUriBase64Prefix, key_uri_data);
|
||||||
|
}
|
||||||
|
NotifyEncryptionToMediaPlaylist(encryption_method, key_uri, empty_key_id,
|
||||||
iv, "identity", "", media_playlist.get());
|
iv, "identity", "", media_playlist.get());
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (IsFairplaySystemId(system_id)) {
|
||||||
|
std::string key_uri;
|
||||||
if (IsFairplaySystemId(system_id)) {
|
if (!key_uri_.empty()) {
|
||||||
// Use key_id as the key_uri. The player needs to have custom logic to
|
key_uri = key_uri_;
|
||||||
// convert it to the actual key url.
|
} else {
|
||||||
std::string key_uri_data = VectorToString(key_id);
|
// Use key_id as the key_uri. The player needs to have custom logic to
|
||||||
std::string key_uri_data_base64 =
|
// convert it to the actual key uri.
|
||||||
Base64EncodeData(kUriFairplayPrefix, key_uri_data);
|
std::string key_uri_data = VectorToString(key_id);
|
||||||
|
key_uri = Base64EncodeData(kUriFairplayPrefix, key_uri_data);
|
||||||
|
}
|
||||||
|
|
||||||
// Fairplay defines IV to be carried with the key, not the playlist.
|
// Fairplay defines IV to be carried with the key, not the playlist.
|
||||||
NotifyEncryptionToMediaPlaylist(encryption_method,
|
const std::vector<uint8_t> empty_iv;
|
||||||
key_uri_data_base64, std::vector<uint8_t>(),
|
NotifyEncryptionToMediaPlaylist(encryption_method, key_uri, empty_key_id,
|
||||||
std::vector<uint8_t>(),
|
empty_iv, "com.apple.streamingkeydelivery",
|
||||||
"com.apple.streamingkeydelivery", "1",
|
"1", media_playlist.get());
|
||||||
media_playlist.get());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,16 @@ class SimpleHlsNotifier : public HlsNotifier {
|
||||||
/// shifting buffer, only for live HLS.
|
/// shifting buffer, only for live HLS.
|
||||||
/// @param prefix is the used as the prefix for MediaPlaylist URIs. May be
|
/// @param prefix is the used as the prefix for MediaPlaylist URIs. May be
|
||||||
/// empty for relative URI from the playlist.
|
/// empty for relative URI from the playlist.
|
||||||
|
/// @param key_uri defines the key uri for "identity" and
|
||||||
|
/// "com.apple.streamingkeydelivery" key formats. Ignored if the
|
||||||
|
/// playlist is not encrypted or not using the above key formats.
|
||||||
/// @param output_dir is the output directory of the playlists. May be empty
|
/// @param output_dir is the output directory of the playlists. May be empty
|
||||||
/// to write to current directory.
|
/// to write to current directory.
|
||||||
/// @param master_playlist_name is the name of the master playlist.
|
/// @param master_playlist_name is the name of the master playlist.
|
||||||
SimpleHlsNotifier(HlsPlaylistType playlist_type,
|
SimpleHlsNotifier(HlsPlaylistType playlist_type,
|
||||||
double time_shift_buffer_depth,
|
double time_shift_buffer_depth,
|
||||||
const std::string& prefix,
|
const std::string& prefix,
|
||||||
|
const std::string& key_uri,
|
||||||
const std::string& output_dir,
|
const std::string& output_dir,
|
||||||
const std::string& master_playlist_name);
|
const std::string& master_playlist_name);
|
||||||
~SimpleHlsNotifier() override;
|
~SimpleHlsNotifier() override;
|
||||||
|
@ -88,6 +92,7 @@ class SimpleHlsNotifier : public HlsNotifier {
|
||||||
|
|
||||||
const double time_shift_buffer_depth_ = 0;
|
const double time_shift_buffer_depth_ = 0;
|
||||||
const std::string prefix_;
|
const std::string prefix_;
|
||||||
|
const std::string key_uri_;
|
||||||
const std::string output_dir_;
|
const std::string output_dir_;
|
||||||
uint32_t target_duration_ = 0;
|
uint32_t target_duration_ = 0;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,9 @@ using ::testing::_;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char kMasterPlaylistName[] = "master.m3u8";
|
const char kMasterPlaylistName[] = "master.m3u8";
|
||||||
|
const char kEmptyKeyUri[] = "";
|
||||||
|
const char kFairplayKeyUri[] = "skd://www.license.com/getkey?key_id=testing";
|
||||||
|
const char kIdentityKeyUri[] = "https://www.license.com/getkey?key_id=testing";
|
||||||
const HlsPlaylistType kVodPlaylist = HlsPlaylistType::kVod;
|
const HlsPlaylistType kVodPlaylist = HlsPlaylistType::kVod;
|
||||||
const HlsPlaylistType kLivePlaylist = HlsPlaylistType::kLive;
|
const HlsPlaylistType kLivePlaylist = HlsPlaylistType::kLive;
|
||||||
|
|
||||||
|
@ -139,7 +142,8 @@ class SimpleHlsNotifierTest : public ::testing::Test {
|
||||||
|
|
||||||
TEST_F(SimpleHlsNotifierTest, Init) {
|
TEST_F(SimpleHlsNotifierTest, Init) {
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
EXPECT_TRUE(notifier.Init());
|
EXPECT_TRUE(notifier.Init());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +175,8 @@ TEST_F(SimpleHlsNotifierTest, RebaseSegmentUrl) {
|
||||||
.WillOnce(Return(mock_media_playlist));
|
.WillOnce(Return(mock_media_playlist));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
|
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
@ -211,7 +216,8 @@ TEST_F(SimpleHlsNotifierTest, RebaseInitSegmentUrl) {
|
||||||
.WillOnce(Return(mock_media_playlist));
|
.WillOnce(Return(mock_media_playlist));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
|
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
@ -250,7 +256,8 @@ TEST_F(SimpleHlsNotifierTest, RebaseSegmentUrlRelativeToPlaylist) {
|
||||||
.WillOnce(Return(mock_media_playlist));
|
.WillOnce(Return(mock_media_playlist));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kEmptyPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kEmptyPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
|
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
@ -271,7 +278,7 @@ TEST_F(SimpleHlsNotifierTest, RebaseSegmentUrlRelativeToPlaylist) {
|
||||||
TEST_F(SimpleHlsNotifierTest, RebaseAbsoluteSegmentPrefixAndOutputDirMatch) {
|
TEST_F(SimpleHlsNotifierTest, RebaseAbsoluteSegmentPrefixAndOutputDirMatch) {
|
||||||
const char kAbsoluteOutputDir[] = "/tmp/something/";
|
const char kAbsoluteOutputDir[] = "/tmp/something/";
|
||||||
SimpleHlsNotifier test_notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier test_notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAbsoluteOutputDir,
|
kTestPrefix, kEmptyKeyUri, kAbsoluteOutputDir,
|
||||||
kMasterPlaylistName);
|
kMasterPlaylistName);
|
||||||
|
|
||||||
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
||||||
|
@ -313,7 +320,7 @@ TEST_F(SimpleHlsNotifierTest,
|
||||||
RebaseAbsoluteSegmentCompletelyDifferentDirectory) {
|
RebaseAbsoluteSegmentCompletelyDifferentDirectory) {
|
||||||
const char kAbsoluteOutputDir[] = "/tmp/something/";
|
const char kAbsoluteOutputDir[] = "/tmp/something/";
|
||||||
SimpleHlsNotifier test_notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier test_notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAbsoluteOutputDir,
|
kTestPrefix, kEmptyKeyUri, kAbsoluteOutputDir,
|
||||||
kMasterPlaylistName);
|
kMasterPlaylistName);
|
||||||
|
|
||||||
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
||||||
|
@ -350,7 +357,8 @@ TEST_F(SimpleHlsNotifierTest,
|
||||||
|
|
||||||
TEST_F(SimpleHlsNotifierTest, Flush) {
|
TEST_F(SimpleHlsNotifierTest, Flush) {
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
std::unique_ptr<MockMasterPlaylist> mock_master_playlist(
|
||||||
new MockMasterPlaylist());
|
new MockMasterPlaylist());
|
||||||
EXPECT_CALL(*mock_master_playlist,
|
EXPECT_CALL(*mock_master_playlist,
|
||||||
|
@ -379,7 +387,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyNewStream) {
|
||||||
.WillOnce(Return(mock_media_playlist));
|
.WillOnce(Return(mock_media_playlist));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
|
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
@ -422,7 +431,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyNewSegment) {
|
||||||
.WillOnce(Return(kLongestSegmentDuration));
|
.WillOnce(Return(kLongestSegmentDuration));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
MockMasterPlaylist* mock_master_playlist_ptr = mock_master_playlist.get();
|
MockMasterPlaylist* mock_master_playlist_ptr = mock_master_playlist.get();
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
@ -454,7 +464,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyNewSegment) {
|
||||||
|
|
||||||
TEST_F(SimpleHlsNotifierTest, NotifyNewSegmentWithoutStreamsRegistered) {
|
TEST_F(SimpleHlsNotifierTest, NotifyNewSegmentWithoutStreamsRegistered) {
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
EXPECT_TRUE(notifier.Init());
|
EXPECT_TRUE(notifier.Init());
|
||||||
EXPECT_FALSE(notifier.NotifyNewSegment(1u, "anything", 0u, 0u, 0u, 0u));
|
EXPECT_FALSE(notifier.NotifyNewSegment(1u, "anything", 0u, 0u, 0u, 0u));
|
||||||
}
|
}
|
||||||
|
@ -464,7 +475,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateWidevine) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -526,7 +538,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateWidevineNoKeyidsInPssh) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -579,12 +592,13 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateWidevineNoKeyidsInPssh) {
|
||||||
widevine_system_id_, iv, pssh_box));
|
widevine_system_id_, iv, pssh_box));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateIdentifyKey) {
|
TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateIdentityKey) {
|
||||||
// Pointer released by SimpleHlsNotifier.
|
// Pointer released by SimpleHlsNotifier.
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -613,7 +627,8 @@ TEST_F(SimpleHlsNotifierTest, WidevineMultipleKeyIdsNoContentIdInPssh) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
uint32_t stream_id =
|
uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -690,7 +705,8 @@ TEST_F(SimpleHlsNotifierTest, EncryptionScheme) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kIdentityKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kCencProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kCencProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -698,16 +714,11 @@ TEST_F(SimpleHlsNotifierTest, EncryptionScheme) {
|
||||||
const std::vector<uint8_t> iv(16, 0x45);
|
const std::vector<uint8_t> iv(16, 0x45);
|
||||||
const std::vector<uint8_t> dummy_pssh_data(10, 'p');
|
const std::vector<uint8_t> dummy_pssh_data(10, 'p');
|
||||||
|
|
||||||
std::string expected_key_uri_base64;
|
EXPECT_CALL(*mock_media_playlist,
|
||||||
base::Base64Encode(std::string(key_id.begin(), key_id.end()),
|
AddEncryptionInfo(MediaPlaylist::EncryptionMethod::kSampleAesCenc,
|
||||||
&expected_key_uri_base64);
|
StrEq(kIdentityKeyUri), StrEq(""),
|
||||||
|
StrEq("0x45454545454545454545454545454545"),
|
||||||
EXPECT_CALL(
|
StrEq("identity"), _));
|
||||||
*mock_media_playlist,
|
|
||||||
AddEncryptionInfo(
|
|
||||||
MediaPlaylist::EncryptionMethod::kSampleAesCenc,
|
|
||||||
StrEq("data:text/plain;base64," + expected_key_uri_base64), StrEq(""),
|
|
||||||
StrEq("0x45454545454545454545454545454545"), StrEq("identity"), _));
|
|
||||||
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
||||||
stream_id, key_id, common_system_id_, iv, dummy_pssh_data));
|
stream_id, key_id, common_system_id_, iv, dummy_pssh_data));
|
||||||
}
|
}
|
||||||
|
@ -719,23 +730,18 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateFairplay) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kLivePlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kLivePlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kLivePlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kLivePlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kFairplayKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
const std::vector<uint8_t> key_id(16, 0x12);
|
const std::vector<uint8_t> key_id(16, 0x12);
|
||||||
const std::vector<uint8_t> dummy_pssh_data(10, 'p');
|
const std::vector<uint8_t> dummy_pssh_data(10, 'p');
|
||||||
|
|
||||||
std::string expected_key_uri_base64;
|
|
||||||
base::Base64Encode(std::string(key_id.begin(), key_id.end()),
|
|
||||||
&expected_key_uri_base64);
|
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
*mock_media_playlist,
|
*mock_media_playlist,
|
||||||
AddEncryptionInfo(
|
AddEncryptionInfo(MediaPlaylist::EncryptionMethod::kSampleAes,
|
||||||
MediaPlaylist::EncryptionMethod::kSampleAes,
|
StrEq(kFairplayKeyUri), StrEq(""), StrEq(""),
|
||||||
StrEq("skd://" + expected_key_uri_base64),
|
StrEq("com.apple.streamingkeydelivery"), StrEq("1")));
|
||||||
StrEq(""),
|
|
||||||
StrEq(""),
|
|
||||||
StrEq("com.apple.streamingkeydelivery"), StrEq("1")));
|
|
||||||
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
||||||
stream_id, key_id, fairplay_system_id_, std::vector<uint8_t>(),
|
stream_id, key_id, fairplay_system_id_, std::vector<uint8_t>(),
|
||||||
dummy_pssh_data));
|
dummy_pssh_data));
|
||||||
|
@ -747,7 +753,8 @@ TEST_F(SimpleHlsNotifierTest, WidevineCencEncryptionScheme) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kCencProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kCencProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -795,7 +802,8 @@ TEST_F(SimpleHlsNotifierTest, WidevineNotifyEncryptionUpdateEmptyIv) {
|
||||||
MockMediaPlaylist* mock_media_playlist =
|
MockMediaPlaylist* mock_media_playlist =
|
||||||
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
new MockMediaPlaylist(kVodPlaylist, "playlist.m3u8", "", "");
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
const uint32_t stream_id =
|
const uint32_t stream_id =
|
||||||
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
SetupStream(kSampleAesProtectionScheme, mock_media_playlist, ¬ifier);
|
||||||
|
|
||||||
|
@ -862,7 +870,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateWithoutStreamsRegistered) {
|
||||||
std::vector<uint8_t> pssh_data;
|
std::vector<uint8_t> pssh_data;
|
||||||
std::vector<uint8_t> key_id;
|
std::vector<uint8_t> key_id;
|
||||||
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
SimpleHlsNotifier notifier(kVodPlaylist, kTestTimeShiftBufferDepth,
|
||||||
kTestPrefix, kAnyOutputDir, kMasterPlaylistName);
|
kTestPrefix, kEmptyKeyUri, kAnyOutputDir,
|
||||||
|
kMasterPlaylistName);
|
||||||
EXPECT_TRUE(notifier.Init());
|
EXPECT_TRUE(notifier.Init());
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
notifier.NotifyEncryptionUpdate(1238u, key_id, system_id, iv, pssh_data));
|
notifier.NotifyEncryptionUpdate(1238u, key_id, system_id, iv, pssh_data));
|
||||||
|
@ -921,9 +930,8 @@ TEST_P(LiveOrEventSimpleHlsNotifierTest, NotifyNewSegment) {
|
||||||
.AsUTF8Unsafe())))
|
.AsUTF8Unsafe())))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(GetParam(),
|
SimpleHlsNotifier notifier(GetParam(), kTestTimeShiftBufferDepth, kTestPrefix,
|
||||||
kTestTimeShiftBufferDepth, kTestPrefix,
|
kEmptyKeyUri, kAnyOutputDir, kMasterPlaylistName);
|
||||||
kAnyOutputDir, kMasterPlaylistName);
|
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
EXPECT_TRUE(notifier.Init());
|
EXPECT_TRUE(notifier.Init());
|
||||||
|
@ -967,9 +975,8 @@ TEST_P(LiveOrEventSimpleHlsNotifierTest, NotifyNewSegmentsWithMultipleStreams) {
|
||||||
*mock_master_playlist,
|
*mock_master_playlist,
|
||||||
AddMediaPlaylist(static_cast<MediaPlaylist*>(mock_media_playlist2)));
|
AddMediaPlaylist(static_cast<MediaPlaylist*>(mock_media_playlist2)));
|
||||||
|
|
||||||
SimpleHlsNotifier notifier(GetParam(),
|
SimpleHlsNotifier notifier(GetParam(), kTestTimeShiftBufferDepth, kTestPrefix,
|
||||||
kTestTimeShiftBufferDepth, kTestPrefix,
|
kEmptyKeyUri, kAnyOutputDir, kMasterPlaylistName);
|
||||||
kAnyOutputDir, kMasterPlaylistName);
|
|
||||||
MockMasterPlaylist* mock_master_playlist_ptr = mock_master_playlist.get();
|
MockMasterPlaylist* mock_master_playlist_ptr = mock_master_playlist.get();
|
||||||
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
InjectMasterPlaylist(std::move(mock_master_playlist), ¬ifier);
|
||||||
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
InjectMediaPlaylistFactory(std::move(factory), ¬ifier);
|
||||||
|
|
|
@ -31,6 +31,10 @@ struct HlsParams {
|
||||||
/// Defines the live window, or the guaranteed duration of the time shifting
|
/// Defines the live window, or the guaranteed duration of the time shifting
|
||||||
/// buffer for 'live' playlists.
|
/// buffer for 'live' playlists.
|
||||||
double time_shift_buffer_depth = 0;
|
double time_shift_buffer_depth = 0;
|
||||||
|
/// Defines the key uri for "identity" and "com.apple.streamingkeydelivery"
|
||||||
|
/// key formats. Ignored if the playlist is not encrypted or not using the
|
||||||
|
/// above key formats.
|
||||||
|
std::string key_uri;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -810,7 +810,7 @@ Status Packager::Initialize(
|
||||||
|
|
||||||
internal->hls_notifier.reset(new hls::SimpleHlsNotifier(
|
internal->hls_notifier.reset(new hls::SimpleHlsNotifier(
|
||||||
hls_params.playlist_type, hls_params.time_shift_buffer_depth,
|
hls_params.playlist_type, hls_params.time_shift_buffer_depth,
|
||||||
hls_params.base_url,
|
hls_params.base_url, hls_params.key_uri,
|
||||||
master_playlist_path.DirName().AsEndingWithSeparator().AsUTF8Unsafe(),
|
master_playlist_path.DirName().AsEndingWithSeparator().AsUTF8Unsafe(),
|
||||||
master_playlist_name.AsUTF8Unsafe()));
|
master_playlist_name.AsUTF8Unsafe()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue