parent
ddeacb2525
commit
d88ed2798c
|
@ -93,3 +93,8 @@ HLS options
|
||||||
|
|
||||||
True forces the muxer to order streams in the order given
|
True forces the muxer to order streams in the order given
|
||||||
on the command-line. False uses the previous unordered behavior.
|
on the command-line. False uses the previous unordered behavior.
|
||||||
|
|
||||||
|
--create_session_keys
|
||||||
|
|
||||||
|
Playback of Offline HLS assets shall use EXT-X-SESSION-KEY to declare all
|
||||||
|
eligible content keys in the master playlist.
|
|
@ -70,6 +70,8 @@ struct HlsParams {
|
||||||
/// playlist. A negative number indicates a negative time offset from the end
|
/// playlist. A negative number indicates a negative time offset from the end
|
||||||
/// of the last media segment in the playlist.
|
/// of the last media segment in the playlist.
|
||||||
std::optional<double> start_time_offset;
|
std::optional<double> start_time_offset;
|
||||||
|
/// Create EXT-X-SESSION-KEY in master playlist
|
||||||
|
bool create_session_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -46,3 +46,8 @@ ABSL_FLAG(std::optional<double>,
|
||||||
"beginning of the playlist. A negative number indicates a "
|
"beginning of the playlist. A negative number indicates a "
|
||||||
"negative time offset from the end of the last media segment "
|
"negative time offset from the end of the last media segment "
|
||||||
"in the playlist.");
|
"in the playlist.");
|
||||||
|
ABSL_FLAG(bool,
|
||||||
|
create_session_keys,
|
||||||
|
false,
|
||||||
|
"Playback of Offline HLS assets shall use EXT-X-SESSION-KEY "
|
||||||
|
"to declare all eligible content keys in the master playlist.");
|
||||||
|
|
|
@ -16,5 +16,6 @@ ABSL_DECLARE_FLAG(std::string, hls_key_uri);
|
||||||
ABSL_DECLARE_FLAG(std::string, hls_playlist_type);
|
ABSL_DECLARE_FLAG(std::string, hls_playlist_type);
|
||||||
ABSL_DECLARE_FLAG(int32_t, hls_media_sequence_number);
|
ABSL_DECLARE_FLAG(int32_t, hls_media_sequence_number);
|
||||||
ABSL_DECLARE_FLAG(std::optional<double>, hls_start_time_offset);
|
ABSL_DECLARE_FLAG(std::optional<double>, hls_start_time_offset);
|
||||||
|
ABSL_DECLARE_FLAG(bool, create_session_keys);
|
||||||
|
|
||||||
#endif // PACKAGER_APP_HLS_FLAGS_H_
|
#endif // PACKAGER_APP_HLS_FLAGS_H_
|
||||||
|
|
|
@ -543,6 +543,7 @@ std::optional<PackagingParams> GetPackagingParams() {
|
||||||
hls_params.media_sequence_number =
|
hls_params.media_sequence_number =
|
||||||
absl::GetFlag(FLAGS_hls_media_sequence_number);
|
absl::GetFlag(FLAGS_hls_media_sequence_number);
|
||||||
hls_params.start_time_offset = absl::GetFlag(FLAGS_hls_start_time_offset);
|
hls_params.start_time_offset = absl::GetFlag(FLAGS_hls_start_time_offset);
|
||||||
|
hls_params.create_session_keys = absl::GetFlag(FLAGS_create_session_keys);
|
||||||
|
|
||||||
TestParams& test_params = packaging_params.test_params;
|
TestParams& test_params = packaging_params.test_params;
|
||||||
test_params.dump_stream_info = absl::GetFlag(FLAGS_dump_stream_info);
|
test_params.dump_stream_info = absl::GetFlag(FLAGS_dump_stream_info);
|
||||||
|
|
|
@ -550,11 +550,13 @@ void AppendPlaylists(const std::string& default_audio_language,
|
||||||
MasterPlaylist::MasterPlaylist(const std::filesystem::path& file_name,
|
MasterPlaylist::MasterPlaylist(const std::filesystem::path& file_name,
|
||||||
const std::string& default_audio_language,
|
const std::string& default_audio_language,
|
||||||
const std::string& default_text_language,
|
const std::string& default_text_language,
|
||||||
bool is_independent_segments)
|
bool is_independent_segments,
|
||||||
|
bool create_session_keys)
|
||||||
: file_name_(file_name),
|
: file_name_(file_name),
|
||||||
default_audio_language_(default_audio_language),
|
default_audio_language_(default_audio_language),
|
||||||
default_text_language_(default_text_language),
|
default_text_language_(default_text_language),
|
||||||
is_independent_segments_(is_independent_segments) {}
|
is_independent_segments_(is_independent_segments),
|
||||||
|
create_session_keys_(create_session_keys) {}
|
||||||
|
|
||||||
MasterPlaylist::~MasterPlaylist() {}
|
MasterPlaylist::~MasterPlaylist() {}
|
||||||
|
|
||||||
|
@ -568,6 +570,23 @@ bool MasterPlaylist::WriteMasterPlaylist(
|
||||||
if (is_independent_segments_) {
|
if (is_independent_segments_) {
|
||||||
content.append("\n#EXT-X-INDEPENDENT-SEGMENTS\n");
|
content.append("\n#EXT-X-INDEPENDENT-SEGMENTS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate over the playlists and add the session keys to the master playlist.
|
||||||
|
if (create_session_keys_) {
|
||||||
|
std::set<std::string> session_keys;
|
||||||
|
for (const auto& playlist : playlists) {
|
||||||
|
for (const auto& entry : playlist->entries()) {
|
||||||
|
if (entry->type() == HlsEntry::EntryType::kExtKey) {
|
||||||
|
auto encryption_entry = dynamic_cast<EncryptionInfoEntry*>(entry.get());
|
||||||
|
session_keys.emplace(encryption_entry->ToString("#EXT-X-SESSION-KEY"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// session_keys will now contain all the unique session keys.
|
||||||
|
for (const auto& session_key : session_keys)
|
||||||
|
content.append(session_key + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
AppendPlaylists(default_audio_language_, default_text_language_, base_url,
|
AppendPlaylists(default_audio_language_, default_text_language_, base_url,
|
||||||
playlists, &content);
|
playlists, &content);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ class MasterPlaylist {
|
||||||
MasterPlaylist(const std::filesystem::path& file_name,
|
MasterPlaylist(const std::filesystem::path& file_name,
|
||||||
const std::string& default_audio_language,
|
const std::string& default_audio_language,
|
||||||
const std::string& default_text_language,
|
const std::string& default_text_language,
|
||||||
const bool is_independent_segments);
|
const bool is_independent_segments,
|
||||||
|
const bool create_session_keys = false);
|
||||||
virtual ~MasterPlaylist();
|
virtual ~MasterPlaylist();
|
||||||
|
|
||||||
/// Writes Master Playlist to output_dir + <name of playlist>.
|
/// Writes Master Playlist to output_dir + <name of playlist>.
|
||||||
|
@ -53,6 +54,7 @@ class MasterPlaylist {
|
||||||
const std::string default_audio_language_;
|
const std::string default_audio_language_;
|
||||||
const std::string default_text_language_;
|
const std::string default_text_language_;
|
||||||
bool is_independent_segments_;
|
bool is_independent_segments_;
|
||||||
|
bool create_session_keys_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace hls
|
} // namespace hls
|
||||||
|
|
|
@ -40,6 +40,7 @@ const uint32_t kEC3JocComplexityZero = 0;
|
||||||
const uint32_t kEC3JocComplexity = 16;
|
const uint32_t kEC3JocComplexity = 16;
|
||||||
const bool kAC4IMSFlagEnabled = true;
|
const bool kAC4IMSFlagEnabled = true;
|
||||||
const bool kAC4CBIFlagEnabled = true;
|
const bool kAC4CBIFlagEnabled = true;
|
||||||
|
const bool kCreateSessionKeys = true;
|
||||||
|
|
||||||
std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
|
std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
|
@ -143,7 +144,8 @@ class MasterPlaylistTest : public ::testing::Test {
|
||||||
: master_playlist_(new MasterPlaylist(kDefaultMasterPlaylistName,
|
: master_playlist_(new MasterPlaylist(kDefaultMasterPlaylistName,
|
||||||
kDefaultAudioLanguage,
|
kDefaultAudioLanguage,
|
||||||
kDefaultTextLanguage,
|
kDefaultTextLanguage,
|
||||||
!kIsIndependentSegments)),
|
!kIsIndependentSegments,
|
||||||
|
kCreateSessionKeys)),
|
||||||
test_output_dir_("memory://test_dir"),
|
test_output_dir_("memory://test_dir"),
|
||||||
master_playlist_path_(std::filesystem::u8path(test_output_dir_) /
|
master_playlist_path_(std::filesystem::u8path(test_output_dir_) /
|
||||||
kDefaultMasterPlaylistName) {}
|
kDefaultMasterPlaylistName) {}
|
||||||
|
@ -849,6 +851,55 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnly) {
|
||||||
ASSERT_EQ(expected, actual);
|
ASSERT_EQ(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MasterPlaylistTest, WriteMasterPlaylistWithEncryption) {
|
||||||
|
std::unique_ptr<MockMediaPlaylist> media_playlists[] = {
|
||||||
|
// VIDEO
|
||||||
|
CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", 300000, 200000),
|
||||||
|
|
||||||
|
// AUDIO
|
||||||
|
CreateAudioPlaylist("audio-1.m3u8", "audio 1", "audio-group-1",
|
||||||
|
"audiocodec", "en", 2, 50000, 30000,
|
||||||
|
kEC3JocComplexityZero, !kAC4IMSFlagEnabled,
|
||||||
|
!kAC4CBIFlagEnabled),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all the media playlists to the master playlist.
|
||||||
|
std::list<MediaPlaylist*> media_playlist_list;
|
||||||
|
for (const auto& media_playlist : media_playlists) {
|
||||||
|
media_playlist.get()->AddEncryptionInfoForTesting(
|
||||||
|
MediaPlaylist::EncryptionMethod::kSampleAes, "http://example.com", "",
|
||||||
|
"0x12345678", "com.widevine", "1/2/4");
|
||||||
|
media_playlist_list.push_back(media_playlist.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char kBaseUrl[] = "http://playlists.org/";
|
||||||
|
EXPECT_TRUE(master_playlist_->WriteMasterPlaylist(kBaseUrl, test_output_dir_,
|
||||||
|
media_playlist_list));
|
||||||
|
|
||||||
|
std::string actual;
|
||||||
|
ASSERT_TRUE(
|
||||||
|
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||||
|
|
||||||
|
// Expected master playlist content with encryption.
|
||||||
|
std::string expected =
|
||||||
|
"#EXTM3U\n"
|
||||||
|
"## Generated with https://github.com/shaka-project/shaka-packager "
|
||||||
|
"version test\n"
|
||||||
|
"#EXT-X-SESSION-KEY:METHOD=SAMPLE-AES,URI=\"http://example.com\","
|
||||||
|
"IV=0x12345678,KEYFORMATVERSIONS=\"1/2/4\",KEYFORMAT=\"com.widevine\"\n"
|
||||||
|
"\n"
|
||||||
|
"#EXT-X-MEDIA:TYPE=AUDIO,URI=\"http://playlists.org/audio-1.m3u8\","
|
||||||
|
"GROUP-ID=\"audio-group-1\",LANGUAGE=\"en\",NAME=\"audio 1\","
|
||||||
|
"DEFAULT=YES,AUTOSELECT=YES,CHANNELS=\"2\"\n"
|
||||||
|
"\n"
|
||||||
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=230000,"
|
||||||
|
"CODECS=\"sdvideocodec,audiocodec\",RESOLUTION=800x600,"
|
||||||
|
"AUDIO=\"audio-group-1\",CLOSED-CAPTIONS=NONE\n"
|
||||||
|
"http://playlists.org/video-1.m3u8\n";
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnlyJOC) {
|
TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnlyJOC) {
|
||||||
const uint64_t kAudioChannels = 6;
|
const uint64_t kAudioChannels = 6;
|
||||||
const uint64_t kAudioMaxBitrate = 50000;
|
const uint64_t kAudioMaxBitrate = 50000;
|
||||||
|
|
|
@ -165,6 +165,12 @@ std::string CreatePlaylistHeader(
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
HlsEntry::HlsEntry(HlsEntry::EntryType type) : type_(type) {}
|
||||||
|
HlsEntry::~HlsEntry() {}
|
||||||
|
|
||||||
class SegmentInfoEntry : public HlsEntry {
|
class SegmentInfoEntry : public HlsEntry {
|
||||||
public:
|
public:
|
||||||
// If |use_byte_range| true then this will append EXT-X-BYTERANGE
|
// If |use_byte_range| true then this will append EXT-X-BYTERANGE
|
||||||
|
@ -233,75 +239,6 @@ std::string SegmentInfoEntry::ToString() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EncryptionInfoEntry : public HlsEntry {
|
|
||||||
public:
|
|
||||||
EncryptionInfoEntry(MediaPlaylist::EncryptionMethod method,
|
|
||||||
const std::string& url,
|
|
||||||
const std::string& key_id,
|
|
||||||
const std::string& iv,
|
|
||||||
const std::string& key_format,
|
|
||||||
const std::string& key_format_versions);
|
|
||||||
|
|
||||||
std::string ToString() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
EncryptionInfoEntry(const EncryptionInfoEntry&) = delete;
|
|
||||||
EncryptionInfoEntry& operator=(const EncryptionInfoEntry&) = delete;
|
|
||||||
|
|
||||||
const MediaPlaylist::EncryptionMethod method_;
|
|
||||||
const std::string url_;
|
|
||||||
const std::string key_id_;
|
|
||||||
const std::string iv_;
|
|
||||||
const std::string key_format_;
|
|
||||||
const std::string key_format_versions_;
|
|
||||||
};
|
|
||||||
|
|
||||||
EncryptionInfoEntry::EncryptionInfoEntry(MediaPlaylist::EncryptionMethod method,
|
|
||||||
const std::string& url,
|
|
||||||
const std::string& key_id,
|
|
||||||
const std::string& iv,
|
|
||||||
const std::string& key_format,
|
|
||||||
const std::string& key_format_versions)
|
|
||||||
: HlsEntry(HlsEntry::EntryType::kExtKey),
|
|
||||||
method_(method),
|
|
||||||
url_(url),
|
|
||||||
key_id_(key_id),
|
|
||||||
iv_(iv),
|
|
||||||
key_format_(key_format),
|
|
||||||
key_format_versions_(key_format_versions) {}
|
|
||||||
|
|
||||||
std::string EncryptionInfoEntry::ToString() {
|
|
||||||
std::string tag_string;
|
|
||||||
Tag tag("#EXT-X-KEY", &tag_string);
|
|
||||||
|
|
||||||
if (method_ == MediaPlaylist::EncryptionMethod::kSampleAes) {
|
|
||||||
tag.AddString("METHOD", "SAMPLE-AES");
|
|
||||||
} else if (method_ == MediaPlaylist::EncryptionMethod::kAes128) {
|
|
||||||
tag.AddString("METHOD", "AES-128");
|
|
||||||
} else if (method_ == MediaPlaylist::EncryptionMethod::kSampleAesCenc) {
|
|
||||||
tag.AddString("METHOD", "SAMPLE-AES-CTR");
|
|
||||||
} else {
|
|
||||||
DCHECK(method_ == MediaPlaylist::EncryptionMethod::kNone);
|
|
||||||
tag.AddString("METHOD", "NONE");
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.AddQuotedString("URI", url_);
|
|
||||||
|
|
||||||
if (!key_id_.empty()) {
|
|
||||||
tag.AddString("KEYID", key_id_);
|
|
||||||
}
|
|
||||||
if (!iv_.empty()) {
|
|
||||||
tag.AddString("IV", iv_);
|
|
||||||
}
|
|
||||||
if (!key_format_versions_.empty()) {
|
|
||||||
tag.AddQuotedString("KEYFORMATVERSIONS", key_format_versions_);
|
|
||||||
}
|
|
||||||
if (!key_format_.empty()) {
|
|
||||||
tag.AddQuotedString("KEYFORMAT", key_format_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DiscontinuityEntry : public HlsEntry {
|
class DiscontinuityEntry : public HlsEntry {
|
||||||
public:
|
public:
|
||||||
|
@ -340,10 +277,58 @@ std::string PlacementOpportunityEntry::ToString() {
|
||||||
return "#EXT-X-PLACEMENT-OPPORTUNITY";
|
return "#EXT-X-PLACEMENT-OPPORTUNITY";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
EncryptionInfoEntry::EncryptionInfoEntry(MediaPlaylist::EncryptionMethod method,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& key_id,
|
||||||
|
const std::string& iv,
|
||||||
|
const std::string& key_format,
|
||||||
|
const std::string& key_format_versions)
|
||||||
|
: HlsEntry(HlsEntry::EntryType::kExtKey),
|
||||||
|
method_(method),
|
||||||
|
url_(url),
|
||||||
|
key_id_(key_id),
|
||||||
|
iv_(iv),
|
||||||
|
key_format_(key_format),
|
||||||
|
key_format_versions_(key_format_versions) {}
|
||||||
|
|
||||||
HlsEntry::HlsEntry(HlsEntry::EntryType type) : type_(type) {}
|
std::string EncryptionInfoEntry::ToString() {
|
||||||
HlsEntry::~HlsEntry() {}
|
return ToString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncryptionInfoEntry::ToString(std::string tag_name) {
|
||||||
|
std::string tag_string;
|
||||||
|
if (tag_name.empty())
|
||||||
|
tag_name = "#EXT-X-KEY";
|
||||||
|
Tag tag(tag_name, &tag_string);
|
||||||
|
|
||||||
|
if (method_ == MediaPlaylist::EncryptionMethod::kSampleAes) {
|
||||||
|
tag.AddString("METHOD", "SAMPLE-AES");
|
||||||
|
} else if (method_ == MediaPlaylist::EncryptionMethod::kAes128) {
|
||||||
|
tag.AddString("METHOD", "AES-128");
|
||||||
|
} else if (method_ == MediaPlaylist::EncryptionMethod::kSampleAesCenc) {
|
||||||
|
tag.AddString("METHOD", "SAMPLE-AES-CTR");
|
||||||
|
} else {
|
||||||
|
DCHECK(method_ == MediaPlaylist::EncryptionMethod::kNone);
|
||||||
|
tag.AddString("METHOD", "NONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.AddQuotedString("URI", url_);
|
||||||
|
|
||||||
|
if (!key_id_.empty()) {
|
||||||
|
tag.AddString("KEYID", key_id_);
|
||||||
|
}
|
||||||
|
if (!iv_.empty()) {
|
||||||
|
tag.AddString("IV", iv_);
|
||||||
|
}
|
||||||
|
if (!key_format_versions_.empty()) {
|
||||||
|
tag.AddQuotedString("KEYFORMATVERSIONS", key_format_versions_);
|
||||||
|
}
|
||||||
|
if (!key_format_.empty()) {
|
||||||
|
tag.AddQuotedString("KEYFORMAT", key_format_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag_string;
|
||||||
|
}
|
||||||
|
|
||||||
MediaPlaylist::MediaPlaylist(const HlsParams& hls_params,
|
MediaPlaylist::MediaPlaylist(const HlsParams& hls_params,
|
||||||
const std::string& file_name,
|
const std::string& file_name,
|
||||||
|
@ -383,6 +368,17 @@ void MediaPlaylist::SetForcedSubtitleForTesting(const bool forced_subtitle) {
|
||||||
forced_subtitle_ = forced_subtitle;
|
forced_subtitle_ = forced_subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaPlaylist::AddEncryptionInfoForTesting(
|
||||||
|
MediaPlaylist::EncryptionMethod method,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& key_id,
|
||||||
|
const std::string& iv,
|
||||||
|
const std::string& key_format,
|
||||||
|
const std::string& key_format_versions) {
|
||||||
|
entries_.emplace_back(new EncryptionInfoEntry(
|
||||||
|
method, url, key_id, iv, key_format, key_format_versions));
|
||||||
|
}
|
||||||
|
|
||||||
bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) {
|
bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) {
|
||||||
const int32_t time_scale = GetTimeScale(media_info);
|
const int32_t time_scale = GetTimeScale(media_info);
|
||||||
if (time_scale == 0) {
|
if (time_scale == 0) {
|
||||||
|
|
|
@ -83,6 +83,9 @@ class MediaPlaylist {
|
||||||
const std::string& codec() const { return codec_; }
|
const std::string& codec() const { return codec_; }
|
||||||
const std::string& supplemental_codec() const { return supplemental_codec_; }
|
const std::string& supplemental_codec() const { return supplemental_codec_; }
|
||||||
const media::FourCC& compatible_brand() const { return compatible_brand_; }
|
const media::FourCC& compatible_brand() const { return compatible_brand_; }
|
||||||
|
const std::list<std::unique_ptr<HlsEntry>>& entries() const {
|
||||||
|
return entries_;
|
||||||
|
}
|
||||||
|
|
||||||
/// For testing only.
|
/// For testing only.
|
||||||
void SetStreamTypeForTesting(MediaPlaylistStreamType stream_type);
|
void SetStreamTypeForTesting(MediaPlaylistStreamType stream_type);
|
||||||
|
@ -100,6 +103,14 @@ class MediaPlaylist {
|
||||||
void SetCharacteristicsForTesting(
|
void SetCharacteristicsForTesting(
|
||||||
const std::vector<std::string>& characteristics);
|
const std::vector<std::string>& characteristics);
|
||||||
|
|
||||||
|
/// For testing only.
|
||||||
|
void AddEncryptionInfoForTesting(MediaPlaylist::EncryptionMethod method,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& key_id,
|
||||||
|
const std::string& iv,
|
||||||
|
const std::string& key_format,
|
||||||
|
const std::string& key_format_versions);
|
||||||
|
|
||||||
/// This must succeed before calling any other public methods.
|
/// This must succeed before calling any other public methods.
|
||||||
/// @param media_info is the info of the segments that are going to be added
|
/// @param media_info is the info of the segments that are going to be added
|
||||||
/// to this playlist.
|
/// to this playlist.
|
||||||
|
@ -310,6 +321,30 @@ class MediaPlaylist {
|
||||||
DISALLOW_COPY_AND_ASSIGN(MediaPlaylist);
|
DISALLOW_COPY_AND_ASSIGN(MediaPlaylist);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EncryptionInfoEntry : public HlsEntry {
|
||||||
|
public:
|
||||||
|
EncryptionInfoEntry(MediaPlaylist::EncryptionMethod method,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& key_id,
|
||||||
|
const std::string& iv,
|
||||||
|
const std::string& key_format,
|
||||||
|
const std::string& key_format_versions);
|
||||||
|
|
||||||
|
std::string ToString() override;
|
||||||
|
std::string ToString(std::string);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EncryptionInfoEntry(const EncryptionInfoEntry&) = delete;
|
||||||
|
EncryptionInfoEntry& operator=(const EncryptionInfoEntry&) = delete;
|
||||||
|
|
||||||
|
const MediaPlaylist::EncryptionMethod method_;
|
||||||
|
const std::string url_;
|
||||||
|
const std::string key_id_;
|
||||||
|
const std::string iv_;
|
||||||
|
const std::string key_format_;
|
||||||
|
const std::string key_format_versions_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace hls
|
} // namespace hls
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,8 @@ SimpleHlsNotifier::SimpleHlsNotifier(const HlsParams& hls_params)
|
||||||
: hls_params.default_text_language;
|
: hls_params.default_text_language;
|
||||||
master_playlist_.reset(new MasterPlaylist(
|
master_playlist_.reset(new MasterPlaylist(
|
||||||
master_playlist_path.filename(), default_audio_langauge,
|
master_playlist_path.filename(), default_audio_langauge,
|
||||||
default_text_language, hls_params.is_independent_segments));
|
default_text_language, hls_params.is_independent_segments,
|
||||||
|
hls_params.create_session_keys));
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleHlsNotifier::~SimpleHlsNotifier() {}
|
SimpleHlsNotifier::~SimpleHlsNotifier() {}
|
||||||
|
|
Loading…
Reference in New Issue