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> ¤tSegment, 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