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