• 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 
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);
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 
171 private:
172     bool SaveData(uint8_t* data, uint32_t len);
173     void PutRequestIntoDownloader(unsigned int duration, int64_t startPos, int64_t endPos, const std::string &url);
174     void UpdateDownloadFinished(const std::string& url, const std::string& location);
175     uint32_t GetSegmentRemainDuration(const std::shared_ptr<DashBufferSegment>& currentSegment);
176     std::shared_ptr<DashInitSegment> GetDashInitSegment(int32_t streamId);
177     bool CleanAllSegmentBuffer(bool isCleanAll, int64_t& remainLastNumberSeq);
178     void CleanByTimeInternal(int64_t& remainLastNumberSeq, size_t& clearTail, bool& isEnd);
179     void ClearReadSegmentList();
180     void UpdateInitSegmentState(int32_t currentStreamId);
181     bool ReadInitSegment(uint8_t *buff, uint32_t wantReadLength, uint32_t &realReadLength,
182                          int32_t currentStreamId);
183     std::shared_ptr<DashBufferSegment> GetCurrentSegment();
184     bool IsSegmentFinished(uint32_t &realReadLength, DashReadRet &readRet);
185     bool CheckReadInterrupt(uint32_t &realReadLength, uint32_t wantReadLength, DashReadRet &readRet,
186                             const std::atomic<bool> &isInterruptNeeded);
187     uint32_t GetMaxReadLength(uint32_t wantReadLength, const std::shared_ptr<DashBufferSegment> &currentSegment,
188                               int32_t currentStreamId) const;
189     size_t GetRingBufferInitSize(MediaAVCodec::MediaType streamType) const;
190     void OnWriteRingBuffer(uint32_t len);
191     bool HandleBuffering(const std::atomic<bool> &isInterruptNeeded);
192     void SaveDataHandleBuffering();
193     bool HandleCache();
194     void HandleCachedDuration();
195     int32_t GetWaterLineAbove();
196     void CalculateBitRate(size_t fragmentSize, double duration);
197     void UpdateCachedPercent(BufferingInfoType infoType);
198     void UpdateBufferSegment(const std::shared_ptr<DashBufferSegment> &mediaSegment, uint32_t len);
199 
200 private:
201     static constexpr uint32_t MIN_RETENTION_DURATION_MS = 5 * 1000;
202     std::shared_ptr<RingBuffer> buffer_;
203     std::shared_ptr<Downloader> downloader_;
204     std::shared_ptr<DownloadRequest> downloadRequest_;
205     std::shared_ptr<DashBufferSegment> mediaSegment_;
206     std::list<std::shared_ptr<DashBufferSegment>> segmentList_;
207     std::vector<std::shared_ptr<DashInitSegment>> initSegments_;
208     std::mutex segmentMutex_;
209     DataSaveFunc dataSave_;
210     StatusCallbackFunc statusCallback_;
211     SegmentDownloadDoneCbFunc downloadDoneCbFunc_;
212     bool startedPlayStatus_{false};
213     int streamId_{0};
214     MediaAVCodec::MediaType streamType_;
215     std::atomic<bool> isCleaningBuffer_{false};
216 
217     // support ringbuffer size of duration
218     uint64_t currentBitrate_{1 * 1024 * 1024};
219     bool userDefinedBufferDuration_{false};
220     uint64_t expectDuration_{0};
221 
222     uint32_t ringBufferCapcity_ {0};
223     uint64_t lastCheckTime_ {0};
224     uint64_t totalBits_ {0};
225     uint64_t lastBits_ {0};
226     double downloadSpeed_ {0};
227     uint64_t downloadDuringTime_ {0};
228     uint64_t downloadBits_ {0};
229     uint64_t totalDownloadDuringTime_ {0};
230     struct RecordData {
231         double downloadRate {0};
232         uint64_t bufferDuring {0};
233     };
234     std::shared_ptr<RecordData> recordData_;
235     SteadyClock steadyClock_;
236 
237     // play water line
238     Callback* callback_{nullptr};
239     uint32_t waterLineAbove_{0};
240     std::atomic<bool> isBuffering_{false};
241     uint32_t downloadBiteRate_{0};
242     int64_t realTimeBitBate_{0};
243     uint64_t lastDurationRecord_{0};
244     uint32_t lastCachedSize_{0};
245     bool isFirstFrameArrived_{false};
246     std::atomic<bool> isAllSegmentFinished_{false};
247 };
248 }
249 }
250 }
251 }
252 #endif