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,
33 kTrickPlayFactorField,
37 struct FieldNameToTypeMapping {
38 const char* field_name;
42 const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
43 {
"stream_selector", kStreamSelectorField},
44 {
"stream", kStreamSelectorField},
45 {
"input", kInputField},
47 {
"output", kOutputField},
48 {
"out", kOutputField},
49 {
"init_segment", kOutputField},
50 {
"segment_template", kSegmentTemplateField},
51 {
"template", kSegmentTemplateField},
52 {
"bandwidth", kBandwidthField},
53 {
"bw", kBandwidthField},
54 {
"bitrate", kBandwidthField},
55 {
"language", kLanguageField},
56 {
"lang", kLanguageField},
57 {
"output_format", kOutputFormatField},
58 {
"format", kOutputFormatField},
59 {
"hls_name", kHlsNameField},
60 {
"hls_group_id", kHlsGroupIdField},
61 {
"playlist_name", kHlsPlaylistNameField},
62 {
"trick_play_factor", kTrickPlayFactorField},
63 {
"tpf", kTrickPlayFactorField},
64 {
"skip_encryption", kSkipEncryptionField},
67 FieldType GetFieldType(
const std::string& field_name) {
68 for (
size_t idx = 0; idx < arraysize(kFieldNameTypeMappings); ++idx) {
69 if (field_name == kFieldNameTypeMappings[idx].field_name)
70 return kFieldNameTypeMappings[idx].field_type;
77 StreamDescriptor::StreamDescriptor() {}
79 StreamDescriptor::~StreamDescriptor() {}
81 bool InsertStreamDescriptor(
const std::string& descriptor_string,
82 StreamDescriptorList* descriptor_list) {
83 StreamDescriptor descriptor;
86 base::StringPairs pairs;
87 if (!base::SplitStringIntoKeyValuePairs(descriptor_string,
91 LOG(ERROR) <<
"Invalid stream descriptors name/value pairs.";
94 for (base::StringPairs::const_iterator iter = pairs.begin();
95 iter != pairs.end(); ++iter) {
96 switch (GetFieldType(iter->first)) {
97 case kStreamSelectorField:
98 descriptor.stream_selector = iter->second;
101 descriptor.input = iter->second;
104 descriptor.output = iter->second;
106 case kSegmentTemplateField:
107 descriptor.segment_template = iter->second;
109 case kBandwidthField: {
111 if (!base::StringToUint(iter->second, &bw)) {
112 LOG(ERROR) <<
"Non-numeric bandwidth specified.";
115 descriptor.bandwidth = bw;
118 case kLanguageField: {
120 if (language ==
"und") {
121 LOG(ERROR) <<
"Unknown/invalid language specified: " << iter->second;
124 descriptor.language = language;
127 case kOutputFormatField: {
128 MediaContainerName output_format =
129 DetermineContainerFromFormatName(iter->second);
130 if (output_format == CONTAINER_UNKNOWN) {
131 LOG(ERROR) <<
"Unrecognized output format " << iter->second;
134 descriptor.output_format = output_format;
137 case kHlsNameField: {
138 descriptor.hls_name = iter->second;
141 case kHlsGroupIdField: {
142 descriptor.hls_group_id = iter->second;
145 case kHlsPlaylistNameField: {
146 descriptor.hls_playlist_name = iter->second;
149 case kTrickPlayFactorField: {
151 if (!base::StringToUint(iter->second, &factor)) {
152 LOG(ERROR) <<
"Non-numeric trick play factor " << iter->second
157 LOG(ERROR) <<
"Stream trick_play_factor should be > 0.";
160 descriptor.trick_play_factor = factor;
163 case kSkipEncryptionField: {
164 unsigned skip_encryption_value;
165 if (!base::StringToUint(iter->second, &skip_encryption_value)) {
166 LOG(ERROR) <<
"Non-numeric option for skip encryption field "
167 "specified (" << iter->second <<
").";
170 if (skip_encryption_value > 1) {
171 LOG(ERROR) <<
"skip_encryption should be either 0 or 1.";
175 descriptor.skip_encryption = skip_encryption_value > 0;
179 LOG(ERROR) <<
"Unknown field in stream descriptor (\"" << iter->first
185 if (descriptor.input.empty()) {
186 LOG(ERROR) <<
"Stream input not specified.";
189 if (!FLAGS_dump_stream_info && descriptor.stream_selector.empty()) {
190 LOG(ERROR) <<
"Stream stream_selector not specified.";
194 if (descriptor.output_format == CONTAINER_UNKNOWN) {
195 const std::string& output_name = descriptor.output.empty()
196 ? descriptor.segment_template
198 if (!output_name.empty()) {
199 descriptor.output_format = DetermineContainerFromFileName(output_name);
200 if (descriptor.output_format == CONTAINER_UNKNOWN) {
201 LOG(ERROR) <<
"Unable to determine output format for file "
208 if (descriptor.output_format == MediaContainerName::CONTAINER_MPEG2TS) {
209 if (descriptor.segment_template.empty()) {
210 LOG(ERROR) <<
"Please specify segment_template. Single file TS output is "
216 if (!descriptor.output.empty()) {
217 LOG(WARNING) <<
"TS output '" << descriptor.output
218 <<
"' ignored. TS muxer does not support initialization "
219 "segment generation.";
225 const bool output_specified =
226 !descriptor.output.empty() ||
227 (descriptor.output_format == CONTAINER_MPEG2TS &&
228 !descriptor.segment_template.empty());
229 if (!FLAGS_dump_stream_info && !output_specified) {
230 LOG(ERROR) <<
"Stream output not specified.";
233 descriptor_list->insert(descriptor);
std::string LanguageToISO_639_2(const std::string &language)