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 "DashMpdParser"
16
17 #include <ctime>
18 #include "common/log.h"
19 #include "securec.h"
20 #include "dash_mpd_parser.h"
21 #include "dash_mpd_util.h"
22 #include "utils/time_utils.h"
23
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_STREAM_SOURCE, "HiStreamer" };
26 }
27
28 namespace OHOS {
29 namespace Media {
30 namespace Plugins {
31 namespace HttpPlugin {
32 namespace {
33 constexpr unsigned int DEFAULT_YEAR = 1900;
34 constexpr unsigned int DEFAULT_YEAR_LEN = 70;
35 constexpr unsigned int DEFAULT_DAY = 2;
36 }
37
~DashMpdParser()38 DashMpdParser::~DashMpdParser()
39 {
40 Clear();
41 }
42
String2Time(const std::string szTime)43 time_t DashMpdParser::String2Time(const std::string szTime)
44 {
45 if (szTime.length() == 0) {
46 return 0;
47 }
48
49 struct tm tm1;
50 memset_s(&tm1, sizeof(tm1), 0, sizeof(tm1));
51 struct tm tmBase;
52 memset_s(&tmBase, sizeof(tmBase), 0, sizeof(tmBase));
53 time_t t1;
54 time_t tBase;
55
56 if (-1 == sscanf_s(szTime.c_str(), "%4d-%2d-%2dT%2d:%2d:%2d", &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour,
57 &tm1.tm_min, &tm1.tm_sec)) {
58 MEDIA_LOG_E("String2Time format error " PUBLIC_LOG_S, szTime.c_str());
59 }
60
61 tm1.tm_year -= DEFAULT_YEAR;
62 tm1.tm_mon--;
63 // day + 1 for as 1970/1/1 00:00:00.000 in windows(return -1) and mac(return -28800) return different
64 tm1.tm_mday += 1;
65
66 tm1.tm_isdst = -1;
67
68 tmBase.tm_mday = DEFAULT_DAY;
69 tmBase.tm_year = DEFAULT_YEAR_LEN;
70 tmBase.tm_isdst = -1;
71
72 t1 = mktime(&tm1);
73 tBase = mktime(&tmBase);
74
75 return t1 - tBase;
76 }
77
ParsePeriod(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement)78 void DashMpdParser::ParsePeriod(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement)
79 {
80 DashPeriodInfo *periodInfo = new DashPeriodInfo;
81 if (periodInfo != nullptr) {
82 IDashMpdNode *periodNode = IDashMpdNode::CreateNode("Period");
83 if (periodNode == nullptr) {
84 delete periodInfo;
85 return;
86 }
87
88 periodNode->ParseNode(xmlParser, rootElement);
89
90 GetPeriodAttr(periodNode, periodInfo);
91 GetPeriodElement(xmlParser, rootElement, periodInfo);
92
93 dashMpdInfo_.periodInfoList_.push_back(periodInfo);
94 IDashMpdNode::DestroyNode(periodNode);
95 } else {
96 MEDIA_LOG_E("ParsePeriod periodInfo == nullptr");
97 }
98 }
99
GetPeriodAttr(IDashMpdNode * periodNode,DashPeriodInfo * periodInfo)100 void DashMpdParser::GetPeriodAttr(IDashMpdNode *periodNode, DashPeriodInfo *periodInfo)
101 {
102 std::string tempStr;
103 periodNode->GetAttr("id", periodInfo->id_);
104
105 periodNode->GetAttr("start", tempStr);
106 DashStrToDuration(tempStr, periodInfo->start_);
107
108 periodNode->GetAttr("duration", tempStr);
109 DashStrToDuration(tempStr, periodInfo->duration_);
110
111 periodNode->GetAttr("bitstreamSwitching", tempStr);
112 if (tempStr == "true") {
113 periodInfo->bitstreamSwitching_ = true;
114 } else {
115 periodInfo->bitstreamSwitching_ = false;
116 }
117 }
118
GetPeriodElement(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashPeriodInfo * periodInfo)119 void DashMpdParser::GetPeriodElement(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
120 DashPeriodInfo *periodInfo)
121 {
122 DashList<std::shared_ptr<XmlElement>> adptSetElementList;
123 DashElementList dashElementList;
124 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
125 while (childElement != nullptr) {
126 if (this->stopFlag_) {
127 break;
128 }
129
130 ProcessPeriodElement(xmlParser, periodInfo, adptSetElementList, childElement, dashElementList);
131 childElement = childElement->GetSiblingNext();
132 }
133
134 // parse element SegmentBase
135 if (dashElementList.segBaseElement_ != nullptr) {
136 ParseSegmentBase(xmlParser, dashElementList.segBaseElement_, &periodInfo->periodSegBase_);
137 }
138
139 // parse element SegmentList
140 if (dashElementList.segListElement_ != nullptr) {
141 ParseSegmentList(xmlParser, dashElementList.segListElement_, &periodInfo->periodSegList_);
142 }
143
144 // parse element SegmentTemplate
145 if (dashElementList.segTmplElement_ != nullptr) {
146 ParseSegmentTemplate(xmlParser, dashElementList.segTmplElement_, &periodInfo->periodSegTmplt_);
147 }
148
149 // parse AdaptationSet label last
150 while (adptSetElementList.size() > 0) {
151 if (this->stopFlag_) {
152 break;
153 }
154
155 std::shared_ptr<XmlElement> adptSetElement = adptSetElementList.front();
156 if (adptSetElement != nullptr) {
157 ParseAdaptationSet(xmlParser, adptSetElement, periodInfo);
158 }
159
160 adptSetElementList.pop_front();
161 }
162 }
163
ProcessPeriodElement(const std::shared_ptr<XmlParser> & xmlParser,DashPeriodInfo * periodInfo,DashList<std::shared_ptr<XmlElement>> & adptSetElementList,std::shared_ptr<XmlElement> & childElement,DashElementList & dashElementList)164 void DashMpdParser::ProcessPeriodElement(const std::shared_ptr<XmlParser> &xmlParser, DashPeriodInfo *periodInfo,
165 DashList<std::shared_ptr<XmlElement>> &adptSetElementList,
166 std::shared_ptr<XmlElement> &childElement, DashElementList &dashElementList)
167 {
168 std::string elementNameStr = childElement->GetName();
169 if (!elementNameStr.empty()) {
170 xmlParser->SkipElementNameSpace(elementNameStr);
171
172 if (elementNameStr == MPD_LABEL_BASE_URL) {
173 // parse element BaseURL
174 std::string strValue = childElement->GetText();
175 if (!strValue.empty()) {
176 periodInfo->baseUrl_.push_back(strValue);
177 }
178 } else if (elementNameStr == MPD_LABEL_SEGMENT_BASE) {
179 dashElementList.segBaseElement_ = childElement;
180 } else if (elementNameStr == MPD_LABEL_SEGMENT_LIST) {
181 dashElementList.segListElement_ = childElement;
182 } else if (elementNameStr == MPD_LABEL_SEGMENT_TEMPLATE) {
183 dashElementList.segTmplElement_ = childElement;
184 } else if (elementNameStr == MPD_LABEL_ADAPTATIONSET) {
185 // parse element AdaptationSet
186 adptSetElementList.push_back(childElement);
187 }
188 }
189 }
190
ParseAdaptationSet(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashPeriodInfo * periodInfo)191 void DashMpdParser::ParseAdaptationSet(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
192 DashPeriodInfo *periodInfo)
193 {
194 DashAdptSetInfo *adptSetInfo = new DashAdptSetInfo;
195 if (adptSetInfo != nullptr) {
196 IDashMpdNode *adptSetNode = IDashMpdNode::CreateNode(MPD_LABEL_ADAPTATIONSET);
197 if (adptSetNode == nullptr) {
198 delete adptSetInfo;
199 return;
200 }
201
202 adptSetNode->ParseNode(xmlParser, rootElement);
203 GetAdaptationSetAttr(adptSetNode, adptSetInfo);
204 GetAdaptationSetElement(xmlParser, rootElement, periodInfo, adptSetInfo);
205
206 periodInfo->adptSetList_.push_back(adptSetInfo);
207 IDashMpdNode::DestroyNode(adptSetNode);
208 } else {
209 MEDIA_LOG_E("ParseAdaptationSet adptSetInfo == nullptr");
210 }
211 }
212
GetAdaptationSetAttr(IDashMpdNode * adptSetNode,DashAdptSetInfo * adptSetInfo)213 void DashMpdParser::GetAdaptationSetAttr(IDashMpdNode *adptSetNode, DashAdptSetInfo *adptSetInfo)
214 {
215 GetAdptSetCommonAttr(adptSetNode, adptSetInfo);
216
217 double dValue;
218 adptSetNode->GetAttr("maxPlayoutRate", dValue);
219 const double eps = 1e-8; // Limiting the Error Range
220 if (fabs(dValue) > eps) {
221 adptSetInfo->commonAttrsAndElements_.maxPlayoutRate_ = dValue;
222 }
223
224 std::string str;
225 adptSetNode->GetAttr("codingDependency", str);
226 if (str == "true") {
227 adptSetInfo->commonAttrsAndElements_.codingDependency_ = 1;
228 }
229
230 adptSetNode->GetAttr("scanType", str);
231 if (str == "interlaced") {
232 adptSetInfo->commonAttrsAndElements_.scanType_ = VideoScanType::VIDEO_SCAN_INTERLACED;
233 } else if (str == "unknown") {
234 adptSetInfo->commonAttrsAndElements_.scanType_ = VideoScanType::VIDEO_SCAN_UNKNOW;
235 }
236 adptSetNode->GetAttr("mimeType", adptSetInfo->mimeType_);
237 adptSetNode->GetAttr("lang", adptSetInfo->lang_);
238 adptSetNode->GetAttr("contentType", adptSetInfo->contentType_);
239 adptSetNode->GetAttr("par", adptSetInfo->par_);
240 adptSetNode->GetAttr("minFrameRate", adptSetInfo->minFrameRate_);
241 adptSetNode->GetAttr("maxFrameRate", adptSetInfo->maxFrameRate_);
242 adptSetNode->GetAttr("videoType", adptSetInfo->videoType_);
243
244 adptSetNode->GetAttr("id", adptSetInfo->id_);
245 adptSetNode->GetAttr("group", adptSetInfo->group_);
246 adptSetNode->GetAttr("minBandwidth", adptSetInfo->minBandwidth_);
247 adptSetNode->GetAttr("maxBandwidth", adptSetInfo->maxBandwidth_);
248 adptSetNode->GetAttr("minWidth", adptSetInfo->minWidth_);
249 adptSetNode->GetAttr("maxWidth", adptSetInfo->maxWidth_);
250 adptSetNode->GetAttr("minHeight", adptSetInfo->minHeight_);
251 adptSetNode->GetAttr("maxHeight", adptSetInfo->maxHeight_);
252 adptSetNode->GetAttr("cameraIndex", adptSetInfo->cameraIndex_);
253
254 adptSetNode->GetAttr("bitstreamSwitching", str);
255 if (str == "true") {
256 adptSetInfo->bitstreamSwitching_ = true;
257 }
258
259 adptSetNode->GetAttr("segmentAlignment", str);
260 if (str == "true") {
261 adptSetInfo->segmentAlignment_ = true;
262 }
263
264 adptSetNode->GetAttr("subsegmentAlignment", str);
265 if (str == "true") {
266 adptSetInfo->subSegmentAlignment_ = true;
267 }
268 }
269
GetAdptSetCommonAttr(IDashMpdNode * adptSetNode,DashAdptSetInfo * adptSetInfo) const270 void DashMpdParser::GetAdptSetCommonAttr(IDashMpdNode *adptSetNode, DashAdptSetInfo *adptSetInfo) const
271 {
272 adptSetNode->GetAttr("width", adptSetInfo->commonAttrsAndElements_.width_);
273 adptSetNode->GetAttr("height", adptSetInfo->commonAttrsAndElements_.height_);
274 adptSetNode->GetAttr("startWithSAP", adptSetInfo->commonAttrsAndElements_.startWithSAP_);
275 adptSetNode->GetAttr("sar", adptSetInfo->commonAttrsAndElements_.sar_);
276 adptSetNode->GetAttr("mimeType", adptSetInfo->commonAttrsAndElements_.mimeType_);
277 adptSetNode->GetAttr("codecs", adptSetInfo->commonAttrsAndElements_.codecs_);
278 adptSetNode->GetAttr("audioSamplingRate", adptSetInfo->commonAttrsAndElements_.audioSamplingRate_);
279 adptSetNode->GetAttr("frameRate", adptSetInfo->commonAttrsAndElements_.frameRate_);
280 adptSetNode->GetAttr("profiles", adptSetInfo->commonAttrsAndElements_.profiles_);
281 }
282
GetAdaptationSetElement(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,const DashPeriodInfo * periodInfo,DashAdptSetInfo * adptSetInfo)283 void DashMpdParser::GetAdaptationSetElement(std::shared_ptr<XmlParser> xmlParser,
284 std::shared_ptr<XmlElement> rootElement, const DashPeriodInfo *periodInfo,
285 DashAdptSetInfo *adptSetInfo)
286 {
287 // parse element in AdaptationSet
288 DashList<std::shared_ptr<XmlElement>> representationElementList;
289 DashElementList dashElementList;
290 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
291 while (childElement != nullptr) {
292 if (this->stopFlag_) {
293 break;
294 }
295
296 ProcessAdpSetElement(xmlParser, adptSetInfo, representationElementList, childElement, dashElementList);
297 childElement = childElement->GetSiblingNext();
298 }
299
300 // parse element SegmentBase
301 if (dashElementList.segBaseElement_ != nullptr) {
302 ParseSegmentBase(xmlParser, dashElementList.segBaseElement_, &adptSetInfo->adptSetSegBase_);
303 }
304
305 // parse element SegmentList
306 if (dashElementList.segListElement_ != nullptr) {
307 ParseSegmentList(xmlParser, dashElementList.segListElement_, &adptSetInfo->adptSetSegList_);
308 }
309
310 // parse element SegmentTemplate
311 if (dashElementList.segTmplElement_ != nullptr) {
312 ParseSegmentTemplate(xmlParser, dashElementList.segTmplElement_, &adptSetInfo->adptSetSegTmplt_);
313 }
314
315 // (segmentTemplate/segmentList/segmentBase) in adaptationset inherit from period
316 if (adptSetInfo->adptSetSegTmplt_ != nullptr && periodInfo->periodSegTmplt_ != nullptr) {
317 InheritMultSegBase(&adptSetInfo->adptSetSegTmplt_->multSegBaseInfo_,
318 &periodInfo->periodSegTmplt_->multSegBaseInfo_);
319 }
320
321 if (adptSetInfo->adptSetSegList_ != nullptr && periodInfo->periodSegList_ != nullptr) {
322 InheritMultSegBase(&adptSetInfo->adptSetSegList_->multSegBaseInfo_,
323 &periodInfo->periodSegList_->multSegBaseInfo_);
324 }
325
326 if (adptSetInfo->adptSetSegBase_ != nullptr && periodInfo->periodSegBase_ != nullptr) {
327 InheritSegBase(adptSetInfo->adptSetSegBase_, periodInfo->periodSegBase_);
328 }
329
330 // parse representation last
331 while (representationElementList.size() > 0) {
332 if (this->stopFlag_) {
333 break;
334 }
335
336 std::shared_ptr<XmlElement> representationElement = representationElementList.front();
337 if (representationElement != nullptr) {
338 ParseRepresentation(xmlParser, representationElement, periodInfo, adptSetInfo);
339 }
340
341 representationElementList.pop_front();
342 }
343 }
344
ProcessAdpSetElement(std::shared_ptr<XmlParser> & xmlParser,DashAdptSetInfo * adptSetInfo,DashList<std::shared_ptr<XmlElement>> & representationElementList,std::shared_ptr<XmlElement> & childElement,DashElementList & dashElementList)345 void DashMpdParser::ProcessAdpSetElement(std::shared_ptr<XmlParser> &xmlParser, DashAdptSetInfo *adptSetInfo,
346 DashList<std::shared_ptr<XmlElement>> &representationElementList,
347 std::shared_ptr<XmlElement> &childElement, DashElementList &dashElementList)
348 {
349 std::string elementNameStr = childElement->GetName();
350 if (!elementNameStr.empty()) {
351 xmlParser->SkipElementNameSpace(elementNameStr);
352
353 if (elementNameStr == MPD_LABEL_BASE_URL) {
354 // parse element BaseURL
355 std::string strValue = childElement->GetText();
356 if (!strValue.empty()) {
357 adptSetInfo->baseUrl_.push_back(strValue);
358 }
359 } else if (elementNameStr == MPD_LABEL_CONTENT_COMPONENT) {
360 // parse element ContentComponent
361 ParseContentComponent(xmlParser, childElement, adptSetInfo->contentCompList_);
362 } else if (elementNameStr == MPD_LABEL_SEGMENT_BASE) {
363 dashElementList.segBaseElement_ = childElement;
364 } else if (elementNameStr == MPD_LABEL_SEGMENT_LIST) {
365 dashElementList.segListElement_ = childElement;
366 } else if (elementNameStr == MPD_LABEL_SEGMENT_TEMPLATE) {
367 dashElementList.segTmplElement_ = childElement;
368 } else if (elementNameStr == MPD_LABEL_REPRESENTATION) {
369 // get element Representation
370 representationElementList.push_back(childElement);
371 } else if (elementNameStr == MPD_LABEL_CONTENT_PROTECTION) {
372 // parse element ContentProtection
373 ParseContentProtection(xmlParser, childElement,
374 adptSetInfo->commonAttrsAndElements_.contentProtectionList_);
375 } else if (elementNameStr == MPD_LABEL_ESSENTIAL_PROPERTY) {
376 ParseEssentialProperty(xmlParser, childElement,
377 adptSetInfo->commonAttrsAndElements_.essentialPropertyList_);
378 }
379 }
380 }
381
ParseSegmentUrl(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashSegUrl * > & segUrlList)382 void DashMpdParser::ParseSegmentUrl(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
383 DashList<DashSegUrl *> &segUrlList)
384 {
385 DashSegUrl *segUrl = new (std::nothrow) DashSegUrl;
386 if (segUrl == nullptr) {
387 return;
388 }
389
390 IDashMpdNode *segUrlNode = IDashMpdNode::CreateNode(MPD_LABEL_SEGMENT_URL);
391 if (segUrlNode == nullptr) {
392 delete segUrl;
393 return;
394 }
395
396 segUrlNode->ParseNode(xmlParser, rootElement);
397 segUrlNode->GetAttr("media", segUrl->media_);
398 segUrlNode->GetAttr("mediaRange", segUrl->mediaRange_);
399 segUrlNode->GetAttr("index", segUrl->index_);
400 segUrlNode->GetAttr("indexRange", segUrl->indexRange_);
401
402 segUrlList.push_back(segUrl);
403 IDashMpdNode::DestroyNode(segUrlNode);
404 }
405
ParseContentComponent(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashContentCompInfo * > & contentCompInfoList)406 void DashMpdParser::ParseContentComponent(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
407 DashList<DashContentCompInfo *> &contentCompInfoList)
408 {
409 DashContentCompInfo *contentCompInfo = new (std::nothrow) DashContentCompInfo;
410 if (contentCompInfo == nullptr) {
411 return;
412 }
413
414 IDashMpdNode *contentCompNode = IDashMpdNode::CreateNode(MPD_LABEL_CONTENT_COMPONENT);
415 if (contentCompNode != nullptr) {
416 contentCompNode->ParseNode(xmlParser, rootElement);
417 contentCompNode->GetAttr("id", contentCompInfo->id_);
418 contentCompNode->GetAttr("par", contentCompInfo->par_);
419 contentCompNode->GetAttr("lang", contentCompInfo->lang_);
420 contentCompNode->GetAttr("contentType", contentCompInfo->contentType_);
421
422 contentCompInfoList.push_back(contentCompInfo);
423 IDashMpdNode::DestroyNode(contentCompNode);
424 } else {
425 MEDIA_LOG_E("ParseContentComponent contentCompNode == nullptr");
426 delete contentCompInfo;
427 }
428 }
429
ParseSegmentBase(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashSegBaseInfo ** segBaseInfo)430 void DashMpdParser::ParseSegmentBase(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
431 DashSegBaseInfo **segBaseInfo)
432 {
433 if (segBaseInfo == nullptr) {
434 MEDIA_LOG_E("ParseSegmentBase segBaseInfo == nullptr");
435 return;
436 }
437
438 DashSegBaseInfo *segBase = new (std::nothrow) DashSegBaseInfo;
439 if (segBase == nullptr) {
440 return;
441 }
442
443 IDashMpdNode *segBaseNode = IDashMpdNode::CreateNode(MPD_LABEL_SEGMENT_BASE);
444 if (segBaseNode != nullptr) {
445 segBaseNode->ParseNode(xmlParser, rootElement);
446 segBaseNode->GetAttr("timescale", segBase->timeScale_);
447 segBaseNode->GetAttr("presentationTimeOffset", segBase->presentationTimeOffset_);
448 segBaseNode->GetAttr("indexRange", segBase->indexRange_);
449 std::string tmp;
450 segBaseNode->GetAttr("indexRangeExact", tmp);
451 if (tmp == "true") {
452 segBase->indexRangeExact_ = true;
453 } else {
454 segBase->indexRangeExact_ = false;
455 }
456
457 // parse element SegmentBase
458 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
459 while (childElement != nullptr) {
460 if (this->stopFlag_) {
461 break;
462 }
463
464 ParseElementUrlType(xmlParser, segBase, childElement);
465 childElement = childElement->GetSiblingNext();
466 }
467
468 *segBaseInfo = segBase;
469 IDashMpdNode::DestroyNode(segBaseNode);
470 } else {
471 MEDIA_LOG_E("ParseSegmentBase segBaseNode == nullptr");
472 delete segBase;
473 }
474 }
475
ParseElementUrlType(std::shared_ptr<XmlParser> & xmlParser,DashSegBaseInfo * segBase,std::shared_ptr<XmlElement> & childElement)476 void DashMpdParser::ParseElementUrlType(std::shared_ptr<XmlParser> &xmlParser, DashSegBaseInfo *segBase,
477 std::shared_ptr<XmlElement> &childElement)
478 {
479 std::string elementNameStr = childElement->GetName();
480 if (!elementNameStr.empty()) {
481 xmlParser->SkipElementNameSpace(elementNameStr);
482
483 if (elementNameStr == MPD_LABEL_INITIALIZATION) {
484 // parse element Initialization
485 ParseUrlType(xmlParser, childElement, elementNameStr, &segBase->initialization_);
486 } else if (elementNameStr == MPD_LABEL_REPRESENTATION_INDEX) {
487 // parse element RepresentationIndex
488 ParseUrlType(xmlParser, childElement, elementNameStr, &segBase->representationIndex_);
489 }
490 }
491 }
492
ParseSegmentList(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashSegListInfo ** segListInfo)493 void DashMpdParser::ParseSegmentList(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
494 DashSegListInfo **segListInfo)
495 {
496 if (segListInfo == nullptr) {
497 MEDIA_LOG_E("ParseSegmentList segListInfo == nullptr");
498 return;
499 }
500
501 DashSegListInfo *segList = new (std::nothrow) DashSegListInfo;
502 if (segList == nullptr) {
503 return;
504 }
505
506 IDashMpdNode *segListNode = IDashMpdNode::CreateNode(MPD_LABEL_SEGMENT_LIST);
507 if (segListNode != nullptr) {
508 segListNode->ParseNode(xmlParser, rootElement);
509 segListNode->GetAttr("duration", segList->multSegBaseInfo_.duration_);
510 segListNode->GetAttr("startNumber", segList->multSegBaseInfo_.startNumber_);
511 segListNode->GetAttr("timescale", segList->multSegBaseInfo_.segBaseInfo_.timeScale_);
512 segListNode->GetAttr("presentationTimeOffset",
513 segList->multSegBaseInfo_.segBaseInfo_.presentationTimeOffset_);
514 // parse element SegmentList
515 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
516 while (childElement != nullptr) {
517 if (this->stopFlag_) {
518 break;
519 }
520
521 ParseSegmentListElement(xmlParser, segList, childElement);
522 childElement = childElement->GetSiblingNext();
523 }
524
525 *segListInfo = segList;
526 IDashMpdNode::DestroyNode(segListNode);
527 } else {
528 MEDIA_LOG_E("ParseSegmentList segListNode == nullptr");
529 delete segList;
530 }
531 }
532
ParseSegmentListElement(std::shared_ptr<XmlParser> & xmlParser,DashSegListInfo * segList,std::shared_ptr<XmlElement> & childElement)533 void DashMpdParser::ParseSegmentListElement(std::shared_ptr<XmlParser> &xmlParser, DashSegListInfo *segList,
534 std::shared_ptr<XmlElement> &childElement)
535 {
536 std::string elementNameStr = childElement->GetName();
537 if (!elementNameStr.empty()) {
538 xmlParser->SkipElementNameSpace(elementNameStr);
539
540 if (elementNameStr == MPD_LABEL_SEGMENT_TIMELINE) {
541 // parse element SegmentTimeline
542 ParseSegmentTimeline(xmlParser, childElement, segList->multSegBaseInfo_.segTimeline_);
543 } else if (elementNameStr == MPD_LABEL_BITSTREAM_SWITCHING) {
544 // parse element BitstreamSwitching
545 ParseUrlType(xmlParser, childElement, elementNameStr,
546 &segList->multSegBaseInfo_.bitstreamSwitching_);
547 } else if (elementNameStr == MPD_LABEL_INITIALIZATION) {
548 // parse element Initialization
549 ParseUrlType(xmlParser, childElement, elementNameStr,
550 &segList->multSegBaseInfo_.segBaseInfo_.initialization_);
551 } else if (elementNameStr == MPD_LABEL_REPRESENTATION_INDEX) {
552 // parse element RepresentationIndex
553 ParseUrlType(xmlParser, childElement, elementNameStr,
554 &segList->multSegBaseInfo_.segBaseInfo_.representationIndex_);
555 } else if (elementNameStr == MPD_LABEL_SEGMENT_URL) {
556 // parse element SegmentURL
557 ParseSegmentUrl(xmlParser, childElement, segList->segmentUrl_);
558 }
559 }
560 }
561
InheritMultSegBase(DashMultSegBaseInfo * lowerMultSegBaseInfo,const DashMultSegBaseInfo * higherMultSegBaseInfo)562 void DashMpdParser::InheritMultSegBase(DashMultSegBaseInfo *lowerMultSegBaseInfo,
563 const DashMultSegBaseInfo *higherMultSegBaseInfo)
564 {
565 if (lowerMultSegBaseInfo->duration_ == 0 && higherMultSegBaseInfo->duration_ > 0) {
566 lowerMultSegBaseInfo->duration_ = higherMultSegBaseInfo->duration_;
567 }
568
569 if (lowerMultSegBaseInfo->segBaseInfo_.timeScale_ == 0 && higherMultSegBaseInfo->segBaseInfo_.timeScale_ > 0) {
570 lowerMultSegBaseInfo->segBaseInfo_.timeScale_ = higherMultSegBaseInfo->segBaseInfo_.timeScale_;
571 }
572
573 if (lowerMultSegBaseInfo->startNumber_.length() == 0 && higherMultSegBaseInfo->startNumber_.length() > 0) {
574 lowerMultSegBaseInfo->startNumber_ = higherMultSegBaseInfo->startNumber_;
575 }
576 }
577
InheritSegBase(DashSegBaseInfo * lowerSegBaseInfo,const DashSegBaseInfo * higherSegBaseInfo) const578 void DashMpdParser::InheritSegBase(DashSegBaseInfo *lowerSegBaseInfo, const DashSegBaseInfo *higherSegBaseInfo) const
579 {
580 if (lowerSegBaseInfo->timeScale_ == 0 && higherSegBaseInfo->timeScale_ > 0) {
581 lowerSegBaseInfo->timeScale_ = higherSegBaseInfo->timeScale_;
582 }
583 }
584
ParseSegmentTemplate(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashSegTmpltInfo ** segTmpltInfo)585 void DashMpdParser::ParseSegmentTemplate(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
586 DashSegTmpltInfo **segTmpltInfo)
587 {
588 if (segTmpltInfo == nullptr) {
589 MEDIA_LOG_E("ParseSegmentTemplate segTmpltInfo == nullptr");
590 return;
591 }
592
593 DashSegTmpltInfo *segTmplt = new DashSegTmpltInfo;
594 if (segTmplt != nullptr) {
595 IDashMpdNode *segTmpltNode = IDashMpdNode::CreateNode(MPD_LABEL_SEGMENT_TEMPLATE);
596 if (segTmpltNode == nullptr) {
597 delete segTmplt;
598 return;
599 }
600
601 segTmpltNode->ParseNode(xmlParser, rootElement);
602 segTmpltNode->GetAttr("timescale", segTmplt->multSegBaseInfo_.segBaseInfo_.timeScale_);
603 segTmpltNode->GetAttr("presentationTimeOffset",
604 segTmplt->multSegBaseInfo_.segBaseInfo_.presentationTimeOffset_);
605 segTmpltNode->GetAttr("duration", segTmplt->multSegBaseInfo_.duration_);
606 segTmpltNode->GetAttr("startNumber", segTmplt->multSegBaseInfo_.startNumber_);
607 segTmpltNode->GetAttr("media", segTmplt->segTmpltMedia_);
608 segTmpltNode->GetAttr("index", segTmplt->segTmpltIndex_);
609 segTmpltNode->GetAttr("initialization", segTmplt->segTmpltInitialization_);
610 segTmpltNode->GetAttr("bitstreamSwitching", segTmplt->segTmpltBitstreamSwitching_);
611
612 // parse element SegmentTemplate
613 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
614 while (childElement != nullptr) {
615 if (this->stopFlag_) {
616 break;
617 }
618
619 ParseElement(xmlParser, segTmplt, childElement);
620 childElement = childElement->GetSiblingNext();
621 }
622
623 *segTmpltInfo = segTmplt;
624 IDashMpdNode::DestroyNode(segTmpltNode);
625 }
626 }
627
ParseElement(std::shared_ptr<XmlParser> & xmlParser,DashSegTmpltInfo * segTmplt,std::shared_ptr<XmlElement> & childElement)628 void DashMpdParser::ParseElement(std::shared_ptr<XmlParser> &xmlParser, DashSegTmpltInfo *segTmplt,
629 std::shared_ptr<XmlElement> &childElement)
630 {
631 std::string elementNameStr = childElement->GetName();
632 if (!elementNameStr.empty()) {
633 xmlParser->SkipElementNameSpace(elementNameStr);
634
635 if (elementNameStr == MPD_LABEL_SEGMENT_TIMELINE) {
636 // parse element SegmentTimeline
637 ParseSegmentTimeline(xmlParser, childElement, segTmplt->multSegBaseInfo_.segTimeline_);
638 } else if (elementNameStr == MPD_LABEL_BITSTREAM_SWITCHING) {
639 // parse element BitstreamSwitching
640 ParseUrlType(xmlParser, childElement, elementNameStr,
641 &segTmplt->multSegBaseInfo_.bitstreamSwitching_);
642 } else if (elementNameStr == MPD_LABEL_INITIALIZATION) {
643 // parse element Initialization
644 ParseUrlType(xmlParser, childElement, elementNameStr,
645 &segTmplt->multSegBaseInfo_.segBaseInfo_.initialization_);
646 } else if (elementNameStr == MPD_LABEL_REPRESENTATION_INDEX) {
647 // parse element RepresentationIndex
648 ParseUrlType(xmlParser, childElement, elementNameStr,
649 &segTmplt->multSegBaseInfo_.segBaseInfo_.representationIndex_);
650 }
651 }
652 }
653
ParseRepresentation(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,const DashPeriodInfo * periodInfo,DashAdptSetInfo * adptSetInfo)654 void DashMpdParser::ParseRepresentation(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
655 const DashPeriodInfo *periodInfo,
656 DashAdptSetInfo *adptSetInfo)
657 {
658 DashRepresentationInfo *representationInfo = new (std::nothrow) DashRepresentationInfo;
659 if (representationInfo == nullptr) {
660 return;
661 }
662
663 IDashMpdNode *representationNode = IDashMpdNode::CreateNode(MPD_LABEL_REPRESENTATION);
664 if (representationNode != nullptr) {
665 representationNode->ParseNode(xmlParser, rootElement);
666
667 GetRepresentationAttr(representationNode, representationInfo);
668 GetRepresentationElement(xmlParser, rootElement, periodInfo, adptSetInfo, representationInfo);
669
670 adptSetInfo->representationList_.push_back(representationInfo);
671 IDashMpdNode::DestroyNode(representationNode);
672 } else {
673 MEDIA_LOG_E("ParseRepresentation representationNode == nullptr");
674 delete representationInfo;
675 }
676 }
677
GetRepresentationAttr(IDashMpdNode * representationNode,DashRepresentationInfo * representationInfo)678 void DashMpdParser::GetRepresentationAttr(IDashMpdNode *representationNode, DashRepresentationInfo *representationInfo)
679 {
680 representationNode->GetAttr("id", representationInfo->id_);
681 representationNode->GetAttr("volumeAdjust_", representationInfo->volumeAdjust_);
682 representationNode->GetAttr("bandwidth", representationInfo->bandwidth_);
683 representationNode->GetAttr("qualityRanking", representationInfo->qualityRanking_);
684 representationNode->GetAttr("width", representationInfo->commonAttrsAndElements_.width_);
685 representationNode->GetAttr("height", representationInfo->commonAttrsAndElements_.height_);
686 representationNode->GetAttr("frameRate", representationInfo->commonAttrsAndElements_.frameRate_);
687 representationNode->GetAttr("codecs", representationInfo->commonAttrsAndElements_.codecs_);
688 representationNode->GetAttr("mimeType", representationInfo->commonAttrsAndElements_.mimeType_);
689 representationNode->GetAttr("startWithSAP", representationInfo->commonAttrsAndElements_.startWithSAP_);
690 representationNode->GetAttr("cuvvVersion", representationInfo->commonAttrsAndElements_.cuvvVersion_);
691 }
692
GetRepresentationElement(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,const DashPeriodInfo * periodInfo,const DashAdptSetInfo * adptSetInfo,DashRepresentationInfo * representationInfo)693 void DashMpdParser::GetRepresentationElement(std::shared_ptr<XmlParser> xmlParser,
694 std::shared_ptr<XmlElement> rootElement,
695 const DashPeriodInfo *periodInfo, const DashAdptSetInfo *adptSetInfo,
696 DashRepresentationInfo *representationInfo)
697 {
698 // parse element Representation
699 DashElementList dashElementList;
700 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
701 while (childElement != nullptr) {
702 if (this->stopFlag_) {
703 break;
704 }
705
706 ProcessRepresentationElement(xmlParser, representationInfo, childElement, dashElementList);
707 childElement = childElement->GetSiblingNext();
708 }
709
710 // parse element SegmentBase
711 if (dashElementList.segBaseElement_ != nullptr) {
712 ParseSegmentBase(xmlParser, dashElementList.segBaseElement_, &representationInfo->representationSegBase_);
713 }
714
715 // parse element SegmentList
716 if (dashElementList.segListElement_ != nullptr) {
717 ParseSegmentList(xmlParser, dashElementList.segListElement_, &representationInfo->representationSegList_);
718 }
719
720 // parse element SegmentTemplate
721 if (dashElementList.segTmplElement_ != nullptr) {
722 ParseSegmentTemplate(xmlParser, dashElementList.segTmplElement_, &representationInfo->representationSegTmplt_);
723 }
724
725 // (segmentTemplate/segmentList/segmentBase) in representation inherit from adaptationset or period
726 if (representationInfo->representationSegTmplt_ != nullptr && adptSetInfo->adptSetSegTmplt_ != nullptr) {
727 InheritMultSegBase(&representationInfo->representationSegTmplt_->multSegBaseInfo_,
728 &adptSetInfo->adptSetSegTmplt_->multSegBaseInfo_);
729 } else if (representationInfo->representationSegTmplt_ != nullptr && periodInfo->periodSegTmplt_ != nullptr) {
730 InheritMultSegBase(&representationInfo->representationSegTmplt_->multSegBaseInfo_,
731 &periodInfo->periodSegTmplt_->multSegBaseInfo_);
732 }
733
734 if (representationInfo->representationSegList_ != nullptr && adptSetInfo->adptSetSegList_ != nullptr) {
735 InheritMultSegBase(&representationInfo->representationSegList_->multSegBaseInfo_,
736 &adptSetInfo->adptSetSegList_->multSegBaseInfo_);
737 } else if (representationInfo->representationSegList_ != nullptr && periodInfo->periodSegList_ != nullptr) {
738 InheritMultSegBase(&representationInfo->representationSegList_->multSegBaseInfo_,
739 &periodInfo->periodSegList_->multSegBaseInfo_);
740 }
741
742 if (representationInfo->representationSegBase_ != nullptr && adptSetInfo->adptSetSegBase_ != nullptr) {
743 InheritSegBase(representationInfo->representationSegBase_, adptSetInfo->adptSetSegBase_);
744 } else if (representationInfo->representationSegBase_ != nullptr && periodInfo->periodSegBase_ != nullptr) {
745 InheritSegBase(representationInfo->representationSegBase_, periodInfo->periodSegBase_);
746 }
747 }
748
ProcessRepresentationElement(std::shared_ptr<XmlParser> & xmlParser,DashRepresentationInfo * representationInfo,std::shared_ptr<XmlElement> & childElement,DashElementList & dashElementList)749 void DashMpdParser::ProcessRepresentationElement(std::shared_ptr<XmlParser> &xmlParser,
750 DashRepresentationInfo *representationInfo,
751 std::shared_ptr<XmlElement> &childElement,
752 DashElementList &dashElementList)
753 {
754 std::string elementNameStr = childElement->GetName();
755 if (!elementNameStr.empty()) {
756 xmlParser->SkipElementNameSpace(elementNameStr);
757
758 if (elementNameStr == MPD_LABEL_BASE_URL) {
759 // parse element BaseURL
760 std::string strValue = childElement->GetText();
761 if (!strValue.empty()) {
762 representationInfo->baseUrl_.push_back(strValue);
763 }
764 } else if (elementNameStr == MPD_LABEL_SEGMENT_BASE) {
765 dashElementList.segBaseElement_ = childElement;
766 } else if (elementNameStr == MPD_LABEL_SEGMENT_LIST) {
767 dashElementList.segListElement_ = childElement;
768 } else if (elementNameStr == MPD_LABEL_SEGMENT_TEMPLATE) {
769 dashElementList.segTmplElement_ = childElement;
770 } else if (elementNameStr == MPD_LABEL_CONTENT_PROTECTION) {
771 // parse element ContentProtection
772 ParseContentProtection(xmlParser, childElement,
773 representationInfo->commonAttrsAndElements_.contentProtectionList_);
774 } else if (elementNameStr == MPD_LABEL_ESSENTIAL_PROPERTY) {
775 ParseEssentialProperty(xmlParser, childElement,
776 representationInfo->commonAttrsAndElements_.essentialPropertyList_);
777 } else if (elementNameStr == MPD_LABEL_AUDIO_CHANNEL_CONFIGURATION) {
778 ParseAudioChannelConfiguration(
779 xmlParser, childElement,
780 representationInfo->commonAttrsAndElements_.audioChannelConfigurationList_);
781 }
782 }
783 }
784
ParseContentProtection(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashDescriptor * > & contentProtectionList)785 void DashMpdParser::ParseContentProtection(std::shared_ptr<XmlParser> xmlParser,
786 std::shared_ptr<XmlElement> rootElement,
787 DashList<DashDescriptor *> &contentProtectionList)
788 {
789 DashDescriptor *contentProtection = new (std::nothrow) DashDescriptor;
790 if (contentProtection == nullptr) {
791 return;
792 }
793
794 IDashMpdNode *contentProtectionNode = IDashMpdNode::CreateNode(MPD_LABEL_CONTENT_PROTECTION);
795 if (contentProtectionNode != nullptr) {
796 contentProtectionNode->ParseNode(xmlParser, rootElement);
797 contentProtectionNode->GetAttr("schemeIdUri", contentProtection->schemeIdUrl_);
798 contentProtectionNode->GetAttr("value", contentProtection->value_);
799 contentProtectionNode->GetAttr(MPD_LABEL_DEFAULT_KID, contentProtection->defaultKid_);
800
801 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
802 while (childElement != nullptr) {
803 if (this->stopFlag_) {
804 break;
805 }
806
807 GetContentProtection(xmlParser, contentProtection, childElement);
808 childElement = childElement->GetSiblingNext();
809 }
810
811 contentProtectionList.push_back(contentProtection);
812 IDashMpdNode::DestroyNode(contentProtectionNode);
813 } else {
814 MEDIA_LOG_E("contentProtectionNode == nullptr");
815 delete contentProtection;
816 }
817 }
818
GetContentProtection(const std::shared_ptr<XmlParser> & xmlParser,DashDescriptor * contentProtection,std::shared_ptr<XmlElement> & childElement) const819 void DashMpdParser::GetContentProtection(const std::shared_ptr<XmlParser> &xmlParser, DashDescriptor *contentProtection,
820 std::shared_ptr<XmlElement> &childElement) const
821 {
822 std::string elementNameStr = childElement->GetName();
823 if (!elementNameStr.empty()) {
824 xmlParser->SkipElementNameSpace(elementNameStr);
825
826 if (elementNameStr == MPD_LABEL_PSSH && contentProtection->elementMap_.size() == 0) {
827 // only support one pssh in ContentProtection
828 std::string psshValue = childElement->GetText();
829 if (!psshValue.empty()) {
830 std::string pssh(MPD_LABEL_PSSH);
831 contentProtection->elementMap_.insert(
832 std::map<std::string, std::string>::value_type(pssh, psshValue));
833 }
834 }
835 }
836 }
837
ParseEssentialProperty(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashDescriptor * > & essentialPropertyList)838 void DashMpdParser::ParseEssentialProperty(std::shared_ptr<XmlParser> xmlParser,
839 std::shared_ptr<XmlElement> rootElement,
840 DashList<DashDescriptor *> &essentialPropertyList)
841 {
842 DashDescriptor *essentialProperty = new (std::nothrow) DashDescriptor;
843 if (essentialProperty == nullptr) {
844 return;
845 }
846
847 IDashMpdNode *essentialPropertyNode = IDashMpdNode::CreateNode(MPD_LABEL_ESSENTIAL_PROPERTY);
848 if (essentialPropertyNode != nullptr) {
849 essentialPropertyNode->ParseNode(xmlParser, rootElement);
850 essentialPropertyNode->GetAttr("schemeIdUri", essentialProperty->schemeIdUrl_);
851 essentialPropertyNode->GetAttr("value", essentialProperty->value_);
852
853 essentialPropertyList.push_back(essentialProperty);
854 IDashMpdNode::DestroyNode(essentialPropertyNode);
855 } else {
856 MEDIA_LOG_E("essentialPropertyNode == nullptr");
857 delete essentialProperty;
858 }
859 }
860
ParseAudioChannelConfiguration(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashDescriptor * > & propertyList)861 void DashMpdParser::ParseAudioChannelConfiguration(std::shared_ptr<XmlParser> xmlParser,
862 std::shared_ptr<XmlElement> rootElement,
863 DashList<DashDescriptor *> &propertyList)
864 {
865 DashDescriptor *channelProperty = new (std::nothrow) DashDescriptor;
866 if (channelProperty == nullptr) {
867 return;
868 }
869
870 IDashMpdNode *node = IDashMpdNode::CreateNode(MPD_LABEL_AUDIO_CHANNEL_CONFIGURATION);
871 if (node != nullptr) {
872 node->ParseNode(xmlParser, rootElement);
873 node->GetAttr("schemeIdUri", channelProperty->schemeIdUrl_);
874 node->GetAttr("value", channelProperty->value_);
875 propertyList.push_back(channelProperty);
876
877 IDashMpdNode::DestroyNode(node);
878 } else {
879 MEDIA_LOG_E("audioChannelConfigurationNode=null");
880 delete channelProperty;
881 }
882 }
883
ParseSegmentTimeline(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,DashList<DashSegTimeline * > & segTmlineList)884 void DashMpdParser::ParseSegmentTimeline(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
885 DashList<DashSegTimeline *> &segTmlineList)
886 {
887 // parse element SegmentTimeliness
888 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
889 while (childElement != nullptr) {
890 if (this->stopFlag_) {
891 break;
892 }
893
894 std::string elementNameStr = childElement->GetName();
895 if (!elementNameStr.empty()) {
896 xmlParser->SkipElementNameSpace(elementNameStr);
897 if (elementNameStr != MPD_LABEL_SEGMENT_TIMELINE_S) {
898 childElement = childElement->GetSiblingNext();
899 continue;
900 }
901
902 DashSegTimeline *segTimeLine = new (std::nothrow) DashSegTimeline;
903 if (segTimeLine == nullptr) {
904 MEDIA_LOG_E("segTimeLine == nullptr");
905 break;
906 }
907
908 IDashMpdNode *node = IDashMpdNode::CreateNode("SegmentTimeline");
909 if (node != nullptr) {
910 node->ParseNode(xmlParser, childElement);
911 node->GetAttr("t", segTimeLine->t_);
912 node->GetAttr("d", segTimeLine->d_);
913 node->GetAttr("r", segTimeLine->r_);
914
915 segTmlineList.push_back(segTimeLine);
916 IDashMpdNode::DestroyNode(node);
917 } else {
918 MEDIA_LOG_E("SegmentTimeline node == nullptr");
919 delete segTimeLine;
920 break;
921 }
922 }
923
924 childElement = childElement->GetSiblingNext();
925 }
926 }
927
ParseUrlType(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement,const std::string urlTypeName,DashUrlType ** urlTypeInfo)928 void DashMpdParser::ParseUrlType(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement,
929 const std::string urlTypeName,
930 DashUrlType **urlTypeInfo)
931 {
932 if (urlTypeInfo == nullptr) {
933 MEDIA_LOG_E("ParseUrlType urlTypeInfo == nullptr");
934 return;
935 }
936
937 if (*urlTypeInfo != nullptr) {
938 MEDIA_LOG_W("ParseUrlType " PUBLIC_LOG_S ", the value is not nullptr", urlTypeName.c_str());
939 return;
940 }
941
942 DashUrlType *urlType = new (std::nothrow) DashUrlType;
943 if (urlType == nullptr) {
944 return;
945 }
946
947 IDashMpdNode *urlTypeNode = IDashMpdNode::CreateNode(urlTypeName);
948 if (urlTypeNode != nullptr) {
949 urlTypeNode->ParseNode(xmlParser, rootElement);
950 urlTypeNode->GetAttr("sourceURL", urlType->sourceUrl_);
951 urlTypeNode->GetAttr("range", urlType->range_);
952
953 IDashMpdNode::DestroyNode(urlTypeNode);
954 }
955
956 *urlTypeInfo = urlType;
957 }
958
ParseProgramInfo(std::list<std::string> & programStrList) const959 void DashMpdParser::ParseProgramInfo(std::list<std::string> &programStrList) const {}
960
ParseBaseUrl(std::list<std::string> & baseUrlStrList) const961 void DashMpdParser::ParseBaseUrl(std::list<std::string> &baseUrlStrList) const {}
962
ParseLocation(std::list<std::string> & locationStrlist) const963 void DashMpdParser::ParseLocation(std::list<std::string> &locationStrlist) const {}
964
ParseMetrics(std::list<std::string> & metricsStrList) const965 void DashMpdParser::ParseMetrics(std::list<std::string> &metricsStrList) const {}
966
GetMpdAttr(IDashMpdNode * mpdNode)967 void DashMpdParser::GetMpdAttr(IDashMpdNode *mpdNode)
968 {
969 mpdNode->GetAttr("profiles", dashMpdInfo_.profile_);
970 mpdNode->GetAttr("mediaType", dashMpdInfo_.mediaType_);
971 mpdNode->GetAttr("hwDefaultViewIndex", dashMpdInfo_.hwDefaultViewIndex_);
972 mpdNode->GetAttr("hwTotalViewNumber", dashMpdInfo_.hwTotalViewNumber_);
973
974 std::string type;
975 mpdNode->GetAttr("type", type);
976
977 if (type == "dynamic") {
978 dashMpdInfo_.type_ = DashType::DASH_TYPE_DYNAMIC;
979 } else {
980 dashMpdInfo_.type_ = DashType::DASH_TYPE_STATIC;
981 }
982
983 std::string time;
984 mpdNode->GetAttr("mediaPresentationDuration", time);
985 DashStrToDuration(time, dashMpdInfo_.mediaPresentationDuration_);
986
987 mpdNode->GetAttr("minimumUpdatePeriod", time);
988 DashStrToDuration(time, dashMpdInfo_.minimumUpdatePeriod_);
989
990 mpdNode->GetAttr("minBufferTime", time);
991 DashStrToDuration(time, dashMpdInfo_.minBufferTime_);
992
993 mpdNode->GetAttr("timeShiftBufferDepth", time);
994 DashStrToDuration(time, dashMpdInfo_.timeShiftBufferDepth_);
995
996 mpdNode->GetAttr("suggestedPresentationDelay", time);
997 DashStrToDuration(time, dashMpdInfo_.suggestedPresentationDelay_);
998
999 mpdNode->GetAttr("maxSegmentDuration", time);
1000 DashStrToDuration(time, dashMpdInfo_.maxSegmentDuration_);
1001
1002 mpdNode->GetAttr("maxSubsegmentDuration", time);
1003 DashStrToDuration(time, dashMpdInfo_.maxSubSegmentDuration_);
1004
1005 std::string startTime;
1006 mpdNode->GetAttr("availabilityStartTime", startTime);
1007 dashMpdInfo_.availabilityStartTime_ = (int64_t)String2Time(startTime) * S_2_MS;
1008 }
1009
GetMpdElement(std::shared_ptr<XmlParser> xmlParser,std::shared_ptr<XmlElement> rootElement)1010 void DashMpdParser::GetMpdElement(std::shared_ptr<XmlParser> xmlParser, std::shared_ptr<XmlElement> rootElement)
1011 {
1012 DashList<std::shared_ptr<XmlElement>> periodElementList;
1013 std::shared_ptr<XmlElement> childElement = rootElement->GetChild();
1014 while (childElement != nullptr) {
1015 if (this->stopFlag_) {
1016 break;
1017 }
1018
1019 ProcessMpdElement(xmlParser, periodElementList, childElement);
1020 childElement = childElement->GetSiblingNext();
1021 }
1022 ParsePeriodElement(xmlParser, periodElementList);
1023 }
1024
ProcessMpdElement(const std::shared_ptr<XmlParser> & xmlParser,DashList<std::shared_ptr<XmlElement>> & periodElementList,std::shared_ptr<XmlElement> & childElement)1025 void DashMpdParser::ProcessMpdElement(const std::shared_ptr<XmlParser> &xmlParser,
1026 DashList <std::shared_ptr<XmlElement>> &periodElementList,
1027 std::shared_ptr<XmlElement> &childElement)
1028 {
1029 std::string elementNameStr = childElement->GetName();
1030 if (!elementNameStr.empty()) {
1031 xmlParser->SkipElementNameSpace(elementNameStr);
1032
1033 if (elementNameStr == MPD_LABEL_BASE_URL) {
1034 std::string strValue = childElement->GetText();
1035 if (!strValue.empty()) {
1036 dashMpdInfo_.baseUrl_.push_back(strValue);
1037 }
1038 } else if (elementNameStr == MPD_LABEL_PERIOD) {
1039 periodElementList.push_back(childElement);
1040 }
1041 }
1042 }
1043
ParsePeriodElement(std::shared_ptr<XmlParser> & xmlParser,DashList<std::shared_ptr<XmlElement>> & periodElementList)1044 void DashMpdParser::ParsePeriodElement(std::shared_ptr<XmlParser> &xmlParser,
1045 DashList<std::shared_ptr<XmlElement>> &periodElementList)
1046 {
1047 // parse Period label last
1048 while (periodElementList.size() > 0) {
1049 if (this->stopFlag_) {
1050 break;
1051 }
1052
1053 std::shared_ptr<XmlElement> periodElement = periodElementList.front();
1054 if (periodElement != nullptr) {
1055 ParsePeriod(xmlParser, periodElement);
1056 }
1057
1058 periodElementList.pop_front();
1059 }
1060 }
1061
ParseMPD(const char * mpdData,uint32_t length)1062 void DashMpdParser::ParseMPD(const char *mpdData, uint32_t length)
1063 {
1064 if (this->stopFlag_) {
1065 return;
1066 }
1067
1068 std::shared_ptr<XmlParser> xmlParser = std::make_shared<XmlParser>();
1069 int32_t ret = xmlParser->ParseFromBuffer(mpdData, length);
1070 std::shared_ptr<XmlElement> rootElement = xmlParser->GetRootElement();
1071 if (ret != static_cast<int32_t>(XmlBaseRtnValue::XML_BASE_OK) || this->stopFlag_ || rootElement == nullptr) {
1072 MEDIA_LOG_E("Parse error or stop " PUBLIC_LOG_D32 ", ret=" PUBLIC_LOG_D32, this->stopFlag_, ret);
1073 return;
1074 }
1075
1076 IDashMpdNode *mpdNode = IDashMpdNode::CreateNode(MPD_LABEL_MPD);
1077 if (mpdNode == nullptr) {
1078 return;
1079 }
1080
1081 // parse attribute in MPD label
1082 mpdNode->ParseNode(xmlParser, rootElement);
1083 GetMpdAttr(mpdNode);
1084
1085 // parse element in MPD label
1086 GetMpdElement(xmlParser, rootElement);
1087
1088 IDashMpdNode::DestroyNode(mpdNode);
1089 }
1090
GetMPD(DashMpdInfo * & mpdInfo)1091 void DashMpdParser::GetMPD(DashMpdInfo *&mpdInfo)
1092 {
1093 mpdInfo = &dashMpdInfo_;
1094 }
1095
Clear()1096 void DashMpdParser::Clear()
1097 {
1098 while (dashMpdInfo_.periodInfoList_.size() > 0) {
1099 DashPeriodInfo *periodInfo = dashMpdInfo_.periodInfoList_.front();
1100 if (periodInfo != nullptr) {
1101 ClearAdaptationSet(periodInfo->adptSetList_);
1102 FreeSegmentBase(periodInfo->periodSegBase_);
1103 FreeSegmentList(periodInfo->periodSegList_);
1104 FreeSegmentTemplate(periodInfo->periodSegTmplt_);
1105 delete periodInfo;
1106 }
1107 dashMpdInfo_.periodInfoList_.pop_front();
1108 }
1109
1110 while (dashMpdInfo_.baseUrl_.size() > 0) {
1111 dashMpdInfo_.baseUrl_.pop_front();
1112 }
1113
1114 dashMpdInfo_.type_ = DashType::DASH_TYPE_STATIC;
1115 dashMpdInfo_.mediaPresentationDuration_ = 0;
1116 dashMpdInfo_.minimumUpdatePeriod_ = 0;
1117 dashMpdInfo_.minBufferTime_ = 0;
1118 dashMpdInfo_.timeShiftBufferDepth_ = 0;
1119 dashMpdInfo_.suggestedPresentationDelay_ = 0;
1120 dashMpdInfo_.maxSegmentDuration_ = 0;
1121 dashMpdInfo_.maxSubSegmentDuration_ = 0;
1122 dashMpdInfo_.availabilityStartTime_ = 0;
1123 dashMpdInfo_.availabilityEndTime_ = 0;
1124 dashMpdInfo_.hwDefaultViewIndex_ = 0;
1125 dashMpdInfo_.hwTotalViewNumber_ = 0;
1126 dashMpdInfo_.profile_ = "";
1127 dashMpdInfo_.mediaType_ = "";
1128 stopFlag_ = 0;
1129 }
1130
StopParseMpd()1131 void DashMpdParser::StopParseMpd()
1132 {
1133 this->stopFlag_ = 1;
1134 }
1135
FreeSegmentBase(DashSegBaseInfo * segBaseInfo) const1136 void DashMpdParser::FreeSegmentBase(DashSegBaseInfo *segBaseInfo) const
1137 {
1138 if (segBaseInfo != nullptr) {
1139 ClearSegmentBase(segBaseInfo);
1140
1141 delete segBaseInfo;
1142 }
1143 }
1144
FreeSegmentList(DashSegListInfo * segListInfo)1145 void DashMpdParser::FreeSegmentList(DashSegListInfo *segListInfo)
1146 {
1147 if (segListInfo != nullptr) {
1148 ClearMultSegBase(&segListInfo->multSegBaseInfo_);
1149
1150 while (segListInfo->segmentUrl_.size() > 0) {
1151 DashSegUrl *segUrl = segListInfo->segmentUrl_.front();
1152 if (segUrl != nullptr) {
1153 delete segUrl;
1154 }
1155
1156 segListInfo->segmentUrl_.pop_front();
1157 }
1158
1159 delete segListInfo;
1160 }
1161 }
1162
FreeSegmentTemplate(DashSegTmpltInfo * segTmpltInfo)1163 void DashMpdParser::FreeSegmentTemplate(DashSegTmpltInfo *segTmpltInfo)
1164 {
1165 if (segTmpltInfo != nullptr) {
1166 ClearMultSegBase(&segTmpltInfo->multSegBaseInfo_);
1167
1168 delete segTmpltInfo;
1169 }
1170 }
1171
ClearAdaptationSet(DashList<DashAdptSetInfo * > & adptSetInfoList)1172 void DashMpdParser::ClearAdaptationSet(DashList<DashAdptSetInfo *> &adptSetInfoList)
1173 {
1174 while (adptSetInfoList.size() > 0) {
1175 DashAdptSetInfo *adptSetInfo = adptSetInfoList.front();
1176 if (adptSetInfo != nullptr) {
1177 ClearContentComp(adptSetInfo->contentCompList_);
1178 ClearRepresentation(adptSetInfo->representationList_);
1179 ClearCommonAttrsAndElements(&adptSetInfo->commonAttrsAndElements_);
1180 ClearRoleList(adptSetInfo->roleList_);
1181
1182 FreeSegmentBase(adptSetInfo->adptSetSegBase_);
1183 FreeSegmentList(adptSetInfo->adptSetSegList_);
1184 FreeSegmentTemplate(adptSetInfo->adptSetSegTmplt_);
1185
1186 delete adptSetInfo;
1187 }
1188
1189 adptSetInfoList.pop_front();
1190 }
1191 }
1192
ClearContentComp(DashList<DashContentCompInfo * > & contentCompList)1193 void DashMpdParser::ClearContentComp(DashList<DashContentCompInfo *> &contentCompList)
1194 {
1195 while (contentCompList.size() > 0) {
1196 DashContentCompInfo *contentCompInfo = contentCompList.front();
1197 if (contentCompInfo != nullptr) {
1198 ClearRoleList(contentCompInfo->roleList_);
1199
1200 delete contentCompInfo;
1201 }
1202
1203 contentCompList.pop_front();
1204 }
1205 }
1206
ClearRepresentation(DashList<DashRepresentationInfo * > & representationList)1207 void DashMpdParser::ClearRepresentation(DashList<DashRepresentationInfo *> &representationList)
1208 {
1209 while (representationList.size() > 0) {
1210 DashRepresentationInfo *representationInfo = representationList.front();
1211 if (representationInfo != nullptr) {
1212 ClearCommonAttrsAndElements(&representationInfo->commonAttrsAndElements_);
1213
1214 FreeSegmentBase(representationInfo->representationSegBase_);
1215 FreeSegmentList(representationInfo->representationSegList_);
1216 FreeSegmentTemplate(representationInfo->representationSegTmplt_);
1217
1218 delete representationInfo;
1219 }
1220
1221 representationList.pop_front();
1222 }
1223 }
1224
ClearSegmentBase(DashSegBaseInfo * segBaseInfo) const1225 void DashMpdParser::ClearSegmentBase(DashSegBaseInfo *segBaseInfo) const
1226 {
1227 if (segBaseInfo != nullptr) {
1228 if (segBaseInfo->initialization_ != nullptr) {
1229 delete segBaseInfo->initialization_;
1230 segBaseInfo->initialization_ = nullptr;
1231 }
1232
1233 if (segBaseInfo->representationIndex_ != nullptr) {
1234 delete segBaseInfo->representationIndex_;
1235 segBaseInfo->representationIndex_ = nullptr;
1236 }
1237 }
1238 }
1239
ClearMultSegBase(DashMultSegBaseInfo * multSegBaseInfo)1240 void DashMpdParser::ClearMultSegBase(DashMultSegBaseInfo *multSegBaseInfo)
1241 {
1242 if (multSegBaseInfo != nullptr) {
1243 if (multSegBaseInfo->bitstreamSwitching_ != nullptr) {
1244 delete multSegBaseInfo->bitstreamSwitching_;
1245 multSegBaseInfo->bitstreamSwitching_ = nullptr;
1246 }
1247
1248 while (multSegBaseInfo->segTimeline_.size() > 0) {
1249 DashSegTimeline *segTimeline = multSegBaseInfo->segTimeline_.front();
1250 if (segTimeline != nullptr) {
1251 delete segTimeline;
1252 }
1253
1254 multSegBaseInfo->segTimeline_.pop_front();
1255 }
1256
1257 ClearSegmentBase(&multSegBaseInfo->segBaseInfo_);
1258 }
1259 }
1260
ClearPropertyList(DashList<DashDescriptor * > & propertyList)1261 static void ClearPropertyList(DashList<DashDescriptor *> &propertyList)
1262 {
1263 while (propertyList.size() > 0) {
1264 DashDescriptor *property = propertyList.front();
1265 if (property != nullptr) {
1266 delete property;
1267 }
1268 propertyList.pop_front();
1269 }
1270 }
1271
ClearCommonAttrsAndElements(DashCommonAttrsAndElements * commonAttrsAndElements)1272 void DashMpdParser::ClearCommonAttrsAndElements(DashCommonAttrsAndElements *commonAttrsAndElements)
1273 {
1274 if (commonAttrsAndElements == nullptr) {
1275 return;
1276 }
1277 ClearPropertyList(commonAttrsAndElements->audioChannelConfigurationList_);
1278 ClearPropertyList(commonAttrsAndElements->contentProtectionList_);
1279 ClearPropertyList(commonAttrsAndElements->essentialPropertyList_);
1280 }
1281
ClearRoleList(DashList<DashDescriptor * > & roleList)1282 void DashMpdParser::ClearRoleList(DashList<DashDescriptor *> &roleList)
1283 {
1284 while (roleList.size() > 0) {
1285 DashDescriptor *role = roleList.front();
1286 if (role != nullptr) {
1287 delete role;
1288 }
1289
1290 roleList.pop_front();
1291 }
1292 }
1293 } // namespace HttpPluginLite
1294 } // namespace Plugin
1295 } // namespace Media
1296 } // namespace OHOS