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 
16 #include "dash_period_manager.h"
17 #include "dash_manager_util.h"
18 
19 namespace OHOS {
20 namespace Media {
21 namespace Plugins {
22 namespace HttpPlugin {
23 /**
24  * @brief   ContentComponent contain mime type such as audio/application
25  *
26  * @param   contentComp         contentcomponent list
27  * @param   pattern             audio/application
28  *
29  * @return  bool
30  */
ContainType(DashList<DashContentCompInfo * > contentComp,const std::string & pattern)31 static bool ContainType(DashList<DashContentCompInfo *> contentComp, const std::string &pattern)
32 {
33     bool flag = false;
34     for (DashList<DashContentCompInfo *>::iterator it = contentComp.begin(); it != contentComp.end(); ++it) {
35         std::string type((*it)->contentType_);
36         if (!type.empty() && type == pattern) {
37             flag = true;
38             break;
39         }
40     }
41 
42     return flag;
43 }
44 
GetMimeTypeFromRepresentation(const DashAdptSetInfo * adptSetInfo,std::string & mimeType)45 static void GetMimeTypeFromRepresentation(const DashAdptSetInfo *adptSetInfo, std::string &mimeType)
46 {
47     DashList<DashRepresentationInfo *> representationList = adptSetInfo->representationList_;
48     for (DashRepresentationInfo *representationInfo : representationList) {
49         mimeType = representationInfo->commonAttrsAndElements_.mimeType_;
50         if (!mimeType.empty()) {
51             break;
52         }
53     }
54 }
55 
DashPeriodManager(DashPeriodInfo * period)56 DashPeriodManager::DashPeriodManager(DashPeriodInfo *period)
57 {
58     SetPeriodInfo(period);
59 }
60 
~DashPeriodManager()61 DashPeriodManager::~DashPeriodManager()
62 {
63     Clear();
64 }
65 
Empty() const66 bool DashPeriodManager::Empty() const
67 {
68     return (this->periodInfo_ == nullptr);
69 }
70 
Reset()71 void DashPeriodManager::Reset()
72 {
73     Clear();
74     this->periodInfo_ = nullptr;
75     this->previousPeriodInfo_ = nullptr;
76 }
77 
Init()78 void DashPeriodManager::Init()
79 {
80     if (this->periodInfo_ == nullptr) {
81         return;
82     }
83 
84     DashList<DashAdptSetInfo *> adptSets = this->periodInfo_->adptSetList_;
85     if (adptSets.size() == 0) {
86         return;
87     }
88 
89     // before init, clear the init segment and adaptationset vectors
90     Clear();
91 
92     ParseAdptSetList(adptSets);
93 
94     ParseInitSegment();
95 }
96 
Clear()97 void DashPeriodManager::Clear()
98 {
99     if (initSegment_ != nullptr) {
100         delete initSegment_;
101         initSegment_ = nullptr;
102     }
103 
104     segTmpltFlag_ = 0;
105     videoAdptSetsVector_.clear();
106     audioAdptSetsVector_.clear();
107     subtitleAdptSetsVector_.clear();
108     subtitleMimeType_.clear();
109 }
110 
ParseAdptSetList(DashList<DashAdptSetInfo * > adptSetList)111 void DashPeriodManager::ParseAdptSetList(DashList<DashAdptSetInfo *> adptSetList)
112 {
113     for (DashList<DashAdptSetInfo *>::iterator it = adptSetList.begin(); it != adptSetList.end(); ++it) {
114         // get the AdaptationSet type by parse attribute mimeType/contentType, if the both attributes disappear, parse
115         // element ContentComponent
116         std::string mimeType((*it)->commonAttrsAndElements_.mimeType_);
117         std::string contentType((*it)->contentType_);
118 
119         DashList<DashContentCompInfo *> contentCompList((*it)->contentCompList_);
120 
121         // if mimeType of AdaptationSet disappear, get mimeType from AdaptationSet.Representation
122         if (mimeType.empty()) {
123             GetMimeTypeFromRepresentation(*it, mimeType);
124         }
125 
126         // if mimeType or contentType appear, parse it
127         if (!mimeType.empty()) {
128             ParseAdptSetTypeByMime(mimeType, *it);
129         } else if (!contentType.empty()) {
130             ParseAdptSetTypeByMime(contentType, *it);
131         } else if (!contentCompList.empty()) {
132             // if AdaptationSet and AdaptationSet.Representation can not find mime/contentType. we parse
133             // ContentComponent
134             ParseAdptSetTypeByComp(contentCompList, *it);
135         } else {
136             // if attributes mimeType/contentType both disappear and element ContentComponent disappear, think the
137             // AdaptationSet is video
138             videoAdptSetsVector_.push_back(*it);
139         }
140     }
141 }
142 
ParseAdptSetTypeByMime(std::string mimeType,DashAdptSetInfo * adptSetInfo)143 void DashPeriodManager::ParseAdptSetTypeByMime(std::string mimeType, DashAdptSetInfo *adptSetInfo)
144 {
145     if (adptSetInfo->mimeType_.empty()) {
146         adptSetInfo->mimeType_.append(mimeType);
147     }
148 
149     if (mimeType.find(VIDEO_MIME_TYPE) != std::string::npos) {
150         videoAdptSetsVector_.push_back(adptSetInfo);
151     } else if (mimeType.find(AUDIO_MIME_TYPE) != std::string::npos) {
152         audioAdptSetsVector_.push_back(adptSetInfo);
153     } else if (mimeType.find(SUBTITLE_MIME_APPLICATION) != std::string::npos ||
154                mimeType.find(SUBTITLE_MIME_TEXT) != std::string::npos) {
155         // if exist application(such as application/ttml+xml) in mimeType/contentType, we think as subtitle
156         if (subtitleMimeType_.empty()) {
157             // parse subtitle mime type first time, store as subtitleMimeType
158             subtitleMimeType_ =
159                 ((mimeType.find(SUBTITLE_MIME_APPLICATION) != std::string::npos) ? SUBTITLE_MIME_APPLICATION
160                                                                                  : SUBTITLE_MIME_TEXT);
161         } else if (mimeType.find(subtitleMimeType_) == std::string::npos) {
162             // only use one mimeType("application" or "text/"), skip another one
163             return;
164         }
165 
166         subtitleAdptSetsVector_.push_back(adptSetInfo);
167     } else {
168         videoAdptSetsVector_.push_back(adptSetInfo);
169     }
170 }
171 
ParseAdptSetTypeByComp(DashList<DashContentCompInfo * > contentCompList,DashAdptSetInfo * adptSetInfo)172 void DashPeriodManager::ParseAdptSetTypeByComp(DashList<DashContentCompInfo *> contentCompList,
173                                                DashAdptSetInfo *adptSetInfo)
174 {
175     if (ContainType(contentCompList, VIDEO_MIME_TYPE)) {
176         videoAdptSetsVector_.push_back(adptSetInfo);
177     } else if (ContainType(contentCompList, AUDIO_MIME_TYPE)) {
178         audioAdptSetsVector_.push_back(adptSetInfo);
179     } else if (ContainType(contentCompList, SUBTITLE_MIME_APPLICATION) ||
180                ContainType(contentCompList, SUBTITLE_MIME_TEXT)) {
181         if (subtitleMimeType_.empty()) {
182             // parse subtitle mime type first time, store as subtitleMimeType
183             subtitleMimeType_ = ((ContainType(contentCompList, SUBTITLE_MIME_APPLICATION)) ? SUBTITLE_MIME_APPLICATION
184                                                                                            : SUBTITLE_MIME_TEXT);
185         } else if (!ContainType(contentCompList, subtitleMimeType_)) {
186             // only use one mimeType("application" or "text/"), skip another one
187             return;
188         }
189         subtitleAdptSetsVector_.push_back(adptSetInfo);
190     } else {
191         videoAdptSetsVector_.push_back(adptSetInfo);
192     }
193 }
194 
ParseInitSegment()195 void DashPeriodManager::ParseInitSegment()
196 {
197     // ----------  init initial segment -------------------
198     if (periodInfo_->periodSegBase_ && periodInfo_->periodSegBase_->initialization_) {
199         // first get initSegment from <Period> <SegmentBase> <Initialization /> </SegmentBase>  </Period>
200         initSegment_ = CloneUrlType(periodInfo_->periodSegBase_->initialization_);
201     } else if (periodInfo_->periodSegList_ &&
202                periodInfo_->periodSegList_->multSegBaseInfo_.segBaseInfo_.initialization_) {
203         // second get initSegment from <SegmentList> <Initialization sourceURL="seg-m-init.mp4"/> </SegmentList>
204         initSegment_ = CloneUrlType(periodInfo_->periodSegList_->multSegBaseInfo_.segBaseInfo_.initialization_);
205     } else if (periodInfo_->periodSegTmplt_) {
206         ParseInitSegmentBySegTmplt();
207     } else if (initSegment_ != nullptr) {
208         delete initSegment_;
209         initSegment_ = nullptr;
210     }
211 
212     // if sourceUrl is not present, use BaseURL in mpd
213 }
214 
ParseInitSegmentBySegTmplt()215 void DashPeriodManager::ParseInitSegmentBySegTmplt()
216 {
217     if (periodInfo_->periodSegTmplt_->multSegBaseInfo_.segBaseInfo_.initialization_) {
218         initSegment_ = CloneUrlType(periodInfo_->periodSegTmplt_->multSegBaseInfo_.segBaseInfo_.initialization_);
219     } else if (periodInfo_->periodSegTmplt_->segTmpltInitialization_.length() > 0) {
220         initSegment_ = new DashUrlType;
221         if (initSegment_ != nullptr) {
222             initSegment_->sourceUrl_ = periodInfo_->periodSegTmplt_->segTmpltInitialization_;
223             segTmpltFlag_ = 1;
224         }
225     } else if (initSegment_ != nullptr) {
226         delete initSegment_;
227         initSegment_ = nullptr;
228     }
229 }
230 
SetPeriodInfo(DashPeriodInfo * period)231 void DashPeriodManager::SetPeriodInfo(DashPeriodInfo *period)
232 {
233     periodInfo_ = period;
234 
235     // if periodInfo changed, update it
236     if (previousPeriodInfo_ == nullptr || previousPeriodInfo_ != period) {
237         Init();
238         previousPeriodInfo_ = period;
239     }
240 }
241 
GetBaseUrlList(std::list<std::string> & baseUrlList)242 void DashPeriodManager::GetBaseUrlList(std::list<std::string> &baseUrlList)
243 {
244     if (this->periodInfo_ != nullptr) {
245         baseUrlList = this->periodInfo_->baseUrl_;
246     }
247 }
248 
GetAdptSetsByStreamType(DashVector<DashAdptSetInfo * > & adptSetInfo,MediaAVCodec::MediaType streamType)249 void DashPeriodManager::GetAdptSetsByStreamType(DashVector<DashAdptSetInfo *> &adptSetInfo,
250                                                 MediaAVCodec::MediaType streamType)
251 {
252     switch (streamType) {
253         case MediaAVCodec::MediaType::MEDIA_TYPE_VID:
254             adptSetInfo = videoAdptSetsVector_;
255             break;
256         case MediaAVCodec::MediaType::MEDIA_TYPE_AUD:
257             adptSetInfo = audioAdptSetsVector_;
258             break;
259         case MediaAVCodec::MediaType::MEDIA_TYPE_SUBTITLE:
260             adptSetInfo = subtitleAdptSetsVector_;
261             break;
262         default:
263             adptSetInfo = videoAdptSetsVector_;
264             break;
265     }
266 }
267 
GetInitSegment(int32_t & flag)268 DashUrlType *DashPeriodManager::GetInitSegment(int32_t &flag)
269 {
270     flag = this->segTmpltFlag_;
271     return this->initSegment_;
272 }
273 
GetPeriod()274 DashPeriodInfo *DashPeriodManager::GetPeriod()
275 {
276     return this->periodInfo_;
277 }
278 
GetPreviousPeriod()279 DashPeriodInfo *DashPeriodManager::GetPreviousPeriod()
280 {
281     return this->previousPeriodInfo_;
282 }
283 } // namespace HttpPluginLite
284 } // namespace Plugin
285 } // namespace Media
286 } // namespace OHOS