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