Add Text Codec To Codec String
This change has the hls master playlist add the text codec string to the list of codecs in a variant. Bug: 72942756 Change-Id: Ib25bb2064a291d10d7b1d261a4307991df62220c
This commit is contained in:
parent
c7929b1505
commit
30b5fdf19f
|
@ -5,5 +5,5 @@
|
||||||
|
|
||||||
#EXT-X-MEDIA:TYPE=SUBTITLES,URI="stream_0.m3u8",GROUP-ID="default-text-group",NAME="stream_0",AUTOSELECT=YES
|
#EXT-X-MEDIA:TYPE=SUBTITLES,URI="stream_0.m3u8",GROUP-ID="default-text-group",NAME="stream_0",AUTOSELECT=YES
|
||||||
|
|
||||||
#EXT-X-STREAM-INF:BANDWIDTH=1105163,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group"
|
#EXT-X-STREAM-INF:BANDWIDTH=1105163,CODECS="avc1.64001e,mp4a.40.2,wvtt",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group"
|
||||||
stream_2.m3u8
|
stream_2.m3u8
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "packager/base/files/file_path.h"
|
#include "packager/base/files/file_path.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
#include "packager/base/strings/string_util.h"
|
||||||
#include "packager/base/strings/stringprintf.h"
|
#include "packager/base/strings/stringprintf.h"
|
||||||
#include "packager/file/file.h"
|
#include "packager/file/file.h"
|
||||||
#include "packager/hls/base/media_playlist.h"
|
#include "packager/hls/base/media_playlist.h"
|
||||||
|
@ -34,7 +35,8 @@ void AppendVersionString(std::string* content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Variant {
|
struct Variant {
|
||||||
std::string audio_codec;
|
std::set<std::string> audio_codecs;
|
||||||
|
std::set<std::string> text_codecs;
|
||||||
const std::string* audio_group_id = nullptr;
|
const std::string* audio_group_id = nullptr;
|
||||||
const std::string* text_group_id = nullptr;
|
const std::string* text_group_id = nullptr;
|
||||||
uint64_t audio_bitrate = 0;
|
uint64_t audio_bitrate = 0;
|
||||||
|
@ -48,10 +50,15 @@ uint64_t MaxBitrate(const std::list<const MediaPlaylist*> playlists) {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetAudioGroupCodecString(
|
std::set<std::string> GetGroupCodecString(
|
||||||
const std::list<const MediaPlaylist*>& group) {
|
const std::list<const MediaPlaylist*>& group) {
|
||||||
// TODO(vaage): Should be a concatenation of all the codecs in the group.
|
std::set<std::string> codecs;
|
||||||
return group.front()->codec();
|
|
||||||
|
for (const MediaPlaylist* playlist : group) {
|
||||||
|
codecs.insert(playlist->codec());
|
||||||
|
}
|
||||||
|
|
||||||
|
return codecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Variant> AudioGroupsToVariants(
|
std::list<Variant> AudioGroupsToVariants(
|
||||||
|
@ -60,9 +67,9 @@ std::list<Variant> AudioGroupsToVariants(
|
||||||
|
|
||||||
for (const auto& group : groups) {
|
for (const auto& group : groups) {
|
||||||
Variant variant;
|
Variant variant;
|
||||||
variant.audio_codec = GetAudioGroupCodecString(group.second);
|
|
||||||
variant.audio_group_id = &group.first;
|
variant.audio_group_id = &group.first;
|
||||||
variant.audio_bitrate = MaxBitrate(group.second);
|
variant.audio_bitrate = MaxBitrate(group.second);
|
||||||
|
variant.audio_codecs = GetGroupCodecString(group.second);
|
||||||
|
|
||||||
variants.push_back(variant);
|
variants.push_back(variant);
|
||||||
}
|
}
|
||||||
|
@ -102,6 +109,7 @@ std::list<Variant> SubtitleGroupsToVariants(
|
||||||
for (const auto& group : groups) {
|
for (const auto& group : groups) {
|
||||||
Variant variant;
|
Variant variant;
|
||||||
variant.text_group_id = &group.first;
|
variant.text_group_id = &group.first;
|
||||||
|
variant.text_codecs = GetGroupCodecString(group.second);
|
||||||
|
|
||||||
variants.push_back(variant);
|
variants.push_back(variant);
|
||||||
}
|
}
|
||||||
|
@ -131,7 +139,8 @@ std::list<Variant> BuildVariants(
|
||||||
for (const auto& audio_variant : audio_variants) {
|
for (const auto& audio_variant : audio_variants) {
|
||||||
for (const auto& subtitle_variant : subtitle_variants) {
|
for (const auto& subtitle_variant : subtitle_variants) {
|
||||||
Variant variant;
|
Variant variant;
|
||||||
variant.audio_codec = audio_variant.audio_codec;
|
variant.audio_codecs = audio_variant.audio_codecs;
|
||||||
|
variant.text_codecs = subtitle_variant.text_codecs;
|
||||||
variant.audio_group_id = audio_variant.audio_group_id;
|
variant.audio_group_id = audio_variant.audio_group_id;
|
||||||
variant.text_group_id = subtitle_variant.text_group_id;
|
variant.text_group_id = subtitle_variant.text_group_id;
|
||||||
variant.audio_bitrate = audio_variant.audio_bitrate;
|
variant.audio_bitrate = audio_variant.audio_bitrate;
|
||||||
|
@ -151,17 +160,6 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
|
||||||
std::string* out) {
|
std::string* out) {
|
||||||
DCHECK(out);
|
DCHECK(out);
|
||||||
|
|
||||||
const uint64_t bitrate = playlist.Bitrate() + variant.audio_bitrate;
|
|
||||||
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
CHECK(playlist.GetDisplayResolution(&width, &height));
|
|
||||||
|
|
||||||
std::string codecs = playlist.codec();
|
|
||||||
if (!variant.audio_codec.empty()) {
|
|
||||||
base::StringAppendF(&codecs, ",%s", variant.audio_codec.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tag_name;
|
std::string tag_name;
|
||||||
switch (playlist.stream_type()) {
|
switch (playlist.stream_type()) {
|
||||||
case MediaPlaylist::MediaPlaylistStreamType::kVideo:
|
case MediaPlaylist::MediaPlaylistStreamType::kVideo:
|
||||||
|
@ -177,8 +175,20 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
|
||||||
}
|
}
|
||||||
Tag tag(tag_name, out);
|
Tag tag(tag_name, out);
|
||||||
|
|
||||||
|
const uint64_t bitrate = playlist.Bitrate() + variant.audio_bitrate;
|
||||||
tag.AddNumber("BANDWIDTH", bitrate);
|
tag.AddNumber("BANDWIDTH", bitrate);
|
||||||
tag.AddQuotedString("CODECS", codecs);
|
|
||||||
|
std::vector<std::string> all_codecs;
|
||||||
|
all_codecs.push_back(playlist.codec());
|
||||||
|
all_codecs.insert(all_codecs.end(), variant.audio_codecs.begin(),
|
||||||
|
variant.audio_codecs.end());
|
||||||
|
all_codecs.insert(all_codecs.end(), variant.text_codecs.begin(),
|
||||||
|
variant.text_codecs.end());
|
||||||
|
tag.AddQuotedString("CODECS", base::JoinString(all_codecs, ","));
|
||||||
|
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
CHECK(playlist.GetDisplayResolution(&width, &height));
|
||||||
tag.AddNumberPair("RESOLUTION", width, 'x', height);
|
tag.AddNumberPair("RESOLUTION", width, 'x', height);
|
||||||
|
|
||||||
if (variant.audio_group_id) {
|
if (variant.audio_group_id) {
|
||||||
|
|
|
@ -97,6 +97,7 @@ std::unique_ptr<MockMediaPlaylist> CreateTextPlaylist(
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& group,
|
const std::string& group,
|
||||||
|
const std::string& codec,
|
||||||
const std::string& language) {
|
const std::string& language) {
|
||||||
std::unique_ptr<MockMediaPlaylist> playlist(
|
std::unique_ptr<MockMediaPlaylist> playlist(
|
||||||
new MockMediaPlaylist(kVodPlaylist, filename, name, group));
|
new MockMediaPlaylist(kVodPlaylist, filename, name, group));
|
||||||
|
@ -104,6 +105,7 @@ std::unique_ptr<MockMediaPlaylist> CreateTextPlaylist(
|
||||||
EXPECT_CALL(*playlist, GetLanguage()).WillRepeatedly(Return(language));
|
EXPECT_CALL(*playlist, GetLanguage()).WillRepeatedly(Return(language));
|
||||||
playlist->SetStreamTypeForTesting(
|
playlist->SetStreamTypeForTesting(
|
||||||
MediaPlaylist::MediaPlaylistStreamType::kSubtitle);
|
MediaPlaylist::MediaPlaylistStreamType::kSubtitle);
|
||||||
|
playlist->SetCodecForTesting(codec);
|
||||||
|
|
||||||
return playlist;
|
return playlist;
|
||||||
}
|
}
|
||||||
|
@ -336,11 +338,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
|
||||||
|
|
||||||
// Text, eng.m3u8.
|
// Text, eng.m3u8.
|
||||||
std::unique_ptr<MockMediaPlaylist> text_eng =
|
std::unique_ptr<MockMediaPlaylist> text_eng =
|
||||||
CreateTextPlaylist("eng.m3u8", "english", "textgroup", "en");
|
CreateTextPlaylist("eng.m3u8", "english", "textgroup", "textcodec", "en");
|
||||||
|
|
||||||
// Text, fr.m3u8.
|
// Text, fr.m3u8.
|
||||||
std::unique_ptr<MockMediaPlaylist> text_fr =
|
std::unique_ptr<MockMediaPlaylist> text_fr =
|
||||||
CreateTextPlaylist("fr.m3u8", "french", "textgroup", "fr");
|
CreateTextPlaylist("fr.m3u8", "french", "textgroup", "textcodec", "fr");
|
||||||
|
|
||||||
const char kBaseUrl[] = "http://playlists.org/";
|
const char kBaseUrl[] = "http://playlists.org/";
|
||||||
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
||||||
|
@ -361,10 +363,10 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
|
||||||
"#EXT-X-MEDIA:TYPE=SUBTITLES,URI=\"http://playlists.org/fr.m3u8\","
|
"#EXT-X-MEDIA:TYPE=SUBTITLES,URI=\"http://playlists.org/fr.m3u8\","
|
||||||
"GROUP-ID=\"textgroup\",LANGUAGE=\"fr\",NAME=\"french\",AUTOSELECT=YES\n"
|
"GROUP-ID=\"textgroup\",LANGUAGE=\"fr\",NAME=\"french\",AUTOSELECT=YES\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\","
|
||||||
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n"
|
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n"
|
||||||
"http://playlists.org/sd.m3u8\n"
|
"http://playlists.org/sd.m3u8\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=600000,CODECS=\"sdvideocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=600000,CODECS=\"sdvideocodec,textcodec\","
|
||||||
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n"
|
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n"
|
||||||
"http://playlists.org/hd.m3u8\n";
|
"http://playlists.org/hd.m3u8\n";
|
||||||
|
|
||||||
|
@ -377,12 +379,12 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
|
||||||
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000);
|
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000);
|
||||||
|
|
||||||
// Text, eng.m3u8.
|
// Text, eng.m3u8.
|
||||||
std::unique_ptr<MockMediaPlaylist> text_eng =
|
std::unique_ptr<MockMediaPlaylist> text_eng = CreateTextPlaylist(
|
||||||
CreateTextPlaylist("eng.m3u8", "english", "en-text-group", "en");
|
"eng.m3u8", "english", "en-text-group", "textcodec", "en");
|
||||||
|
|
||||||
// Text, fr.m3u8.
|
// Text, fr.m3u8.
|
||||||
std::unique_ptr<MockMediaPlaylist> text_fr =
|
std::unique_ptr<MockMediaPlaylist> text_fr = CreateTextPlaylist(
|
||||||
CreateTextPlaylist("fr.m3u8", "french", "fr-text-group", "fr");
|
"fr.m3u8", "french", "fr-text-group", "textcodec", "fr");
|
||||||
|
|
||||||
const char kBaseUrl[] = "http://playlists.org/";
|
const char kBaseUrl[] = "http://playlists.org/";
|
||||||
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
||||||
|
@ -404,11 +406,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
|
||||||
"GROUP-ID=\"fr-text-group\",LANGUAGE=\"fr\",NAME=\"french\","
|
"GROUP-ID=\"fr-text-group\",LANGUAGE=\"fr\",NAME=\"french\","
|
||||||
"AUTOSELECT=YES\n"
|
"AUTOSELECT=YES\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\","
|
||||||
"RESOLUTION=800x600,SUBTITLES=\"en-text-group\"\n"
|
"RESOLUTION=800x600,SUBTITLES=\"en-text-group\"\n"
|
||||||
"http://playlists.org/sd.m3u8\n"
|
"http://playlists.org/sd.m3u8\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\","
|
||||||
"RESOLUTION=800x600,SUBTITLES=\"fr-text-group\"\n"
|
"RESOLUTION=800x600,SUBTITLES=\"fr-text-group\"\n"
|
||||||
"http://playlists.org/sd.m3u8\n";
|
"http://playlists.org/sd.m3u8\n";
|
||||||
|
|
||||||
|
@ -426,7 +428,7 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
|
||||||
|
|
||||||
// Text, english.m3u8.
|
// Text, english.m3u8.
|
||||||
std::unique_ptr<MockMediaPlaylist> text =
|
std::unique_ptr<MockMediaPlaylist> text =
|
||||||
CreateTextPlaylist("eng.m3u8", "english", "textgroup", "en");
|
CreateTextPlaylist("eng.m3u8", "english", "textgroup", "textcodec", "en");
|
||||||
|
|
||||||
const char kBaseUrl[] = "http://playlists.org/";
|
const char kBaseUrl[] = "http://playlists.org/";
|
||||||
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
|
||||||
|
@ -448,8 +450,9 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
|
||||||
"GROUP-ID=\"textgroup\",LANGUAGE=\"en\",NAME=\"english\",DEFAULT=YES,"
|
"GROUP-ID=\"textgroup\",LANGUAGE=\"en\",NAME=\"english\",DEFAULT=YES,"
|
||||||
"AUTOSELECT=YES\n"
|
"AUTOSELECT=YES\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audiogroup\",SUBTITLES=\"textgroup\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audiogroup\",SUBTITLES="
|
||||||
|
"\"textgroup\"\n"
|
||||||
"http://playlists.org/sd.m3u8\n";
|
"http://playlists.org/sd.m3u8\n";
|
||||||
|
|
||||||
ASSERT_EQ(expected, actual);
|
ASSERT_EQ(expected, actual);
|
||||||
|
@ -469,8 +472,10 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {
|
||||||
"audiocodec", "en", kAudioChannels, kAudioBitRate),
|
"audiocodec", "en", kAudioChannels, kAudioBitRate),
|
||||||
|
|
||||||
// SUBTITLES
|
// SUBTITLES
|
||||||
CreateTextPlaylist("text-1.m3u8", "text 1", "text-group-1", "en"),
|
CreateTextPlaylist("text-1.m3u8", "text 1", "text-group-1", "textcodec",
|
||||||
CreateTextPlaylist("text-2.m3u8", "text 2", "text-group-2", "en"),
|
"en"),
|
||||||
|
CreateTextPlaylist("text-2.m3u8", "text 2", "text-group-2", "textcodec",
|
||||||
|
"en"),
|
||||||
|
|
||||||
// VIDEO
|
// VIDEO
|
||||||
CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoBitRate),
|
CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoBitRate),
|
||||||
|
@ -513,32 +518,40 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {
|
||||||
"GROUP-ID=\"text-group-2\",LANGUAGE=\"en\",NAME=\"text 2\","
|
"GROUP-ID=\"text-group-2\",LANGUAGE=\"en\",NAME=\"text 2\","
|
||||||
"DEFAULT=YES,AUTOSELECT=YES\n"
|
"DEFAULT=YES,AUTOSELECT=YES\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-"
|
||||||
|
"group-1\"\n"
|
||||||
"http://playlists.org/video-1.m3u8\n"
|
"http://playlists.org/video-1.m3u8\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-"
|
||||||
|
"group-1\"\n"
|
||||||
"http://playlists.org/video-2.m3u8\n"
|
"http://playlists.org/video-2.m3u8\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-"
|
||||||
|
"group-2\"\n"
|
||||||
"http://playlists.org/video-1.m3u8\n"
|
"http://playlists.org/video-1.m3u8\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-"
|
||||||
|
"group-2\"\n"
|
||||||
"http://playlists.org/video-2.m3u8\n"
|
"http://playlists.org/video-2.m3u8\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-"
|
||||||
|
"group-1\"\n"
|
||||||
"http://playlists.org/video-1.m3u8\n"
|
"http://playlists.org/video-1.m3u8\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-"
|
||||||
|
"group-1\"\n"
|
||||||
"http://playlists.org/video-2.m3u8\n"
|
"http://playlists.org/video-2.m3u8\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-"
|
||||||
|
"group-2\"\n"
|
||||||
"http://playlists.org/video-1.m3u8\n"
|
"http://playlists.org/video-1.m3u8\n"
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec\","
|
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec,"
|
||||||
"RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n"
|
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-"
|
||||||
|
"group-2\"\n"
|
||||||
"http://playlists.org/video-2.m3u8\n"
|
"http://playlists.org/video-2.m3u8\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\","
|
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\","
|
||||||
|
|
|
@ -342,7 +342,7 @@ bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) {
|
||||||
codec_ = media_info.audio_info().codec();
|
codec_ = media_info.audio_info().codec();
|
||||||
} else {
|
} else {
|
||||||
stream_type_ = MediaPlaylistStreamType::kSubtitle;
|
stream_type_ = MediaPlaylistStreamType::kSubtitle;
|
||||||
codec_ = media_info.text_info().format();
|
codec_ = media_info.text_info().codec();
|
||||||
}
|
}
|
||||||
|
|
||||||
time_scale_ = time_scale;
|
time_scale_ = time_scale;
|
||||||
|
|
|
@ -103,7 +103,7 @@ TEST_F(MediaPlaylistMultiSegmentTest, SetMediaInfoText) {
|
||||||
MediaInfo media_info;
|
MediaInfo media_info;
|
||||||
media_info.set_reference_time_scale(kTimeScale);
|
media_info.set_reference_time_scale(kTimeScale);
|
||||||
MediaInfo::TextInfo* text_info = media_info.mutable_text_info();
|
MediaInfo::TextInfo* text_info = media_info.mutable_text_info();
|
||||||
text_info->set_format("vtt");
|
text_info->set_codec("wvtt");
|
||||||
EXPECT_TRUE(media_playlist_.SetMediaInfo(media_info));
|
EXPECT_TRUE(media_playlist_.SetMediaInfo(media_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,8 @@ TEST_F(MediaPlaylistSingleSegmentTest, InitRangeWithOffset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closest to the normal use case where there is an init range and then
|
// Closest to the normal use case where there is an init range and then
|
||||||
// subsegment ranges. There is index range between the subsegment and init range.
|
// subsegment ranges. There is index range between the subsegment and init
|
||||||
|
// range.
|
||||||
TEST_F(MediaPlaylistSingleSegmentTest, AddSegmentByteRange) {
|
TEST_F(MediaPlaylistSingleSegmentTest, AddSegmentByteRange) {
|
||||||
const std::string kExpectedOutput =
|
const std::string kExpectedOutput =
|
||||||
"#EXTM3U\n"
|
"#EXTM3U\n"
|
||||||
|
@ -203,8 +204,7 @@ TEST_F(MediaPlaylistSingleSegmentTest, AddSegmentByteRange) {
|
||||||
valid_video_media_info_.mutable_init_range()->set_end(500);
|
valid_video_media_info_.mutable_init_range()->set_end(500);
|
||||||
|
|
||||||
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));
|
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));
|
||||||
media_playlist_.AddSegment("file.mp4", 0, 10 * kTimeScale, 1000,
|
media_playlist_.AddSegment("file.mp4", 0, 10 * kTimeScale, 1000, 1 * kMBytes);
|
||||||
1 * kMBytes);
|
|
||||||
media_playlist_.AddSegment("file.mp4", 10 * kTimeScale, 10 * kTimeScale,
|
media_playlist_.AddSegment("file.mp4", 10 * kTimeScale, 10 * kTimeScale,
|
||||||
1001000, 2 * kMBytes);
|
1001000, 2 * kMBytes);
|
||||||
|
|
||||||
|
@ -381,8 +381,8 @@ TEST_F(MediaPlaylistMultiSegmentTest, WriteToFileWithEncryptionInfoEmptyIv) {
|
||||||
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));
|
ASSERT_TRUE(media_playlist_.SetMediaInfo(valid_video_media_info_));
|
||||||
|
|
||||||
media_playlist_.AddEncryptionInfo(MediaPlaylist::EncryptionMethod::kSampleAes,
|
media_playlist_.AddEncryptionInfo(MediaPlaylist::EncryptionMethod::kSampleAes,
|
||||||
"http://example.com", "", "", "com.widevine",
|
"http://example.com", "", "",
|
||||||
"");
|
"com.widevine", "");
|
||||||
media_playlist_.AddSegment("file1.ts", 0, 10 * kTimeScale, kZeroByteOffset,
|
media_playlist_.AddSegment("file1.ts", 0, 10 * kTimeScale, kZeroByteOffset,
|
||||||
kMBytes);
|
kMBytes);
|
||||||
media_playlist_.AddSegment("file2.ts", 10 * kTimeScale, 30 * kTimeScale,
|
media_playlist_.AddSegment("file2.ts", 10 * kTimeScale, 30 * kTimeScale,
|
||||||
|
@ -489,7 +489,8 @@ TEST_F(MediaPlaylistMultiSegmentTest, InitSegment) {
|
||||||
const char kExpectedOutput[] =
|
const char kExpectedOutput[] =
|
||||||
"#EXTM3U\n"
|
"#EXTM3U\n"
|
||||||
"#EXT-X-VERSION:6\n"
|
"#EXT-X-VERSION:6\n"
|
||||||
"## Generated with https://github.com/google/shaka-packager version test\n"
|
"## Generated with https://github.com/google/shaka-packager version "
|
||||||
|
"test\n"
|
||||||
"#EXT-X-TARGETDURATION:30\n"
|
"#EXT-X-TARGETDURATION:30\n"
|
||||||
"#EXT-X-PLAYLIST-TYPE:VOD\n"
|
"#EXT-X-PLAYLIST-TYPE:VOD\n"
|
||||||
"#EXT-X-MAP:URI=\"init_segment.mp4\"\n"
|
"#EXT-X-MAP:URI=\"init_segment.mp4\"\n"
|
||||||
|
|
|
@ -128,31 +128,22 @@ void AddAudioInfo(const AudioStreamInfo* audio_stream_info,
|
||||||
|
|
||||||
void AddTextInfo(const TextStreamInfo& text_stream_info,
|
void AddTextInfo(const TextStreamInfo& text_stream_info,
|
||||||
MediaInfo* media_info) {
|
MediaInfo* media_info) {
|
||||||
MediaInfo::TextInfo* text_info = media_info->mutable_text_info();
|
|
||||||
// For now, set everything as subtitle.
|
// For now, set everything as subtitle.
|
||||||
|
MediaInfo::TextInfo* text_info = media_info->mutable_text_info();
|
||||||
text_info->set_type(MediaInfo::TextInfo::SUBTITLE);
|
text_info->set_type(MediaInfo::TextInfo::SUBTITLE);
|
||||||
if (text_stream_info.codec_string() == "wvtt") {
|
text_info->set_codec(text_stream_info.codec_string());
|
||||||
text_info->set_format("vtt");
|
|
||||||
} else {
|
|
||||||
LOG(WARNING) << "Unhandled codec " << text_stream_info.codec_string()
|
|
||||||
<< " copying it as format.";
|
|
||||||
text_info->set_format(text_stream_info.codec_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
text_info->set_language(text_stream_info.language());
|
text_info->set_language(text_stream_info.language());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMediaInfoStreamInfo(const StreamInfo& stream_info,
|
void SetMediaInfoStreamInfo(const StreamInfo& stream_info,
|
||||||
MediaInfo* media_info) {
|
MediaInfo* media_info) {
|
||||||
if (stream_info.stream_type() == kStreamAudio) {
|
if (stream_info.stream_type() == kStreamAudio) {
|
||||||
AddAudioInfo(static_cast<const AudioStreamInfo*>(&stream_info),
|
AddAudioInfo(static_cast<const AudioStreamInfo*>(&stream_info), media_info);
|
||||||
media_info);
|
|
||||||
} else if (stream_info.stream_type() == kStreamText) {
|
} else if (stream_info.stream_type() == kStreamText) {
|
||||||
AddTextInfo(static_cast<const TextStreamInfo&>(stream_info), media_info);
|
AddTextInfo(static_cast<const TextStreamInfo&>(stream_info), media_info);
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(stream_info.stream_type(), kStreamVideo);
|
DCHECK_EQ(stream_info.stream_type(), kStreamVideo);
|
||||||
AddVideoInfo(static_cast<const VideoStreamInfo*>(&stream_info),
|
AddVideoInfo(static_cast<const VideoStreamInfo*>(&stream_info), media_info);
|
||||||
media_info);
|
|
||||||
}
|
}
|
||||||
if (stream_info.duration() > 0) {
|
if (stream_info.duration() > 0) {
|
||||||
// |stream_info.duration()| contains the media duration from the original
|
// |stream_info.duration()| contains the media duration from the original
|
||||||
|
@ -204,7 +195,6 @@ bool SetVodInformation(const MuxerListener::MediaRanges& media_ranges,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (media_ranges.init_range) {
|
if (media_ranges.init_range) {
|
||||||
SetRange(media_ranges.init_range->start, media_ranges.init_range->end,
|
SetRange(media_ranges.init_range->start, media_ranges.init_range->end,
|
||||||
media_info->mutable_init_range());
|
media_info->mutable_init_range());
|
||||||
|
|
|
@ -109,7 +109,7 @@ TEST_F(AdaptationSetTest, CheckAdaptationSetAudioContentType) {
|
||||||
TEST_F(AdaptationSetTest, CheckAdaptationSetTextContentType) {
|
TEST_F(AdaptationSetTest, CheckAdaptationSetTextContentType) {
|
||||||
const char kTextMediaInfo[] =
|
const char kTextMediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'ttml'\n"
|
" codec: 'ttml'\n"
|
||||||
" language: 'en'\n"
|
" language: 'en'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_TEXT\n";
|
"container_type: CONTAINER_TEXT\n";
|
||||||
|
@ -1072,7 +1072,7 @@ TEST_F(OnDemandAdaptationSetTest,
|
||||||
TEST_F(OnDemandAdaptationSetTest, Text) {
|
TEST_F(OnDemandAdaptationSetTest, Text) {
|
||||||
const char kTextMediaInfo[] =
|
const char kTextMediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'ttml'\n"
|
" codec: 'ttml'\n"
|
||||||
" language: 'en'\n"
|
" language: 'en'\n"
|
||||||
" type: SUBTITLE\n"
|
" type: SUBTITLE\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
|
@ -68,7 +68,7 @@ message MediaInfo {
|
||||||
CAPTION = 1;
|
CAPTION = 1;
|
||||||
SUBTITLE = 2;
|
SUBTITLE = 2;
|
||||||
}
|
}
|
||||||
optional string format = 1;
|
optional string codec = 1;
|
||||||
optional string language = 2;
|
optional string language = 2;
|
||||||
optional TextType type = 3;
|
optional TextType type = 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,20 +30,22 @@ bool IsKeyRotationDefaultKeyId(const std::string& key_id) {
|
||||||
|
|
||||||
std::string TextCodecString(const MediaInfo& media_info) {
|
std::string TextCodecString(const MediaInfo& media_info) {
|
||||||
CHECK(media_info.has_text_info());
|
CHECK(media_info.has_text_info());
|
||||||
const std::string& format = media_info.text_info().format();
|
const auto container_type = media_info.container_type();
|
||||||
// DASH IOP mentions that the codec for ttml in mp4 is stpp.
|
|
||||||
if (format == "ttml" &&
|
// Codecs are not needed when mimeType is "text/*". Having a codec would be
|
||||||
(media_info.container_type() == MediaInfo::CONTAINER_MP4)) {
|
// redundant.
|
||||||
return "stpp";
|
if (container_type == MediaInfo::CONTAINER_TEXT) {
|
||||||
}
|
return "";
|
||||||
if (format == "vtt" &&
|
|
||||||
(media_info.container_type() == MediaInfo::CONTAINER_MP4)) {
|
|
||||||
return "wvtt";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise codec doesn't need to be specified, e.g. vtt and ttml+xml are
|
// DASH IOP mentions that the codec for ttml in mp4 is stpp, so override
|
||||||
// obvious from the mime type.
|
// the default codec value.
|
||||||
return "";
|
const std::string& codec = media_info.text_info().codec();
|
||||||
|
if (codec == "ttml" && container_type == MediaInfo::CONTAINER_MP4) {
|
||||||
|
return "stpp";
|
||||||
|
}
|
||||||
|
|
||||||
|
return codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -118,7 +120,7 @@ std::string GetBaseCodec(const MediaInfo& media_info) {
|
||||||
} else if (media_info.has_audio_info()) {
|
} else if (media_info.has_audio_info()) {
|
||||||
codec = media_info.audio_info().codec();
|
codec = media_info.audio_info().codec();
|
||||||
} else if (media_info.has_text_info()) {
|
} else if (media_info.has_text_info()) {
|
||||||
codec = media_info.text_info().format();
|
codec = media_info.text_info().codec();
|
||||||
}
|
}
|
||||||
// Convert, for example, "mp4a.40.2" to simply "mp4a".
|
// Convert, for example, "mp4a.40.2" to simply "mp4a".
|
||||||
// "mp4a.40.2" and "mp4a.40.5" can exist in the same AdaptationSet.
|
// "mp4a.40.2" and "mp4a.40.5" can exist in the same AdaptationSet.
|
||||||
|
@ -186,7 +188,9 @@ bool MoreThanOneTrue(bool b1, bool b2, bool b3) {
|
||||||
return (b1 && b2) || (b2 && b3) || (b3 && b1);
|
return (b1 && b2) || (b2 && b3) || (b3 && b1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtLeastOneTrue(bool b1, bool b2, bool b3) { return b1 || b2 || b3; }
|
bool AtLeastOneTrue(bool b1, bool b2, bool b3) {
|
||||||
|
return b1 || b2 || b3;
|
||||||
|
}
|
||||||
|
|
||||||
bool OnlyOneTrue(bool b1, bool b2, bool b3) {
|
bool OnlyOneTrue(bool b1, bool b2, bool b3) {
|
||||||
return !MoreThanOneTrue(b1, b2, b3) && AtLeastOneTrue(b1, b2, b3);
|
return !MoreThanOneTrue(b1, b2, b3) && AtLeastOneTrue(b1, b2, b3);
|
||||||
|
@ -375,5 +379,4 @@ void AddContentProtectionElements(const MediaInfo& media_info,
|
||||||
AddContentProtectionElementsHelperTemplated(media_info, parent);
|
AddContentProtectionElementsHelperTemplated(media_info, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -213,7 +213,7 @@ TEST_P(PeriodTest, SetDurationAndGetXml) {
|
||||||
TEST_P(PeriodTest, Text) {
|
TEST_P(PeriodTest, Text) {
|
||||||
const char kTextMediaInfo[] =
|
const char kTextMediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'ttml'\n"
|
" codec: 'ttml'\n"
|
||||||
" language: 'en'\n"
|
" language: 'en'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_TEXT\n";
|
"container_type: CONTAINER_TEXT\n";
|
||||||
|
|
|
@ -452,7 +452,7 @@ std::string Representation::GetAudioMimeType() const {
|
||||||
|
|
||||||
std::string Representation::GetTextMimeType() const {
|
std::string Representation::GetTextMimeType() const {
|
||||||
CHECK(media_info_.has_text_info());
|
CHECK(media_info_.has_text_info());
|
||||||
if (media_info_.text_info().format() == "ttml") {
|
if (media_info_.text_info().codec() == "ttml") {
|
||||||
switch (media_info_.container_type()) {
|
switch (media_info_.container_type()) {
|
||||||
case MediaInfo::CONTAINER_TEXT:
|
case MediaInfo::CONTAINER_TEXT:
|
||||||
return "application/ttml+xml";
|
return "application/ttml+xml";
|
||||||
|
@ -464,7 +464,7 @@ std::string Representation::GetTextMimeType() const {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (media_info_.text_info().format() == "vtt") {
|
if (media_info_.text_info().codec() == "wvtt") {
|
||||||
if (media_info_.container_type() == MediaInfo::CONTAINER_TEXT) {
|
if (media_info_.container_type() == MediaInfo::CONTAINER_TEXT) {
|
||||||
return "text/vtt";
|
return "text/vtt";
|
||||||
} else if (media_info_.container_type() == MediaInfo::CONTAINER_MP4) {
|
} else if (media_info_.container_type() == MediaInfo::CONTAINER_MP4) {
|
||||||
|
@ -476,7 +476,7 @@ std::string Representation::GetTextMimeType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(ERROR) << "Cannot determine MIME type for format: "
|
LOG(ERROR) << "Cannot determine MIME type for format: "
|
||||||
<< media_info_.text_info().format()
|
<< media_info_.text_info().codec()
|
||||||
<< " container: " << media_info_.container_type();
|
<< " container: " << media_info_.container_type();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,7 @@ TEST_F(RepresentationTest,
|
||||||
TEST_F(RepresentationTest, TtmlXmlMimeType) {
|
TEST_F(RepresentationTest, TtmlXmlMimeType) {
|
||||||
const char kTtmlXmlMediaInfo[] =
|
const char kTtmlXmlMediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'ttml'\n"
|
" codec: 'ttml'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_TEXT\n";
|
"container_type: CONTAINER_TEXT\n";
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ TEST_F(RepresentationTest, TtmlXmlMimeType) {
|
||||||
TEST_F(RepresentationTest, TtmlMp4MimeType) {
|
TEST_F(RepresentationTest, TtmlMp4MimeType) {
|
||||||
const char kTtmlMp4MediaInfo[] =
|
const char kTtmlMp4MediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'ttml'\n"
|
" codec: 'ttml'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_MP4\n";
|
"container_type: CONTAINER_MP4\n";
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ TEST_F(RepresentationTest, TtmlMp4MimeType) {
|
||||||
TEST_F(RepresentationTest, WebVttMimeType) {
|
TEST_F(RepresentationTest, WebVttMimeType) {
|
||||||
const char kWebVttMediaInfo[] =
|
const char kWebVttMediaInfo[] =
|
||||||
"text_info {\n"
|
"text_info {\n"
|
||||||
" format: 'vtt'\n"
|
" codec: 'wvtt'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_TEXT\n";
|
"container_type: CONTAINER_TEXT\n";
|
||||||
|
|
||||||
|
|
|
@ -88,22 +88,32 @@ MuxerListenerFactory::StreamData ToMuxerListenerData(
|
||||||
// TODO(rkuroiwa): Write TTML and WebVTT parser (demuxing) for a better check
|
// TODO(rkuroiwa): Write TTML and WebVTT parser (demuxing) for a better check
|
||||||
// and for supporting live/segmenting (muxing). With a demuxer and a muxer,
|
// and for supporting live/segmenting (muxing). With a demuxer and a muxer,
|
||||||
// CreateAllJobs() shouldn't treat text as a special case.
|
// CreateAllJobs() shouldn't treat text as a special case.
|
||||||
std::string DetermineTextFileFormat(const std::string& file) {
|
bool DetermineTextFileCodec(const std::string& file, std::string* out) {
|
||||||
|
CHECK(out);
|
||||||
|
|
||||||
std::string content;
|
std::string content;
|
||||||
if (!File::ReadFileToString(file.c_str(), &content)) {
|
if (!File::ReadFileToString(file.c_str(), &content)) {
|
||||||
LOG(ERROR) << "Failed to open file " << file
|
LOG(ERROR) << "Failed to open file " << file
|
||||||
<< " to determine file format.";
|
<< " to determine file format.";
|
||||||
return "";
|
return false;
|
||||||
}
|
|
||||||
MediaContainerName container_name = DetermineContainer(
|
|
||||||
reinterpret_cast<const uint8_t*>(content.data()), content.size());
|
|
||||||
if (container_name == CONTAINER_WEBVTT) {
|
|
||||||
return "vtt";
|
|
||||||
} else if (container_name == CONTAINER_TTML) {
|
|
||||||
return "ttml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
const uint8_t* content_data =
|
||||||
|
reinterpret_cast<const uint8_t*>(content.data());
|
||||||
|
MediaContainerName container_name =
|
||||||
|
DetermineContainer(content_data, content.size());
|
||||||
|
|
||||||
|
if (container_name == CONTAINER_WEBVTT) {
|
||||||
|
*out = "wvtt";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container_name == CONTAINER_TTML) {
|
||||||
|
*out = "ttml";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaContainerName GetOutputFormat(const StreamDescriptor& descriptor) {
|
MediaContainerName GetOutputFormat(const StreamDescriptor& descriptor) {
|
||||||
|
@ -278,14 +288,21 @@ class FakeClock : public base::Clock {
|
||||||
|
|
||||||
bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor,
|
bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor,
|
||||||
MediaInfo* text_media_info) {
|
MediaInfo* text_media_info) {
|
||||||
const std::string& language = stream_descriptor.language;
|
std::string codec;
|
||||||
const std::string format = DetermineTextFileFormat(stream_descriptor.input);
|
if (!DetermineTextFileCodec(stream_descriptor.input, &codec)) {
|
||||||
if (format.empty()) {
|
|
||||||
LOG(ERROR) << "Failed to determine the text file format for "
|
LOG(ERROR) << "Failed to determine the text file format for "
|
||||||
<< stream_descriptor.input;
|
<< stream_descriptor.input;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MediaInfo::TextInfo* text_info = text_media_info->mutable_text_info();
|
||||||
|
text_info->set_codec(codec);
|
||||||
|
|
||||||
|
const std::string& language = stream_descriptor.language;
|
||||||
|
if (!language.empty()) {
|
||||||
|
text_info->set_language(language);
|
||||||
|
}
|
||||||
|
|
||||||
text_media_info->set_media_file_name(stream_descriptor.output);
|
text_media_info->set_media_file_name(stream_descriptor.output);
|
||||||
text_media_info->set_container_type(MediaInfo::CONTAINER_TEXT);
|
text_media_info->set_container_type(MediaInfo::CONTAINER_TEXT);
|
||||||
|
|
||||||
|
@ -299,11 +316,6 @@ bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor,
|
||||||
text_media_info->set_bandwidth(kDefaultTextBandwidth);
|
text_media_info->set_bandwidth(kDefaultTextBandwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaInfo::TextInfo* text_info = text_media_info->mutable_text_info();
|
|
||||||
text_info->set_format(format);
|
|
||||||
if (!language.empty())
|
|
||||||
text_info->set_language(language);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue