1 /*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define HST_LOG_TAG "DashMpdUtil"
16
17 #include <cstring>
18 #include <cstdlib>
19 #include "common/log.h"
20 #include "dash_mpd_util.h"
21 #include "utils/time_utils.h"
22
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_STREAM_SOURCE, "HiStreamer" };
25 }
26
27 namespace OHOS {
28 namespace Media {
29 namespace Plugins {
30 namespace HttpPlugin {
31
32 static const int MATRIX_COEFFICIENTS_BT_2020 = 9;
33 static const int COLOUR_PRIMARIES_BT_2020 = 9;
34 static const int TRANSFER_CHARACTERISTICS_BT_2020 = 14;
35
36 static const std::string MPD_SCHEME_CICP_MATRIX_COEFFICIENTS = "cicp:MatrixCoefficients";
37 static const std::string MPD_SCHEME_CICP_COLOUR_PRIMARIES = "cicp:ColourPrimaries";
38 static const std::string MPD_SCHEME_CICP_TRANSFER_CHARACTERISTICS = "cicp:TransferCharacteristics";
39
DashUrlIsAbsolute(const std::string & url)40 bool DashUrlIsAbsolute(const std::string &url)
41 {
42 if (url.find("http://") == 0 || url.find("https://") == 0) {
43 return true;
44 }
45
46 return false;
47 }
48
DashAppendBaseUrl(std::string & srcUrl,DashList<std::string> baseUrlList)49 void DashAppendBaseUrl(std::string &srcUrl, DashList<std::string> baseUrlList)
50 {
51 if (baseUrlList.size() > 0) {
52 std::string baseUrl = baseUrlList.front();
53 DashAppendBaseUrl(srcUrl, baseUrl);
54 }
55 }
56
DashAppendBaseUrl(std::string & srcUrl,std::string baseUrl)57 void DashAppendBaseUrl(std::string &srcUrl, std::string baseUrl)
58 {
59 if (DashUrlIsAbsolute(baseUrl)) {
60 // absolute url use baseUrl
61 srcUrl = baseUrl;
62 } else {
63 if (baseUrl.find('/') == 0) {
64 BuildSrcUrl(srcUrl, baseUrl);
65 } else {
66 // relative path
67 srcUrl.append(baseUrl);
68 }
69 }
70 }
71
BuildSrcUrl(std::string & srcUrl,std::string & baseUrl)72 void BuildSrcUrl(std::string &srcUrl, std::string &baseUrl)
73 {
74 if (DashUrlIsAbsolute(srcUrl)) {
75 std::string urlSchem;
76 size_t urlSchemIndex = srcUrl.find("://");
77 if (urlSchemIndex != std::string::npos) {
78 size_t urlSchemLength = strlen("://");
79 urlSchem = srcUrl.substr(0, urlSchemIndex + urlSchemLength);
80 srcUrl = srcUrl.substr(urlSchemIndex + urlSchemLength);
81 }
82
83 size_t urlPathIndex = srcUrl.find('/');
84 if (urlPathIndex != std::string::npos) {
85 srcUrl = srcUrl.substr(0, urlPathIndex);
86 }
87
88 srcUrl = urlSchem.append(srcUrl).append(baseUrl);
89 } else {
90 srcUrl = baseUrl;
91 }
92 }
93
ReplaceSubStr(std::string & str,uint32_t position,uint32_t length,const std::string & dstSubStr)94 static std::string &ReplaceSubStr(std::string &str, uint32_t position, uint32_t length, const std::string &dstSubStr)
95 {
96 if (str.length() > position + length) {
97 return str.replace(position, length, dstSubStr);
98 }
99 return str;
100 }
101
DashSubstituteTmpltStr(std::string & segTmpltStr,const std::string & segTmpltIdentifier,std::string substitutionStr)102 int32_t DashSubstituteTmpltStr(std::string &segTmpltStr, const std::string &segTmpltIdentifier,
103 std::string substitutionStr)
104 {
105 std::string::size_type pos = segTmpltStr.find(segTmpltIdentifier);
106 uint32_t identifierLength = segTmpltIdentifier.length();
107 while (pos != std::string::npos && (pos + identifierLength) < segTmpltStr.length()) {
108 std::string str = segTmpltStr.substr(pos + identifierLength);
109 // contain format %0[width]d
110 if (str[0] == '%' && str[1] == '0') {
111 std::string::size_type posEnd = str.find("$");
112 // not find end '$', drop the representation
113 if (posEnd == std::string::npos) {
114 return -1;
115 }
116
117 GetSubstitutionStr(substitutionStr, str);
118 segTmpltStr =
119 ReplaceSubStr(segTmpltStr, (uint32_t) pos, (uint32_t) (posEnd + identifierLength + 1),
120 substitutionStr);
121 } else if (str[0] == '$') {
122 segTmpltStr = ReplaceSubStr(segTmpltStr, (uint32_t) pos, identifierLength + 1, substitutionStr);
123 } else {
124 // error format, should drop the representation
125 return -1;
126 }
127
128 pos = segTmpltStr.find(segTmpltIdentifier);
129 }
130
131 return 0;
132 }
133
GetSubstitutionStr(std::string & substitutionStr,std::string & str)134 void GetSubstitutionStr(std::string &substitutionStr, std::string &str)
135 {
136 size_t strLength = strlen("%0");
137 str = str.substr(strLength);
138 int32_t formatWidth = atoi(str.c_str());
139 if (static_cast<int32_t>(substitutionStr.length()) < formatWidth) {
140 for (int32_t i = formatWidth - static_cast<int32_t>(substitutionStr.length()); i > 0; i--) {
141 substitutionStr = "0" + substitutionStr;
142 }
143 }
144 }
145
DashStrToDuration(const std::string & str,uint32_t & duration)146 int32_t DashStrToDuration(const std::string &str, uint32_t &duration)
147 {
148 int64_t time = 0;
149 int32_t secondTime = 0;
150 char *end = nullptr;
151 char *start = const_cast<char *>(str.c_str());
152 if (str.length() == 0 || *start != 'P') {
153 return -1;
154 }
155
156 start++;
157 do {
158 int32_t coefficient = 0;
159 double num = strtod(start, &end);
160
161 if (start != end && end) {
162 start = end;
163 }
164
165 switch (*start) {
166 case 'M':
167 if (secondTime) {
168 coefficient = M_2_S;
169 }
170 break;
171 case 'Y':
172 break;
173 case 'D':
174 coefficient = D_2_H * H_2_M * M_2_S;
175 break;
176 case 'T':
177 secondTime = 1;
178 break;
179 case 'H':
180 coefficient = H_2_M * M_2_S;
181 break;
182 case 'S':
183 coefficient = 1;
184 break;
185 default:
186 break;
187 }
188
189 time += (int64_t)(num * S_2_MS) * coefficient;
190 if (*start) {
191 start++;
192 }
193 } while (*start);
194
195 duration = static_cast<uint32_t>(time);
196
197 return 0;
198 }
199
DashGetAttrIndex(const std::string & attrName,const char * const * nodeAttrs,uint32_t attrNums)200 uint32_t DashGetAttrIndex(const std::string &attrName, const char *const *nodeAttrs, uint32_t attrNums)
201 {
202 uint32_t i;
203 for (i = 0; i < attrNums; i++) {
204 if (attrName == nodeAttrs[i]) {
205 break;
206 }
207 }
208
209 return i;
210 }
211
DashParseRange(const std::string & rangeStr,int64_t & startRange,int64_t & endRange)212 void DashParseRange(const std::string &rangeStr, int64_t &startRange, int64_t &endRange)
213 {
214 if (rangeStr.length() > 0) {
215 std::string::size_type separatePosition = rangeStr.find_first_of('-');
216 if (separatePosition == std::string::npos) {
217 MEDIA_LOG_W("range is error, no - in " PUBLIC_LOG_S, rangeStr.c_str());
218 return;
219 }
220
221 if (separatePosition == 0) {
222 MEDIA_LOG_W("not support, the - is begin at string " PUBLIC_LOG_S, rangeStr.c_str());
223 return;
224 }
225
226 std::string firstRange = rangeStr.substr(0, separatePosition);
227 startRange = atoll(firstRange.c_str());
228
229 if (separatePosition < rangeStr.length() - 1) {
230 std::string lastRange = rangeStr.substr(separatePosition + 1, rangeStr.length() - separatePosition - 1);
231 endRange = atoll(lastRange.c_str());
232 }
233 MEDIA_LOG_D("startRange=" PUBLIC_LOG_D64 ", endRange=" PUBLIC_LOG_D64 ", range="
234 PUBLIC_LOG_S, startRange, endRange, rangeStr.c_str());
235 }
236 }
237
DashStreamIsHdr(DashList<DashDescriptor * > essentialPropertyList)238 bool DashStreamIsHdr(DashList<DashDescriptor*> essentialPropertyList)
239 {
240 int matrixCoefficients = 1;
241 int colourPrimaries = 1;
242 int transferCharacteristics = 1;
243
244 for (auto descriptor : essentialPropertyList) {
245 if (descriptor != nullptr && descriptor->value_.length() > 0) {
246 if (descriptor->schemeIdUrl_.find(MPD_SCHEME_CICP_MATRIX_COEFFICIENTS) != std::string::npos) {
247 matrixCoefficients = atoi(descriptor->value_.c_str());
248 } else if (descriptor->schemeIdUrl_.find(MPD_SCHEME_CICP_COLOUR_PRIMARIES) != std::string::npos) {
249 colourPrimaries = atoi(descriptor->value_.c_str());
250 } else if (descriptor->schemeIdUrl_.find(MPD_SCHEME_CICP_TRANSFER_CHARACTERISTICS) != std::string::npos) {
251 transferCharacteristics = atoi(descriptor->value_.c_str());
252 }
253 }
254 }
255
256 if (matrixCoefficients >= MATRIX_COEFFICIENTS_BT_2020 &&
257 colourPrimaries >= COLOUR_PRIMARIES_BT_2020 &&
258 transferCharacteristics >= TRANSFER_CHARACTERISTICS_BT_2020) {
259 return true;
260 }
261
262 return false;
263 }
264
265 } // namespace HttpPluginLite
266 } // namespace Plugin
267 } // namespace Media
268 } // namespace OHOS