HLS with fragmented MP4
- 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
This commit is contained in:
parent
cc04698460
commit
4891d9a6bf
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
|
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue