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