• 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 #define HST_LOG_TAG "HttpMediaDownloader"
16 
17 #include "http/http_media_downloader.h"
18 #include <arpa/inet.h>
19 #include <netdb.h>
20 #include <regex>
21 #include <climits>
22 #include "network/network_typs.h"
23 #include "common/media_core.h"
24 #include "avcodec_trace.h"
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Plugins {
29 namespace HttpPlugin {
30 namespace {
31 #ifdef OHOS_LITE
32 constexpr int RING_BUFFER_SIZE = 5 * 48 * 1024;
33 constexpr int WATER_LINE = RING_BUFFER_SIZE / 30; // 30 WATER_LINE:8192
34 #else
35 constexpr int RING_BUFFER_SIZE = 5 * 1024 * 1024;
36 constexpr int MAX_BUFFER_SIZE = 19 * 1024 * 1024;
37 constexpr int WATER_LINE = 8192; //  WATER_LINE:8192
38 constexpr int CURRENT_BIT_RATE = 1 * 1024 * 1024;
39 #endif
40 constexpr uint32_t SAMPLE_INTERVAL = 1000; // Sample time interval, ms
41 constexpr int START_PLAY_WATER_LINE = 512 * 1024;
42 constexpr int DATA_USAGE_NTERVAL = 300 * 1000;
43 constexpr double ZERO_THRESHOLD = 1e-9;
44 constexpr size_t PLAY_WATER_LINE = 5 * 1024;
45 constexpr size_t FLV_PLAY_WATER_LINE = 20 * 1024;
46 constexpr size_t DEFAULT_WATER_LINE_ABOVE = 48 * 10 * 1024;
47 constexpr int FIVE_MICROSECOND = 5;
48 constexpr int32_t ONE_HUNDRED_MILLIONSECOND = 100;
49 constexpr int32_t SAVE_DATA_LOG_FREQUENCE = 50;
50 constexpr int IS_DOWNLOAD_MIN_BIT = 100; // Determine whether it is downloading
51 constexpr uint32_t DURATION_CHANGE_AMOUT_MILLIONSECOND = 500;
52 constexpr int32_t DEFAULT_BIT_RATE = 1638400;
53 constexpr int UPDATE_CACHE_STEP = 5 * 1024;
54 constexpr size_t MIN_WATER_LINE_ABOVE = 100 * 1024;
55 constexpr int32_t ONE_SECONDS = 1000;
56 constexpr int32_t TWO_SECONDS = 2000;
57 constexpr int32_t TEN_MILLISECONDS = 10;
58 constexpr float WATER_LINE_ABOVE_LIMIT_RATIO = 0.6;
59 constexpr float CACHE_LEVEL_1 = 0.5;
60 constexpr float DEFAULT_CACHE_TIME = 5;
61 constexpr size_t MAX_BUFFERING_TIME_OUT = 30 * 1000;
62 constexpr size_t MAX_BUFFERING_TIME_OUT_DELAY = 60 * 1000;
63 constexpr size_t MAX_WATER_LINE_ABOVE = 8 * 1024 * 1024;
64 constexpr uint32_t OFFSET_NOT_UPDATE_THRESHOLD = 8;
65 constexpr float DOWNLOAD_WATER_LINE_RATIO = 0.90;
66 constexpr uint32_t ALLOW_SEEK_MIN_SIZE = 1 * 1024 * 1024;
67 constexpr uint64_t ALLOW_CLEAR_MIDDLE_DATA_MIN_SIZE = 2 * 1024 * 1024;
68 constexpr size_t AUDIO_WATER_LINE_ABOVE = 16 * 1024;
69 constexpr uint32_t CLEAR_SAVE_DATA_SIZE = 1 * 1024 * 1024;
70 constexpr size_t LARGE_OFFSET_SPAN_THRESHOLD = 10 * 1024 * 1024;
71 constexpr int32_t STATE_CHANGE_THRESHOLD = 2;
72 constexpr size_t LARGE_VIDEO_THRESHOLD = 18 * 1024 * 1024;
73 constexpr size_t BUFFER_REDUNDANCY = 4 * 1024 * 1024;
74 constexpr size_t IGNORE_BUFFERING_WITH_START_TIME_MS = 5000;
75 constexpr size_t IGNORE_BUFFERING_EXTRA_CACHE_BEYOND_MS = 300;
76 constexpr float FLV_AUTO_SELECT_SMOOTH_FACTOR = 0.8;
77 constexpr size_t FLV_AUTO_SELECT_TIME_GAP = 3;
78 
79 }
InitRingBuffer(uint32_t expectBufferDuration)80 void HttpMediaDownloader::InitRingBuffer(uint32_t expectBufferDuration)
81 {
82     int totalBufferSize = CURRENT_BIT_RATE * static_cast<int32_t>(expectBufferDuration);
83     if (totalBufferSize < RING_BUFFER_SIZE) {
84         MEDIA_LOG_I("HTTP Failed setting ring buffer size: " PUBLIC_LOG_D32 ". already lower than the min buffer size: "
85         PUBLIC_LOG_D32 ", setting buffer size: " PUBLIC_LOG_D32 ". ",
86         totalBufferSize, RING_BUFFER_SIZE, RING_BUFFER_SIZE);
87         ringBuffer_ = std::make_shared<RingBuffer>(RING_BUFFER_SIZE);
88         totalBufferSize_ = RING_BUFFER_SIZE;
89     } else if (totalBufferSize > MAX_BUFFER_SIZE) {
90         MEDIA_LOG_I("HTTP Failed setting ring buffer size: " PUBLIC_LOG_D32 ". already exceed the max buffer size: "
91         PUBLIC_LOG_D32 ", setting buffer size: " PUBLIC_LOG_D32 ". ",
92         totalBufferSize, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
93         ringBuffer_ = std::make_shared<RingBuffer>(MAX_BUFFER_SIZE);
94         totalBufferSize_ = MAX_BUFFER_SIZE;
95     } else {
96         ringBuffer_ = std::make_shared<RingBuffer>(totalBufferSize);
97         totalBufferSize_ = totalBufferSize;
98         MEDIA_LOG_I("HTTP Success setted ring buffer size: " PUBLIC_LOG_D32, totalBufferSize);
99     }
100     ringBuffer_->Init();
101 }
102 
InitCacheBuffer(uint32_t expectBufferDuration)103 void HttpMediaDownloader::InitCacheBuffer(uint32_t expectBufferDuration)
104 {
105     int totalBufferSize = CURRENT_BIT_RATE * static_cast<int32_t>(expectBufferDuration);
106     cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferImpl>();
107     FALSE_RETURN_MSG(cacheMediaBuffer_ != nullptr, "HTTP CacheBuffer create failed.");
108     if (totalBufferSize < RING_BUFFER_SIZE) {
109         MEDIA_LOG_I("HTTP Failed setting cache buffer size: " PUBLIC_LOG_D32
110                     ". already lower than the min buffer size: " PUBLIC_LOG_D32
111                     ", setting buffer size: " PUBLIC_LOG_D32 ". ", totalBufferSize,
112                     RING_BUFFER_SIZE, RING_BUFFER_SIZE);
113         isCacheBufferInited_ = cacheMediaBuffer_->Init(RING_BUFFER_SIZE, CHUNK_SIZE);
114         totalBufferSize_ = RING_BUFFER_SIZE;
115     } else if (totalBufferSize > MAX_BUFFER_SIZE) {
116         MEDIA_LOG_I("HTTP Failed setting cache buffer size: " PUBLIC_LOG_D32 ". already exceed the max buffer size: "
117         PUBLIC_LOG_D32 ", setting buffer size: " PUBLIC_LOG_D32 ". ",
118         totalBufferSize, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
119         isCacheBufferInited_ = cacheMediaBuffer_->Init(MAX_BUFFER_SIZE, CHUNK_SIZE);
120         totalBufferSize_ = MAX_BUFFER_SIZE;
121     } else {
122         isCacheBufferInited_ = cacheMediaBuffer_->Init(totalBufferSize, CHUNK_SIZE);
123         totalBufferSize_ = totalBufferSize;
124         MEDIA_LOG_I("HTTP Success setted cache buffer size: " PUBLIC_LOG_D32, totalBufferSize);
125     }
126     FALSE_RETURN_MSG(isCacheBufferInited_, "HTTP CacheBufferInit error");
127 }
128 
HttpMediaDownloader(std::string url,uint32_t expectBufferDuration,std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)129 HttpMediaDownloader::HttpMediaDownloader(std::string url, uint32_t expectBufferDuration,
130     std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)
131 {
132     if (static_cast<int32_t>(url.find(".flv")) != -1) {
133         MEDIA_LOG_I("HTTP isflv.");
134         isRingBuffer_ = true;
135     }
136     if (isRingBuffer_) {
137         InitRingBuffer(expectBufferDuration);
138     } else {
139         InitCacheBuffer(expectBufferDuration);
140     }
141     isBuffering_ = true;
142     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
143 
144     if (sourceLoader != nullptr) {
145         sourceLoader_ = sourceLoader;
146         isLargeOffsetSpan_ = true;
147         downloader_ = std::make_shared<Downloader>("http", sourceLoader);
148         MEDIA_LOG_I("HTTP app download.");
149     } else {
150         downloader_ = std::make_shared<Downloader>("http");
151     }
152 
153     timeoutInterval_ = MAX_BUFFERING_TIME_OUT;
154     writeBitrateCaculator_ = std::make_shared<WriteBitrateCaculator>();
155     steadyClock_.Reset();
156     loopInterruptClock_.Reset();
157     waterLineAbove_ = PLAY_WATER_LINE;
158     recordData_ = std::make_shared<RecordData>();
159 }
160 
~HttpMediaDownloader()161 HttpMediaDownloader::~HttpMediaDownloader()
162 {
163     MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~HttpMediaDownloader dtor", FAKE_POINTER(this));
164     Close(false);
165 }
166 
GetContentType()167 std::string HttpMediaDownloader::GetContentType()
168 {
169     FALSE_RETURN_V(downloader_ != nullptr, "");
170     MEDIA_LOG_I("In");
171     return downloader_->GetContentType();
172 }
173 
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)174 bool HttpMediaDownloader::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
175 {
176     MEDIA_LOG_I("HTTP Open download in");
177     isDownloadFinish_ = false;
178     openTime_ = steadyClock_.ElapsedMilliseconds();
179     auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool&& notBlock) {
180         return SaveData(std::forward<decltype(data)>(data), std::forward<decltype(len)>(len),
181             std::forward<decltype(notBlock)>(notBlock));
182     };
183     FALSE_RETURN_V(statusCallback_ != nullptr, false);
184     auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
185                                   std::shared_ptr<DownloadRequest>& request) {
186         statusCallback_(status, downloader_, std::forward<decltype(request)>(request));
187     };
188     auto downloadDoneCallback = [this] (const std::string &url, const std::string& location) {
189         if (downloadRequest_ != nullptr && downloadRequest_->IsEos()
190             && (totalBits_ / BYTES_TO_BIT) >= downloadRequest_->GetFileContentLengthNoWait()) {
191             isDownloadFinish_ = true;
192         }
193         int64_t nowTime = steadyClock_.ElapsedMilliseconds();
194         double downloadTime = (static_cast<double>(nowTime) - static_cast<double>(startDownloadTime_)) /
195             SECOND_TO_MILLISECONDS;
196         if (downloadTime > ZERO_THRESHOLD) {
197             avgDownloadSpeed_ = totalBits_ / downloadTime;
198         }
199         MEDIA_LOG_D("HTTP Download done, average download speed: " PUBLIC_LOG_D32 " bit/s",
200             static_cast<int32_t>(avgDownloadSpeed_));
201         MEDIA_LOG_I("HTTP Download done, data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
202             totalBits_, static_cast<int64_t>(downloadTime * SECOND_TO_MILLISECONDS));
203         HandleBuffering();
204     };
205     RequestInfo requestInfo;
206     requestInfo.url = defaultStream_ != nullptr ? defaultStream_->url : url;
207     requestInfo.httpHeader = httpHeader;
208     downloadRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
209     downloadRequest_->SetDownloadDoneCb(downloadDoneCallback);
210     downloader_->Download(downloadRequest_, -1); // -1
211     if (isRingBuffer_) {
212         ringBuffer_->SetMediaOffset(0);
213     }
214 
215     writeBitrateCaculator_->StartClock();
216     downloader_->Start();
217     return true;
218 }
219 
Close(bool isAsync)220 void HttpMediaDownloader::Close(bool isAsync)
221 {
222     if (isRingBuffer_) {
223         ringBuffer_->SetActive(false);
224     }
225     isInterrupt_ = true;
226     if (downloader_) {
227         downloader_->Stop(isAsync);
228     }
229     cvReadWrite_.NotifyOne();
230     if (!isDownloadFinish_) {
231         int64_t nowTime = steadyClock_.ElapsedMilliseconds();
232         double downloadTime = (static_cast<double>(nowTime) - static_cast<double>(startDownloadTime_)) /
233             SECOND_TO_MILLISECONDS;
234         if (downloadTime > ZERO_THRESHOLD) {
235             avgDownloadSpeed_ = totalBits_ / downloadTime;
236         }
237         MEDIA_LOG_D("HTTP Download close, average download speed: " PUBLIC_LOG_D32 " bit/s",
238             static_cast<int32_t>(avgDownloadSpeed_));
239         MEDIA_LOG_D("HTTP Download close, data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
240             totalBits_, static_cast<int64_t>(downloadTime * SECOND_TO_MILLISECONDS));
241     }
242 }
243 
Pause()244 void HttpMediaDownloader::Pause()
245 {
246     if (isRingBuffer_) {
247         bool cleanData = GetSeekable() != Seekable::SEEKABLE;
248         ringBuffer_->SetActive(false, cleanData);
249     }
250     isInterrupt_ = true;
251     downloader_->Pause();
252     cvReadWrite_.NotifyOne();
253 }
254 
Resume()255 void HttpMediaDownloader::Resume()
256 {
257     if (isRingBuffer_) {
258         ringBuffer_->SetActive(true);
259     }
260     isInterrupt_ = false;
261     downloader_->Resume();
262     cvReadWrite_.NotifyOne();
263 }
264 
OnClientErrorEvent()265 void HttpMediaDownloader::OnClientErrorEvent()
266 {
267     if (callback_ != nullptr) {
268         MEDIA_LOG_I("HTTP Read time out, OnEvent");
269         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
270         isTimeoutErrorNotified_.store(true);
271     }
272 }
273 
HandleBuffering()274 bool HttpMediaDownloader::HandleBuffering()
275 {
276     if (isBuffering_ && GetBufferingTimeOut() && callback_) {
277         MEDIA_LOG_I("HTTP cachebuffer buffering time out.");
278         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "buffering"});
279         isTimeoutErrorNotified_.store(true);
280         isBuffering_ = false;
281         return false;
282     }
283     if (IsNeedBufferForPlaying()) {
284         return false;
285     }
286     if (!isBuffering_ || downloadRequest_ == nullptr || downloadRequest_->IsChunkedVod()) {
287         bufferingTime_ = 0;
288         return false;
289     }
290     size_t fileContenLen = downloadRequest_->GetFileContentLength();
291     if (fileContenLen > readOffset_) {
292         size_t fileRemain = fileContenLen - readOffset_;
293         waterLineAbove_ = std::min(fileRemain, waterLineAbove_);
294     }
295 
296     UpdateWaterLineAbove();
297     UpdateCachedPercent(BufferingInfoType::BUFFERING_PERCENT);
298     HandleWaterline();
299     if (!isBuffering_ && !isFirstFrameArrived_) {
300         bufferingTime_ = 0;
301     }
302     if (!isBuffering_ && isFirstFrameArrived_ && callback_ != nullptr) {
303         MEDIA_LOG_I("HTTP CacheData onEvent BUFFERING_END, bufferSize: " PUBLIC_LOG_ZU ", waterLineAbove_: "
304         PUBLIC_LOG_ZU ", isBuffering: " PUBLIC_LOG_D32 ", canWrite: " PUBLIC_LOG_D32 " readOffset: "
305         PUBLIC_LOG_ZU " writeOffset: " PUBLIC_LOG_ZU, GetCurrentBufferSize(), waterLineAbove_, isBuffering_.load(),
306         canWrite_.load(), readOffset_, writeOffset_);
307         UpdateCachedPercent(BufferingInfoType::BUFFERING_END);
308         callback_->OnEvent({PluginEventType::BUFFERING_END, {BufferingInfoType::BUFFERING_END}, "end"});
309         bufferingTime_ = 0;
310     }
311     return isBuffering_.load();
312 }
313 
HandleWaterline()314 void HttpMediaDownloader::HandleWaterline()
315 {
316     AutoLock lk(bufferingEndMutex_);
317     if (!canWrite_) {
318         MEDIA_LOG_I("HTTP canWrite_ false");
319         isBuffering_ = false;
320     }
321     size_t currentWaterLine = waterLineAbove_;
322     size_t currentOffset = readOffset_;
323     {
324         AutoLock lock(initCacheMutex_);
325         if (initCacheSize_.load() != -1) {
326             currentWaterLine = static_cast<size_t>(initCacheSize_.load());
327             currentOffset = static_cast<size_t>(expectOffset_.load());
328             MEDIA_LOG_I("currentOffset:" PUBLIC_LOG_ZU, currentOffset);
329         }
330         if (GetCurrentBufferSize() >= currentWaterLine || HandleBreak()) {
331             MEDIA_LOG_I("HTTP Buffer is enough, bufferSize:" PUBLIC_LOG_ZU " waterLineAbove: " PUBLIC_LOG_ZU
332                 " avgDownloadSpeed: " PUBLIC_LOG_F, GetCurrentBufferSize(), currentWaterLine, avgDownloadSpeed_);
333             MEDIA_LOG_I("initCacheSize_: " PUBLIC_LOG_D32, static_cast<int32_t>(initCacheSize_.load()));
334             isBuffering_ = false;
335             if (initCacheSize_.load() != -1) {
336                 callback_->OnEvent({PluginEventType::INITIAL_BUFFER_SUCCESS,
337                                         {BufferingInfoType::BUFFERING_END}, "end"});
338                 MEDIA_LOG_I("initCacheSize_: " PUBLIC_LOG_D32, static_cast<int32_t>(initCacheSize_.load()));
339                 initCacheSize_.store(-1);
340                 expectOffset_.store(-1);
341             }
342         }
343     }
344     if (!isBuffering_) {
345         MEDIA_LOG_I("HandleBuffering bufferingEndCond NotifyAll.");
346         bufferingEndCond_.NotifyAll();
347     }
348 }
349 
IsStartDurationOfFlvMultiStream()350 bool HttpMediaDownloader::IsStartDurationOfFlvMultiStream()
351 {
352     return isRingBuffer_ && playMediaStreams_.size() > 0 &&
353         (steadyClock_.ElapsedMilliseconds() - openTime_) < IGNORE_BUFFERING_WITH_START_TIME_MS;
354 }
355 
StartBufferingCheck(unsigned int & wantReadLength)356 bool HttpMediaDownloader::StartBufferingCheck(unsigned int& wantReadLength)
357 {
358     AutoLock lk(savedataMutex_);
359     if (!isFirstFrameArrived_ || IsStartDurationOfFlvMultiStream()) {
360         if (GetCurrentBufferSize() >= wantReadLength || HandleBreak()) {
361             return false;
362         } else {
363             waterLineAbove_ = wantReadLength;
364             return true;
365         }
366     }
367     if (HandleBreak() || isBuffering_) {
368         return false;
369     }
370     if (!isRingBuffer_ && cacheMediaBuffer_ != nullptr && !isLargeOffsetSpan_ &&
371         cacheMediaBuffer_->IsReadSplit(readOffset_) && isNeedClearHasRead_) {
372         MEDIA_LOG_I("HTTP IsReadSplit, StartBuffering return, readOffset_ " PUBLIC_LOG_ZU, readOffset_);
373         wantReadLength = std::min(static_cast<size_t>(wantReadLength), GetCurrentBufferSize());
374         return false;
375     }
376     size_t cacheWaterLine = 0;
377     size_t fileRemain = 0;
378     size_t fileContenLen = downloadRequest_->GetFileContentLength();
379     cacheWaterLine = std::max(static_cast<size_t>(wantReadLength), PLAY_WATER_LINE);
380     if (isRingBuffer_) {
381         cacheWaterLine = std::max(static_cast<size_t>(wantReadLength), FLV_PLAY_WATER_LINE);
382     }
383     if (fileContenLen > readOffset_) {
384         fileRemain = fileContenLen - readOffset_;
385         cacheWaterLine = std::min(fileRemain, cacheWaterLine);
386     }
387     if (isRingBuffer_ && extraCache_ >= IGNORE_BUFFERING_EXTRA_CACHE_BEYOND_MS) {
388         return false;
389     }
390     if (GetCurrentBufferSize() >= cacheWaterLine) {
391         return false;
392     }
393     if (GetCurrentBufferSize() >= wantReadLength) {
394         return false;
395     }
396     return true;
397 }
398 
StartBuffering(unsigned int & wantReadLength)399 bool HttpMediaDownloader::StartBuffering(unsigned int& wantReadLength)
400 {
401     MEDIA_LOG_D("HTTP StartBuffering in.");
402     if (!StartBufferingCheck(wantReadLength)) {
403         return false;
404     }
405 
406     if (isNeedResume_.load()) {
407         isNeedResume_.store(false);
408         totalConsumeSize_ = 0;
409         downloader_->Resume();
410         if (!StartBufferingCheck(wantReadLength)) {
411             return false;
412         }
413     }
414 
415     if (!canWrite_.load()) { // Clear cacheBuffer when we can neither read nor write.
416         MEDIA_LOG_I("HTTP ClearCacheBuffer.");
417         ClearCacheBuffer();
418         canWrite_ = true;
419     }
420     if (IsStartDurationOfFlvMultiStream()) {
421         return false;
422     }
423     isBuffering_ = true;
424     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
425     if (!isFirstFrameArrived_) {
426         return true;
427     }
428     if (callback_ != nullptr) {
429         MEDIA_LOG_I("HTTP CacheData OnEvent BUFFERING_START, waterLineAbove: " PUBLIC_LOG_ZU " bufferSize "
430             PUBLIC_LOG_ZU " readOffset: " PUBLIC_LOG_ZU " writeOffset: " PUBLIC_LOG_ZU, waterLineAbove_,
431             GetCurrentBufferSize(), readOffset_, writeOffset_);
432         callback_->OnEvent({PluginEventType::BUFFERING_START, {BufferingInfoType::BUFFERING_START}, "start"});
433     }
434     UpdateCachedPercent(BufferingInfoType::BUFFERING_START);
435     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
436     return true;
437 }
438 
ReadRingBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)439 Status HttpMediaDownloader::ReadRingBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
440 {
441     FALSE_RETURN_V(downloadRequest_ != nullptr, Status::ERROR_UNKNOWN);
442     size_t fileContentLength = downloadRequest_->GetFileContentLength();
443     uint64_t mediaOffset = ringBuffer_->GetMediaOffset();
444     if (fileContentLength > mediaOffset) {
445         uint64_t remain = fileContentLength - mediaOffset;
446         readDataInfo.wantReadLength_ = remain < readDataInfo.wantReadLength_ ? remain :
447             readDataInfo.wantReadLength_;
448     }
449     readDataInfo.realReadLength_ = 0;
450     wantedReadLength_ = static_cast<size_t>(readDataInfo.wantReadLength_);
451     while (ringBuffer_->GetSize() < readDataInfo.wantReadLength_ && !isInterruptNeeded_.load()) {
452         readDataInfo.isEos_ = downloadRequest_->IsEos();
453         if (readDataInfo.isEos_) {
454             return CheckIsEosRingBuffer(buff, readDataInfo);
455         }
456         bool isClosed = downloadRequest_->IsClosed();
457         if (isClosed && ringBuffer_->GetSize() == 0) {
458             MEDIA_LOG_I("HttpMediaDownloader read return, isClosed: " PUBLIC_LOG_D32, isClosed);
459             readDataInfo.realReadLength_ = 0;
460             return Status::END_OF_STREAM;
461         }
462         Task::SleepInTask(FIVE_MICROSECOND);
463     }
464     if (isInterruptNeeded_.load()) {
465         readDataInfo.realReadLength_ = 0;
466         return Status::END_OF_STREAM;
467     }
468     readDataInfo.realReadLength_ = ringBuffer_->ReadBuffer(buff, readDataInfo.wantReadLength_, 2);  // wait 2 times
469     MEDIA_LOG_D("HTTP ReadRingBuffer: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
470                  PUBLIC_LOG_D32, readDataInfo.wantReadLength_, readDataInfo.realReadLength_, readDataInfo.isEos_);
471     return Status::OK;
472 }
473 
ReadCacheBufferLoop(unsigned char * buff,ReadDataInfo & readDataInfo)474 Status HttpMediaDownloader::ReadCacheBufferLoop(unsigned char* buff, ReadDataInfo& readDataInfo)
475 {
476     FALSE_RETURN_V(downloadRequest_ != nullptr, Status::ERROR_UNKNOWN);
477     if (downloadRequest_ != nullptr) {
478         readDataInfo.isEos_ = downloadRequest_->IsEos();
479     }
480     if (readDataInfo.isEos_ || GetDownloadErrorState()) {
481         return CheckIsEosCacheBuffer(buff, readDataInfo);
482     }
483     bool isClosed = downloadRequest_->IsClosed();
484     if (isClosed && cacheMediaBuffer_->GetBufferSize(readOffset_) == 0) {
485         MEDIA_LOG_I("Http read return, isClosed: " PUBLIC_LOG_D32, isClosed);
486         readDataInfo.realReadLength_ = 0;
487         return Status::END_OF_STREAM;
488     }
489     return Status::ERROR_UNKNOWN;
490 }
491 
ReadCacheBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)492 Status HttpMediaDownloader::ReadCacheBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
493 {
494     size_t remain = cacheMediaBuffer_->GetBufferSize(readOffset_);
495     MediaAVCodec::AVCodecTrace trace("HttpMediaDownloader::Read, readOffset: " + std::to_string(readOffset_) +
496         ", expectedLen: " + std::to_string(readDataInfo.wantReadLength_) + ", bufferSize: " + std::to_string(remain));
497     MEDIA_LOG_D("HTTP Read in: wantReadLength " PUBLIC_LOG_D32 " readOffset_ " PUBLIC_LOG_ZU " bufferSize: "
498         PUBLIC_LOG_ZU, readDataInfo.wantReadLength_, readOffset_, remain);
499     size_t hasReadSize = 0;
500     wantedReadLength_ = static_cast<size_t>(readDataInfo.wantReadLength_);
501     int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
502     while (hasReadSize < readDataInfo.wantReadLength_ && !isInterruptNeeded_.load()) {
503         if (CheckLoopTimeout(loopStartTime)) {
504             break;
505         }
506         Status tempStatus = ReadCacheBufferLoop(buff, readDataInfo);
507         if (tempStatus != Status::ERROR_UNKNOWN) {
508             return tempStatus;
509         }
510         auto size = cacheMediaBuffer_->Read(buff + hasReadSize, readOffset_ + hasReadSize,
511                                             readDataInfo.wantReadLength_ - hasReadSize);
512         if (size == 0) {
513             Task::SleepInTask(FIVE_MICROSECOND); // 5
514         } else {
515             hasReadSize += size;
516         }
517     }
518     if (hasReadSize > 0 || (!isLargeOffsetSpan_ && !isNeedClearHasRead_)) {
519         canWrite_ = true;
520     }
521     if (isInterruptNeeded_.load()) {
522         readDataInfo.realReadLength_ = hasReadSize;
523         return Status::END_OF_STREAM;
524     }
525     readDataInfo.realReadLength_ = hasReadSize;
526     readOffset_ += hasReadSize;
527     isMinAndMaxOffsetUpdate_ = false;
528     isSeekWait_ = false;
529     timeoutInterval_ = MAX_BUFFERING_TIME_OUT;
530     MEDIA_LOG_D("HTTP Read Success: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
531         PUBLIC_LOG_D32 " readOffset_ " PUBLIC_LOG_ZU, readDataInfo.wantReadLength_,
532         readDataInfo.realReadLength_, readDataInfo.isEos_, readOffset_);
533     return Status::OK;
534 }
535 
HandleDownloadWaterLine()536 void HttpMediaDownloader::HandleDownloadWaterLine()
537 {
538     if (downloader_ == nullptr || !isFirstFrameArrived_ || isBuffering_ || isLargeOffsetSpan_) {
539         return;
540     }
541     if (!isNeedClearHasRead_ || sourceLoader_ != nullptr) {
542         return;
543     }
544     uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
545     size_t cachedDataSize = static_cast<size_t>(totalBufferSize_) > freeSize ?
546                                 static_cast<size_t>(totalBufferSize_) - freeSize : 0;
547     size_t downloadWaterLine = static_cast<size_t>(DOWNLOAD_WATER_LINE_RATIO *
548         static_cast<float>(totalBufferSize_));
549     if (canWrite_.load()) {
550         if (cachedDataSize >= downloadWaterLine) {
551             canWrite_ = false;
552             MEDIA_LOG_D("HTTP downloadWaterLine above, stop write, downloadWaterLine: " PUBLIC_LOG_ZU,
553                 downloadWaterLine);
554         }
555     } else {
556         if (cachedDataSize < downloadWaterLine) {
557             canWrite_ = true;
558             MEDIA_LOG_D("HTTP downloadWaterLine below, resume write, downloadWaterLine: " PUBLIC_LOG_ZU,
559                 downloadWaterLine);
560         }
561     }
562 }
563 
CheckDownloadPos(unsigned int wantReadLength)564 void HttpMediaDownloader::CheckDownloadPos(unsigned int wantReadLength)
565 {
566     size_t writeOffsetTmp = writeOffset_;
567     size_t remain = GetCurrentBufferSize();
568     if ((!isLargeOffsetSpan_ && cacheMediaBuffer_->IsReadSplit(readOffset_) && isNeedClearHasRead_) ||
569         (isSeekWait_ && canWrite_)) {
570         MEDIA_LOG_I("HTTP CheckDownloadPos return, IsReadSplit.");
571         return;
572     }
573     if (remain < wantReadLength && isServerAcceptRange_ &&
574         (writeOffsetTmp < readOffset_ || writeOffsetTmp > readOffset_ + remain)) {
575         MEDIA_LOG_I("HTTP CheckDownloadPos, change download pos.");
576         ChangeDownloadPos(remain > 0);
577     }
578 }
579 
HandleRingBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)580 Status HttpMediaDownloader::HandleRingBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
581 {
582     if (isBuffering_ && GetBufferingTimeOut() && callback_ && !isReportedErrorCode_) {
583         MEDIA_LOG_I("HTTP ringbuffer read time out.");
584         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
585         isTimeoutErrorNotified_.store(true);
586         return Status::END_OF_STREAM;
587     }
588     bool isNeedErrorAgain = GetCurrentBufferSize() <= 0;
589     if (isBuffering_ && CheckBufferingOneSeconds() && !downloadRequest_->IsChunkedVod() && isNeedErrorAgain) {
590         MEDIA_LOG_I("HTTP Return error again.");
591         return Status::ERROR_AGAIN;
592     }
593     if (StartBuffering(readDataInfo.wantReadLength_) && isNeedErrorAgain) {
594         return Status::ERROR_AGAIN;
595     }
596     return ReadRingBuffer(buff, readDataInfo);
597 }
598 
HandleCacheBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)599 Status HttpMediaDownloader::HandleCacheBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
600 {
601     if (isBuffering_ && GetBufferingTimeOut() && callback_ && !isReportedErrorCode_) {
602         MEDIA_LOG_I("HTTP cachebuffer read time out.");
603         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
604         isTimeoutErrorNotified_.store(true);
605         return Status::END_OF_STREAM;
606     }
607     if (isBuffering_ && canWrite_ && CheckBufferingOneSeconds() && !downloadRequest_->IsChunkedVod()) {
608         MEDIA_LOG_I("HTTP Return error again.");
609         return Status::ERROR_AGAIN;
610     }
611     UpdateMinAndMaxReadOffset();
612     CheckDownloadPos(readDataInfo.wantReadLength_);
613     ClearHasReadBuffer();
614     if (StartBuffering(readDataInfo.wantReadLength_)) {
615         return Status::ERROR_AGAIN;
616     }
617     Status res = ReadCacheBuffer(buff, readDataInfo);
618 
619     if (isNeedResume_.load() && readDataInfo.realReadLength_ > 0) {
620         totalConsumeSize_ += readDataInfo.realReadLength_;
621         if (totalConsumeSize_ > DEFAULT_WATER_LINE_ABOVE) {
622             isNeedResume_.store(false);
623             totalConsumeSize_ = 0;
624             downloader_->Resume();
625             MEDIA_LOG_D("HTTP downloader resume.");
626         }
627     }
628 
629     HandleDownloadWaterLine();
630     return res;
631 }
632 
WaitCacheBufferInit()633 void HttpMediaDownloader::WaitCacheBufferInit()
634 {
635     if (cacheMediaBuffer_ == nullptr || !isCacheBufferInited_) {
636         AutoLock lock(sleepMutex_);
637         if (cacheMediaBuffer_ == nullptr || !isCacheBufferInited_) {
638             MEDIA_LOG_I("HTTP wait for CacheBufferInit begin " PUBLIC_LOG_D32, isCacheBufferInited_);
639             sleepCond_.WaitFor(lock, MAX_BUFFERING_TIME_OUT, [this]() {
640                 return isInterruptNeeded_.load() || isCacheBufferInited_;
641             });
642             MEDIA_LOG_I("HTTP wait for CacheBufferInit end " PUBLIC_LOG_D32, isCacheBufferInited_);
643         }
644     }
645 }
646 
ReadDelegate(unsigned char * buff,ReadDataInfo & readDataInfo)647 Status HttpMediaDownloader::ReadDelegate(unsigned char* buff, ReadDataInfo& readDataInfo)
648 {
649     if (isRingBuffer_) {
650         FALSE_RETURN_V_MSG(ringBuffer_ != nullptr, Status::END_OF_STREAM, "ringBuffer_ = nullptr");
651         FALSE_RETURN_V_MSG(!isInterruptNeeded_.load(), Status::END_OF_STREAM, "isInterruptNeeded");
652         FALSE_RETURN_V_MSG(readDataInfo.wantReadLength_ > 0, Status::END_OF_STREAM, "wantReadLength_ <= 0");
653         return HandleRingBuffer(buff, readDataInfo);
654     } else {
655         WaitCacheBufferInit();
656         FALSE_RETURN_V_MSG(!isInterruptNeeded_.load(), Status::END_OF_STREAM, "isInterruptNeeded");
657         FALSE_RETURN_V_MSG(isCacheBufferInited_, Status::END_OF_STREAM, "CacheBufferInit fail");
658         FALSE_RETURN_V_MSG(readDataInfo.wantReadLength_ > 0, Status::END_OF_STREAM, "wantReadLength_ <= 0");
659         return HandleCacheBuffer(buff, readDataInfo);
660     }
661 }
662 
Read(unsigned char * buff,ReadDataInfo & readDataInfo)663 Status HttpMediaDownloader::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
664 {
665     uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
666     readTime_ = now;
667     auto ret = ReadDelegate(buff, readDataInfo);
668     readTotalBytes_ += readDataInfo.realReadLength_;
669     if (now > lastReadCheckTime_ && now - lastReadCheckTime_ > SAMPLE_INTERVAL) {
670         readRecordDuringTime_ = now - lastReadCheckTime_;   // ms
671         float readDuration = static_cast<float>(readRecordDuringTime_) / SECOND_TO_MILLISECONDS; // s
672         if (readDuration > ZERO_THRESHOLD) {
673             float readSpeed = static_cast<float>(readTotalBytes_ * BYTES_TO_BIT) / readDuration; // bps
674             readBitrate_ = static_cast<uint64_t>(readSpeed);     // bps
675             currentBitRate_ = readSpeed > 0 ? static_cast<int32_t>(readSpeed) : currentBitRate_;     // bps
676             size_t curBufferSize = GetCurrentBufferSize();
677             MEDIA_LOG_D("HTTP Current read speed: " PUBLIC_LOG_D32 " Kbit/s,Current buffer size: " PUBLIC_LOG_U64
678             " KByte", static_cast<int32_t>(readSpeed / 1024), static_cast<uint64_t>(curBufferSize / 1024));
679             MediaAVCodec::AVCodecTrace trace("HttpMediaDownloader::Read, read speed: " +
680                 std::to_string(readSpeed) + " bit/s, bufferSize: " + std::to_string(curBufferSize) + " Byte");
681             readTotalBytes_ = 0;
682         }
683         lastReadCheckTime_ = now;
684         readRecordDuringTime_ = 0;
685     }
686     return ret;
687 }
688 
CheckIsEosRingBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)689 Status HttpMediaDownloader::CheckIsEosRingBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
690 {
691     if (ringBuffer_->GetSize() == 0) {
692         MEDIA_LOG_I("HTTP read return, isEos: " PUBLIC_LOG_D32, readDataInfo.isEos_);
693         return readDataInfo.realReadLength_ == 0 ? Status::END_OF_STREAM : Status::OK;
694     } else {
695         readDataInfo.realReadLength_ = ringBuffer_->ReadBuffer(buff, readDataInfo.wantReadLength_, 2); // 2
696         return Status::OK;
697     }
698 }
699 
CheckIsEosCacheBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)700 Status HttpMediaDownloader::CheckIsEosCacheBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
701 {
702     if (cacheMediaBuffer_->GetBufferSize(readOffset_) == 0) {
703         MEDIA_LOG_I("HTTP read return, isEos: " PUBLIC_LOG_D32, readDataInfo.isEos_);
704         if (readDataInfo.realReadLength_ > 0 && isLargeOffsetSpan_) {
705             canWrite_ = true;
706         }
707         return readDataInfo.realReadLength_ == 0 ? Status::END_OF_STREAM : Status::OK;
708     } else {
709         readDataInfo.realReadLength_ = cacheMediaBuffer_->Read(buff, readOffset_, readDataInfo.wantReadLength_);
710         readOffset_ += readDataInfo.realReadLength_;
711         if (isLargeOffsetSpan_) {
712             canWrite_ = true;
713         }
714         isMinAndMaxOffsetUpdate_ = false;
715         isSeekWait_ = false;
716         MEDIA_LOG_D("HTTP read return, isEos: " PUBLIC_LOG_D32, readDataInfo.isEos_);
717         return Status::OK;
718     }
719 }
720 
SeekRingBuffer(int64_t offset)721 bool HttpMediaDownloader::SeekRingBuffer(int64_t offset)
722 {
723     FALSE_RETURN_V(ringBuffer_ != nullptr, false);
724     MEDIA_LOG_I("HTTP Seek in, buffer size " PUBLIC_LOG_ZU ", offset " PUBLIC_LOG_D64, ringBuffer_->GetSize(), offset);
725     if (ringBuffer_->Seek(offset)) {
726         MEDIA_LOG_I("HTTP ringBuffer_ seek success.");
727         return true;
728     }
729     ringBuffer_->SetActive(false); // First clear buffer, avoid no available buffer then task pause never exit.
730     downloader_->Pause();
731     ringBuffer_->Clear();
732     ringBuffer_->SetActive(true);
733     bool result = downloader_->Seek(offset);
734     if (result) {
735         ringBuffer_->SetMediaOffset(offset);
736     } else {
737         MEDIA_LOG_D("HTTP Seek failed");
738     }
739     downloader_->Resume();
740     return result;
741 }
742 
UpdateMinAndMaxReadOffset()743 void HttpMediaDownloader::UpdateMinAndMaxReadOffset()
744 {
745     if ((!isLargeOffsetSpan_ && isMinAndMaxOffsetUpdate_) || !isNeedClearHasRead_ || sourceLoader_ != nullptr) {
746         return;
747     }
748     uint64_t readOffsetTmp = static_cast<uint64_t>(readOffset_);
749     if (GetCurrentBufferSize() == 0 && readOffsetTmp < minReadOffset_) {
750         maxReadOffset_ = readOffsetTmp;
751         minReadOffset_ = readOffsetTmp;
752         maxOffsetNotUpdateCount_ = 0;
753         minOffsetNotUpdateCount_ = 0;
754         ClearCacheBuffer();
755         return;
756     }
757 
758     if (maxReadOffset_ < readOffsetTmp) {
759         maxReadOffset_ = readOffsetTmp;
760         maxOffsetNotUpdateCount_ = 0;
761     } else {
762         maxOffsetNotUpdateCount_++;
763     }
764     if (maxOffsetNotUpdateCount_ > OFFSET_NOT_UPDATE_THRESHOLD) {
765         maxReadOffset_ = readOffsetTmp;
766         minReadOffset_ = readOffsetTmp;
767         maxOffsetNotUpdateCount_ = 0;
768     }
769     if (readOffsetTmp < maxReadOffset_ && readOffsetTmp > minReadOffset_) {
770         minReadOffset_ = readOffsetTmp;
771         minOffsetNotUpdateCount_ = 0;
772     } else {
773         minOffsetNotUpdateCount_++;
774     }
775     if (minOffsetNotUpdateCount_ > OFFSET_NOT_UPDATE_THRESHOLD) {
776         minReadOffset_ = readOffsetTmp;
777         minOffsetNotUpdateCount_ = 0;
778     }
779 
780     minReadOffset_ = std::min(minReadOffset_, static_cast<uint64_t>(readOffsetTmp));
781     minReadOffset_ = std::min(minReadOffset_, maxReadOffset_);
782     isMinAndMaxOffsetUpdate_ = true;
783 
784     uint64_t span = maxReadOffset_ > minReadOffset_ ? maxReadOffset_ - minReadOffset_ : 0;
785     if (span > LARGE_OFFSET_SPAN_THRESHOLD) {
786         isLargeOffsetSpan_ = true;
787         cacheMediaBuffer_->SetIsLargeOffsetSpan(true);
788         canWrite_ = true;
789     } else if (stateChangeCount_ <= STATE_CHANGE_THRESHOLD) {
790         isLargeOffsetSpan_ = false;
791         cacheMediaBuffer_->SetIsLargeOffsetSpan(false);
792         stateChangeCount_++;
793     }
794     MEDIA_LOG_D("HTTP UpdateMinAndMaxReadOffset, readOffset: " PUBLIC_LOG_U64 " minReadOffset_: "
795         PUBLIC_LOG_U64 " maxReadOffset_: " PUBLIC_LOG_U64, readOffsetTmp, minReadOffset_, maxReadOffset_);
796 }
797 
ChangeDownloadPos(bool isSeekHit)798 bool HttpMediaDownloader::ChangeDownloadPos(bool isSeekHit)
799 {
800     MEDIA_LOG_D("HTTP ChangeDownloadPos in, offset: " PUBLIC_LOG_ZU, readOffset_);
801 
802     uint64_t seekOffset = readOffset_;
803     if (isSeekHit) {
804         isNeedDropData_ = true;
805         OSAL::SleepFor(TEN_MILLISECONDS);
806         downloader_->Pause();
807         isNeedDropData_ = false;
808         seekOffset += GetCurrentBufferSize();
809         size_t fileContentLength = downloadRequest_->GetFileContentLength();
810         if (seekOffset >= static_cast<uint64_t>(fileContentLength)) {
811             MEDIA_LOG_W("HTTP seekOffset invalid, readOffset " PUBLIC_LOG_ZU " seekOffset " PUBLIC_LOG_U64
812                 " fileContentLength " PUBLIC_LOG_ZU, readOffset_, seekOffset, fileContentLength);
813             return true;
814         }
815     } else {
816         isNeedClean_ = true;
817         OSAL::SleepFor(TEN_MILLISECONDS);
818         downloader_->Pause();
819         isNeedClean_ = false;
820     }
821 
822     isHitSeeking_ = true;
823     bool result = downloader_->Seek(seekOffset);
824     isHitSeeking_ = false;
825     if (result) {
826         writeOffset_ = static_cast<size_t>(seekOffset);
827     } else {
828         MEDIA_LOG_E("HTTP Downloader seek fail.");
829     }
830     downloader_->Resume();
831     MEDIA_LOG_D("HTTP ChangeDownloadPos out, seekOffset" PUBLIC_LOG_U64, seekOffset);
832     return result;
833 }
834 
HandleSeekHit(int64_t offset)835 bool HttpMediaDownloader::HandleSeekHit(int64_t offset)
836 {
837     MEDIA_LOG_D("HTTP Seek hit.");
838     if (!isLargeOffsetSpan_ && cacheMediaBuffer_->IsReadSplit(offset) && isNeedClearHasRead_) {
839         MEDIA_LOG_D("HTTP seek hit return, because IsReadSplit.");
840         return true;
841     }
842     size_t fileContentLength = downloadRequest_->GetFileContentLength();
843     size_t downloadOffset = static_cast<size_t>(offset) + cacheMediaBuffer_->GetBufferSize(offset);
844     if (downloadOffset >= fileContentLength) {
845         MEDIA_LOG_W("HTTP downloadOffset invalid, offset " PUBLIC_LOG_D64 " downloadOffset " PUBLIC_LOG_ZU
846             " fileContentLength " PUBLIC_LOG_ZU, offset, downloadOffset, fileContentLength);
847         return true;
848     }
849 
850     size_t changeDownloadPosThreshold = DEFAULT_WATER_LINE_ABOVE;
851     if (!isLargeOffsetSpan_ && static_cast<size_t>(offset) < maxReadOffset_) {
852         changeDownloadPosThreshold = AUDIO_WATER_LINE_ABOVE;
853     }
854 
855     if (writeOffset_ != downloadOffset && cacheMediaBuffer_->GetBufferSize(offset) < changeDownloadPosThreshold) {
856         MEDIA_LOG_I("HTTP HandleSeekHit ChangeDownloadPos, writeOffset_: " PUBLIC_LOG_ZU " downloadOffset: "
857             PUBLIC_LOG_ZU " bufferSize: " PUBLIC_LOG_ZU, writeOffset_, downloadOffset,
858             cacheMediaBuffer_->GetBufferSize(offset));
859         return ChangeDownloadPos(true);
860     } else {
861         MEDIA_LOG_D("HTTP Seek hit, continue download.");
862     }
863     return true;
864 }
865 
SeekCacheBuffer(int64_t offset,bool & isSeekHit)866 bool HttpMediaDownloader::SeekCacheBuffer(int64_t offset, bool& isSeekHit)
867 {
868     readOffset_ = static_cast<size_t>(offset);
869     if (cacheMediaBuffer_->GetBufferSize(offset) == 0 && offset < 500) { // 500
870         NotifyInitSuccess();
871     }
872     cacheMediaBuffer_->Seek(offset); // Notify the cacheBuffer where to read.
873     UpdateMinAndMaxReadOffset();
874 
875     if (!isServerAcceptRange_) {
876         MEDIA_LOG_D("HTTP Don't support range, return true.");
877         return true;
878     }
879 
880     size_t remain = cacheMediaBuffer_->GetBufferSize(offset);
881     MEDIA_LOG_I("HTTP Seek: buffer size " PUBLIC_LOG_ZU ", offset " PUBLIC_LOG_D64, remain, offset);
882     if (remain > 0) {
883         isSeekHit = true;
884         return HandleSeekHit(offset);
885     }
886     isSeekHit = false;
887     MEDIA_LOG_I("HTTP Seek miss.");
888 
889     size_t fileContentLength = downloadRequest_->GetFileContentLength();
890     isNeedClearHasRead_ = fileContentLength > LARGE_VIDEO_THRESHOLD ? true : false;
891 
892     uint64_t diff = static_cast<size_t>(offset) > writeOffset_ ?
893         static_cast<size_t>(offset) - writeOffset_ : 0;
894     if (diff > 0 && diff < ALLOW_SEEK_MIN_SIZE && sourceLoader_ == nullptr) {
895         isSeekWait_ = true;
896         MEDIA_LOG_I("HTTP Seek miss, diff is too small so return and wait.");
897         return true;
898     }
899     return ChangeDownloadPos(false);
900 }
901 
SeekToPos(int64_t offset,bool & isSeekHit)902 bool HttpMediaDownloader::SeekToPos(int64_t offset, bool& isSeekHit)
903 {
904     if (isRingBuffer_) {
905         return SeekRingBuffer(offset);
906     } else {
907         return SeekCacheBuffer(offset, isSeekHit);
908     }
909 }
910 
GetContentLength() const911 size_t HttpMediaDownloader::GetContentLength() const
912 {
913     if (downloadRequest_->IsClosed()) {
914         return 0; // 0
915     }
916     return downloadRequest_->GetFileContentLength();
917 }
918 
GetDuration() const919 int64_t HttpMediaDownloader::GetDuration() const
920 {
921     return 0;
922 }
923 
GetSeekable() const924 Seekable HttpMediaDownloader::GetSeekable() const
925 {
926     return downloadRequest_->IsChunked(isInterruptNeeded_);
927 }
928 
SetCallback(Callback * cb)929 void HttpMediaDownloader::SetCallback(Callback* cb)
930 {
931     callback_ = cb;
932 }
933 
SetStatusCallback(StatusCallbackFunc cb)934 void HttpMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
935 {
936     statusCallback_ = cb;
937 }
938 
GetStartedStatus()939 bool HttpMediaDownloader::GetStartedStatus()
940 {
941     return startedPlayStatus_;
942 }
943 
SetReadBlockingFlag(bool isReadBlockingAllowed)944 void HttpMediaDownloader::SetReadBlockingFlag(bool isReadBlockingAllowed)
945 {
946     if (isRingBuffer_) {
947         FALSE_RETURN(ringBuffer_ != nullptr);
948         ringBuffer_->SetReadBlocking(isReadBlockingAllowed);
949     }
950 }
951 
SaveRingBufferData(uint8_t * data,uint32_t len,bool notBlock)952 uint32_t HttpMediaDownloader::SaveRingBufferData(uint8_t* data, uint32_t len, bool notBlock)
953 {
954     FALSE_RETURN_V(ringBuffer_->WriteBuffer(data, len), false);
955     cvReadWrite_.NotifyOne();
956     size_t bufferSize = ringBuffer_->GetSize();
957     double ratio = (static_cast<double>(bufferSize)) / RING_BUFFER_SIZE;
958     if ((bufferSize >= WATER_LINE ||
959         bufferSize >= downloadRequest_->GetFileContentLength() / 2) && !aboveWaterline_) { // 2
960         aboveWaterline_ = true;
961         MEDIA_LOG_D("HTTP Send http aboveWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
962         if (callback_ != nullptr) {
963             callback_->OnEvent({PluginEventType::ABOVE_LOW_WATERLINE, {ratio}, "http"});
964         }
965         startedPlayStatus_ = true;
966     } else if (bufferSize < WATER_LINE && aboveWaterline_) {
967         aboveWaterline_ = false;
968         MEDIA_LOG_D("HTTP Send http belowWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
969         if (callback_ != nullptr) {
970             callback_->OnEvent({PluginEventType::BELOW_LOW_WATERLINE, {ratio}, "http"});
971         }
972     }
973     if (writeBitrateCaculator_ != nullptr) {
974         writeBitrateCaculator_->UpdateWriteBytes(len);
975         writeBitrateCaculator_->StartClock();
976         uint64_t writeBitrate = writeBitrateCaculator_->GetWriteBitrate();
977         uint64_t writeTime  = writeBitrateCaculator_->GetWriteTime();
978         if (writeTime > ONE_SECONDS) {
979             MEDIA_LOG_I("waterLineAbove: " PUBLIC_LOG_ZU " writeBitrate: " PUBLIC_LOG_U64 " readBitrate: "
980                 PUBLIC_LOG_D32, waterLineAbove_, writeBitrate, currentBitRate_);
981             writeBitrateCaculator_->ResetClock();
982             if (downloadSpeeds_.size() >= FLV_AUTO_SELECT_TIME_GAP) { // 3s
983                 downloadSpeeds_.pop_front();
984                 downloadSpeeds_.push_back(writeBitrate);
985                 CheckAutoSelectBitrate();
986             } else {
987                 downloadSpeeds_.push_back(writeBitrate);
988             }
989         }
990     }
991     HandleCachedDuration();
992     return len;
993 }
994 
SaveData(uint8_t * data,uint32_t len,bool notBlock)995 uint32_t HttpMediaDownloader::SaveData(uint8_t* data, uint32_t len, bool notBlock)
996 {
997     if (!isRingBuffer_ && (cacheMediaBuffer_ == nullptr || !isCacheBufferInited_)) {
998         FALSE_RETURN_V_MSG(downloadRequest_ != nullptr, 0, "downloadRequest_ nullptr");
999         if (cacheMediaBuffer_ == nullptr) {
1000             cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferImpl>();
1001         }
1002         if (cacheMediaBuffer_ == nullptr) {
1003             {
1004                 AutoLock lock(sleepMutex_);
1005                 isCacheBufferInited_ = false;
1006             }
1007             sleepCond_.NotifyAll();
1008             MEDIA_LOG_I("HTTP CacheBuffer create failed.");
1009             return false;
1010         }
1011         size_t fileContenLen = downloadRequest_->GetFileContentLength();
1012         if (fileContenLen > 0) {
1013             uint64_t bufferSize = static_cast<uint64_t>(fileContenLen + BUFFER_REDUNDANCY);
1014             totalBufferSize_ = std::min(MAX_CACHE_BUFFER_SIZE, bufferSize);
1015         } else {
1016             totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
1017         }
1018         MEDIA_LOG_I("HTTP setting buffer size: " PUBLIC_LOG_D32 " fileContenLen: " PUBLIC_LOG_ZU,
1019             totalBufferSize_, fileContenLen);
1020         {
1021             AutoLock lock(sleepMutex_);
1022             isCacheBufferInited_ = cacheMediaBuffer_->Init(totalBufferSize_, CHUNK_SIZE);
1023         }
1024         sleepCond_.NotifyAll();
1025         FALSE_RETURN_V_MSG(isCacheBufferInited_, 0, "HTTP CacheBufferInit failed");
1026     }
1027 
1028     if (cacheMediaBuffer_ == nullptr && ringBuffer_ == nullptr) {
1029         return 0;
1030     }
1031     OnWriteBuffer(len);
1032     uint32_t ret = 0;
1033     if (isRingBuffer_) {
1034         ret = SaveRingBufferData(data, len, notBlock);
1035     } else {
1036         ret = SaveCacheBufferData(data, len, notBlock);
1037         HandleDownloadWaterLine();
1038     }
1039     HandleBuffering();
1040     return ret;
1041 }
1042 
CacheBufferFullLoop()1043 bool HttpMediaDownloader::CacheBufferFullLoop()
1044 {
1045     {
1046         AutoLock lock(initCacheMutex_);
1047         if (initCacheSize_.load() != -1 &&
1048             GetBufferSize() >= static_cast<size_t>(initCacheSize_.load())) {
1049             callback_->OnEvent({PluginEventType::INITIAL_BUFFER_SUCCESS,
1050                                     {BufferingInfoType::BUFFERING_END}, "end"});
1051             initCacheSize_.store(-1);
1052             expectOffset_.store(-1);
1053         }
1054     }
1055     MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "HTTP CacheMediaBuffer full, waiting seek or read.");
1056     if (isHitSeeking_ || isNeedDropData_) {
1057         canWrite_ = true;
1058         return true;
1059     }
1060     OSAL::SleepFor(ONE_HUNDRED_MILLIONSECOND);
1061     return false;
1062 }
1063 
SaveCacheBufferDataNotblock(uint8_t * data,uint32_t len)1064 uint32_t HttpMediaDownloader::SaveCacheBufferDataNotblock(uint8_t* data, uint32_t len)
1065 {
1066     AutoLock lk(savedataMutex_);
1067     isServerAcceptRange_ = downloadRequest_->IsServerAcceptRange();
1068 
1069     size_t res = cacheMediaBuffer_->Write(data, writeOffset_, len);
1070     writeOffset_ += res;
1071 
1072     MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "SaveCacheBufferDataNotblock writeOffset " PUBLIC_LOG_ZU " res "
1073         PUBLIC_LOG_ZU, writeOffset_, res);
1074 
1075     writeBitrateCaculator_->UpdateWriteBytes(res);
1076     uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
1077     MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "SaveCacheBufferDataNotblock, freeSize: " PUBLIC_LOG_U64, freeSize);
1078     HandleCachedDuration();
1079     writeBitrateCaculator_->StartClock();
1080     uint64_t writeTime  = writeBitrateCaculator_->GetWriteTime() / SECOND_TO_MILLISECONDS;
1081     if (writeTime > ONE_SECONDS) {
1082         writeBitrateCaculator_->ResetClock();
1083     }
1084 
1085     if (res < len) {
1086         cacheMediaBuffer_->Dump(0);
1087         isNeedResume_.store(true);
1088     }
1089 
1090     return res;
1091 }
1092 
SaveCacheBufferData(uint8_t * data,uint32_t len,bool notBlock)1093 uint32_t HttpMediaDownloader::SaveCacheBufferData(uint8_t* data, uint32_t len, bool notBlock)
1094 {
1095     if (notBlock) {
1096         return SaveCacheBufferDataNotblock(data, len);
1097     }
1098 
1099     if (isNeedClean_) {
1100         return len;
1101     }
1102 
1103     isServerAcceptRange_ = downloadRequest_->IsServerAcceptRange();
1104 
1105     size_t hasWriteSize = 0;
1106     while (hasWriteSize < len && !isInterruptNeeded_.load() && !isInterrupt_.load()) {
1107         if (isNeedClean_) {
1108             MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "isNeedClean true.");
1109             return len;
1110         }
1111         size_t res = cacheMediaBuffer_->Write(data + hasWriteSize, writeOffset_, len - hasWriteSize);
1112         writeOffset_ += res;
1113         hasWriteSize += res;
1114         writeBitrateCaculator_->UpdateWriteBytes(res);
1115         MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "HTTP writeOffset " PUBLIC_LOG_ZU " res "
1116             PUBLIC_LOG_ZU, writeOffset_, res);
1117         if ((isLargeOffsetSpan_ || canWrite_.load()) && (res > 0 || hasWriteSize == len)) {
1118             HandleCachedDuration();
1119             writeBitrateCaculator_->StartClock();
1120             uint64_t writeTime  = writeBitrateCaculator_->GetWriteTime() / SECOND_TO_MILLISECONDS;
1121             if (writeTime > ONE_SECONDS) {
1122                 writeBitrateCaculator_->ResetClock();
1123             }
1124             continue;
1125         }
1126         MEDIA_LOG_W("HTTP CacheMediaBuffer full.");
1127         writeBitrateCaculator_->StopClock();
1128         canWrite_ = false;
1129         HandleBuffering();
1130         while (!isInterrupt_.load() && !isNeedClean_.load() && !canWrite_.load() && !isInterruptNeeded_.load()) {
1131             if (CacheBufferFullLoop()) {
1132                 return len;
1133             }
1134         }
1135         canWrite_ = true;
1136     }
1137     if (isInterruptNeeded_.load() || isInterrupt_.load()) {
1138         MEDIA_LOG_I("HTTP isInterruptNeeded true, return false.");
1139         return 0;
1140     }
1141     return len;
1142 }
1143 
OnWriteBuffer(uint32_t len)1144 void HttpMediaDownloader::OnWriteBuffer(uint32_t len)
1145 {
1146     {
1147         AutoLock lock(initCacheMutex_);
1148         if (initCacheSize_.load() != -1 &&
1149             GetCurrentBufferSize() >= static_cast<size_t>(initCacheSize_.load())) {
1150             callback_->OnEvent({ PluginEventType::INITIAL_BUFFER_SUCCESS, {BufferingInfoType::BUFFERING_END}, "end"});
1151             initCacheSize_.store(-1);
1152             expectOffset_.store(-1);
1153         }
1154     }
1155     if (startDownloadTime_ == 0) {
1156         int64_t nowTime = steadyClock_.ElapsedMilliseconds();
1157         startDownloadTime_ = nowTime;
1158         lastReportUsageTime_ = nowTime;
1159     }
1160     uint32_t writeBits = len * BYTES_TO_BIT;
1161     totalBits_ += writeBits;
1162     dataUsage_ += writeBits;
1163     if ((totalBits_ > START_PLAY_WATER_LINE) && (playDelayTime_ == 0)) {
1164         auto startPlayTime = steadyClock_.ElapsedMilliseconds();
1165         playDelayTime_ = startPlayTime - openTime_;
1166         MEDIA_LOG_D("HTTP Start play delay time: " PUBLIC_LOG_D64, playDelayTime_);
1167     }
1168     DownloadReport();
1169 }
1170 
CalculateCurrentDownloadSpeed()1171 double HttpMediaDownloader::CalculateCurrentDownloadSpeed()
1172 {
1173     double downloadRate = 0;
1174     double tmpNumerator = static_cast<double>(downloadBits_);
1175     double tmpDenominator = static_cast<double>(downloadDuringTime_) / SECOND_TO_MILLISECONDS;
1176     totalDownloadDuringTime_ += downloadDuringTime_;
1177     if (tmpDenominator > ZERO_THRESHOLD) {
1178         downloadRate = tmpNumerator / tmpDenominator;
1179         avgDownloadSpeed_ = downloadRate;
1180         downloadDuringTime_ = 0;
1181         downloadBits_ = 0;
1182     }
1183     return downloadRate;
1184 }
1185 
DownloadReport()1186 void HttpMediaDownloader::DownloadReport()
1187 {
1188     uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
1189     if ((static_cast<int64_t>(now) - lastCheckTime_) > static_cast<int64_t>(SAMPLE_INTERVAL)) {
1190         uint64_t curDownloadBits = totalBits_ - lastBits_;
1191         if (curDownloadBits >= IS_DOWNLOAD_MIN_BIT) {
1192             downloadDuringTime_ = now - static_cast<uint64_t>(lastCheckTime_);
1193             downloadBits_ = curDownloadBits;
1194             double downloadRate = CalculateCurrentDownloadSpeed();
1195             // remaining buffer size
1196             size_t remainingBuffer = GetCurrentBufferSize();    // Byte
1197             MEDIA_LOG_D("Current download speed : " PUBLIC_LOG_D32 " Kbit/s,Current buffer size : " PUBLIC_LOG_U64
1198                 " KByte", static_cast<int32_t>(downloadRate / 1024), static_cast<uint64_t>(remainingBuffer / 1024));
1199             MediaAVCodec::AVCodecTrace trace("HttpMediaDownloader::DownloadReport, download speed: " +
1200                 std::to_string(downloadRate) + " bit/s, bufferSize: " + std::to_string(remainingBuffer) + " Byte");
1201             // Remaining playable time: s
1202             uint64_t bufferDuration = 0;
1203             if (readBitrate_ > 0) {
1204                 bufferDuration = static_cast<uint64_t>(remainingBuffer * BYTES_TO_BIT) / readBitrate_;
1205             } else {
1206                 bufferDuration = static_cast<uint64_t>(remainingBuffer * BYTES_TO_BIT) / CURRENT_BIT_RATE;
1207             }
1208             if (recordData_ != nullptr) {
1209                 recordData_->downloadRate = downloadRate;
1210                 recordData_->bufferDuring = bufferDuration;
1211             }
1212         }
1213         lastBits_ = totalBits_;
1214         lastCheckTime_ = static_cast<int64_t>(now);
1215     }
1216 
1217     if (!isDownloadFinish_ && (static_cast<int64_t>(now) - lastReportUsageTime_) > DATA_USAGE_NTERVAL) {
1218         MEDIA_LOG_D("Data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D32 "ms", dataUsage_, DATA_USAGE_NTERVAL);
1219         dataUsage_ = 0;
1220         lastReportUsageTime_ = static_cast<int64_t>(now);
1221     }
1222 }
1223 
SetDemuxerState(int32_t streamId)1224 void HttpMediaDownloader::SetDemuxerState(int32_t streamId)
1225 {
1226     MEDIA_LOG_I("HTTP SetDemuxerState");
1227     isFirstFrameArrived_ = true;
1228 }
1229 
SetDownloadErrorState()1230 void HttpMediaDownloader::SetDownloadErrorState()
1231 {
1232     MEDIA_LOG_I("HTTP SetDownloadErrorState");
1233     downloadErrorState_ = true;
1234     if (callback_ != nullptr && !isReportedErrorCode_) {
1235         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_NOT_RETRY}, "read"});
1236         isTimeoutErrorNotified_.store(true);
1237     }
1238     Close(true);
1239 }
1240 
SetInterruptState(bool isInterruptNeeded)1241 void HttpMediaDownloader::SetInterruptState(bool isInterruptNeeded)
1242 {
1243     MEDIA_LOG_I("SetInterruptState: " PUBLIC_LOG_D32, isInterruptNeeded);
1244     {
1245         AutoLock lk(bufferingEndMutex_);
1246         isInterruptNeeded_ = isInterruptNeeded;
1247         if (isInterruptNeeded_) {
1248             MEDIA_LOG_I("SetInterruptState, bufferingEndCond NotifyAll.");
1249             bufferingEndCond_.NotifyAll();
1250             sleepCond_.NotifyAll();
1251         }
1252     }
1253     if (ringBuffer_ != nullptr && isInterruptNeeded) {
1254         ringBuffer_->SetActive(false);
1255     }
1256     if (downloader_ != nullptr) {
1257         downloader_->SetInterruptState(isInterruptNeeded);
1258     }
1259 }
1260 
GetBufferSize() const1261 size_t HttpMediaDownloader::GetBufferSize() const
1262 {
1263     return GetCurrentBufferSize();
1264 }
1265 
GetBuffer()1266 RingBuffer& HttpMediaDownloader::GetBuffer()
1267 {
1268     return *ringBuffer_;
1269 }
1270 
GetReadFrame()1271 bool HttpMediaDownloader::GetReadFrame()
1272 {
1273     return isFirstFrameArrived_;
1274 }
1275 
GetDownloadErrorState()1276 bool HttpMediaDownloader::GetDownloadErrorState()
1277 {
1278     return downloadErrorState_;
1279 }
1280 
GetStatusCallbackFunc()1281 StatusCallbackFunc HttpMediaDownloader::GetStatusCallbackFunc()
1282 {
1283     return statusCallback_;
1284 }
1285 
GetDownloadInfo(DownloadInfo & downloadInfo)1286 void HttpMediaDownloader::GetDownloadInfo(DownloadInfo& downloadInfo)
1287 {
1288     if (recordSpeedCount_ == 0) {
1289         MEDIA_LOG_E("HttpMediaDownloader is 0, can't get avgDownloadRate");
1290         downloadInfo.avgDownloadRate = 0;
1291     } else {
1292         downloadInfo.avgDownloadRate = avgSpeedSum_ / recordSpeedCount_;
1293     }
1294     downloadInfo.avgDownloadSpeed = avgDownloadSpeed_;
1295     downloadInfo.totalDownLoadBits = totalBits_;
1296     downloadInfo.isTimeOut = isTimeOut_;
1297 }
1298 
GetDownloadInfo()1299 std::pair<int32_t, int32_t> HttpMediaDownloader::GetDownloadInfo()
1300 {
1301     MEDIA_LOG_I("HttpMediaDownloader::GetDownloadInfo.");
1302     if (recordSpeedCount_ == 0) {
1303         MEDIA_LOG_E("recordSpeedCount is 0, can't get avgDownloadRate");
1304         return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1305     }
1306     auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1307     return rateAndSpeed;
1308 }
1309 
GetDownloadRateAndSpeed()1310 std::pair<int32_t, int32_t> HttpMediaDownloader::GetDownloadRateAndSpeed()
1311 {
1312     MEDIA_LOG_I("HttpMediaDownloader::GetDownloadRateAndSpeed.");
1313     if (recordSpeedCount_ == 0) {
1314         MEDIA_LOG_E("recordSpeedCount is 0, can't get avgDownloadRate");
1315         return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1316     }
1317     auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1318     return rateAndSpeed;
1319 }
1320 
GetPlaybackInfo(PlaybackInfo & playbackInfo)1321 void HttpMediaDownloader::GetPlaybackInfo(PlaybackInfo& playbackInfo)
1322 {
1323     if (downloader_ != nullptr) {
1324         downloader_->GetIp(playbackInfo.serverIpAddress);
1325     }
1326     double tmpDownloadTime = static_cast<double>(totalDownloadDuringTime_) / SECOND_TO_MILLISECONDS;
1327     if (tmpDownloadTime > ZERO_THRESHOLD) {
1328         playbackInfo.averageDownloadRate = static_cast<int64_t>(totalBits_ / tmpDownloadTime);
1329     } else {
1330         playbackInfo.averageDownloadRate = 0;
1331     }
1332     playbackInfo.isDownloading = isDownloadFinish_ ? false : true;
1333     if (recordData_ != nullptr) {
1334         playbackInfo.downloadRate = static_cast<int64_t>(recordData_->downloadRate);
1335         size_t remainingBuffer = GetCurrentBufferSize();
1336         uint64_t bufferDuration = 0;
1337         if (readBitrate_ > 0) {
1338             bufferDuration = static_cast<uint64_t>(remainingBuffer * BYTES_TO_BIT) / readBitrate_;
1339         } else {
1340             bufferDuration = static_cast<uint64_t>(remainingBuffer * BYTES_TO_BIT) / CURRENT_BIT_RATE;
1341         }
1342         playbackInfo.bufferDuration = static_cast<int64_t>(bufferDuration);
1343     } else {
1344         playbackInfo.downloadRate = 0;
1345         playbackInfo.bufferDuration = 0;
1346     }
1347 }
1348 
HandleBreak()1349 bool HttpMediaDownloader::HandleBreak()
1350 {
1351     MEDIA_LOG_D("HTTP HandleBreak");
1352     if (downloadErrorState_) {
1353         MEDIA_LOG_I("downloadErrorState true.");
1354         return true;
1355     }
1356     if (downloadRequest_ == nullptr) {
1357         MEDIA_LOG_I("downloadRequest is nullptr.");
1358         return true;
1359     }
1360     if (downloadRequest_->IsEos()) {
1361         MEDIA_LOG_I("isEos true");
1362         return true;
1363     }
1364     if (downloadRequest_->IsClosed()) {
1365         MEDIA_LOG_I("IsClosed true");
1366         return true;
1367     }
1368     if (downloadRequest_->IsChunkedVod()) {
1369         MEDIA_LOG_I("IsChunkedVod true");
1370         return true;
1371     }
1372     return false;
1373 }
1374 
GetCurrentBufferSize() const1375 size_t HttpMediaDownloader::GetCurrentBufferSize() const
1376 {
1377     size_t bufferSize = 0;
1378     if (isRingBuffer_) {
1379         if (ringBuffer_ != nullptr) {
1380             bufferSize = ringBuffer_->GetSize();
1381         }
1382     } else {
1383         if (cacheMediaBuffer_ != nullptr) {
1384             bufferSize = cacheMediaBuffer_->GetBufferSize(readOffset_);
1385         }
1386     }
1387     return bufferSize;
1388 }
1389 
SetCurrentBitRate(int32_t bitRate,int32_t streamID)1390 Status HttpMediaDownloader::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
1391 {
1392     MEDIA_LOG_I("HTTP SetCurrentBitRate: " PUBLIC_LOG_D32, bitRate);
1393     if (bitRate <= 0) {
1394         videoBitrate_ = DEFAULT_BIT_RATE;
1395     } else {
1396         videoBitrate_ = std::max(videoBitrate_, static_cast<uint32_t>(bitRate));
1397     }
1398     currentBitRate_ = static_cast<int32_t>(videoBitrate_);
1399     return Status::OK;
1400 }
1401 
HandleCachedDuration()1402 void HttpMediaDownloader::HandleCachedDuration()
1403 {
1404     int32_t tmpBitRate = currentBitRate_;
1405     if (tmpBitRate <= 0 || callback_ == nullptr) {
1406         return;
1407     }
1408     cachedDuration_ = static_cast<uint64_t>((static_cast<int64_t>(GetCurrentBufferSize()) *
1409         BYTES_TO_BIT * SECOND_TO_MILLISECONDS) / static_cast<int64_t>(tmpBitRate));
1410     // Subtraction of unsigned integers requires size comparison first.
1411     if ((cachedDuration_ > lastDurationReacord_ &&
1412         cachedDuration_ - lastDurationReacord_ > DURATION_CHANGE_AMOUT_MILLIONSECOND) ||
1413         (lastDurationReacord_ > cachedDuration_ &&
1414         lastDurationReacord_ - cachedDuration_ > DURATION_CHANGE_AMOUT_MILLIONSECOND)) {
1415         MEDIA_LOG_D("HTTP OnEvent cachedDuration: " PUBLIC_LOG_U64, cachedDuration_);
1416         callback_->OnEvent({PluginEventType::CACHED_DURATION, {cachedDuration_}, "buffering_duration"});
1417         lastDurationReacord_ = cachedDuration_;
1418     }
1419 }
1420 
UpdateCachedPercent(BufferingInfoType infoType)1421 void HttpMediaDownloader::UpdateCachedPercent(BufferingInfoType infoType)
1422 {
1423     if (waterLineAbove_ == 0 || callback_ == nullptr) {
1424         MEDIA_LOG_E("UpdateCachedPercent: ERROR");
1425         return;
1426     }
1427     if (infoType == BufferingInfoType::BUFFERING_START) {
1428         lastCachedSize_ = 0;
1429         isBufferingStart_ = true;
1430         return;
1431     }
1432     if (infoType == BufferingInfoType::BUFFERING_END) {
1433         lastCachedSize_ = 0;
1434         isBufferingStart_ = false;
1435         return;
1436     }
1437     if (infoType != BufferingInfoType::BUFFERING_PERCENT || !isBufferingStart_) {
1438         return;
1439     }
1440     int32_t bufferSize = static_cast<int32_t>(GetCurrentBufferSize());
1441     if (bufferSize < lastCachedSize_) {
1442         return;
1443     }
1444     int32_t deltaSize = bufferSize - lastCachedSize_;
1445     if (deltaSize >= static_cast<int32_t>(UPDATE_CACHE_STEP)) {
1446         int percent = (bufferSize >= static_cast<int32_t>(waterLineAbove_)) ?
1447                         100 : bufferSize * 100 / static_cast<int32_t>(waterLineAbove_); // 100
1448         callback_->OnEvent({PluginEventType::EVENT_BUFFER_PROGRESS, {percent}, "buffer percent"});
1449         lastCachedSize_ = bufferSize;
1450     }
1451 }
1452 
CheckBufferingOneSeconds()1453 bool HttpMediaDownloader::CheckBufferingOneSeconds()
1454 {
1455     MEDIA_LOG_I("HTTP CheckBufferingOneSeconds in");
1456     int32_t sleepTime = 0;
1457     // return error again 1 time 1s, avoid ffmpeg error
1458     while (sleepTime < (isFirstFrameArrived_ ? TWO_SECONDS : ONE_HUNDRED_MILLIONSECOND) &&
1459            !isInterruptNeeded_.load()) {
1460         if (!isBuffering_) {
1461             break;
1462         }
1463         if (HandleBreak()) {
1464             isBuffering_ = false;
1465             break;
1466         }
1467         OSAL::SleepFor(TEN_MILLISECONDS);
1468         sleepTime += TEN_MILLISECONDS;
1469     }
1470     MEDIA_LOG_I("HTTP CheckBufferingOneSeconds out");
1471     return isBuffering_.load();
1472 }
1473 
SetAppUid(int32_t appUid)1474 void HttpMediaDownloader::SetAppUid(int32_t appUid)
1475 {
1476     if (downloader_) {
1477         downloader_->SetAppUid(appUid);
1478     }
1479 }
1480 
GetCacheDuration(float ratio)1481 float HttpMediaDownloader::GetCacheDuration(float ratio)
1482 {
1483     if (ratio >= 1) {
1484         return CACHE_LEVEL_1;
1485     }
1486     return DEFAULT_CACHE_TIME;
1487 }
1488 
UpdateWaterLineAbove()1489 void HttpMediaDownloader::UpdateWaterLineAbove()
1490 {
1491     if (!isFirstFrameArrived_) {
1492         return;
1493     }
1494     size_t waterLineAbove = DEFAULT_WATER_LINE_ABOVE;
1495     currentBitRate_ = std::max(currentBitRate_, static_cast<int32_t>(videoBitrate_));
1496     if (currentBitRate_ > 0) {
1497         float cacheTime = 0;
1498         uint64_t writeBitrate = writeBitrateCaculator_->GetWriteBitrate();
1499         if (writeBitrate > 0) {
1500             float ratio = static_cast<float>(writeBitrate) / currentBitRate_;
1501             cacheTime = GetCacheDuration(ratio);
1502         } else {
1503             cacheTime = DEFAULT_CACHE_TIME;
1504         }
1505         if (isRingBuffer_) {
1506             cacheTime -= static_cast<float>(static_cast<double>(extraCache_) / static_cast<double>(ONE_SECONDS));
1507             cacheTime = std::max(cacheTime, 0.0f);
1508         }
1509         waterLineAbove = static_cast<size_t>(cacheTime * currentBitRate_ / BYTES_TO_BIT);
1510         if (!isRingBuffer_) {
1511             waterLineAbove = std::max(MIN_WATER_LINE_ABOVE, waterLineAbove);
1512         }
1513     } else {
1514         MEDIA_LOG_D("UpdateWaterLineAbove default: " PUBLIC_LOG_ZU, waterLineAbove);
1515     }
1516     waterLineAbove_ = waterLineAbove;
1517 
1518     if (readOffset_ < maxReadOffset_) {
1519         waterLineAbove_ = DEFAULT_WATER_LINE_ABOVE;
1520     }
1521 
1522     size_t fileRemain = 0;
1523     if (downloadRequest_ != nullptr) {
1524         size_t fileContenLen = downloadRequest_->GetFileContentLength();
1525         if (fileContenLen > readOffset_) {
1526             fileRemain = fileContenLen - readOffset_;
1527             waterLineAbove_ = std::min(fileRemain, waterLineAbove_);
1528         }
1529     }
1530 
1531     waterLineAbove_ = std::min(waterLineAbove_, static_cast<size_t>(MAX_CACHE_BUFFER_SIZE *
1532         WATER_LINE_ABOVE_LIMIT_RATIO));
1533     waterLineAbove_ = std::min(waterLineAbove_, MAX_WATER_LINE_ABOVE);
1534     MEDIA_LOG_D("UpdateWaterLineAbove: " PUBLIC_LOG_ZU " writeBitrate: " PUBLIC_LOG_U64 " readBitrate: "
1535         PUBLIC_LOG_D32, waterLineAbove_, writeBitrateCaculator_->GetWriteBitrate(), currentBitRate_);
1536 }
1537 
GetPlayable()1538 bool HttpMediaDownloader::GetPlayable()
1539 {
1540     if (isBuffering_) {
1541         return false;
1542     }
1543     if (!isFirstFrameArrived_) {
1544         return false;
1545     }
1546     size_t wantedLength = wantedReadLength_;
1547     size_t waterLine = wantedLength > 0 ? std::max(PLAY_WATER_LINE, wantedLength) : 0;
1548     return waterLine == 0 ? GetBufferSize() > waterLine : GetBufferSize() >= waterLine;
1549 }
1550 
GetBufferingTimeOut()1551 bool HttpMediaDownloader::GetBufferingTimeOut()
1552 {
1553     if (bufferingTime_ == 0) {
1554         return false;
1555     } else {
1556         size_t now = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1557         return now >= bufferingTime_ ? now - bufferingTime_ >= timeoutInterval_ : false;
1558     }
1559 }
1560 
GetReadTimeOut(bool isDelay)1561 bool HttpMediaDownloader::GetReadTimeOut(bool isDelay)
1562 {
1563     size_t now = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1564     if (isDelay) {
1565         timeoutInterval_ = MAX_BUFFERING_TIME_OUT_DELAY;
1566     }
1567     return (now >= readTime_) ? (now - readTime_ >= timeoutInterval_) : false;
1568 }
1569 
StopBufferring(bool isAppBackground)1570 Status HttpMediaDownloader::StopBufferring(bool isAppBackground)
1571 {
1572     MEDIA_LOG_I("HttpMediaDownloader:StopBufferring enter");
1573     if (downloader_ == nullptr) {
1574         MEDIA_LOG_E("StopBufferring error.");
1575         return Status::ERROR_NULL_POINTER;
1576     }
1577     isAppBackground_ = isAppBackground;
1578     downloader_->SetAppState(isAppBackground);
1579     if (isAppBackground) {
1580         if (ringBuffer_ != nullptr) {
1581             //flv will relink, unactive buffer to interupt download and clean data.
1582             ringBuffer_->SetActive(false, true);
1583         }
1584         if (cacheMediaBuffer_ != nullptr) {
1585             isInterrupt_ = true;
1586         }
1587     } else {
1588         if (ringBuffer_ != nullptr) {
1589             ringBuffer_->SetActive(true, true);
1590         }
1591         if (cacheMediaBuffer_ != nullptr) {
1592             isInterrupt_ = false;
1593         }
1594     }
1595     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1596     downloader_->StopBufferring();
1597     MEDIA_LOG_I("HttpMediaDownloader:StopBufferring out");
1598     return Status::OK;
1599 }
1600 
WaitForBufferingEnd()1601 void HttpMediaDownloader::WaitForBufferingEnd()
1602 {
1603     AutoLock lk(bufferingEndMutex_);
1604     FALSE_RETURN_MSG(isBuffering_.load(), "isBuffering false.");
1605     MEDIA_LOG_I("WaitForBufferingEnd");
1606     bufferingEndCond_.Wait(lk, [this]() {
1607         MEDIA_LOG_I("Wait in, isBuffering: " PUBLIC_LOG_D32 " isInterruptNeeded: " PUBLIC_LOG_D32,
1608             isBuffering_.load(), isInterruptNeeded_.load());
1609         return !isBuffering_.load() || isInterruptNeeded_.load();
1610     });
1611 }
1612 
ClearHasReadBuffer()1613 bool HttpMediaDownloader::ClearHasReadBuffer()
1614 {
1615     if (!isFirstFrameArrived_ || cacheMediaBuffer_ == nullptr || isLargeOffsetSpan_) {
1616         return false;
1617     }
1618     if (!isNeedClearHasRead_) {
1619         return false;
1620     }
1621     uint64_t minOffset = std::min(minReadOffset_, static_cast<uint64_t>(writeOffset_));
1622     uint64_t clearOffset = minOffset > CLEAR_SAVE_DATA_SIZE ? minOffset - CLEAR_SAVE_DATA_SIZE : 0;
1623     bool res = false;
1624     res = cacheMediaBuffer_->ClearFragmentBeforeOffset(clearOffset);
1625     res = cacheMediaBuffer_->ClearChunksOfFragment(clearOffset) || res;
1626     uint64_t minClearOffset = minOffset + CLEAR_SAVE_DATA_SIZE;
1627     uint64_t maxClearOffset = maxReadOffset_ > CLEAR_SAVE_DATA_SIZE ? maxReadOffset_ - CLEAR_SAVE_DATA_SIZE : 0;
1628     uint64_t diff = maxClearOffset > minClearOffset ? maxClearOffset - minClearOffset : 0;
1629     if (diff > ALLOW_CLEAR_MIDDLE_DATA_MIN_SIZE) {
1630         res = cacheMediaBuffer_->ClearMiddleReadFragment(minClearOffset, maxClearOffset) || res;
1631     }
1632     MEDIA_LOG_D("HTTP ClearHasReadBuffer, res: " PUBLIC_LOG_D32 " clearOffset: " PUBLIC_LOG_U64 " minClearOffset: "
1633         PUBLIC_LOG_U64 " maxClearOffset: " PUBLIC_LOG_U64, res, clearOffset, minClearOffset, maxClearOffset);
1634     return res;
1635 }
1636 
ClearCacheBuffer()1637 void HttpMediaDownloader::ClearCacheBuffer()
1638 {
1639     if (cacheMediaBuffer_ == nullptr || downloader_ == nullptr) {
1640         return;
1641     }
1642     MEDIA_LOG_I("HTTP ClearCacheBuffer begin.");
1643     isNeedDropData_ = true;
1644     downloader_->Pause();
1645     cacheMediaBuffer_->Clear();
1646     isNeedDropData_ = false;
1647     downloader_->Seek(readOffset_);
1648     writeOffset_ = readOffset_;
1649     downloader_->Resume();
1650     uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
1651     MEDIA_LOG_I("HTTP ClearCacheBuffer end, freeSize: " PUBLIC_LOG_U64, freeSize);
1652 }
1653 
SetIsReportedErrorCode()1654 void HttpMediaDownloader::SetIsReportedErrorCode()
1655 {
1656     isReportedErrorCode_ = true;
1657 }
1658 
SetInitialBufferSize(int32_t offset,int32_t size)1659 bool HttpMediaDownloader::SetInitialBufferSize(int32_t offset, int32_t size)
1660 {
1661     AutoLock lock(initCacheMutex_);
1662     bool isInitBufferSizeOk = GetCurrentBufferSize() >= static_cast<size_t>(size) || HandleBreak();
1663     if (isInitBufferSizeOk || !downloader_ || !downloadRequest_ || isTimeoutErrorNotified_.load()) {
1664         MEDIA_LOG_I("HTTP SetInitialBufferSize initCacheSize ok.");
1665         return false;
1666     }
1667     if (downloadRequest_->IsChunkedVod()) {
1668         MEDIA_LOG_I("ChunkedVod, fail to SetInitBufferSize.");
1669         return false;
1670     }
1671     MEDIA_LOG_I("HTTP SetInitialBufferSize initCacheSize " PUBLIC_LOG_U32, size);
1672     if (!isBuffering_.load()) {
1673         isBuffering_.store(true);
1674     }
1675     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1676     expectOffset_.store(offset);
1677     initCacheSize_.store(size);
1678     return true;
1679 }
1680 
SetPlayStrategy(const std::shared_ptr<PlayStrategy> & playStrategy)1681 void HttpMediaDownloader::SetPlayStrategy(const std::shared_ptr<PlayStrategy>& playStrategy)
1682 {
1683     if (playStrategy == nullptr) {
1684         MEDIA_LOG_E("HTTP SetPlayStrategy error.");
1685         return;
1686     }
1687     if (playStrategy->bufferDurationForPlaying > 0) {
1688         bufferDurationForPlaying_ = playStrategy->bufferDurationForPlaying;
1689         waterlineForPlaying_ = static_cast<uint64_t>(static_cast<double>(CURRENT_BIT_RATE) /
1690             static_cast<double>(BYTES_TO_BIT) * bufferDurationForPlaying_);
1691         MEDIA_LOG_I("HTTP buffer duration for playing : " PUBLIC_LOG ".3f", bufferDurationForPlaying_);
1692     }
1693     if (playStrategy->width > 0 && playStrategy->width < USHRT_MAX
1694         && playStrategy->height > 0 && playStrategy->height < USHRT_MAX) {
1695         initResolution_ = playStrategy->width * playStrategy->height;
1696         ChooseStreamByResolution();
1697     }
1698 }
1699 
IsNeedBufferForPlaying()1700 bool HttpMediaDownloader::IsNeedBufferForPlaying()
1701 {
1702     if (bufferDurationForPlaying_ <= 0 || !isDemuxerInitSuccess_.load() || !isBuffering_.load()) {
1703         return false;
1704     }
1705     if (GetBufferingTimeOut()) {
1706         callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT},
1707                             "buffer for playing"});
1708         isTimeoutErrorNotified_.store(true);
1709         AutoLock lk(bufferingEndMutex_);
1710         isBuffering_.store(false);
1711         bufferingEndCond_.NotifyAll();
1712         isDemuxerInitSuccess_.store(false);
1713         bufferingTime_ = 0;
1714         return false;
1715     }
1716     if (GetCurrentBufferSize() >= waterlineForPlaying_ || HandleBreak()) {
1717         MEDIA_LOG_I("HTTP buffer duration for playing is enough, buffersize: " PUBLIC_LOG_ZU " waterLineAbove: "
1718                     PUBLIC_LOG_U64, GetCurrentBufferSize(), waterlineForPlaying_);
1719         AutoLock lk(bufferingEndMutex_);
1720         isBuffering_.store(false);
1721         bufferingEndCond_.NotifyAll();
1722         isDemuxerInitSuccess_.store(false);
1723         bufferingTime_ = 0;
1724         if (isRingBuffer_ && callback_) {
1725             callback_->OnEvent({PluginEventType::BUFFERING_END, {BufferingInfoType::BUFFERING_END}, "end"});
1726         }
1727         return false;
1728     }
1729     return true;
1730 }
1731 
NotifyInitSuccess()1732 void HttpMediaDownloader::NotifyInitSuccess()
1733 {
1734     MEDIA_LOG_I("HTTP NotifyInitSuccess in");
1735     isDemuxerInitSuccess_.store(true);
1736     if (bufferDurationForPlaying_ <= 0 || currentBitRate_ <= 0) {
1737         return;
1738     }
1739     if (currentBitRate_ > 0) {
1740         waterlineForPlaying_ = static_cast<uint64_t>(static_cast<double>(currentBitRate_) /
1741             static_cast<double>(BYTES_TO_BIT) * bufferDurationForPlaying_);
1742     }
1743     isBuffering_.store(true);
1744     bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1745 }
1746 
GetCachedDuration()1747 uint64_t HttpMediaDownloader::GetCachedDuration()
1748 {
1749     MEDIA_LOG_I("HTTP GetCachedDuration: " PUBLIC_LOG_U64, cachedDuration_);
1750     return cachedDuration_;
1751 }
1752 
RestartAndClearBuffer()1753 void HttpMediaDownloader::RestartAndClearBuffer()
1754 {
1755     FALSE_RETURN_MSG(downloader_ != nullptr, "downloader_ is nullptr");
1756     FALSE_RETURN_MSG(ringBuffer_ != nullptr || cacheMediaBuffer_ != nullptr, "buffer is nullptr");
1757     MEDIA_LOG_I("HTTP RestartAndClearBuffer in.");
1758     {
1759         AutoLock lk(bufferingEndMutex_);
1760         isBuffering_.store(false);
1761         bufferingEndCond_.NotifyAll();
1762     }
1763     isAllowResume_.store(true);
1764     if (isRingBuffer_) {
1765         ringBuffer_->SetActive(false);
1766         downloader_->Pause();
1767         ringBuffer_->SetActive(true);
1768         MEDIA_LOG_I("HTTP clear ringbuffer done.");
1769     } else {
1770         downloader_->Pause();
1771         cacheMediaBuffer_->Clear();
1772         MEDIA_LOG_I("HTTP clear cachebuffer done.");
1773     }
1774     downloader_->Resume();
1775     isAllowResume_.store(true);
1776     MEDIA_LOG_I("HTTP RestartAndClearBuffer out.");
1777 }
1778 
IsFlvLive()1779 bool HttpMediaDownloader::IsFlvLive()
1780 {
1781     FALSE_RETURN_V_MSG_E(downloader_ != nullptr, false, "downloader_ is nullptr");
1782     FALSE_RETURN_V_MSG_E(downloadRequest_ != nullptr, false, "downloadRequest_ is nullptr");
1783     size_t fileContenLen = downloadRequest_->GetFileContentLength();
1784     return fileContenLen == 0 && isRingBuffer_;
1785 }
1786 
SetStartPts(int64_t startPts)1787 void HttpMediaDownloader::SetStartPts(int64_t startPts)
1788 {
1789     flvStartPts_ = startPts;
1790 }
1791 
SetExtraCache(uint64_t cacheDuration)1792 void HttpMediaDownloader::SetExtraCache(uint64_t cacheDuration)
1793 {
1794     extraCache_ = cacheDuration;
1795     MEDIA_LOG_D("SetExtraCache extraCache_=" PUBLIC_LOG_U64, extraCache_);
1796 }
1797 
SelectBitRate(uint32_t bitRate)1798 bool HttpMediaDownloader::SelectBitRate(uint32_t bitRate)
1799 {
1800     if (playMediaStreams_.size() <= 1 || !isRingBuffer_) {
1801         MEDIA_LOG_E("HTTP SelectBitRate error.");
1802         return true;
1803     }
1804     if (ringBuffer_ == nullptr || downloader_ == nullptr || downloadRequest_ == nullptr) {
1805         return true;
1806     }
1807     MEDIA_LOG_I("HTTP SelectBitRate " PUBLIC_LOG_U32, bitRate);
1808     defaultStream_ = playMediaStreams_.front();
1809     uint32_t preBitrate = 0;
1810     for (const auto &stream : playMediaStreams_) {
1811         if (preBitrate == 0 && bitRate <= stream->bitrate) {
1812             break;
1813         } else if (bitRate > preBitrate && bitRate <= stream->bitrate) {
1814             uint32_t deltaA = bitRate - preBitrate;
1815             uint32_t deltaB = stream->bitrate - bitRate;
1816             deltaB < deltaA ? defaultStream_ = stream : 0;
1817             break;
1818         } else if (preBitrate == stream->bitrate) {
1819             continue;
1820         } else {
1821             defaultStream_ = stream;
1822             preBitrate = stream->bitrate;
1823         }
1824     }
1825     openTime_ = steadyClock_.ElapsedMilliseconds();
1826     isSelectingBitrate_.store(true);
1827     ringBuffer_->SetActive(false, true);
1828     downloadSpeeds_.clear();
1829     downloader_->Pause(false);
1830     ringBuffer_->SetActive(true, true);
1831     isSelectingBitrate_.store(false);
1832     std::string url = defaultStream_->url;
1833     AddParamForUrl(url, "startPts", std::to_string(flvStartPts_));
1834     MEDIA_LOG_I("flvStartPts_ " PUBLIC_LOG_D64, flvStartPts_);
1835     currentBitRate_ = static_cast<int32_t>(defaultStream_->bitrate);
1836     downloadRequest_->SetUrl(url);
1837     downloadRequest_->SetRangePos(0, -1);
1838     downloader_->Resume();
1839     return true;
1840 }
1841 
AddParamForUrl(std::string & url,const std::string & key,const std::string & value)1842 void HttpMediaDownloader::AddParamForUrl(std::string& url, const std::string& key, const std::string& value)
1843 {
1844     std::string param;
1845     if (url.find("?") == std::string::npos) {
1846         param = "?" + key + "=" + value;
1847     } else {
1848         param = "&" + key + "=" + value;
1849     }
1850     url += param;
1851 }
1852 
SetMediaStreams(const MediaStreamList & mediaStreams)1853 void HttpMediaDownloader::SetMediaStreams(const MediaStreamList& mediaStreams)
1854 {
1855     MEDIA_LOG_I("HTTP MediaStreams size is " PUBLIC_LOG_ZU, static_cast<size_t>(mediaStreams.size()));
1856     playMediaStreams_ = mediaStreams;
1857     defaultStream_ = playMediaStreams_.empty() ? nullptr : playMediaStreams_.front();
1858 }
1859 
ChooseStreamByResolution()1860 void HttpMediaDownloader::ChooseStreamByResolution()
1861 {
1862     if (initResolution_ == 0 || defaultStream_ == nullptr) {
1863         return;
1864     }
1865     for (const auto &stream : playMediaStreams_) {
1866         if (stream == nullptr) {
1867             continue;
1868         }
1869         if (IsNearToInitResolution(defaultStream_, stream)) {
1870             defaultStream_ = stream;
1871         }
1872     }
1873     MEDIA_LOG_I("resolution, width:" PUBLIC_LOG_U32 ", height:" PUBLIC_LOG_U32,
1874                 defaultStream_->width, defaultStream_->height);
1875 }
1876 
IsNearToInitResolution(const std::shared_ptr<PlayMediaStream> & choosedStream,const std::shared_ptr<PlayMediaStream> & currentStream)1877 bool HttpMediaDownloader::IsNearToInitResolution(const std::shared_ptr<PlayMediaStream> &choosedStream,
1878     const std::shared_ptr<PlayMediaStream> &currentStream)
1879 {
1880     if (choosedStream == nullptr || currentStream == nullptr || initResolution_ == 0) {
1881         return false;
1882     }
1883     uint32_t choosedDelta = GetResolutionDelta(choosedStream->width, choosedStream->height);
1884     uint32_t currentDelta = GetResolutionDelta(currentStream->width, currentStream->height);
1885     return (currentDelta < choosedDelta)
1886            || (currentDelta == choosedDelta && currentStream->bitrate < choosedStream->bitrate);
1887 }
1888 
GetResolutionDelta(uint32_t width,uint32_t height)1889 uint32_t HttpMediaDownloader::GetResolutionDelta(uint32_t width, uint32_t height)
1890 {
1891     if (width >= USHRT_MAX || height >= USHRT_MAX) {
1892         return 0;
1893     }
1894 
1895     uint32_t resolution = width * height;
1896     if (resolution > initResolution_) {
1897         return resolution - initResolution_;
1898     } else {
1899         return initResolution_ - resolution;
1900     }
1901 }
1902 
CheckLoopTimeout(int64_t startLoopTime)1903 bool HttpMediaDownloader::CheckLoopTimeout(int64_t startLoopTime)
1904 {
1905     int64_t now = loopInterruptClock_.ElapsedSeconds();
1906     int64_t loopDuration = now > startLoopTime ? now - startLoopTime : 0;
1907     bool isLoopTimeout = loopDuration > LOOP_TIMEOUT ? true : false;
1908     if (isLoopTimeout) {
1909         SetDownloadErrorState();
1910         MEDIA_LOG_E("loop timeout");
1911     }
1912     return isLoopTimeout;
1913 }
1914 
SetIsTriggerAutoMode(bool isAuto)1915 void HttpMediaDownloader::SetIsTriggerAutoMode(bool isAuto)
1916 {
1917     isAutoSelectBitrate_.store(isAuto);
1918 }
1919 
AutoSelectBitRate(uint32_t bitRate)1920 bool HttpMediaDownloader::AutoSelectBitRate(uint32_t bitRate)
1921 {
1922     SelectBitRate(bitRate);
1923     return true;
1924 }
1925 
CheckAutoSelectBitrate()1926 bool HttpMediaDownloader::CheckAutoSelectBitrate()
1927 {
1928     if (!IsAutoSelectConditionOk()) {
1929         return false;
1930     }
1931     uint64_t sumSpeed = 0;
1932     for (const auto &speed : downloadSpeeds_) {
1933         sumSpeed += speed;
1934     }
1935     uint64_t aveSpeed = sumSpeed / downloadSpeeds_.size();
1936     uint32_t desBitRate = 0;
1937     for (const auto &item : playMediaStreams_) {
1938         if (defaultStream_->bitrate == item->bitrate) {
1939             continue;
1940         }
1941         if (item->bitrate > 0 && item->bitrate == desBitRate) {
1942             break;
1943         }
1944         uint32_t smoothSpeed = static_cast<uint32_t>(aveSpeed * FLV_AUTO_SELECT_SMOOTH_FACTOR);
1945         if (defaultStream_->bitrate < item->bitrate && item->bitrate <= smoothSpeed) {
1946             desBitRate = item->bitrate;
1947         }
1948         if (defaultStream_->bitrate > item->bitrate && aveSpeed < defaultStream_->bitrate &&
1949             item->bitrate <= smoothSpeed) {
1950             desBitRate = item->bitrate;
1951         }
1952     }
1953     if (desBitRate <= 0 || desBitRate == defaultStream_->bitrate) {
1954         return false;
1955     }
1956     MEDIA_LOG_I("HTTP CheckAutoSelectBitrate aveRate " PUBLIC_LOG_U64 " desRate " PUBLIC_LOG_U32, aveSpeed, desBitRate);
1957     if (isAutoSelectBitrate_.load() && callback_) {
1958         callback_->OnEvent({PluginEventType::FLV_AUTO_SELECT_BITRATE, {desBitRate},
1959             "auto select bitrate"});
1960     }
1961     return true;
1962 }
1963 
IsAutoSelectConditionOk()1964 bool HttpMediaDownloader::IsAutoSelectConditionOk()
1965 {
1966     if (!isAutoSelectBitrate_.load()) {
1967         return false;
1968     }
1969     if (!isRingBuffer_) {
1970         return false;
1971     }
1972     if (playMediaStreams_.size() <= 1) {
1973         return false;
1974     }
1975     if (defaultStream_ == nullptr) {
1976         return false;
1977     }
1978     if (isSelectingBitrate_.load()) {
1979         return false;
1980     }
1981     if (downloadSpeeds_.size() <= 0) {
1982         return false;
1983     }
1984     return true;
1985 }
1986 
ClearBuffer()1987 void HttpMediaDownloader::ClearBuffer()
1988 {
1989     FALSE_RETURN_MSG(downloader_ != nullptr, "downloader_ is nullptr, fail to ClearBuffer");
1990     FALSE_RETURN_MSG(ringBuffer_ != nullptr || cacheMediaBuffer_ != nullptr, "buffer is nullptr.");
1991     if (isRingBuffer_) {
1992         size_t sizeBefore = ringBuffer_->GetFreeSize();
1993         ringBuffer_->SetActive(false);
1994         ringBuffer_->SetActive(true);
1995         size_t sizeAfter = ringBuffer_->GetFreeSize();
1996         MEDIA_LOG_I("HTTP ClearBuffer done, sizeBefore: " PUBLIC_LOG_ZU " sizeAfter: " PUBLIC_LOG_ZU,
1997             sizeBefore, sizeAfter);
1998     } else {
1999         size_t sizeBefore = cacheMediaBuffer_->GetFreeSize();
2000         cacheMediaBuffer_->Clear();
2001         size_t sizeAfter = cacheMediaBuffer_->GetFreeSize();
2002         MEDIA_LOG_I("HTTP ClearBuffer done, sizeBefore: " PUBLIC_LOG_ZU " sizeAfter: " PUBLIC_LOG_ZU,
2003             sizeBefore, sizeAfter);
2004     }
2005 }
2006 
GetMemorySize()2007 uint64_t HttpMediaDownloader::GetMemorySize()
2008 {
2009     if (totalBufferSize_ <= 0) {
2010         return 0;
2011     }
2012     return static_cast<uint64_t>(totalBufferSize_);
2013 }
2014 
GetCurUrl()2015 std::string HttpMediaDownloader::GetCurUrl()
2016 {
2017     FALSE_RETURN_V_MSG_E(downloadRequest_ != nullptr, "", "currentRequest_ is nullptr");
2018     GetContentLength();
2019     if (!downloadRequest_->haveRedirectRetry_.load()) {
2020         return "";
2021     }
2022     return downloadRequest_->GetUrl();
2023 }
2024 }
2025 }
2026 }
2027 }