Skip to content

Commit

Permalink
HLS with fragmented MP4
Browse files Browse the repository at this point in the history
- Add EXT-X-MAP tag for init segment.
- Do not set output field on stream descriptor if not specified on
  command line. If it's set (internally) then it gets copied to
  MediaInfo that gets passed to the manifest generators.

b/36279481

Change-Id: I762c55b255699ec691817dc4806b0dee2f7504b8
  • Loading branch information
Rintaro Kuroiwa committed Mar 27, 2017
1 parent cc04698 commit 4891d9a
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 34 deletions.
2 changes: 1 addition & 1 deletion packager/app/packager_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
remux_jobs->emplace_back(new RemuxJob(std::move(demuxer)));
previous_input = stream_iter->input;
// Skip setting up muxers if output is not needed.
if (stream_iter->output.empty())
if (stream_iter->output.empty() && stream_iter->segment_template.empty())
continue;
}
DCHECK(!remux_jobs->empty());
Expand Down
11 changes: 7 additions & 4 deletions packager/app/stream_descriptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,15 @@ bool InsertStreamDescriptor(const std::string& descriptor_string,
<< "' ignored. TS muxer does not support initialization "
"segment generation.";
}
// For convenience, set descriptor.output to descriptor.segment_template. It
// is only used for flag checking in variuos places.
descriptor.output = descriptor.segment_template;
}

if (!FLAGS_dump_stream_info && descriptor.output.empty()) {
// For TS output, segment template is sufficient, and does not require an
// output entry.
const bool output_specified =
!descriptor.output.empty() ||
(descriptor.output_format == CONTAINER_MPEG2TS &&
!descriptor.segment_template.empty());
if (!FLAGS_dump_stream_info && !output_specified) {
LOG(ERROR) << "Stream output not specified.";
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion packager/app/test/testdata/bear-640x360-a-enc-golden.m3u8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#EXTM3U
#EXT-X-VERSION:5
#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
Expand Down
2 changes: 1 addition & 1 deletion packager/app/test/testdata/bear-640x360-a-golden.m3u8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#EXTM3U
#EXT-X-VERSION:5
#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
Expand Down
2 changes: 1 addition & 1 deletion packager/app/test/testdata/bear-640x360-v-enc-golden.m3u8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#EXTM3U
#EXT-X-VERSION:5
#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
Expand Down
2 changes: 1 addition & 1 deletion packager/app/test/testdata/bear-640x360-v-golden.m3u8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#EXTM3U
#EXT-X-VERSION:5
#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
Expand Down
53 changes: 35 additions & 18 deletions packager/hls/base/media_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,39 @@ uint32_t GetTimeScale(const MediaInfo& media_info) {
return 0u;
}

std::string CreatePlaylistHeader(
const std::string& init_segment_name,
uint32_t target_duration,
MediaPlaylist::MediaPlaylistType type) {
const std::string version = GetPackagerVersion();
std::string version_line;
if (!version.empty()) {
version_line =
base::StringPrintf("## Generated with %s version %s\n",
GetPackagerProjectUrl().c_str(), version.c_str());
}

// 6 is required for EXT-X-MAP without EXT-X-I-FRAMES-ONLY.
std::string header = base::StringPrintf(
"#EXTM3U\n"
"#EXT-X-VERSION:6\n"
"%s"
"#EXT-X-TARGETDURATION:%d\n",
version_line.c_str(), target_duration);

if (type == MediaPlaylist::MediaPlaylistType::kVod) {
header += "#EXT-X-PLAYLIST-TYPE:VOD\n";
}

// Put EXT-X-MAP at the end since the rest of the playlist is about the
// segment and key info.
if (!init_segment_name.empty()) {
header += "#EXT-X-MAP:URI=\"" + init_segment_name + "\"\n";
}

return header;
}

class SegmentInfoEntry : public HlsEntry {
public:
SegmentInfoEntry(const std::string& file_name, double duration);
Expand Down Expand Up @@ -266,24 +299,8 @@ bool MediaPlaylist::WriteToFile(media::File* file) {
SetTargetDuration(ceil(GetLongestSegmentDuration()));
}

const std::string version = GetPackagerVersion();
std::string version_line;
if (!version.empty()) {
version_line =
base::StringPrintf("## Generated with %s version %s\n",
GetPackagerProjectUrl().c_str(), version.c_str());
}

// KEYFORMAT and KEYFORMATVERSIONS on EXT-X-KEY requires 5 or above.
std::string header = base::StringPrintf(
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"%s"
"#EXT-X-TARGETDURATION:%d\n",
version_line.c_str(), target_duration_);
if (type_ == MediaPlaylistType::kVod) {
header += "#EXT-X-PLAYLIST-TYPE:VOD\n";
}
std::string header = CreatePlaylistHeader(media_info_.init_segment_name(),
target_duration_, type_);

std::string body;
if (!entries_.empty()) {
Expand Down
44 changes: 37 additions & 7 deletions packager/hls/base/media_playlist_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ TEST_F(MediaPlaylistTest, WriteToFile) {
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:0\n"
Expand Down Expand Up @@ -176,7 +176,7 @@ TEST_F(MediaPlaylistTest, SetTargetDuration) {
EXPECT_TRUE(media_playlist_.SetTargetDuration(20));
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:20\n"
Expand Down Expand Up @@ -204,7 +204,7 @@ TEST_F(MediaPlaylistTest, WriteToFileWithSegments) {
media_playlist_.AddSegment("file2.ts", 2700000, 5000000);
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:30\n"
Expand Down Expand Up @@ -235,7 +235,7 @@ TEST_F(MediaPlaylistTest, WriteToFileWithEncryptionInfo) {
media_playlist_.AddSegment("file2.ts", 2700000, 5000000);
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:30\n"
Expand Down Expand Up @@ -269,7 +269,7 @@ TEST_F(MediaPlaylistTest, WriteToFileWithEncryptionInfoEmptyIv) {
media_playlist_.AddSegment("file2.ts", 2700000, 5000000);
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:30\n"
Expand Down Expand Up @@ -302,7 +302,7 @@ TEST_F(MediaPlaylistTest, WriteToFileWithClearLead) {
media_playlist_.AddSegment("file2.ts", 2700000, 5000000);
const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version test\n"
"#EXT-X-TARGETDURATION:30\n"
"#EXT-X-PLAYLIST-TYPE:VOD\n"
Expand Down Expand Up @@ -336,7 +336,7 @@ TEST_F(MediaPlaylistTest, RemoveOldestSegment) {

const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:5\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version "
"test\n"
"#EXT-X-TARGETDURATION:30\n"
Expand Down Expand Up @@ -370,5 +370,35 @@ TEST_F(MediaPlaylistTest, GetLanguage) {
EXPECT_EQ("apa", media_playlist_.GetLanguage()); // no short form exists
}

TEST_F(MediaPlaylistTest, InitSegment) {
valid_video_media_info_.set_reference_time_scale(90000);
valid_video_media_info_.set_init_segment_name("init_segment.mp4");
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));

// 10 seconds.
media_playlist_.AddSegment("file1.mp4", 900000, 1000000);
// 30 seconds.
media_playlist_.AddSegment("file2.mp4", 2700000, 5000000);

const std::string kExpectedOutput =
"#EXTM3U\n"
"#EXT-X-VERSION:6\n"
"## Generated with https://github.com/google/shaka-packager version test\n"
"#EXT-X-TARGETDURATION:30\n"
"#EXT-X-PLAYLIST-TYPE:VOD\n"
"#EXT-X-MAP:URI=\"init_segment.mp4\"\n"
"#EXTINF:10.000,\n"
"file1.mp4\n"
"#EXTINF:30.000,\n"
"file2.mp4\n"
"#EXT-X-ENDLIST\n";

MockFile file;
EXPECT_CALL(file,
Write(MatchesString(kExpectedOutput), kExpectedOutput.size()))
.WillOnce(ReturnArg<1>());
EXPECT_TRUE(media_playlist_.WriteToFile(&file));
}

} // namespace hls
} // namespace shaka

0 comments on commit 4891d9a

Please sign in to comment.