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"
19 namespace edash_packager {
21 bool ValidateFormatTag(
const std::string& format_tag) {
22 DCHECK(!format_tag.empty());
24 if (format_tag.size() > 3 && format_tag[0] ==
'%' && format_tag[1] ==
'0' &&
25 format_tag[format_tag.size() - 1] ==
'd') {
27 if (base::StringToUint(format_tag.substr(2, format_tag.size() - 3), &out))
30 LOG(ERROR) <<
"SegmentTemplate: Format tag should follow this prototype: "
31 <<
"%0[width]d if exist.";
38 bool ValidateSegmentTemplate(
const std::string& segment_template) {
39 if (segment_template.empty())
42 std::vector<std::string> splits;
43 base::SplitString(segment_template,
'$', &splits);
48 if (splits.size() % 2 == 0) {
49 LOG(ERROR) <<
"SegmentTemplate: '$' should appear in pairs.";
53 bool has_number =
false;
54 bool has_time =
false;
56 for (
size_t i = 1; i < splits.size(); i += 2) {
60 size_t format_pos = splits[i].find(
'%');
61 std::string identifier = splits[i].substr(0, format_pos);
62 if (format_pos != std::string::npos) {
63 if (!ValidateFormatTag(splits[i].substr(format_pos)))
68 if (identifier ==
"RepresentationID") {
69 NOTIMPLEMENTED() <<
"SegmentTemplate: $RepresentationID$ is not supported "
72 }
else if (identifier ==
"Number") {
74 }
else if (identifier ==
"Time") {
76 }
else if (identifier ==
"") {
77 if (format_pos != std::string::npos) {
78 LOG(ERROR) <<
"SegmentTemplate: $$ should not have any format tags.";
81 }
else if (identifier !=
"Bandwidth") {
82 LOG(ERROR) <<
"SegmentTemplate: '$" << splits[i]
83 <<
"$' is not a valid identifier.";
87 if (has_number && has_time) {
88 LOG(ERROR) <<
"SegmentTemplate: $Number$ and $Time$ should not co-exist.";
91 if (!has_number && !has_time) {
92 LOG(ERROR) <<
"SegmentTemplate: $Number$ or $Time$ should exist.";
101 std::string GetSegmentName(
const std::string& segment_template,
102 uint64_t segment_start_time,
103 uint32_t segment_index,
104 uint32_t bandwidth) {
105 DCHECK(ValidateSegmentTemplate(segment_template));
107 std::vector<std::string> splits;
108 base::SplitString(segment_template,
'$', &splits);
110 DCHECK_EQ(1u, splits.size() % 2);
112 std::string segment_name;
113 for (
size_t i = 0; i < splits.size(); ++i) {
117 segment_name += splits[i];
120 if (splits[i].empty()) {
125 size_t format_pos = splits[i].find(
'%');
126 std::string identifier = splits[i].substr(0, format_pos);
127 DCHECK(identifier ==
"Number" || identifier ==
"Time" ||
128 identifier ==
"Bandwidth");
130 std::string format_tag;
131 if (format_pos != std::string::npos) {
132 format_tag = splits[i].substr(format_pos);
133 DCHECK(ValidateFormatTag(format_tag));
135 format_tag = format_tag.substr(0, format_tag.size() - 1) + PRIu64;
138 format_tag =
"%01" PRIu64;
141 if (identifier ==
"Number") {
143 segment_name += base::StringPrintf(
144 format_tag.c_str(),
static_cast<uint64_t
>(segment_index + 1));
145 }
else if (identifier ==
"Time") {
147 base::StringPrintf(format_tag.c_str(), segment_start_time);
148 }
else if (identifier ==
"Bandwidth") {
149 segment_name += base::StringPrintf(format_tag.c_str(),
150 static_cast<uint64_t
>(bandwidth));