7 #include "packager/app/stream_descriptor.h"
9 #include "packager/app/packager_util.h"
10 #include "packager/base/logging.h"
11 #include "packager/base/strings/string_number_conversions.h"
12 #include "packager/base/strings/string_split.h"
13 #include "packager/media/base/container_names.h"
14 #include "packager/media/base/language_utils.h"
26 kSegmentTemplateField,
32 kHlsPlaylistNameField,
36 struct FieldNameToTypeMapping {
37 const char* field_name;
41 const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
42 {
"stream_selector", kStreamSelectorField},
43 {
"stream", kStreamSelectorField},
44 {
"input", kInputField},
46 {
"output", kOutputField},
47 {
"out", kOutputField},
48 {
"init_segment", kOutputField},
49 {
"segment_template", kSegmentTemplateField},
50 {
"template", kSegmentTemplateField},
51 {
"bandwidth", kBandwidthField},
52 {
"bw", kBandwidthField},
53 {
"bitrate", kBandwidthField},
54 {
"language", kLanguageField},
55 {
"lang", kLanguageField},
56 {
"output_format", kOutputFormatField},
57 {
"format", kOutputFormatField},
58 {
"hls_name", kHlsNameField},
59 {
"hls_group_id", kHlsGroupIdField},
60 {
"playlist_name", kHlsPlaylistNameField},
61 {
"trick_play_rate", kTrickPlayRateField},
64 FieldType GetFieldType(
const std::string& field_name) {
65 for (
size_t idx = 0; idx < arraysize(kFieldNameTypeMappings); ++idx) {
66 if (field_name == kFieldNameTypeMappings[idx].field_name)
67 return kFieldNameTypeMappings[idx].field_type;
74 StreamDescriptor::StreamDescriptor() {}
76 StreamDescriptor::~StreamDescriptor() {}
78 bool InsertStreamDescriptor(
const std::string& descriptor_string,
79 StreamDescriptorList* descriptor_list) {
80 StreamDescriptor descriptor;
83 base::StringPairs pairs;
84 if (!base::SplitStringIntoKeyValuePairs(descriptor_string,
88 LOG(ERROR) <<
"Invalid stream descriptors name/value pairs.";
91 for (base::StringPairs::const_iterator iter = pairs.begin();
92 iter != pairs.end(); ++iter) {
93 switch (GetFieldType(iter->first)) {
94 case kStreamSelectorField:
95 descriptor.stream_selector = iter->second;
98 descriptor.input = iter->second;
101 descriptor.output = iter->second;
103 case kSegmentTemplateField:
104 descriptor.segment_template = iter->second;
106 case kBandwidthField: {
108 if (!base::StringToUint(iter->second, &bw)) {
109 LOG(ERROR) <<
"Non-numeric bandwidth specified.";
112 descriptor.bandwidth = bw;
115 case kLanguageField: {
117 if (language ==
"und") {
118 LOG(ERROR) <<
"Unknown/invalid language specified: " << iter->second;
121 descriptor.language = language;
124 case kOutputFormatField: {
125 MediaContainerName output_format =
126 DetermineContainerFromFormatName(iter->second);
127 if (output_format == CONTAINER_UNKNOWN) {
128 LOG(ERROR) <<
"Unrecognized output format " << iter->second;
131 descriptor.output_format = output_format;
134 case kHlsNameField: {
135 descriptor.hls_name = iter->second;
138 case kHlsGroupIdField: {
139 descriptor.hls_group_id = iter->second;
142 case kHlsPlaylistNameField: {
143 descriptor.hls_playlist_name = iter->second;
146 case kTrickPlayRateField: {
148 if (!base::StringToUint(iter->second, &rate)) {
149 LOG(ERROR) <<
"Non-numeric trick play rate " << iter->second
154 LOG(ERROR) <<
"Stream trick_play_rate should be > 0.";
157 descriptor.trick_play_rate = rate;
161 LOG(ERROR) <<
"Unknown field in stream descriptor (\"" << iter->first
167 if (descriptor.input.empty()) {
168 LOG(ERROR) <<
"Stream input not specified.";
171 if (!FLAGS_dump_stream_info && descriptor.stream_selector.empty()) {
172 LOG(ERROR) <<
"Stream stream_selector not specified.";
176 if (descriptor.output_format == CONTAINER_UNKNOWN) {
177 const std::string& output_name = descriptor.output.empty()
178 ? descriptor.segment_template
180 if (!output_name.empty()) {
181 descriptor.output_format = DetermineContainerFromFileName(output_name);
182 if (descriptor.output_format == CONTAINER_UNKNOWN) {
183 LOG(ERROR) <<
"Unable to determine output format for file "
190 if (descriptor.output_format == MediaContainerName::CONTAINER_MPEG2TS) {
191 if (descriptor.segment_template.empty()) {
192 LOG(ERROR) <<
"Please specify segment_template. Single file TS output is "
198 if (!descriptor.output.empty()) {
199 LOG(WARNING) <<
"TS output '" << descriptor.output
200 <<
"' ignored. TS muxer does not support initialization "
201 "segment generation.";
207 const bool output_specified =
208 !descriptor.output.empty() ||
209 (descriptor.output_format == CONTAINER_MPEG2TS &&
210 !descriptor.segment_template.empty());
211 if (!FLAGS_dump_stream_info && !output_specified) {
212 LOG(ERROR) <<
"Stream output not specified.";
215 descriptor_list->insert(descriptor);
std::string LanguageToISO_639_2(const std::string &language)