Skip to content

Commit

Permalink
[HLS] Support audio only master playlist
Browse files Browse the repository at this point in the history
Generate an audio only master playlist if there are no videos and
subtitles.

We do not support mixing audio only EXT-X-STREAM-INF with video
EXT-X-STREAM-INF right now.

Fixes #461.

Change-Id: I999b335ad7abbe183ffcb0f5d471948977c2772f
  • Loading branch information
kqyang committed Dec 13, 2018
1 parent cd7640a commit 89611a5
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>

#EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2"

#EXT-X-STREAM-INF:BANDWIDTH=133850,AVERAGE-BANDWIDTH=126393,CODECS="mp4a.40.2",AUDIO="default-audio-group"
bear-640x360-audio.m3u8
3 changes: 3 additions & 0 deletions packager/app/test/testdata/flac-with-encryption/output.m3u8
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>

#EXT-X-MEDIA:TYPE=AUDIO,URI="stream_0.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2"

#EXT-X-STREAM-INF:BANDWIDTH=672924,AVERAGE-BANDWIDTH=631380,CODECS="flac",AUDIO="default-audio-group"
stream_0.m3u8
23 changes: 21 additions & 2 deletions packager/hls/base/master_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,

std::string tag_name;
switch (playlist.stream_type()) {
case MediaPlaylist::MediaPlaylistStreamType::kAudio:
case MediaPlaylist::MediaPlaylistStreamType::kVideo:
tag_name = "#EXT-X-STREAM-INF";
break;
Expand Down Expand Up @@ -219,8 +220,9 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,

uint32_t width;
uint32_t height;
CHECK(playlist.GetDisplayResolution(&width, &height));
tag.AddNumberPair("RESOLUTION", width, 'x', height);
if (playlist.GetDisplayResolution(&width, &height)) {
tag.AddNumberPair("RESOLUTION", width, 'x', height);
}

if (variant.audio_group_id) {
tag.AddQuotedString("AUDIO", *variant.audio_group_id);
Expand Down Expand Up @@ -403,6 +405,23 @@ void AppendPlaylists(const std::string& default_audio_language,
BuildStreamInfTag(*playlist, Variant(), base_url, content);
}
}

// Generate audio-only master playlist when there are no videos and subtitles.
if (!audio_playlist_groups.empty() && video_playlists.empty() &&
subtitle_playlist_groups.empty()) {
content->append("\n");
for (const auto& playlist_group : audio_playlist_groups) {
Variant variant;
// Populate |audio_group_id|, which will be propagated to "AUDIO" field.
// Leaving other fields, e.g. xxx_audio_bitrate in |Variant|, as
// null/empty/zero intentionally as the information is already available
// in audio |playlist|.
variant.audio_group_id = &playlist_group.first;
for (const auto& playlist : playlist_group.second) {
BuildStreamInfTag(*playlist, variant, base_url, content);
}
}
}
}

} // namespace
Expand Down
54 changes: 53 additions & 1 deletion packager/hls/base/master_playlist_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ std::unique_ptr<MockMediaPlaylist> CreateAudioPlaylist(
EXPECT_CALL(*playlist, AvgBitrate())
.Times(AtLeast(1))
.WillRepeatedly(Return(avg_bitrate));
EXPECT_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull())).Times(0);
ON_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull()))
.WillByDefault(Return(false));

return playlist;
}
Expand Down Expand Up @@ -640,5 +641,56 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {

ASSERT_EQ(expected, actual);
}

TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnly) {
const uint64_t kAudioChannels = 2;
const uint64_t kAudioMaxBitrate = 50000;
const uint64_t kAudioAvgBitrate = 30000;

std::unique_ptr<MockMediaPlaylist> media_playlists[] = {
// AUDIO
CreateAudioPlaylist("audio-1.m3u8", "audio 1", "audio-group-1",
"audiocodec", "en", kAudioChannels, kAudioMaxBitrate,
kAudioAvgBitrate),
CreateAudioPlaylist("audio-2.m3u8", "audio 2", "audio-group-2",
"audiocodec", "fr", kAudioChannels, kAudioMaxBitrate,
kAudioAvgBitrate),
};

// Add all the media playlists to the master playlist.
std::list<MediaPlaylist*> media_playlist_list;
for (const auto& media_playlist : media_playlists) {
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_.c_str(), &actual));

const std::string expected =
"#EXTM3U\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\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"
"#EXT-X-MEDIA:TYPE=AUDIO,URI=\"http://playlists.org/audio-2.m3u8\","
"GROUP-ID=\"audio-group-2\",LANGUAGE=\"fr\",NAME=\"audio 2\","
"AUTOSELECT=YES,CHANNELS=\"2\"\n"
"\n"
"#EXT-X-STREAM-INF:BANDWIDTH=50000,AVERAGE-BANDWIDTH=30000,"
"CODECS=\"audiocodec\",AUDIO=\"audio-group-1\"\n"
"http://playlists.org/audio-1.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=50000,AVERAGE-BANDWIDTH=30000,"
"CODECS=\"audiocodec\",AUDIO=\"audio-group-2\"\n"
"http://playlists.org/audio-2.m3u8\n";

ASSERT_EQ(expected, actual);
}

} // namespace hls
} // namespace shaka

0 comments on commit 89611a5

Please # to comment.