DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
stream_descriptor.cc
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/app/stream_descriptor.h"
8 
9 #include "packager/base/logging.h"
10 #include "packager/base/strings/string_number_conversions.h"
11 #include "packager/base/strings/string_split.h"
12 #include "packager/media/base/language_utils.h"
13 
14 namespace shaka {
15 
16 namespace {
17 
18 enum FieldType {
19  kUnknownField = 0,
20  kStreamSelectorField,
21  kInputField,
22  kOutputField,
23  kSegmentTemplateField,
24  kBandwidthField,
25  kLanguageField,
26  kOutputFormatField,
27  kHlsNameField,
28  kHlsGroupIdField,
29  kHlsPlaylistNameField,
30  kTrickPlayFactorField,
31  kSkipEncryptionField,
32 };
33 
34 struct FieldNameToTypeMapping {
35  const char* field_name;
36  FieldType field_type;
37 };
38 
39 const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
40  {"stream_selector", kStreamSelectorField},
41  {"stream", kStreamSelectorField},
42  {"input", kInputField},
43  {"in", kInputField},
44  {"output", kOutputField},
45  {"out", kOutputField},
46  {"init_segment", kOutputField},
47  {"segment_template", kSegmentTemplateField},
48  {"template", kSegmentTemplateField},
49  {"bandwidth", kBandwidthField},
50  {"bw", kBandwidthField},
51  {"bitrate", kBandwidthField},
52  {"language", kLanguageField},
53  {"lang", kLanguageField},
54  {"output_format", kOutputFormatField},
55  {"format", kOutputFormatField},
56  {"hls_name", kHlsNameField},
57  {"hls_group_id", kHlsGroupIdField},
58  {"playlist_name", kHlsPlaylistNameField},
59  {"trick_play_factor", kTrickPlayFactorField},
60  {"tpf", kTrickPlayFactorField},
61  {"skip_encryption", kSkipEncryptionField},
62 };
63 
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;
68  }
69  return kUnknownField;
70 }
71 
72 } // anonymous namespace
73 
74 base::Optional<StreamDescriptor> ParseStreamDescriptor(
75  const std::string& descriptor_string) {
76  StreamDescriptor descriptor;
77 
78  // Split descriptor string into name/value pairs.
79  base::StringPairs pairs;
80  if (!base::SplitStringIntoKeyValuePairs(descriptor_string, '=', ',',
81  &pairs)) {
82  LOG(ERROR) << "Invalid stream descriptors name/value pairs.";
83  return base::nullopt;
84  }
85  for (base::StringPairs::const_iterator iter = pairs.begin();
86  iter != pairs.end(); ++iter) {
87  switch (GetFieldType(iter->first)) {
88  case kStreamSelectorField:
89  descriptor.stream_selector = iter->second;
90  break;
91  case kInputField:
92  descriptor.input = iter->second;
93  break;
94  case kOutputField:
95  descriptor.output = iter->second;
96  break;
97  case kSegmentTemplateField:
98  descriptor.segment_template = iter->second;
99  break;
100  case kBandwidthField: {
101  unsigned bw;
102  if (!base::StringToUint(iter->second, &bw)) {
103  LOG(ERROR) << "Non-numeric bandwidth specified.";
104  return base::nullopt;
105  }
106  descriptor.bandwidth = bw;
107  break;
108  }
109  case kLanguageField: {
110  // TODO(kqyang): Move to packager.cc.
111  std::string language = LanguageToISO_639_2(iter->second);
112  if (language == "und") {
113  LOG(ERROR) << "Unknown/invalid language specified: " << iter->second;
114  return base::nullopt;
115  }
116  descriptor.language = language;
117  break;
118  }
119  case kOutputFormatField: {
120  descriptor.output_format = iter->second;
121  break;
122  }
123  case kHlsNameField: {
124  descriptor.hls_name = iter->second;
125  break;
126  }
127  case kHlsGroupIdField: {
128  descriptor.hls_group_id = iter->second;
129  break;
130  }
131  case kHlsPlaylistNameField: {
132  descriptor.hls_playlist_name = iter->second;
133  break;
134  }
135  case kTrickPlayFactorField: {
136  unsigned factor;
137  if (!base::StringToUint(iter->second, &factor)) {
138  LOG(ERROR) << "Non-numeric trick play factor " << iter->second
139  << " specified.";
140  return base::nullopt;
141  }
142  if (factor == 0) {
143  LOG(ERROR) << "Stream trick_play_factor should be > 0.";
144  return base::nullopt;
145  }
146  descriptor.trick_play_factor = factor;
147  break;
148  }
149  case kSkipEncryptionField: {
150  unsigned skip_encryption_value;
151  if (!base::StringToUint(iter->second, &skip_encryption_value)) {
152  LOG(ERROR) << "Non-numeric option for skip encryption field "
153  "specified (" << iter->second << ").";
154  return base::nullopt;
155  }
156  if (skip_encryption_value > 1) {
157  LOG(ERROR) << "skip_encryption should be either 0 or 1.";
158  return base::nullopt;
159  }
160 
161  descriptor.skip_encryption = skip_encryption_value > 0;
162  break;
163  }
164  default:
165  LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
166  << "\").";
167  return base::nullopt;
168  }
169  }
170  return descriptor;
171 }
172 
173 } // namespace shaka
base::Optional< StreamDescriptor > ParseStreamDescriptor(const std::string &descriptor_string)
std::string LanguageToISO_639_2(const std::string &language)