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 <cstdint>
17 #include "dash_adpt_set_manager.h"
18 #include "dash_manager_util.h"
19 #include "dash_mpd_util.h"
20 
21 namespace OHOS {
22 namespace Media {
23 namespace Plugins {
24 namespace HttpPlugin {
SortByBitrate(const DashRepresentationInfo * x,const DashRepresentationInfo * y)25 static bool SortByBitrate(const DashRepresentationInfo *x, const DashRepresentationInfo *y)
26 {
27     return x->bandwidth_ < y->bandwidth_;
28 }
29 
DashAdptSetManager(DashAdptSetInfo * adptSet)30 DashAdptSetManager::DashAdptSetManager(DashAdptSetInfo *adptSet)
31 {
32     SetAdptSetInfo(adptSet);
33 }
34 
~DashAdptSetManager()35 DashAdptSetManager::~DashAdptSetManager()
36 {
37     Clear();
38 }
39 
40 /**
41  * @brief   Get initialization segment and representation list
42  *
43  * @param   void
44  *
45  * @return  none
46  */
Init()47 void DashAdptSetManager::Init()
48 {
49     if (this->adptSetInfo_ == nullptr) {
50         return;
51     }
52 
53     // clear init segment
54     Clear();
55 
56     // ----------  init initial segment -------------------
57     ParseInitSegment();
58 
59     this->representationList_ = this->adptSetInfo_->representationList_;
60     if (this->representationList_.size() == 0) {
61         return;
62     }
63 
64     this->representationList_.sort(SortByBitrate);
65 }
66 
Clear()67 void DashAdptSetManager::Clear()
68 {
69     if (initSegment_ != nullptr) {
70         delete initSegment_;
71         initSegment_ = nullptr;
72     }
73 
74     segTmpltFlag_ = 0;
75 }
76 
Reset()77 void DashAdptSetManager::Reset()
78 {
79     Clear();
80     adptSetInfo_ = nullptr;
81     previousAdptSetInfo_ = nullptr;
82     this->representationList_.clear();
83 }
84 
ParseInitSegment()85 void DashAdptSetManager::ParseInitSegment()
86 {
87     if (adptSetInfo_->adptSetSegBase_ && adptSetInfo_->adptSetSegBase_->initialization_) {
88         // if exist <AdaptationSet> <SegmentBase> <Initialization /> </SegmentBase>  </AdaptationSet>
89         initSegment_ = CloneUrlType(adptSetInfo_->adptSetSegBase_->initialization_);
90     } else if (adptSetInfo_->adptSetSegList_ &&
91                adptSetInfo_->adptSetSegList_->multSegBaseInfo_.segBaseInfo_.initialization_) {
92         // or exist <SegmentList> <Initialization sourceURL="seg-m-init.mp4"/> </SegmentList>
93         initSegment_ = CloneUrlType(adptSetInfo_->adptSetSegList_->multSegBaseInfo_.segBaseInfo_.initialization_);
94     } else if (adptSetInfo_->adptSetSegTmplt_) {
95         ParseInitSegmentBySegTmplt();
96     } else if (initSegment_ != nullptr) {
97         delete initSegment_;
98         initSegment_ = nullptr;
99     }
100 
101     // if sourceUrl is not present, use BaseURL, use BaseURL in mpd
102 }
103 
ParseInitSegmentBySegTmplt()104 void DashAdptSetManager::ParseInitSegmentBySegTmplt()
105 {
106     if (adptSetInfo_->adptSetSegTmplt_->multSegBaseInfo_.segBaseInfo_.initialization_) {
107         initSegment_ =
108             CloneUrlType(adptSetInfo_->adptSetSegTmplt_->multSegBaseInfo_.segBaseInfo_.initialization_);
109     } else if (adptSetInfo_->adptSetSegTmplt_->segTmpltInitialization_.length() > 0) {
110         initSegment_ = new DashUrlType;
111         if (initSegment_ != nullptr) {
112             initSegment_->sourceUrl_ = adptSetInfo_->adptSetSegTmplt_->segTmpltInitialization_;
113             segTmpltFlag_ = 1;
114         }
115     } else if (initSegment_ != nullptr) {
116         delete initSegment_;
117         initSegment_ = nullptr;
118     }
119 }
120 
SetAdptSetInfo(DashAdptSetInfo * adptSet)121 void DashAdptSetManager::SetAdptSetInfo(DashAdptSetInfo *adptSet)
122 {
123     adptSetInfo_ = adptSet;
124 
125     // adaptationset changed
126     if (previousAdptSetInfo_ == nullptr || previousAdptSetInfo_ != adptSet) {
127         Init();
128         previousAdptSetInfo_ = adptSet;
129     }
130 }
131 
GetBaseUrlList(std::list<std::string> & baseUrlList)132 void DashAdptSetManager::GetBaseUrlList(std::list<std::string> &baseUrlList)
133 {
134     if (this->adptSetInfo_ != nullptr) {
135         baseUrlList = this->adptSetInfo_->baseUrl_;
136     }
137 }
138 
GetBandwidths(DashVector<uint32_t> & bandwidths)139 void DashAdptSetManager::GetBandwidths(DashVector<uint32_t> &bandwidths)
140 {
141     if (representationList_.size() == 0) {
142         return;
143     }
144 
145     for (DashList<DashRepresentationInfo *>::iterator curRep = representationList_.begin();
146          curRep != representationList_.end(); ++curRep) {
147         if (*curRep != nullptr) {
148             bandwidths.push_back((*curRep)->bandwidth_);
149         }
150     }
151 }
152 
GetInitSegment(int32_t & flag)153 DashUrlType *DashAdptSetManager::GetInitSegment(int32_t &flag)
154 {
155     flag = this->segTmpltFlag_;
156     return this->initSegment_;
157 }
158 
GetAdptSetInfo()159 DashAdptSetInfo *DashAdptSetManager::GetAdptSetInfo()
160 {
161     return this->adptSetInfo_;
162 }
163 
GetPreviousAdptSetInfo()164 DashAdptSetInfo *DashAdptSetManager::GetPreviousAdptSetInfo()
165 {
166     return this->previousAdptSetInfo_;
167 }
168 
GetRepresentationByBandwidth(uint32_t bandwidth)169 DashRepresentationInfo *DashAdptSetManager::GetRepresentationByBandwidth(uint32_t bandwidth)
170 {
171     if (this->representationList_.size() == 0) {
172         return nullptr;
173     }
174 
175     DashList<DashRepresentationInfo *>::iterator it = this->representationList_.begin();
176     for (; it != this->representationList_.end(); ++it) {
177         if ((*it)->bandwidth_ == bandwidth) {
178             return (*it);
179         }
180     }
181 
182     return nullptr;
183 }
184 
GetHighRepresentation()185 DashRepresentationInfo *DashAdptSetManager::GetHighRepresentation()
186 {
187     if (this->representationList_.size() == 0) {
188         return nullptr;
189     }
190 
191     DashList<DashRepresentationInfo *>::iterator it = this->representationList_.end();
192     return *(--it); // list sort up
193 }
194 
GetLowRepresentation()195 DashRepresentationInfo *DashAdptSetManager::GetLowRepresentation()
196 {
197     if (this->representationList_.size() == 0) {
198         return nullptr;
199     }
200 
201     DashList<DashRepresentationInfo *>::iterator it = this->representationList_.begin();
202     return (*it); // list sort up
203 }
204 
GetMimeTypeFromRepresentation(const DashAdptSetInfo * adptSetInfo,std::string & mimeType)205 static void GetMimeTypeFromRepresentation(const DashAdptSetInfo *adptSetInfo, std::string &mimeType)
206 {
207     DashList<DashRepresentationInfo *> representationList = adptSetInfo->representationList_;
208     for (DashRepresentationInfo *representationInfo : representationList) {
209         mimeType = representationInfo->commonAttrsAndElements_.mimeType_;
210         if (!mimeType.empty()) {
211             break;
212         }
213     }
214 }
215 
GetMime() const216 std::string DashAdptSetManager::GetMime() const
217 {
218     std::string mimeInfo;
219     if (this->adptSetInfo_ == nullptr) {
220         return mimeInfo;
221     }
222 
223     if (!this->adptSetInfo_->commonAttrsAndElements_.mimeType_.empty()) {
224         mimeInfo = this->adptSetInfo_->commonAttrsAndElements_.mimeType_;
225     } else {
226         // get mime from adaptationset
227         GetMimeTypeFromRepresentation(this->adptSetInfo_, mimeInfo);
228 
229         if (mimeInfo.empty() && !this->adptSetInfo_->contentType_.empty()) {
230             mimeInfo = this->adptSetInfo_->contentType_;
231         }
232     }
233 
234     return mimeInfo;
235 }
236 
IsOnDemand()237 bool DashAdptSetManager::IsOnDemand()
238 {
239     if (adptSetInfo_ == nullptr) {
240         return false;
241     }
242 
243     if (adptSetInfo_->representationList_.size() == 0) {
244         if (adptSetInfo_->adptSetSegBase_ != nullptr && adptSetInfo_->adptSetSegBase_->indexRange_.size() > 0) {
245             return true;
246         }
247     } else {
248         for (auto representation : adptSetInfo_->representationList_) {
249             if (representation->representationSegList_ != nullptr) {
250                 return false;
251             }
252 
253             if (representation->representationSegTmplt_ != nullptr) {
254                 return false;
255             }
256 
257             if (representation->representationSegBase_ != nullptr &&
258                 representation->representationSegBase_->indexRange_.size() > 0) {
259                 return true;
260             }
261         }
262     }
263 
264     return false;
265 }
266 
IsHdr()267 bool DashAdptSetManager::IsHdr()
268 {
269     if (adptSetInfo_ == nullptr ||
270         adptSetInfo_->commonAttrsAndElements_.essentialPropertyList_.size() == 0) {
271         return false;
272     }
273 
274     return DashStreamIsHdr(adptSetInfo_->commonAttrsAndElements_.essentialPropertyList_);
275 }
276 
277 } // namespace HttpPluginLite
278 } // namespace Plugin
279 } // namespace Media
280 } // namespace OHOS