7 #include "packager/media/base/muxer_util.h"
14 #include "packager/base/logging.h"
15 #include "packager/base/strings/string_number_conversions.h"
16 #include "packager/base/strings/string_split.h"
17 #include "packager/base/strings/stringprintf.h"
18 #include "packager/media/base/video_stream_info.h"
22 bool ValidateFormatTag(
const std::string& format_tag) {
23 DCHECK(!format_tag.empty());
25 if (format_tag.size() > 3 && format_tag[0] ==
'%' && format_tag[1] ==
'0' &&
26 format_tag[format_tag.size() - 1] ==
'd') {
28 if (base::StringToUint(format_tag.substr(2, format_tag.size() - 3), &out))
31 LOG(ERROR) <<
"SegmentTemplate: Format tag should follow this prototype: "
32 <<
"%0[width]d if exist.";
39 bool ValidateSegmentTemplate(
const std::string& segment_template) {
40 if (segment_template.empty())
43 std::vector<std::string> splits = base::SplitString(
44 segment_template,
"$", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
49 if (splits.size() % 2 == 0) {
50 LOG(ERROR) <<
"SegmentTemplate: '$' should appear in pairs.";
54 bool has_number =
false;
55 bool has_time =
false;
57 for (
size_t i = 1; i < splits.size(); i += 2) {
61 size_t format_pos = splits[i].find(
'%');
62 std::string identifier = splits[i].substr(0, format_pos);
63 if (format_pos != std::string::npos) {
64 if (!ValidateFormatTag(splits[i].substr(format_pos)))
69 if (identifier ==
"RepresentationID") {
70 NOTIMPLEMENTED() <<
"SegmentTemplate: $RepresentationID$ is not supported "
73 }
else if (identifier ==
"Number") {
75 }
else if (identifier ==
"Time") {
77 }
else if (identifier ==
"") {
78 if (format_pos != std::string::npos) {
79 LOG(ERROR) <<
"SegmentTemplate: $$ should not have any format tags.";
82 }
else if (identifier !=
"Bandwidth") {
83 LOG(ERROR) <<
"SegmentTemplate: '$" << splits[i]
84 <<
"$' is not a valid identifier.";
88 if (has_number && has_time) {
89 LOG(ERROR) <<
"SegmentTemplate: $Number$ and $Time$ should not co-exist.";
92 if (!has_number && !has_time) {
93 LOG(ERROR) <<
"SegmentTemplate: $Number$ or $Time$ should exist.";
102 std::string GetSegmentName(
const std::string& segment_template,
103 uint64_t segment_start_time,
104 uint32_t segment_index,
105 uint32_t bandwidth) {
106 DCHECK(ValidateSegmentTemplate(segment_template));
108 std::vector<std::string> splits = base::SplitString(
109 segment_template,
"$", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
111 DCHECK_EQ(1u, splits.size() % 2);
113 std::string segment_name;
114 for (
size_t i = 0; i < splits.size(); ++i) {
118 segment_name += splits[i];
121 if (splits[i].empty()) {
126 size_t format_pos = splits[i].find(
'%');
127 std::string identifier = splits[i].substr(0, format_pos);
128 DCHECK(identifier ==
"Number" || identifier ==
"Time" ||
129 identifier ==
"Bandwidth");
131 std::string format_tag;
132 if (format_pos != std::string::npos) {
133 format_tag = splits[i].substr(format_pos);
134 DCHECK(ValidateFormatTag(format_tag));
136 format_tag = format_tag.substr(0, format_tag.size() - 1) + PRIu64;
139 format_tag =
"%01" PRIu64;
142 if (identifier ==
"Number") {
144 segment_name += base::StringPrintf(
145 format_tag.c_str(),
static_cast<uint64_t
>(segment_index + 1));
146 }
else if (identifier ==
"Time") {
148 base::StringPrintf(format_tag.c_str(), segment_start_time);
149 }
else if (identifier ==
"Bandwidth") {
150 segment_name += base::StringPrintf(format_tag.c_str(),
151 static_cast<uint64_t
>(bandwidth));
157 KeySource::TrackType GetTrackTypeForEncryption(
const StreamInfo& stream_info,
158 uint32_t max_sd_pixels) {
159 if (stream_info.stream_type() == kStreamAudio)
160 return KeySource::TRACK_TYPE_AUDIO;
162 if (stream_info.stream_type() != kStreamVideo)
163 return KeySource::TRACK_TYPE_UNKNOWN;
165 DCHECK_EQ(kStreamVideo, stream_info.stream_type());
166 const VideoStreamInfo& video_stream_info =
167 static_cast<const VideoStreamInfo&
>(stream_info);
168 uint32_t pixels = video_stream_info.width() * video_stream_info.height();
169 return (pixels > max_sd_pixels) ? KeySource::TRACK_TYPE_HD
170 : KeySource::TRACK_TYPE_SD;