Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement stream ordering in HLS playlist based on input order. #1280

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packager/app/packager_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ int PackagerMain(int argc, char** argv) {
ParseStreamDescriptor(argv[i]);
if (!stream_descriptor)
return kArgumentValidationFailed;
stream_descriptor->output_order = i;
stream_descriptors.push_back(stream_descriptor.value());
}
Packager packager;
Expand Down
1 change: 1 addition & 0 deletions packager/hls/base/hls_notifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class HlsNotifier {
const std::string& playlist_name,
const std::string& stream_name,
const std::string& group_id,
int output_order,
uint32_t* stream_id) = 0;

/// Change the sample duration of stream with @a stream_id.
Expand Down
42 changes: 30 additions & 12 deletions packager/hls/base/master_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ struct Variant {
uint64_t avg_audio_bitrate = 0;
};

uint64_t GetMaximumMaxBitrate(const std::list<const MediaPlaylist*> playlists) {
uint64_t GetMaximumMaxBitrate(
const std::vector<const MediaPlaylist*> playlists) {
uint64_t max = 0;
for (const auto& playlist : playlists) {
max = std::max(max, playlist->MaxBitrate());
}
return max;
}

uint64_t GetMaximumAvgBitrate(const std::list<const MediaPlaylist*> playlists) {
uint64_t GetMaximumAvgBitrate(
const std::vector<const MediaPlaylist*> playlists) {
uint64_t max = 0;
for (const auto& playlist : playlists) {
max = std::max(max, playlist->AvgBitrate());
Expand All @@ -69,7 +71,7 @@ uint64_t GetMaximumAvgBitrate(const std::list<const MediaPlaylist*> playlists) {
}

std::set<std::string> GetGroupCodecString(
const std::list<const MediaPlaylist*>& group) {
const std::vector<const MediaPlaylist*>& group) {
std::set<std::string> codecs;

for (const MediaPlaylist* playlist : group) {
Expand Down Expand Up @@ -97,7 +99,7 @@ std::set<std::string> GetGroupCodecString(
}

std::list<Variant> AudioGroupsToVariants(
const std::map<std::string, std::list<const MediaPlaylist*>>& groups) {
const std::map<std::string, std::vector<const MediaPlaylist*>>& groups) {
std::list<Variant> variants;

for (const auto& group : groups) {
Expand Down Expand Up @@ -139,7 +141,7 @@ const char* GetGroupId(const MediaPlaylist& playlist) {
}

std::list<Variant> SubtitleGroupsToVariants(
const std::map<std::string, std::list<const MediaPlaylist*>>& groups) {
const std::map<std::string, std::vector<const MediaPlaylist*>>& groups) {
std::list<Variant> variants;

for (const auto& group : groups) {
Expand All @@ -160,8 +162,9 @@ std::list<Variant> SubtitleGroupsToVariants(
}

std::list<Variant> BuildVariants(
const std::map<std::string, std::list<const MediaPlaylist*>>& audio_groups,
const std::map<std::string, std::list<const MediaPlaylist*>>&
const std::map<std::string, std::vector<const MediaPlaylist*>>&
audio_groups,
const std::map<std::string, std::vector<const MediaPlaylist*>>&
subtitle_groups) {
std::list<Variant> audio_variants = AudioGroupsToVariants(audio_groups);
std::list<Variant> subtitle_variants =
Expand Down Expand Up @@ -358,7 +361,7 @@ void BuildMediaTag(const MediaPlaylist& playlist,
}

void BuildMediaTags(
const std::map<std::string, std::list<const MediaPlaylist*>>& groups,
const std::map<std::string, std::vector<const MediaPlaylist*>>& groups,
const std::string& default_language,
const std::string& base_url,
std::string* out) {
Expand Down Expand Up @@ -410,11 +413,12 @@ void AppendPlaylists(const std::string& default_audio_language,
const std::string& base_url,
const std::list<MediaPlaylist*>& playlists,
std::string* content) {
std::map<std::string, std::list<const MediaPlaylist*>> audio_playlist_groups;
std::map<std::string, std::list<const MediaPlaylist*>>
std::map<std::string, std::vector<const MediaPlaylist*>>
audio_playlist_groups;
std::map<std::string, std::vector<const MediaPlaylist*>>
subtitle_playlist_groups;
std::list<const MediaPlaylist*> video_playlists;
std::list<const MediaPlaylist*> iframe_playlists;
std::vector<const MediaPlaylist*> video_playlists;
std::vector<const MediaPlaylist*> iframe_playlists;
for (const MediaPlaylist* playlist : playlists) {
switch (playlist->stream_type()) {
case MediaPlaylist::MediaPlaylistStreamType::kAudio:
Expand All @@ -435,6 +439,20 @@ void AppendPlaylists(const std::string& default_audio_language,
}
}

// Sort the streams by input order in the command line.
auto comparator = [](const MediaPlaylist* a, const MediaPlaylist* b) {
return a->output_order() < b->output_order();
};
for (auto& it : audio_playlist_groups) {
std::stable_sort(it.second.begin(), it.second.end(), comparator);
}
for (auto& it : subtitle_playlist_groups) {
std::stable_sort(it.second.begin(), it.second.end(), comparator);
}
std::stable_sort(video_playlists.begin(), video_playlists.end(), comparator);
std::stable_sort(iframe_playlists.begin(), iframe_playlists.end(),
comparator);

if (!audio_playlist_groups.empty()) {
content->append("\n");
BuildMediaTags(audio_playlist_groups, default_audio_language, base_url,
Expand Down
6 changes: 3 additions & 3 deletions packager/hls/base/master_playlist_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
const char kNoGroup[] = "";

std::unique_ptr<MockMediaPlaylist> playlist(
new MockMediaPlaylist(filename, kNoName, kNoGroup));
new MockMediaPlaylist(filename, kNoName, kNoGroup, 0));

playlist->SetStreamTypeForTesting(
MediaPlaylist::MediaPlaylistStreamType::kVideo);
Expand Down Expand Up @@ -91,7 +91,7 @@ std::unique_ptr<MockMediaPlaylist> CreateAudioPlaylist(
bool ac4_ims_flag,
bool ac4_cbi_flag) {
std::unique_ptr<MockMediaPlaylist> playlist(
new MockMediaPlaylist(filename, name, group));
new MockMediaPlaylist(filename, name, group, 0));

EXPECT_CALL(*playlist, GetNumChannels()).WillRepeatedly(Return(channels));
EXPECT_CALL(*playlist, GetEC3JocComplexity())
Expand Down Expand Up @@ -123,7 +123,7 @@ std::unique_ptr<MockMediaPlaylist> CreateTextPlaylist(
const std::string& codec,
const std::string& language) {
std::unique_ptr<MockMediaPlaylist> playlist(
new MockMediaPlaylist(filename, name, group));
new MockMediaPlaylist(filename, name, group, 0));

playlist->SetStreamTypeForTesting(
MediaPlaylist::MediaPlaylistStreamType::kSubtitle);
Expand Down
12 changes: 7 additions & 5 deletions packager/hls/base/media_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,18 @@ HlsEntry::~HlsEntry() {}
MediaPlaylist::MediaPlaylist(const HlsParams& hls_params,
const std::string& file_name,
const std::string& name,
const std::string& group_id)
const std::string& group_id,
int output_order)
: hls_params_(hls_params),
file_name_(file_name),
name_(name),
group_id_(group_id),
output_order_(output_order),
media_sequence_number_(hls_params_.media_sequence_number) {
// When there's a forced media_sequence_number, start with discontinuity
if (media_sequence_number_ > 0)
entries_.emplace_back(new DiscontinuityEntry());
}
// When there's a forced media_sequence_number, start with discontinuity
if (media_sequence_number_ > 0)
entries_.emplace_back(new DiscontinuityEntry());
}

MediaPlaylist::~MediaPlaylist() {}

Expand Down
5 changes: 4 additions & 1 deletion packager/hls/base/media_playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ class MediaPlaylist {
MediaPlaylist(const HlsParams& hls_params,
const std::string& file_name,
const std::string& name,
const std::string& group_id);
const std::string& group_id,
int output_order);
virtual ~MediaPlaylist();

const std::string& file_name() const { return file_name_; }
const std::string& name() const { return name_; }
const std::string& group_id() const { return group_id_; }
int output_order() const { return output_order_; }
MediaPlaylistStreamType stream_type() const { return stream_type_; }
const std::string& codec() const { return codec_; }

Expand Down Expand Up @@ -253,6 +255,7 @@ class MediaPlaylist {
const std::string file_name_;
const std::string name_;
const std::string group_id_;
int output_order_;
MediaInfo media_info_;
MediaPlaylistStreamType stream_type_ = MediaPlaylistStreamType::kUnknown;
// Whether to use byte range for SegmentInfoEntry.
Expand Down
4 changes: 2 additions & 2 deletions packager/hls/base/media_playlist_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class MediaPlaylistTest : public ::testing::Test {
default_group_id_("default_group_id") {
hls_params_.playlist_type = type;
hls_params_.time_shift_buffer_depth = kTimeShiftBufferDepth;
media_playlist_.reset(new MediaPlaylist(hls_params_, default_file_name_,
default_name_, default_group_id_));
media_playlist_.reset(new MediaPlaylist(
hls_params_, default_file_name_, default_name_, default_group_id_, 0));
}

void SetUp() override {
Expand Down
5 changes: 3 additions & 2 deletions packager/hls/base/mock_media_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ namespace hls {

MockMediaPlaylist::MockMediaPlaylist(const std::string& file_name,
const std::string& name,
const std::string& group_id)
: MediaPlaylist(HlsParams(), file_name, name, group_id) {}
const std::string& group_id,
int output_order)
: MediaPlaylist(HlsParams(), file_name, name, group_id, output_order) {}
MockMediaPlaylist::~MockMediaPlaylist() {}

} // namespace hls
Expand Down
3 changes: 2 additions & 1 deletion packager/hls/base/mock_media_playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class MockMediaPlaylist : public MediaPlaylist {
// matter because the return value can be mocked.
MockMediaPlaylist(const std::string& file_name,
const std::string& name,
const std::string& group_id);
const std::string& group_id,
int output_order);
~MockMediaPlaylist() override;

MOCK_METHOD1(SetMediaInfo, bool(const MediaInfo& media_info));
Expand Down
8 changes: 5 additions & 3 deletions packager/hls/base/simple_hls_notifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,10 @@ std::unique_ptr<MediaPlaylist> MediaPlaylistFactory::Create(
const HlsParams& hls_params,
const std::string& file_name,
const std::string& name,
const std::string& group_id) {
const std::string& group_id,
int output_order) {
return std::unique_ptr<MediaPlaylist>(
new MediaPlaylist(hls_params, file_name, name, group_id));
new MediaPlaylist(hls_params, file_name, name, group_id, output_order));
}

SimpleHlsNotifier::SimpleHlsNotifier(const HlsParams& hls_params)
Expand Down Expand Up @@ -304,6 +305,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
const std::string& playlist_name,
const std::string& name,
const std::string& group_id,
int output_order,
uint32_t* stream_id) {
DCHECK(stream_id);

Expand All @@ -312,7 +314,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,

std::unique_ptr<MediaPlaylist> media_playlist =
media_playlist_factory_->Create(hls_params(), relative_playlist_path,
name, group_id);
name, group_id, output_order);
MediaInfo adjusted_media_info = MakeMediaInfoPathsRelativeToPlaylist(
media_info, hls_params().base_url, master_playlist_dir_,
media_playlist->file_name());
Expand Down
4 changes: 3 additions & 1 deletion packager/hls/base/simple_hls_notifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class MediaPlaylistFactory {
virtual std::unique_ptr<MediaPlaylist> Create(const HlsParams& hls_params,
const std::string& file_name,
const std::string& name,
const std::string& group_id);
const std::string& group_id,
int output_order);
};

/// This is thread safe.
Expand All @@ -48,6 +49,7 @@ class SimpleHlsNotifier : public HlsNotifier {
const std::string& playlist_name,
const std::string& stream_name,
const std::string& group_id,
int output_order,
uint32_t* stream_id) override;
bool NotifySampleDuration(uint32_t stream_id,
int32_t sample_duration) override;
Expand Down
Loading