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