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_SEGMENT_DOWNLOADER_H
17 #define HISTREAMER_DASH_SEGMENT_DOWNLOADER_H
18 
19 #include <memory>
20 #include <list>
21 #include <mutex>
22 #include <atomic>
23 #include "dash_common.h"
24 #include "download/downloader.h"
25 #include "media_downloader.h"
26 #include "common/media_core.h"
27 #include "osal/utils/ring_buffer.h"
28 #include "osal/utils/steady_clock.h"
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Plugins {
33 namespace HttpPlugin {
34 
35 enum DashReadRet {
36     DASH_READ_FAILED = 0,
37     DASH_READ_OK = 1,
38     DASH_READ_SEGMENT_DOWNLOAD_FINISH = 2,
39     DASH_READ_END = 3, // segment download finish and buffer read finish
40     DASH_READ_AGAIN = 4,
41     DASH_READ_INTERRUPT = 5
42 };
43 
44 struct DashBufferSegment {
DashBufferSegmentDashBufferSegment45     DashBufferSegment()
46     {
47         streamId_ = -1;
48         duration_ = 0;
49         bandwidth_ = 0;
50         startNumberSeq_ = 1;
51         numberSeq_ = 1;
52         startRangeValue_ = 0;
53         endRangeValue_ = 0;
54         bufferPosHead_ = 0;
55         bufferPosTail_ = 0;
56         contentLength_ = 0;
57         isEos_ = false;
58         isLast_ = false;
59     }
60 
DashBufferSegmentDashBufferSegment61     DashBufferSegment(const DashBufferSegment& srcSegment)
62     {
63         streamId_ = srcSegment.streamId_;
64         duration_ = srcSegment.duration_;
65         bandwidth_ = srcSegment.bandwidth_;
66         startNumberSeq_ = srcSegment.startNumberSeq_;
67         numberSeq_ = srcSegment.numberSeq_;
68         startRangeValue_ = srcSegment.startRangeValue_;
69         endRangeValue_ = srcSegment.endRangeValue_;
70         url_ = srcSegment.url_;
71         byteRange_ = srcSegment.byteRange_;
72         bufferPosHead_ = srcSegment.bufferPosHead_;
73         bufferPosTail_ = srcSegment.bufferPosTail_;
74         contentLength_ = srcSegment.contentLength_;
75         isEos_ = srcSegment.isEos_;
76         isLast_ = srcSegment.isLast_;
77     }
78 
79     DashBufferSegment& operator=(const DashBufferSegment& srcSegment)
80     {
81         if (this != &srcSegment) {
82             streamId_ = srcSegment.streamId_;
83             duration_ = srcSegment.duration_;
84             bandwidth_ = srcSegment.bandwidth_;
85             startNumberSeq_ = srcSegment.startNumberSeq_;
86             numberSeq_ = srcSegment.numberSeq_;
87             startRangeValue_ = srcSegment.startRangeValue_;
88             endRangeValue_ = srcSegment.endRangeValue_;
89             url_ = srcSegment.url_;
90             byteRange_ = srcSegment.byteRange_;
91             bufferPosHead_ = srcSegment.bufferPosHead_;
92             bufferPosTail_ = srcSegment.bufferPosTail_;
93             contentLength_ = srcSegment.contentLength_;
94             isEos_ = srcSegment.isEos_;
95             isLast_ = srcSegment.isLast_;
96         }
97         return *this;
98     }
99 
DashBufferSegmentDashBufferSegment100     explicit DashBufferSegment(const std::shared_ptr<DashSegment> &dashSegment)
101     {
102         streamId_ = dashSegment->streamId_;
103         duration_ = dashSegment->duration_;
104         bandwidth_ = dashSegment->bandwidth_;
105         startNumberSeq_ = dashSegment->startNumberSeq_;
106         numberSeq_ = dashSegment->numberSeq_;
107         startRangeValue_ = dashSegment->startRangeValue_;
108         endRangeValue_ = dashSegment->endRangeValue_;
109         url_ = dashSegment->url_;
110         byteRange_ = dashSegment->byteRange_;
111         bufferPosHead_ = 0;
112         bufferPosTail_ = 0;
113         contentLength_ = 0;
114         isEos_ = false;
115         isLast_ = dashSegment->isLast_;
116     }
117 
118     int32_t streamId_;
119     unsigned int duration_;
120     unsigned int bandwidth_;
121     int64_t startNumberSeq_;
122     int64_t numberSeq_;
123     int64_t startRangeValue_;
124     int64_t endRangeValue_;
125     std::string url_;
126     std::string byteRange_;
127     size_t bufferPosHead_;
128     size_t bufferPosTail_;
129     size_t contentLength_;
130     bool isEos_;
131     bool isLast_;
132 };
133 
134 using SegmentDownloadDoneCbFunc = std::function<void(int streamId)>;
135 
136 class DashSegmentDownloader {
137 public:
138     DashSegmentDownloader(Callback *callback, int streamId, MediaAVCodec::MediaType streamType,
139                           uint64_t expectDuration);
140     virtual ~DashSegmentDownloader();
141 
142     bool Open(const std::shared_ptr<DashSegment> &dashSegment);
143     void Close(bool isAsync, bool isClean);
144     void Pause();
145     void Resume();
146     DashReadRet Read(uint8_t *buff, ReadDataInfo &readDataInfo, const std::atomic<bool> &isInterruptNeeded);
147     void SetStatusCallback(StatusCallbackFunc statusCallbackFunc);
148     void SetDownloadDoneCallback(SegmentDownloadDoneCbFunc doneCbFunc);
149     bool CleanSegmentBuffer(bool isCleanAll, int64_t& remainLastNumberSeq);
150     bool CleanBufferByTime(int64_t& remainLastNumberSeq, bool& isEnd);
151     bool SeekToTime(const std::shared_ptr<DashSegment>& segment, int32_t& streamId);
152     void SetInitSegment(std::shared_ptr<DashInitSegment> initSegment, bool needUpdateState = false);
153     void UpdateStreamId(int streamId);
154     void SetCurrentBitRate(int32_t bitRate);
155     void SetDemuxerState();
156     void SetAllSegmentFinished();
157     int GetStreamId() const;
158     MediaAVCodec::MediaType GetStreamType() const;
159     size_t GetContentLength();
160     bool GetStartedStatus() const;
161     bool IsSegmentFinish() const;
162     uint64_t GetDownloadSpeed() const;
163     uint32_t GetRingBufferCapacity() const;
164     void GetIp(std::string& ip);
165     bool GetDownloadFinishState();
166     std::pair<int64_t, int64_t> GetDownloadRecordData();
167     void SetAppUid(int32_t appUid);
168     void SetInterruptState(bool isInterruptNeeded);
169     uint32_t GetBufferSize() const;
170     bool GetBufferringStatus() const;
171     bool IsAllSegmentFinished() const;
172 
173 private:
174     bool SaveData(uint8_t* data, uint32_t len);
175     void PutRequestIntoDownloader(unsigned int duration, int64_t startPos, int64_t endPos, const std::string &url);
176     void UpdateDownloadFinished(const std::string& url, const std::string& location);
177     bool UpdateInitSegmentFinish();
178     uint32_t GetSegmentRemainDuration(const std::shared_ptr<DashBufferSegment>& currentSegment);
179     std::shared_ptr<DashInitSegment> GetDashInitSegment(int32_t streamId);
180     bool CleanAllSegmentBuffer(bool isCleanAll, int64_t& remainLastNumberSeq);
181     void CleanByTimeInternal(int64_t& remainLastNumberSeq, size_t& clearTail, bool& isEnd);
182     void ClearReadSegmentList();
183     void UpdateInitSegmentState(int32_t currentStreamId);
184     bool ReadInitSegment(uint8_t *buff, uint32_t wantReadLength, uint32_t &realReadLength,
185                          int32_t currentStreamId);
186     std::shared_ptr<DashBufferSegment> GetCurrentSegment();
187     bool IsSegmentFinished(uint32_t &realReadLength, DashReadRet &readRet);
188     bool CheckReadInterrupt(uint32_t &realReadLength, uint32_t wantReadLength, DashReadRet &readRet,
189                             const std::atomic<bool> &isInterruptNeeded);
190     uint32_t GetMaxReadLength(uint32_t wantReadLength, const std::shared_ptr<DashBufferSegment> &currentSegment,
191                               int32_t currentStreamId) const;
192     size_t GetRingBufferInitSize(MediaAVCodec::MediaType streamType) const;
193     void OnWriteRingBuffer(uint32_t len);
194     bool HandleBuffering(const std::atomic<bool> &isInterruptNeeded);
195     void SaveDataHandleBuffering();
196     bool HandleCache();
197     void HandleCachedDuration();
198     int32_t GetWaterLineAbove();
199     void CalculateBitRate(size_t fragmentSize, double duration);
200     void UpdateCachedPercent(BufferingInfoType infoType);
201     void UpdateBufferSegment(const std::shared_ptr<DashBufferSegment> &mediaSegment, uint32_t len);
202 
203 private:
204     static constexpr uint32_t MIN_RETENTION_DURATION_MS = 5 * 1000;
205     std::shared_ptr<RingBuffer> buffer_;
206     std::shared_ptr<Downloader> downloader_;
207     std::shared_ptr<DownloadRequest> downloadRequest_;
208     std::shared_ptr<DashBufferSegment> mediaSegment_;
209     std::list<std::shared_ptr<DashBufferSegment>> segmentList_;
210     std::vector<std::shared_ptr<DashInitSegment>> initSegments_;
211     std::mutex segmentMutex_;
212     std::mutex initSegmentMutex_;
213     DataSaveFunc dataSave_;
214     StatusCallbackFunc statusCallback_;
215     SegmentDownloadDoneCbFunc downloadDoneCbFunc_;
216     bool startedPlayStatus_{false};
217     int streamId_{0};
218     MediaAVCodec::MediaType streamType_;
219     std::atomic<bool> isCleaningBuffer_{false};
220 
221     // support ringbuffer size of duration
222     uint64_t currentBitrate_{1 * 1024 * 1024};
223     bool userDefinedBufferDuration_{false};
224     uint64_t expectDuration_{0};
225 
226     uint32_t ringBufferCapcity_ {0};
227     uint64_t lastCheckTime_ {0};
228     uint64_t totalBits_ {0};
229     uint64_t lastBits_ {0};
230     double downloadSpeed_ {0};
231     uint64_t downloadDuringTime_ {0};
232     uint64_t downloadBits_ {0};
233     uint64_t totalDownloadDuringTime_ {0};
234     struct RecordData {
235         double downloadRate {0};
236         uint64_t bufferDuring {0};
237     };
238     std::shared_ptr<RecordData> recordData_;
239     SteadyClock steadyClock_;
240 
241     // play water line
242     Callback* callback_{nullptr};
243     uint32_t waterLineAbove_{0};
244     std::atomic<bool> isBuffering_{false};
245     uint32_t downloadBiteRate_{0};
246     int64_t realTimeBitBate_{0};
247     uint64_t lastDurationRecord_{0};
248     uint32_t lastCachedSize_{0};
249     bool isFirstFrameArrived_{false};
250     std::atomic<bool> isAllSegmentFinished_{false};
251 };
252 }
253 }
254 }
255 }
256 #endif