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> ¤tStream)
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 }