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 #ifndef HISTREAMER_DASH_MPD_DOWNLOADER_H
17 #define HISTREAMER_DASH_MPD_DOWNLOADER_H
18 
19 #include "dash_common.h"
20 #include "dash_mpd_def.h"
21 #include "dash_mpd_parser.h"
22 #include "dash_mpd_manager.h"
23 #include "dash_period_manager.h"
24 #include "dash_adpt_set_manager.h"
25 #include "dash_representation_manager.h"
26 #include "download/downloader.h"
27 #include "media_downloader.h"
28 #include "meta/media_types.h"
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Plugins {
33 namespace HttpPlugin {
34 
35 using DashMpdEvent = enum DashMpdEvent {
36     DASH_MPD_EVENT_OPEN_OK,
37     DASH_MPD_EVENT_STREAM_INIT,
38     DASH_MPD_EVENT_PARSE_OK
39 };
40 
41 enum DashMpdGetRet {
42     DASH_MPD_GET_ERROR,
43     DASH_MPD_GET_DONE, // get segment normal
44     DASH_MPD_GET_UNDONE, // get segment null, as segment list is empty
45     DASH_MPD_GET_FINISH // get segment finish
46 };
47 
48 using DashMpdSwitchType = enum DashMpdSwitchType {
49     DASH_MPD_SWITCH_TYPE_NONE,
50     DASH_MPD_SWITCH_TYPE_AUTO,
51     DASH_MPD_SWITCH_TYPE_SMOOTH
52 };
53 
54 struct DashMpdBitrateParam {
DashMpdBitrateParamDashMpdBitrateParam55     DashMpdBitrateParam()
56     {
57         waitSegmentFinish_ = false;
58         waitSidxFinish_ = false;
59         streamId_ = -1;
60         bitrate_ = 0;
61         type_ = DASH_MPD_SWITCH_TYPE_NONE;
62         position_ = -1;
63         nextSegTime_ = 0;
64     }
65 
66     bool waitSegmentFinish_;
67     bool waitSidxFinish_;
68     int streamId_;
69     unsigned int bitrate_;
70     DashMpdSwitchType type_;
71     int64_t position_;
72     unsigned int nextSegTime_;
73 };
74 
75 struct DashMpdTrackParam {
DashMpdTrackParamDashMpdTrackParam76     DashMpdTrackParam()
77     {
78         waitSidxFinish_ = false;
79         isEnd_ = false;
80         type_ = MediaAVCodec::MediaType::MEDIA_TYPE_AUD;
81         streamId_ = -1;
82         position_ = -1;
83         nextSegTime_ = 0;
84     }
85 
86     bool waitSidxFinish_;
87     bool isEnd_;
88     MediaAVCodec::MediaType type_;
89     int streamId_;
90     int64_t position_;
91     unsigned int nextSegTime_;
92 };
93 
94 struct MediaSegSampleInfo {
MediaSegSampleInfoMediaSegSampleInfo95     MediaSegSampleInfo()
96     {
97         segCount_ = 0;
98         segDuration_ = 0;
99     }
100 
101     int segCount_;
102     unsigned int segDuration_;
103     std::string mediaUrl_;
104 };
105 
106 struct DashMpdCallback {
107     virtual ~DashMpdCallback() = default;
108     virtual void OnMpdInfoUpdate(DashMpdEvent mpdEvent) = 0;
109     virtual void OnDrmInfoChanged(const std::multimap<std::string, std::vector<uint8_t>>& drmInfos) = 0;
110 };
111 
112 class DashMpdDownloader {
113 public:
114     DashMpdDownloader();
115     virtual ~DashMpdDownloader();
116 
117     void Open(const std::string &url);
118     void Close(bool isAsync);
119     void SetStatusCallback(StatusCallbackFunc cb);
120     void SetMpdCallback(DashMpdCallback *callback);
121     int64_t GetDuration() const;
122     Seekable GetSeekable() const;
123     std::vector<uint32_t> GetBitRates() const;
124     std::vector<uint32_t> GetBitRatesByHdr(bool isHdr) const;
125     void SeekToTs(int streamId, int64_t seekTime, std::shared_ptr<DashSegment> &seg) const;
126     void UpdateDownloadFinished(const std::string &url);
127     int GetInUseVideoStreamId() const;
128     DashMpdGetRet GetNextSegmentByStreamId(int streamId, std::shared_ptr<DashSegment> &seg);
129     DashMpdGetRet GetBreakPointSegment(int streamId, int64_t breakpoint, std::shared_ptr<DashSegment> &seg);
130     DashMpdGetRet GetNextVideoStream(DashMpdBitrateParam &param, int &streamId);
131     DashMpdGetRet GetNextTrackStream(DashMpdTrackParam &param);
132     Status GetStreamInfo(std::vector<StreamInfo> &streams);
133     std::shared_ptr<DashStreamDescription> GetStreamByStreamId(int streamId);
134     std::shared_ptr<DashStreamDescription> GetUsingStreamByType(MediaAVCodec::MediaType type);
135     std::shared_ptr<DashInitSegment> GetInitSegmentByStreamId(int streamId);
136     void SetCurrentNumberSeqByStreamId(int streamId, int64_t numberSeq);
137     void UpdateCurrentNumberSeqByTime(const std::shared_ptr<DashStreamDescription> &streamDesc, uint32_t nextSegTime);
138     void SetHdrStart(bool isHdrStart);
139     void SetInitResolution(unsigned int width, unsigned int height);
140     void SetDefaultLang(const std::string &lang, MediaAVCodec::MediaType type);
141     void SetInterruptState(bool isInterruptNeeded);
142     std::string GetUrl() const;
143 
144 private:
145     void ParseManifest();
146     void ParseSidx();
147     void OpenStream(std::shared_ptr<DashStreamDescription> stream);
148     void DoOpen(const std::string &url, int64_t startRange = -1, int64_t endRange = -1);
149     bool SaveData(uint8_t *data, uint32_t len);
150     void SetOndemandSegBase();
151     bool SetOndemandSegBase(std::list<DashAdptSetInfo *> adptSetList);
152     bool SetOndemandSegBase(std::list<DashRepresentationInfo *> repList);
153     bool CheckToDownloadSidxWithInitSeg(std::shared_ptr<DashStreamDescription> streamDesc);
154     bool GetStreamsInfoInMpd();
155     void GetStreamsInfoInPeriod(DashPeriodInfo *periodInfo, unsigned int periodIndex, const std::string &mpdBaseUrl);
156     void GetStreamsInfoInAdptSet(DashAdptSetInfo *adptSetInfo, const std::string &periodBaseUrl,
157                                  DashStreamDescription &streamDesc);
158     unsigned int GetResolutionDelta(unsigned int width, unsigned int height);
159     bool IsChoosedVideoStream(const std::shared_ptr<DashStreamDescription> &choosedStream,
160         const std::shared_ptr<DashStreamDescription> &currentStream);
161     bool IsNearToInitResolution(const std::shared_ptr<DashStreamDescription> &choosedStream,
162         const std::shared_ptr<DashStreamDescription> &currentStream);
163     bool IsLangMatch(const std::string &lang, MediaAVCodec::MediaType type);
164     bool ChooseStreamToPlay(MediaAVCodec::MediaType type);
165     unsigned int GetSegTimeBySeq(const std::vector<std::shared_ptr<DashSegment>> &segments, int64_t segSeq);
166     DashSegmentInitValue GetSegmentsInMpd(std::shared_ptr<DashStreamDescription> streamDesc);
167     DashSegmentInitValue GetSegmentsInPeriod(DashPeriodInfo *periodInfo, const std::string &mpdBaseUrl,
168                                              std::shared_ptr<DashStreamDescription> streamDesc);
169     DashSegmentInitValue GetSegmentsInAdptSet(DashAdptSetInfo *adptSetInfo, const std::string &periodBaseUrl,
170                                               std::shared_ptr<DashStreamDescription> streamDesc);
171     DashSegmentInitValue GetSegmentsInRepresentation(DashRepresentationInfo *repInfo, const std::string &adptSetBaseUrl,
172                                                      std::shared_ptr<DashStreamDescription> streamDesc);
173     DashSegmentInitValue GetSegmentsByPeriodInfo(DashPeriodInfo *periodInfo, DashAdptSetInfo *adptSetInfo,
174                                                  std::string &periodBaseUrl,
175                                                  std::shared_ptr<DashStreamDescription> streamDesc);
176     DashSegmentInitValue GetSegmentsByAdptSetInfo(const DashAdptSetInfo *adptSetInfo,
177                                                   const DashRepresentationInfo *repInfo,
178                                                   std::string &baseUrl,
179                                                   std::shared_ptr<DashStreamDescription> streamDesc);
180     DashRepresentationInfo *GetRepresemtationFromAdptSet(DashAdptSetInfo *adptSetInfo, unsigned int repIndex);
181 
182     DashSegmentInitValue GetSegmentsWithSegTemplate(const DashSegTmpltInfo *segTmpltInfo, std::string id,
183                                                     std::shared_ptr<DashStreamDescription> streamDesc);
184     DashSegmentInitValue GetSegmentsWithTmpltStatic(const DashSegTmpltInfo *segTmpltInfo, const std::string &mediaUrl,
185                                                     std::shared_ptr<DashStreamDescription> streamDesc);
186     DashSegmentInitValue GetSegmentsWithTmpltDurationStatic(const DashSegTmpltInfo *segTmpltInfo,
187                                                             const std::string &mediaUrl, unsigned int timeScale,
188                                                             std::shared_ptr<DashStreamDescription> desc);
189     DashSegmentInitValue GetSegmentsWithTmpltTimelineStatic(const DashSegTmpltInfo *segTmpltInfo,
190                                                             const std::string &mediaUrl, unsigned int timeScale,
191                                                             std::shared_ptr<DashStreamDescription> desc);
192     DashSegmentInitValue GetSegmentsInOneTimeline(const DashSegTimeline *timeline, const MediaSegSampleInfo &sampleInfo,
193                                                   int64_t &segmentSeq, uint64_t &startTime,
194                                                   std::shared_ptr<DashStreamDescription> streamDesc);
195 
196     DashSegmentInitValue GetSegmentsWithSegList(const DashSegListInfo *segListInfo, const std::string &baseUrl,
197                                                 std::shared_ptr<DashStreamDescription> streamDesc);
198     void GetSegDurationFromTimeline(unsigned int periodDuration, unsigned int timeScale,
199                                     const DashMultSegBaseInfo *multSegBaseInfo, std::list<unsigned int> &durationList);
200     int GetSegCountFromTimeline(DashList<DashSegTimeline *>::iterator &it,
201                                 const DashList<DashSegTimeline *>::iterator &end,
202                                 unsigned int periodDuration, unsigned int timeScale, uint64_t startTime);
203 
204     DashSegmentInitValue GetSegmentsWithBaseUrl(std::list<std::string> baseUrlList,
205                                                 std::shared_ptr<DashStreamDescription> streamDesc);
206 
207     bool GetInitSegFromPeriod(const std::string &periodBaseUrl, const std::string &repId,
208                               std::shared_ptr<DashStreamDescription> streamDesc);
209     bool GetInitSegFromAdptSet(const std::string &adptSetBaseUrl, const std::string &repId,
210                                std::shared_ptr<DashStreamDescription> streamDesc);
211     bool GetInitSegFromRepresentation(const std::string &repBaseUrl, const std::string &repId,
212                                       std::shared_ptr<DashStreamDescription> streamDesc);
213     DashMpdGetRet GetSegmentsInNewStream(std::shared_ptr<DashStreamDescription> destStream);
214     void UpdateInitSegUrl(std::shared_ptr<DashStreamDescription> streamDesc, const DashUrlType *urlType,
215                           int segTmpltFlag,
216                           std::string representationID);
217 
218     bool PutStreamToDownload();
219     void GetDrmInfos(std::vector<DashDrmInfo>& drmInfos);
220     void ProcessDrmInfos();
221     void GetDrmInfos(const std::string &drmId, const DashList<DashDescriptor *> &contentProtections,
222                      std::vector<DashDrmInfo> &drmInfoList);
223     void BuildDashSegment(std::list<std::shared_ptr<SubSegmentIndex>> &subSegIndexList) const;
224     void GetStreamDescriptions(const std::string &periodBaseUrl, DashStreamDescription &streamDesc,
225                                const std::string &adptSetBaseUrl,
226                                std::list<DashRepresentationInfo *> &repList);
227     void GetAdpDrmInfos(std::vector<DashDrmInfo> &drmInfos, DashPeriodInfo *const &periodInfo,
228                         const std::string &periodDrmId);
229 
230 private:
231     std::string url_ {};
232     std::string downloadContent_ {}; // mpd content or sidx content
233     std::string defaultAudioLang_ {};
234     std::string defaultSubtitleLang_ {};
235     DashMpdCallback* callback_ {nullptr};
236     std::shared_ptr<Downloader> downloader_ {nullptr};
237     std::shared_ptr<DownloadRequest> downloadRequest_ {nullptr};
238     std::shared_ptr<DashMpdParser> mpdParser_ {nullptr};
239     std::shared_ptr<DashMpdManager> mpdManager_ {nullptr};
240     std::shared_ptr<DashPeriodManager> periodManager_ {nullptr};
241     std::shared_ptr<DashAdptSetManager> adptSetManager_ {nullptr};
242     std::shared_ptr<DashRepresentationManager> representationManager_ {nullptr};
243     DashMpdInfo* mpdInfo_ {nullptr};
244     unsigned int duration_ {0};
245     std::vector<std::shared_ptr<DashStreamDescription>> streamDescriptions_;
246     std::shared_ptr<DashStreamDescription> currentDownloadStream_ {nullptr};
247     DataSaveFunc dataSave_ {nullptr};
248     StatusCallbackFunc statusCallback_ {nullptr};
249     bool ondemandSegBase_ {false};
250     bool notifyOpenOk_ {false};
251     bool isHdrStart_ {false};
252     unsigned int initResolution_ {0};
253     std::atomic<bool> isInterruptNeeded_{false};
254     std::vector<DashDrmInfo> localDrmInfos_;
255 };
256 }
257 }
258 }
259 }
260 #endif