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