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 "HlsMediaDownloader"
16
17 #include "hls_media_downloader.h"
18 #include "media_downloader.h"
19 #include "hls_playlist_downloader.h"
20 #include "securec.h"
21 #include <algorithm>
22 #include "plugin/plugin_time.h"
23 #include "openssl/aes.h"
24 #include "osal/task/task.h"
25 #include "network/network_typs.h"
26 #include "common/media_core.h"
27 #include <arpa/inet.h>
28 #include <netdb.h>
29 #include <regex>
30 #include "avcodec_trace.h"
31
32 namespace OHOS {
33 namespace Media {
34 namespace Plugins {
35 namespace HttpPlugin {
36 namespace {
37 constexpr uint32_t DECRYPT_COPY_LEN = 128;
38 constexpr int MIN_WITDH = 480;
39 constexpr int SECOND_WITDH = 720;
40 constexpr int THIRD_WITDH = 1080;
41 constexpr uint64_t MAX_BUFFER_SIZE = 19 * 1024 * 1024;
42 constexpr uint32_t SAMPLE_INTERVAL = 1000; // Sampling time interval: ms
43 constexpr int MAX_RECORD_COUNT = 10;
44 constexpr int START_PLAY_WATER_LINE = 512 * 1024;
45 constexpr int DATA_USAGE_NTERVAL = 300 * 1000;
46 constexpr double ZERO_THRESHOLD = 1e-9;
47 constexpr size_t PLAY_WATER_LINE = 5 * 1024;
48 constexpr int IS_DOWNLOAD_MIN_BIT = 100;
49 constexpr size_t DEFAULT_WATER_LINE_ABOVE = 512 * 1024;
50 constexpr uint32_t DURATION_CHANGE_AMOUT_MILLIONSECOND = 500;
51 constexpr int UPDATE_CACHE_STEP = 5 * 1024;
52 constexpr int SEEK_STATUS_RETRY_TIMES = 100;
53 constexpr int SEEK_STATUS_SLEEP_TIME = 50;
54 constexpr uint64_t CURRENT_BIT_RATE = 1 * 1024 * 1024; // bps
55 constexpr int32_t ONE_SECONDS = 1000;
56 constexpr int32_t TEN_MILLISECONDS = 10;
57 constexpr size_t MIN_WATER_LINE_ABOVE = 300 * 1024;
58 constexpr float WATER_LINE_ABOVE_LIMIT_RATIO = 0.6;
59 constexpr float CACHE_LEVEL_1 = 0.3;
60 constexpr int32_t DEFAULT_CACHE_TIME = 5;
61 constexpr int TRANSFER_SIZE_RATE_2 = 2;
62 constexpr int TRANSFER_SIZE_RATE_3 = 3;
63 constexpr int TRANSFER_SIZE_RATE_4 = 4;
64 constexpr int SLEEP_TIME_100 = 100;
65 constexpr size_t MAX_BUFFERING_TIME_OUT = 30 * 1000;
66 constexpr int32_t HUNDRED_PERCENTS = 100;
67 constexpr int32_t HALF_DIVIDE = 2;
68 constexpr uint64_t READ_BACK_SAVE_SIZE = 1 * 1024 * 1024;
69 constexpr int32_t SAVE_DATA_LOG_FREQUENCE = 10;
70 constexpr uint32_t KILO = 1024;
71 }
72
73 // hls manifest, m3u8 --- content get from m3u8 url, we get play list from the content
74 // fragment --- one item in play list, download media data according to the fragment address.
HlsMediaDownloader(const std::map<std::string,std::string> & httpHeader)75 HlsMediaDownloader::HlsMediaDownloader(const std::map<std::string, std::string>& httpHeader) noexcept
76 {
77 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
78 cacheMediaBuffer_->Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE);
79 isBuffering_ = true;
80 bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
81 totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
82 httpHeader_ = httpHeader;
83 MEDIA_LOG_I("HLS setting buffer size: " PUBLIC_LOG_U64, MAX_CACHE_BUFFER_SIZE);
84 HlsInit();
85 }
86
HlsMediaDownloader(int expectBufferDuration,const std::map<std::string,std::string> & httpHeader)87 HlsMediaDownloader::HlsMediaDownloader(int expectBufferDuration, const std::map<std::string, std::string>& httpHeader)
88 {
89 expectDuration_ = static_cast<uint64_t>(expectBufferDuration);
90 userDefinedBufferDuration_ = true;
91 totalBufferSize_ = expectDuration_ * CURRENT_BIT_RATE;
92 httpHeader_ = httpHeader;
93 MEDIA_LOG_I("user define buffer duration.");
94 MEDIA_LOG_I("HLS setting buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
95 HlsInit();
96 }
97
HlsMediaDownloader(std::string mimeType,const std::map<std::string,std::string> & httpHeader)98 HlsMediaDownloader::HlsMediaDownloader(std::string mimeType, const std::map<std::string, std::string>& httpHeader)
99 {
100 mimeType_ = mimeType;
101 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
102 httpHeader_ = httpHeader;
103 cacheMediaBuffer_->Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE);
104 totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
105 MEDIA_LOG_I("HLS setting buffer size: " PUBLIC_LOG_U64, MAX_CACHE_BUFFER_SIZE);
106 HlsInit();
107 }
108
HlsInit()109 void HlsMediaDownloader::HlsInit()
110 {
111 downloader_ = std::make_shared<Downloader>("hlsMedia");
112 playList_ = std::make_shared<BlockingQueue<PlayInfo>>("PlayList");
113 dataSave_ = [this] (uint8_t*&& data, uint32_t&& len) {
114 return SaveData(std::forward<decltype(data)>(data), std::forward<decltype(len)>(len));
115 };
116 playlistDownloader_ = std::make_shared<HlsPlayListDownloader>(httpHeader_);
117 playlistDownloader_->SetPlayListCallback(this);
118 writeBitrateCaculator_ = std::make_shared<WriteBitrateCaculator>();
119 waterLineAbove_ = PLAY_WATER_LINE;
120 steadyClock_.Reset();
121 aesKey_.rounds = 0;
122 for (size_t i = 0; i < sizeof(aesKey_.rd_key) / sizeof(aesKey_.rd_key[0]); ++i) {
123 aesKey_.rd_key[i] = 0;
124 }
125 }
126
~HlsMediaDownloader()127 HlsMediaDownloader::~HlsMediaDownloader()
128 {
129 MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~HlsMediaDownloader dtor in", FAKE_POINTER(this));
130 if (playlistDownloader_ != nullptr) {
131 playlistDownloader_ = nullptr;
132 }
133 if (downloader_ != nullptr) {
134 downloader_->Stop(false);
135 }
136 MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~HlsMediaDownloader dtor out", FAKE_POINTER(this));
137 }
138
SpliceOffset(uint32_t tsIndex,uint32_t offset32)139 size_t SpliceOffset(uint32_t tsIndex, uint32_t offset32)
140 {
141 uint64_t offset64 = 0;
142 offset64 = tsIndex;
143 offset64 = (offset64 << 32); // 32
144 offset64 |= offset32;
145 return static_cast<size_t>(offset64);
146 }
147
PutRequestIntoDownloader(const PlayInfo & playInfo)148 void HlsMediaDownloader::PutRequestIntoDownloader(const PlayInfo& playInfo)
149 {
150 if (fragmentDownloadStart[playInfo.url_]) {
151 writeTsIndex_ > 0 ? writeTsIndex_-- : 0;
152 return;
153 }
154 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
155 std::shared_ptr<DownloadRequest>& request) {
156 statusCallback_(status, downloader_, std::forward<decltype(request)>(request));
157 };
158 auto downloadDoneCallback = [this] (const std::string &url, const std::string& location) {
159 UpdateDownloadFinished(url, location);
160 };
161
162 RequestInfo requestInfo;
163 requestInfo.url = playInfo.url_;
164 requestInfo.httpHeader = httpHeader_;
165 // TO DO: If the fragment file is too large, should not requestWholeFile.
166 downloadRequest_ = std::make_shared<DownloadRequest>(playInfo.duration_, dataSave_,
167 realStatusCallback, requestInfo, true);
168 // push request to back queue for seek
169 fragmentDownloadStart[playInfo.url_] = true;
170 int64_t startTimePos = playInfo.startTimePos_;
171 curUrl_ = playInfo.url_;
172 if (writeTsIndex_ == 0) {
173 readOffset_ = SpliceOffset(writeTsIndex_, 0);
174 MEDIA_LOG_I("readOffset, PutRequestIntoDownloader init readOffset." PUBLIC_LOG_U64, readOffset_);
175 readTsIndex_ = writeTsIndex_;
176 uint32_t readTsIndexTempValue = readTsIndex_.load();
177 MEDIA_LOG_I("readTsIndex_, PutRequestIntoDownloader init readTsIndex_." PUBLIC_LOG_U32, readTsIndexTempValue);
178 }
179 writeOffset_ = SpliceOffset(writeTsIndex_, 0);
180 MEDIA_LOG_I("writeOffset_, PutRequestIntoDwonloader update writeOffset_." PUBLIC_LOG_U64, writeOffset_);
181
182 {
183 AutoLock lock(tsStorageInfoMutex_);
184 if (tsStorageInfo_.count(writeTsIndex_) <= 0) {
185 tsStorageInfo_[writeTsIndex_] = std::make_pair(0, false);
186 }
187 }
188
189 downloadRequest_->SetIsM3u8Request(true);
190 downloadRequest_->SetDownloadDoneCb(downloadDoneCallback);
191 downloadRequest_->SetStartTimePos(startTimePos);
192 downloader_->Download(downloadRequest_, -1); // -1
193 downloader_->Start();
194 }
195
SaveHttpHeader(const std::map<std::string,std::string> & httpHeader)196 void HlsMediaDownloader::SaveHttpHeader(const std::map<std::string, std::string>& httpHeader)
197 {
198 httpHeader_ = httpHeader;
199 }
200
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)201 bool HlsMediaDownloader::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
202 {
203 isDownloadFinish_ = false;
204 SaveHttpHeader(httpHeader);
205 writeBitrateCaculator_->StartClock();
206 playlistDownloader_->SetMimeType(mimeType_);
207 playlistDownloader_->Open(url, httpHeader);
208 steadyClock_.Reset();
209 openTime_ = steadyClock_.ElapsedMilliseconds();
210 if (userDefinedBufferDuration_) {
211 MEDIA_LOG_I("User seeting buffer duration playlistDownloader_ opened.");
212 totalBufferSize_ = expectDuration_ * CURRENT_BIT_RATE;
213 if (totalBufferSize_ < MIN_BUFFER_SIZE) {
214 MEDIA_LOG_I("Failed setting buffer size: " PUBLIC_LOG_ZU ". already lower than the min buffer size: "
215 PUBLIC_LOG_ZU ", setting buffer size: " PUBLIC_LOG_ZU ". ",
216 totalBufferSize_, MIN_BUFFER_SIZE, MIN_BUFFER_SIZE);
217 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
218 cacheMediaBuffer_->Init(MIN_BUFFER_SIZE, CHUNK_SIZE);
219 totalBufferSize_ = MIN_BUFFER_SIZE;
220 } else if (totalBufferSize_ > MAX_CACHE_BUFFER_SIZE) {
221 MEDIA_LOG_I("Failed setting buffer size: " PUBLIC_LOG_ZU ". already exceed the max buffer size: "
222 PUBLIC_LOG_U64 ", setting buffer size: " PUBLIC_LOG_U64 ". ",
223 totalBufferSize_, MAX_CACHE_BUFFER_SIZE, MAX_CACHE_BUFFER_SIZE);
224 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
225 cacheMediaBuffer_->Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE);
226 totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
227 } else {
228 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
229 cacheMediaBuffer_->Init(totalBufferSize_, CHUNK_SIZE);
230 MEDIA_LOG_I("HLS Success setted buffer size: " PUBLIC_LOG_ZU ". ", totalBufferSize_);
231 }
232 }
233 return true;
234 }
235
Close(bool isAsync)236 void HlsMediaDownloader::Close(bool isAsync)
237 {
238 MEDIA_LOG_I("0x%{public}06" PRIXPTR " HLS Close enter", FAKE_POINTER(this));
239 isInterrupt_ = true;
240 if (playList_) {
241 playList_->SetActive(false);
242 }
243 if (playlistDownloader_) {
244 playlistDownloader_->Close();
245 }
246 if (downloader_) {
247 downloader_->Stop(isAsync);
248 }
249 isStopped = true;
250 if (!isDownloadFinish_) {
251 MEDIA_LOG_D("HLS Download close, average download speed: " PUBLIC_LOG_D32 " bit/s", avgDownloadSpeed_);
252 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
253 auto downloadTime = nowTime - startDownloadTime_;
254 MEDIA_LOG_D("HLS Download close, Data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
255 totalBits_, downloadTime);
256 }
257 }
258
Pause()259 void HlsMediaDownloader::Pause()
260 {
261 MEDIA_LOG_I("HLS Pause enter");
262 playlistDownloader_->Pause();
263 }
264
Resume()265 void HlsMediaDownloader::Resume()
266 {
267 MEDIA_LOG_I("HLS Resume enter");
268 playlistDownloader_->Resume();
269 }
270
CheckReadStatus()271 bool HlsMediaDownloader::CheckReadStatus()
272 {
273 // eos:palylist is empty, request is finished, hls is vod, do not select bitrate
274 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
275 FALSE_RETURN_V(downloadRequest_ != nullptr, false);
276 bool isEos = playList_->Empty() && (downloadRequest_ != nullptr) &&
277 downloadRequest_->IsEos() && playlistDownloader_ != nullptr &&
278 (playlistDownloader_->GetDuration() > 0) &&
279 playlistDownloader_->IsParseAndNotifyFinished();
280 if (isEos) {
281 MEDIA_LOG_I("HLS download done.");
282 return true;
283 }
284 if (playlistDownloader_->GetDuration() > 0 && playlistDownloader_->IsParseAndNotifyFinished() &&
285 static_cast<int64_t>(seekTime_) >= playlistDownloader_->GetDuration()) {
286 MEDIA_LOG_I("HLS seek to tail.");
287 return true;
288 }
289 return false;
290 }
291
CheckBreakCondition()292 bool HlsMediaDownloader::CheckBreakCondition()
293 {
294 if (downloadErrorState_) {
295 MEDIA_LOG_I("HLS downloadErrorState break");
296 return true;
297 }
298 if (CheckReadStatus()) {
299 MEDIA_LOG_I("HLS download complete break");
300 return true;
301 }
302 return false;
303 }
304
HandleBuffering()305 bool HlsMediaDownloader::HandleBuffering()
306 {
307 if (!isBuffering_) {
308 return false;
309 }
310 if (isFirstFrameArrived_) {
311 UpdateWaterLineAbove();
312 UpdateCachedPercent(BufferingInfoType::BUFFERING_PERCENT);
313 }
314 {
315 AutoLock lk(bufferingEndMutex_);
316 if (!canWrite_) {
317 MEDIA_LOG_I("HLS canWrite false");
318 isBuffering_ = false;
319 }
320 {
321 AutoLock lock(tsStorageInfoMutex_);
322 if (tsStorageInfo_[readTsIndex_].second == true && backPlayList_.size() > 0 &&
323 readTsIndex_ >= backPlayList_.size() - 1) {
324 MEDIA_LOG_I("HLS readTS download complete.");
325 isBuffering_ = false;
326 }
327 }
328 if (GetCrossTsBuffersize() >= waterLineAbove_ || CheckBreakCondition() ||
329 tsStorageInfo_[readTsIndex_ + 1].second) {
330 MEDIA_LOG_I("HLS CheckBreakCondition true, waterLineAbove: " PUBLIC_LOG_ZU " bufferSize: " PUBLIC_LOG_ZU,
331 waterLineAbove_, GetBufferSize());
332 isBuffering_ = false;
333 }
334 if (!isBuffering_) {
335 MEDIA_LOG_I("HandleBuffering bufferingEndCond NotifyAll.");
336 bufferingEndCond_.NotifyAll();
337 }
338 }
339 if (!isBuffering_ && !isFirstFrameArrived_) {
340 bufferingTime_ = 0;
341 }
342 if (!isBuffering_ && isFirstFrameArrived_ && callback_ != nullptr) {
343 MEDIA_LOG_I("HLS CacheData onEvent BUFFERING_END, waterLineAbove: " PUBLIC_LOG_ZU " readOffset: "
344 PUBLIC_LOG_U64 " writeOffset: " PUBLIC_LOG_U64 " writeTsIndex: " PUBLIC_LOG_U32 " bufferSize: "
345 PUBLIC_LOG_ZU, waterLineAbove_, readOffset_, writeOffset_, writeTsIndex_, GetCrossTsBuffersize());
346 UpdateCachedPercent(BufferingInfoType::BUFFERING_END);
347 callback_->OnEvent({PluginEventType::BUFFERING_END, {BufferingInfoType::BUFFERING_END}, "end"});
348 bufferingTime_ = 0;
349 }
350 return isBuffering_.load();
351 }
352
HandleCache()353 bool HlsMediaDownloader::HandleCache()
354 {
355 size_t waterLine = 0;
356 if (isFirstFrameArrived_) {
357 waterLine = wantedReadLength_ > 0 ?
358 std::max(PLAY_WATER_LINE, static_cast<size_t>(wantedReadLength_)) : 0;
359 } else {
360 waterLine = wantedReadLength_;
361 waterLineAbove_ = waterLine;
362 }
363 bool isAboveLine = GetCrossTsBuffersize() >= waterLine;
364 bool isNextTsReady = true;
365 if (backPlayList_.size() > 0 && readTsIndex_ >= backPlayList_.size() - 1) {
366 isNextTsReady = tsStorageInfo_[readTsIndex_].second;
367 } else {
368 isNextTsReady = tsStorageInfo_[readTsIndex_ + 1].second;
369 }
370 if (isBuffering_ || callback_ == nullptr || !canWrite_ || isAboveLine || isNextTsReady) {
371 return false;
372 }
373 isBuffering_ = true;
374 bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
375 if (!isFirstFrameArrived_) {
376 return true;
377 }
378 callback_->OnEvent({PluginEventType::BUFFERING_START, {BufferingInfoType::BUFFERING_START}, "start"});
379 UpdateCachedPercent(BufferingInfoType::BUFFERING_START);
380 MEDIA_LOG_I("HLS CacheData onEvent BUFFERING_START, waterLineAbove: " PUBLIC_LOG_ZU " readOffset: "
381 PUBLIC_LOG_U64 " writeOffset: " PUBLIC_LOG_U64 " writeTsIndex: " PUBLIC_LOG_U32 " bufferSize: "
382 PUBLIC_LOG_ZU, waterLineAbove_, readOffset_, writeOffset_, writeTsIndex_, GetCrossTsBuffersize());
383 return true;
384 }
385
HandleFfmpegReadback(uint64_t ffmpegOffset)386 void HlsMediaDownloader::HandleFfmpegReadback(uint64_t ffmpegOffset)
387 {
388 if (ffmpegOffset_ <= ffmpegOffset) {
389 return;
390 }
391 MEDIA_LOG_I("Read back, ffmpegOffset: " PUBLIC_LOG_U64 " ffmpegOffset: " PUBLIC_LOG_U64,
392 ffmpegOffset_, ffmpegOffset);
393 uint64_t readBack = ffmpegOffset_ - ffmpegOffset;
394 uint64_t curTsHaveRead = readOffset_ > SpliceOffset(readTsIndex_, 0) ?
395 readOffset_ - SpliceOffset(readTsIndex_, 0) : 0;
396 AutoLock lock(tsStorageInfoMutex_);
397 if (curTsHaveRead >= readBack) {
398 readOffset_ -= readBack;
399 MEDIA_LOG_I("Read back, current ts, update readOffset: " PUBLIC_LOG_U64, readOffset_);
400 } else {
401 if (readTsIndex_ == 0) {
402 readOffset_ = 0; // Cross ts readback, but this is the first ts, so reset readOffset.
403 MEDIA_LOG_W("HLS Read back, this is the first ts: " PUBLIC_LOG_U64, readOffset_);
404 return;
405 }
406 if (tsStorageInfo_.count(readTsIndex_ - 1) <= 0) {
407 readOffset_ = readOffset_ > curTsHaveRead ? readOffset_ - curTsHaveRead : 0;
408 MEDIA_LOG_W("HLS Read back, last ts is not ready, update readOffset to readTsIndex head: "
409 PUBLIC_LOG_U64, readOffset_);
410 return;
411 }
412 readTsIndex_--;
413 uint64_t lastTsReadBack = readBack - curTsHaveRead;
414 uint32_t readTsIndexTempValue = readTsIndex_.load();
415 readOffset_ = SpliceOffset(readTsIndex_, tsStorageInfo_[readTsIndex_].first - lastTsReadBack);
416 MEDIA_LOG_I("HLS Read back, last ts, update readTsIndex: " PUBLIC_LOG_U32 " update readOffset: "
417 PUBLIC_LOG_U64, readTsIndexTempValue, readOffset_);
418 }
419 }
420
CheckDataIntegrity()421 bool HlsMediaDownloader::CheckDataIntegrity()
422 {
423 AutoLock lock(tsStorageInfoMutex_);
424 if (tsStorageInfo_[readTsIndex_].second == false) {
425 return readTsIndex_ == writeTsIndex_;
426 } else {
427 uint64_t head = SpliceOffset(readTsIndex_, 0);
428 uint64_t hasRead = readOffset_ > head ? readOffset_ - head : 0;
429 size_t bufferSize = tsStorageInfo_[readTsIndex_].first > hasRead ?
430 tsStorageInfo_[readTsIndex_].first - hasRead : 0;
431 return bufferSize == GetBufferSize();
432 }
433 }
434
CheckPlaylist(unsigned char * buff,ReadDataInfo & readDataInfo)435 Status HlsMediaDownloader::CheckPlaylist(unsigned char* buff, ReadDataInfo& readDataInfo)
436 {
437 bool isFinishedPlay = CheckReadStatus() || isStopped;
438 if (downloadRequest_ != nullptr) {
439 readDataInfo.isEos_ = downloadRequest_->IsEos();
440 }
441 if (isFinishedPlay && readTsIndex_ < backPlayList_.size() - 1) {
442 return Status::ERROR_UNKNOWN;
443 }
444 if (isFinishedPlay && GetBufferSize() > 0) {
445 size_t readLen = std::min(GetBufferSize(), static_cast<size_t>(readDataInfo.wantReadLength_));
446 readDataInfo.realReadLength_ = cacheMediaBuffer_->Read(buff, readOffset_, readLen);
447 readOffset_ += readDataInfo.realReadLength_;
448 ffmpegOffset_ = readDataInfo.ffmpegOffset + readDataInfo.realReadLength_;
449 canWrite_ = true;
450 OnReadBuffer(readDataInfo.realReadLength_);
451 uint32_t readTsIndexTempValue = readTsIndex_.load();
452 MEDIA_LOG_D("HLS Read Success: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
453 PUBLIC_LOG_D32 " readOffset_ " PUBLIC_LOG_U64 " readTsIndex_ " PUBLIC_LOG_U32, readDataInfo.wantReadLength_,
454 readDataInfo.realReadLength_, readDataInfo.isEos_, readOffset_, readTsIndexTempValue);
455 return Status::OK;
456 }
457 if (isFinishedPlay && GetBufferSize() == 0 && GetSeekable() == Seekable::SEEKABLE &&
458 tsStorageInfo_[writeTsIndex_].second == true) {
459 readDataInfo.realReadLength_ = 0;
460 MEDIA_LOG_I("Hls: CheckPlaylist, eos.");
461 return Status::END_OF_STREAM;
462 }
463 return Status::ERROR_UNKNOWN;
464 }
465
ReadDelegate(unsigned char * buff,ReadDataInfo & readDataInfo)466 Status HlsMediaDownloader::ReadDelegate(unsigned char* buff, ReadDataInfo& readDataInfo)
467 {
468 FALSE_RETURN_V_MSG(cacheMediaBuffer_ != nullptr, Status::END_OF_STREAM, "eos, cacheMediaBuffer_ is nullptr");
469 FALSE_RETURN_V_MSG(!isInterruptNeeded_.load(), Status::END_OF_STREAM, "eos, isInterruptNeeded");
470 MediaAVCodec::AVCodecTrace trace("HlsMediaDownloader::ReadDelegate, expectedLen: " +
471 std::to_string(readDataInfo.wantReadLength_) + ", bufferSize: " + std::to_string(GetBufferSize()));
472 MEDIA_LOG_D("HLS Read in: wantReadLength " PUBLIC_LOG_D32 " readOffset_ " PUBLIC_LOG_U64 " readTsIndex_ "
473 PUBLIC_LOG_U32 " bufferSize: " PUBLIC_LOG_ZU, readDataInfo.wantReadLength_, readOffset_,
474 readTsIndex_.load(), GetBufferSize());
475
476 readDataInfo.isEos_ = CheckReadStatus();
477 if (readDataInfo.isEos_ && GetBufferSize() == 0 && readTsIndex_ == backPlayList_.size() - 1
478 && tsStorageInfo_[readTsIndex_].second == true) {
479 readDataInfo.realReadLength_ = 0;
480 MEDIA_LOG_I("HLS buffer is empty, eos.");
481 return Status::END_OF_STREAM;
482 }
483 if (isBuffering_ && GetBufferingTimeOut() && callback_) {
484 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
485 return Status::END_OF_STREAM;
486 }
487 if (isBuffering_ && CheckBufferingOneSeconds()) {
488 MEDIA_LOG_I("HLS read return error again.");
489 return Status::ERROR_AGAIN;
490 }
491 wantedReadLength_ = static_cast<size_t>(readDataInfo.wantReadLength_);
492 if (!CheckBreakCondition() && HandleCache()) {
493 return Status::ERROR_AGAIN;
494 }
495 Status tmpRes = CheckPlaylist(buff, readDataInfo);
496 if (tmpRes != Status::ERROR_UNKNOWN) {
497 return tmpRes;
498 }
499 FALSE_RETURN_V_MSG(readDataInfo.wantReadLength_ > 0, Status::END_OF_STREAM, "eos, wantReadLength_ <= 0");
500 ReadCacheBuffer(buff, readDataInfo);
501 MEDIA_LOG_D("HLS Read success: wantReadLength " PUBLIC_LOG_D32 " realReadLen: " PUBLIC_LOG_D32 " readOffset_ "
502 PUBLIC_LOG_U64 " readTsIndex_ " PUBLIC_LOG_U32 " bufferSize: " PUBLIC_LOG_ZU, readDataInfo.wantReadLength_,
503 readDataInfo.realReadLength_, readOffset_, readTsIndex_.load(), GetBufferSize());
504 OnReadBuffer(readDataInfo.realReadLength_);
505 return Status::OK;
506 }
507
ReadCacheBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)508 void HlsMediaDownloader::ReadCacheBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
509 {
510 readDataInfo.realReadLength_ = cacheMediaBuffer_->Read(buff, readOffset_, readDataInfo.wantReadLength_);
511 readOffset_ += readDataInfo.realReadLength_;
512 ffmpegOffset_ = readDataInfo.ffmpegOffset + readDataInfo.realReadLength_;
513 if (tsStorageInfo_[readTsIndex_].second == true) {
514 size_t tsEndOffset = SpliceOffset(readTsIndex_, tsStorageInfo_[readTsIndex_].first);
515 if (readOffset_ >= tsEndOffset) {
516 cacheMediaBuffer_->ClearFragmentBeforeOffset(SpliceOffset(readTsIndex_, 0));
517 readTsIndex_++;
518 readOffset_ = SpliceOffset(readTsIndex_, 0);
519 }
520 if (readDataInfo.realReadLength_ < readDataInfo.wantReadLength_ && readTsIndex_ != backPlayList_.size()) {
521 uint32_t crossFragLen = readDataInfo.wantReadLength_ - readDataInfo.realReadLength_;
522 uint32_t crossReadLen = cacheMediaBuffer_->Read(buff + readDataInfo.realReadLength_, readOffset_,
523 crossFragLen);
524 readDataInfo.realReadLength_ = readDataInfo.realReadLength_ + crossReadLen;
525 ffmpegOffset_ += crossReadLen;
526 readOffset_ += crossReadLen;
527 }
528 }
529 canWrite_ = true;
530 }
531
Read(unsigned char * buff,ReadDataInfo & readDataInfo)532 Status HlsMediaDownloader::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
533 {
534 uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
535
536 if (!CheckDataIntegrity()) {
537 MEDIA_LOG_W("Read in, fix download.");
538 SeekToTsForRead(readTsIndex_);
539 return Status::ERROR_AGAIN;
540 }
541
542 HandleFfmpegReadback(readDataInfo.ffmpegOffset);
543
544 auto ret = ReadDelegate(buff, readDataInfo);
545 readTotalBytes_ += readDataInfo.realReadLength_;
546 if (now > lastReadCheckTime_ && now - lastReadCheckTime_ > SAMPLE_INTERVAL) {
547 readRecordDuringTime_ = now - lastReadCheckTime_;
548 double readDuration = static_cast<double>(readRecordDuringTime_) / SECOND_TO_MILLIONSECOND;
549 if (readDuration > ZERO_THRESHOLD) {
550 double readSpeed = readTotalBytes_ * BYTES_TO_BIT / readDuration; // bps
551 currentBitrate_ = static_cast<uint64_t>(readSpeed); // bps
552 MEDIA_LOG_D("Current read speed: " PUBLIC_LOG_D32 " Kbit/s,Current buffer size: " PUBLIC_LOG_U64
553 " KByte", static_cast<int32_t>(readSpeed / KILO), static_cast<uint64_t>(GetBufferSize() / KILO));
554 MediaAVCodec::AVCodecTrace trace("HlsMediaDownloader::Read, read speed: " +
555 std::to_string(readSpeed) + " bit/s, bufferSize: " + std::to_string(GetBufferSize()) + " Byte");
556 readTotalBytes_ = 0;
557 }
558 lastReadCheckTime_ = now;
559 readRecordDuringTime_ = 0;
560 }
561 return ret;
562 }
563
PrepareToSeek()564 void HlsMediaDownloader::PrepareToSeek()
565 {
566 int32_t retry {0};
567 do {
568 retry++;
569 if (retry >= SEEK_STATUS_RETRY_TIMES) { // 100 means retry times
570 MEDIA_LOG_I("HLS Seek may be failed");
571 break;
572 }
573 OSAL::SleepFor(SEEK_STATUS_SLEEP_TIME); // 50 means sleep time pre retry
574 } while (!playlistDownloader_->IsParseAndNotifyFinished());
575
576 downloader_->Cancel();
577 cacheMediaBuffer_.reset();
578 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
579 cacheMediaBuffer_->Init(totalBufferSize_, CHUNK_SIZE);
580
581 AutoLock lock(tsStorageInfoMutex_);
582 tsStorageInfo_.clear();
583
584 memset_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, 0x00, DECRYPT_UNIT_LEN);
585 memset_s(decryptCache_, MIN_BUFFER_SIZE, 0x00, MIN_BUFFER_SIZE);
586 memset_s(decryptBuffer_, MIN_BUFFER_SIZE, 0x00, MIN_BUFFER_SIZE);
587 afterAlignRemainedLength_ = 0;
588 isLastDecryptWriteError_ = false;
589 }
590
SeekToTime(int64_t seekTime,SeekMode mode)591 bool HlsMediaDownloader::SeekToTime(int64_t seekTime, SeekMode mode)
592 {
593 MEDIA_LOG_I("HLS Seek: buffer size " PUBLIC_LOG_ZU ", seekTime " PUBLIC_LOG_D64, GetBufferSize(), seekTime);
594 AutoLock lock(switchMutex_);
595 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
596 FALSE_RETURN_V(cacheMediaBuffer_ != nullptr, false);
597 isSeekingFlag = true;
598 seekTime_ = static_cast<uint64_t>(seekTime);
599 bufferingTime_ = 0;
600 PrepareToSeek();
601 if (seekTime_ < static_cast<uint64_t>(playlistDownloader_->GetDuration())) {
602 SeekToTs(seekTime, mode);
603 } else {
604 readTsIndex_ = backPlayList_.size() > 0 ? backPlayList_.size() - 1 : 0; // 0
605 tsStorageInfo_[readTsIndex_].second = true;
606 }
607 MEDIA_LOG_I("HLS SeekToTime end\n");
608 isSeekingFlag = false;
609 return true;
610 }
611
GetContentLength() const612 size_t HlsMediaDownloader::GetContentLength() const
613 {
614 return 0;
615 }
616
GetDuration() const617 int64_t HlsMediaDownloader::GetDuration() const
618 {
619 FALSE_RETURN_V(playlistDownloader_ != nullptr, 0);
620 MEDIA_LOG_I("GetDuration " PUBLIC_LOG_D64, playlistDownloader_->GetDuration());
621 return playlistDownloader_->GetDuration();
622 }
623
GetSeekable() const624 Seekable HlsMediaDownloader::GetSeekable() const
625 {
626 FALSE_RETURN_V(playlistDownloader_ != nullptr, Seekable::INVALID);
627 return playlistDownloader_->GetSeekable();
628 }
629
SetCallback(Callback * cb)630 void HlsMediaDownloader::SetCallback(Callback* cb)
631 {
632 FALSE_RETURN(playlistDownloader_ != nullptr);
633 callback_ = cb;
634 playlistDownloader_->SetCallback(cb);
635 }
636
ResetPlaylistCapacity(size_t size)637 void HlsMediaDownloader::ResetPlaylistCapacity(size_t size)
638 {
639 size_t remainCapacity = playList_->Capacity() - playList_->Size();
640 if (remainCapacity >= size) {
641 return;
642 }
643 size_t newCapacity = playList_->Size() + size;
644 playList_->ResetCapacity(newCapacity);
645 }
646
PlaylistBackup(const PlayInfo & fragment)647 void HlsMediaDownloader::PlaylistBackup(const PlayInfo& fragment)
648 {
649 FALSE_RETURN(playlistDownloader_ != nullptr);
650 if (playlistDownloader_->IsParseFinished() && (GetSeekable() == Seekable::UNSEEKABLE)) {
651 if (backPlayList_.size() > 0) {
652 backPlayList_.clear();
653 }
654 return;
655 }
656 if (playlistDownloader_->IsParseFinished()) {
657 backPlayList_.push_back(fragment);
658 }
659 }
660
OnPlayListChanged(const std::vector<PlayInfo> & playList)661 void HlsMediaDownloader::OnPlayListChanged(const std::vector<PlayInfo>& playList)
662 {
663 ResetPlaylistCapacity(static_cast<size_t>(playList.size()));
664 for (uint32_t i = 0; i < static_cast<uint32_t>(playList.size()); i++) {
665 auto fragment = playList[i];
666 PlaylistBackup(fragment);
667 if (isSelectingBitrate_ && (GetSeekable() == Seekable::SEEKABLE)) {
668 if (writeTsIndex_ == i) {
669 MEDIA_LOG_I("HLS Switch bitrate");
670 isSelectingBitrate_ = false;
671 fragmentDownloadStart[fragment.url_] = true;
672 } else {
673 fragmentDownloadStart[fragment.url_] = true;
674 continue;
675 }
676 }
677 if (!fragmentDownloadStart[fragment.url_] && !fragmentPushed[fragment.url_]) {
678 playList_->Push(fragment);
679 fragmentPushed[fragment.url_] = true;
680 }
681 }
682 if (!isDownloadStarted_ && !playList_->Empty()) {
683 auto playInfo = playList_->Pop();
684 std::string url = playInfo.url_;
685 isDownloadStarted_ = true;
686 writeTsIndex_ > 0 ? writeTsIndex_++ : 0;
687 PutRequestIntoDownloader(playInfo);
688 }
689 }
690
GetStartedStatus()691 bool HlsMediaDownloader::GetStartedStatus()
692 {
693 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
694 return playlistDownloader_->GetPlayListDownloadStatus() && startedPlayStatus_;
695 }
696
SaveCacheBufferData(uint8_t * data,uint32_t len)697 bool HlsMediaDownloader::SaveCacheBufferData(uint8_t* data, uint32_t len)
698 {
699 size_t hasWriteSize = 0;
700 while (hasWriteSize < len && !isInterruptNeeded_.load() && !isInterrupt_) {
701 size_t res = cacheMediaBuffer_->Write(data + hasWriteSize, writeOffset_, len - hasWriteSize);
702 writeOffset_ += res;
703 hasWriteSize += res;
704 {
705 AutoLock lock(tsStorageInfoMutex_);
706 tsStorageInfo_[writeTsIndex_].first += res;
707 }
708 writeBitrateCaculator_->UpdateWriteBytes(res);
709 MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCE, "writeOffset " PUBLIC_LOG_U64 " res "
710 PUBLIC_LOG_ZU, writeOffset_, res);
711 ClearChunksOfFragment();
712 if (res > 0 || hasWriteSize == len) {
713 HandleCachedDuration();
714 writeBitrateCaculator_->StartClock();
715 uint64_t writeTime = writeBitrateCaculator_->GetWriteTime() / SECOND_TO_MILLIONSECOND;
716 if (writeTime > ONE_SECONDS) {
717 writeBitrateCaculator_->ResetClock();
718 }
719 continue;
720 }
721 writeBitrateCaculator_->StopClock();
722 cacheMediaBuffer_->Dump(0);
723 MEDIA_LOG_W("CacheMediaBuffer full.");
724 canWrite_ = false;
725 HandleBuffering();
726 while (!isInterrupt_ && !canWrite_.load() && !isInterruptNeeded_.load()) {
727 MEDIA_LOG_I("CacheMediaBuffer full, waiting seek or read");
728 if (isSeekingFlag.load()) {
729 MEDIA_LOG_I("HLS CacheMediaBuffer full, isSeeking, return true.");
730 return true;
731 }
732 OSAL::SleepFor(SLEEP_TIME_100);
733 }
734 canWrite_ = true;
735 }
736 if (isInterruptNeeded_.load() || isInterrupt_) {
737 MEDIA_LOG_I("HLS isInterruptNeeded true, return false.");
738 return false;
739 }
740 auto ret = hasWriteSize > 0 && (hasWriteSize == len);
741 return ret;
742 }
743
SaveData(uint8_t * data,uint32_t len)744 bool HlsMediaDownloader::SaveData(uint8_t* data, uint32_t len)
745 {
746 OnWriteCacheBuffer(len);
747 if (isSeekingFlag.load()) {
748 return true;
749 }
750 startedPlayStatus_ = true;
751 bool res = true;
752 if (keyLen_ == 0) {
753 res = SaveCacheBufferData(data, len);
754 } else {
755 res = SaveEncryptData(data, len);
756 }
757 HandleBuffering();
758
759 uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
760 MEDIA_LOG_D("HLS free size: " PUBLIC_LOG_U64, freeSize);
761 return res;
762 }
763
GetDecrptyRealLen(uint8_t * writeDataPoint,uint32_t waitLen,uint32_t writeLen)764 uint32_t HlsMediaDownloader::GetDecrptyRealLen(uint8_t* writeDataPoint, uint32_t waitLen, uint32_t writeLen)
765 {
766 uint32_t realLen;
767 errno_t err {0};
768 if (afterAlignRemainedLength_ > 0) {
769 err = memcpy_s(decryptBuffer_, afterAlignRemainedLength_,
770 afterAlignRemainedBuffer_, afterAlignRemainedLength_);
771 if (err != 0) {
772 MEDIA_LOG_D("afterAlignRemainedLength_: " PUBLIC_LOG_D64, afterAlignRemainedLength_);
773 }
774 }
775 uint32_t minWriteLen = (MIN_BUFFER_SIZE - afterAlignRemainedLength_) > writeLen ?
776 writeLen : MIN_BUFFER_SIZE - afterAlignRemainedLength_;
777 err = memcpy_s(decryptBuffer_ + afterAlignRemainedLength_,
778 minWriteLen, writeDataPoint, minWriteLen);
779 if (err != 0) {
780 MEDIA_LOG_D("minWriteLen: " PUBLIC_LOG_D32, minWriteLen);
781 }
782 realLen = minWriteLen + afterAlignRemainedLength_;
783 AES_cbc_encrypt(decryptBuffer_, decryptCache_, realLen, &aesKey_, iv_, AES_DECRYPT);
784 return realLen;
785 }
786
SaveEncryptData(uint8_t * data,uint32_t len)787 bool HlsMediaDownloader::SaveEncryptData(uint8_t* data, uint32_t len)
788 {
789 uint32_t writeLen = 0;
790 uint8_t *writeDataPoint = data;
791 uint32_t waitLen = len;
792 errno_t err {0};
793 uint32_t realLen;
794 if ((waitLen + afterAlignRemainedLength_) < DECRYPT_UNIT_LEN) {
795 err = memcpy_s(afterAlignRemainedBuffer_ + afterAlignRemainedLength_,
796 DECRYPT_UNIT_LEN - afterAlignRemainedLength_,
797 writeDataPoint, waitLen);
798 if (err != 0) {
799 MEDIA_LOG_D("afterAlignRemainedLength_: " PUBLIC_LOG_D64,
800 DECRYPT_UNIT_LEN - afterAlignRemainedLength_);
801 }
802 afterAlignRemainedLength_ += waitLen;
803 return true;
804 }
805 writeLen = ((waitLen + afterAlignRemainedLength_) / DECRYPT_UNIT_LEN) *
806 DECRYPT_UNIT_LEN - afterAlignRemainedLength_;
807 realLen = GetDecrptyRealLen(writeDataPoint, waitLen, writeLen);
808 totalLen_ += realLen;
809
810 bool isWriteSuccess = SaveCacheBufferData(decryptCache_, realLen);
811
812 err = memset_s(decryptCache_, realLen, 0x00, realLen);
813 if (err != 0) {
814 MEDIA_LOG_D("realLen: " PUBLIC_LOG_D32, realLen);
815 }
816 if (isWriteSuccess) {
817 afterAlignRemainedLength_ = 0;
818 err = memset_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, 0x00, DECRYPT_UNIT_LEN);
819 if (err != 0) {
820 MEDIA_LOG_D("DECRYPT_UNIT_LEN: " PUBLIC_LOG_D64, DECRYPT_UNIT_LEN);
821 }
822 }
823 writeDataPoint += writeLen;
824 waitLen -= writeLen;
825 if (waitLen > 0 && isWriteSuccess) {
826 afterAlignRemainedLength_ = waitLen;
827 err = memcpy_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, writeDataPoint, waitLen);
828 if (err != 0) {
829 MEDIA_LOG_D("waitLen: " PUBLIC_LOG_D32, waitLen);
830 }
831 }
832 return isWriteSuccess;
833 }
834
DownloadRecordHistory(int64_t nowTime)835 void HlsMediaDownloader::DownloadRecordHistory(int64_t nowTime)
836 {
837 if ((static_cast<uint64_t>(nowTime) - lastWriteTime_) >= SAMPLE_INTERVAL) {
838 MEDIA_LOG_I("HLS OnWriteRingBuffer nowTime: " PUBLIC_LOG_D64
839 " lastWriteTime:" PUBLIC_LOG_D64 ".\n", nowTime, lastWriteTime_);
840 BufferDownRecord* record = new BufferDownRecord();
841 record->dataBits = lastWriteBit_;
842 record->timeoff = static_cast<uint64_t>(nowTime) - lastWriteTime_;
843 record->next = bufferDownRecord_;
844 bufferDownRecord_ = record;
845 lastWriteBit_ = 0;
846 lastWriteTime_ = static_cast<uint64_t>(nowTime);
847 BufferDownRecord* tmpRecord = bufferDownRecord_;
848 for (int i = 0; i < MAX_RECORD_COUNT; i++) {
849 if (tmpRecord->next) {
850 tmpRecord = tmpRecord->next;
851 } else {
852 break;
853 }
854 }
855 BufferDownRecord* next = tmpRecord->next;
856 tmpRecord->next = nullptr;
857 tmpRecord = next;
858 while (tmpRecord) {
859 next = tmpRecord->next;
860 delete tmpRecord;
861 tmpRecord = next;
862 }
863 if (autoBufferSize_ && !userDefinedBufferDuration_) {
864 if (CheckRiseBufferSize()) {
865 RiseBufferSize();
866 } else if (CheckPulldownBufferSize()) {
867 DownBufferSize();
868 }
869 }
870 }
871 }
872
OnWriteCacheBuffer(uint32_t len)873 void HlsMediaDownloader::OnWriteCacheBuffer(uint32_t len)
874 {
875 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
876 if (startDownloadTime_ == 0) {
877 startDownloadTime_ = nowTime;
878 lastReportUsageTime_ = nowTime;
879 }
880 uint32_t writeBits = len * BYTES_TO_BIT; // bit
881 bufferedDuration_ += writeBits;
882 totalBits_ += writeBits;
883 lastWriteBit_ += writeBits;
884 dataUsage_ += writeBits;
885 if ((totalBits_ > START_PLAY_WATER_LINE) && (playDelayTime_ == 0)) {
886 auto startPlayTime = steadyClock_.ElapsedMilliseconds();
887 playDelayTime_ = startPlayTime - openTime_;
888 MEDIA_LOG_D("Start play delay time: " PUBLIC_LOG_D64, playDelayTime_);
889 }
890 DownloadRecordHistory(nowTime);
891 DownloadReport();
892 }
893
CalculateCurrentDownloadSpeed()894 double HlsMediaDownloader::CalculateCurrentDownloadSpeed()
895 {
896 double downloadRate = 0;
897 double tmpNumerator = static_cast<double>(downloadBits_);
898 double tmpDenominator = static_cast<double>(downloadDuringTime_) / SECOND_TO_MILLIONSECOND;
899 if (tmpDenominator > ZERO_THRESHOLD) {
900 downloadRate = tmpNumerator / tmpDenominator;
901 avgDownloadSpeed_ = downloadRate;
902 downloadDuringTime_ = 0;
903 downloadBits_ = 0;
904 }
905
906 return downloadRate;
907 }
908
DownloadReport()909 void HlsMediaDownloader::DownloadReport()
910 {
911 uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
912 if (now > lastCheckTime_ && now - lastCheckTime_ > SAMPLE_INTERVAL) {
913 uint64_t curDownloadBits = totalBits_ - lastBits_;
914 if (curDownloadBits >= IS_DOWNLOAD_MIN_BIT) {
915 downloadDuringTime_ = now - lastCheckTime_;
916 downloadBits_ = curDownloadBits;
917 totalDownloadDuringTime_ += downloadDuringTime_;
918
919 std::shared_ptr<RecordData> recordBuff = std::make_shared<RecordData>();
920 double downloadRate = CalculateCurrentDownloadSpeed();
921 recordBuff->downloadRate = downloadRate;
922 size_t remainingBuffer = GetBufferSize();
923 MEDIA_LOG_D("Current download speed : " PUBLIC_LOG_D32 " Kbit/s,Current buffer size : " PUBLIC_LOG_U64
924 " KByte", static_cast<int32_t>(downloadRate / KILO), static_cast<uint64_t>(remainingBuffer / KILO));
925 MediaAVCodec::AVCodecTrace trace("HlsMediaDownloader::DownloadReport, download speed: " +
926 std::to_string(downloadRate) + " bit/s, bufferSize: " + std::to_string(remainingBuffer) + " Byte");
927 // Remaining playable time: s
928 uint64_t bufferDuration = 0;
929 if (currentBitrate_ > 0) {
930 bufferDuration = bufferedDuration_ / currentBitrate_;
931 } else {
932 bufferDuration = bufferedDuration_ / CURRENT_BIT_RATE;
933 }
934 recordBuff->bufferDuring = bufferDuration;
935 recordBuff->next = recordData_;
936 recordData_ = recordBuff;
937 recordCount_++;
938 }
939 // Total amount of downloaded data
940 lastBits_ = totalBits_;
941 lastCheckTime_ = now;
942 }
943 if (!isDownloadFinish_ && (static_cast<int64_t>(now) - lastReportUsageTime_) > DATA_USAGE_NTERVAL) {
944 MEDIA_LOG_D("Data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D32 "ms", dataUsage_, DATA_USAGE_NTERVAL);
945 dataUsage_ = 0;
946 lastReportUsageTime_ = static_cast<int64_t>(now);
947 }
948 }
949
OnSourceKeyChange(const uint8_t * key,size_t keyLen,const uint8_t * iv)950 void HlsMediaDownloader::OnSourceKeyChange(const uint8_t *key, size_t keyLen, const uint8_t *iv)
951 {
952 keyLen_ = keyLen;
953 if (keyLen == 0) {
954 return;
955 }
956 NZERO_LOG(memcpy_s(iv_, DECRYPT_UNIT_LEN, iv, DECRYPT_UNIT_LEN));
957 NZERO_LOG(memcpy_s(key_, DECRYPT_UNIT_LEN, key, keyLen));
958 AES_set_decrypt_key(key_, DECRYPT_COPY_LEN, &aesKey_);
959 }
960
OnDrmInfoChanged(const std::multimap<std::string,std::vector<uint8_t>> & drmInfos)961 void HlsMediaDownloader::OnDrmInfoChanged(const std::multimap<std::string, std::vector<uint8_t>>& drmInfos)
962 {
963 if (callback_ != nullptr) {
964 callback_->OnEvent({PluginEventType::SOURCE_DRM_INFO_UPDATE, {drmInfos}, "drm_info_update"});
965 }
966 }
967
SetStatusCallback(StatusCallbackFunc cb)968 void HlsMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
969 {
970 FALSE_RETURN(playlistDownloader_ != nullptr);
971 statusCallback_ = cb;
972 playlistDownloader_->SetStatusCallback(cb);
973 }
974
GetBitRates()975 std::vector<uint32_t> HlsMediaDownloader::GetBitRates()
976 {
977 FALSE_RETURN_V(playlistDownloader_ != nullptr, std::vector<uint32_t>());
978 return playlistDownloader_->GetBitRates();
979 }
980
SelectBitRate(uint32_t bitRate)981 bool HlsMediaDownloader::SelectBitRate(uint32_t bitRate)
982 {
983 AutoLock lock(switchMutex_);
984 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
985 FALSE_RETURN_V(playList_ != nullptr, false);
986 if (playlistDownloader_->IsBitrateSame(bitRate)) {
987 return true;
988 }
989 // report change bitrate start
990 ReportBitrateStart(bitRate);
991
992 playlistDownloader_->Cancel();
993
994 // clear request queue
995 playList_->SetActive(false, true);
996 playList_->SetActive(true);
997 fragmentDownloadStart.clear();
998 fragmentPushed.clear();
999 backPlayList_.clear();
1000
1001 // switch to des bitrate
1002 playlistDownloader_->SelectBitRate(bitRate);
1003 playlistDownloader_->Start();
1004 isSelectingBitrate_ = true;
1005 playlistDownloader_->UpdateManifest();
1006 return true;
1007 }
1008
SeekToTs(uint64_t seekTime,SeekMode mode)1009 void HlsMediaDownloader::SeekToTs(uint64_t seekTime, SeekMode mode)
1010 {
1011 MEDIA_LOG_I("SeekToTs: in.");
1012 writeTsIndex_ = 0;
1013 double totalDuration = 0;
1014 isDownloadStarted_ = false;
1015 playList_->Clear();
1016 for (const auto &item : backPlayList_) {
1017 double hstTime = item.duration_ * HST_SECOND;
1018 totalDuration += hstTime / HST_NSECOND;
1019 if (seekTime >= static_cast<uint64_t>(totalDuration)) {
1020 writeTsIndex_++;
1021 continue;
1022 }
1023 if (RequestNewTs(seekTime, mode, totalDuration, hstTime, item) == -1) {
1024 seekFailedCount_ ++;
1025 MEDIA_LOG_D("Seek failed count: " PUBLIC_LOG_D32, seekFailedCount_);
1026 continue;
1027 }
1028 }
1029 }
1030
RequestNewTs(uint64_t seekTime,SeekMode mode,double totalDuration,double hstTime,const PlayInfo & item)1031 int64_t HlsMediaDownloader::RequestNewTs(uint64_t seekTime, SeekMode mode, double totalDuration,
1032 double hstTime, const PlayInfo& item)
1033 {
1034 PlayInfo playInfo;
1035 playInfo.url_ = item.url_;
1036 playInfo.duration_ = item.duration_;
1037 if (mode == SeekMode::SEEK_PREVIOUS_SYNC) {
1038 playInfo.startTimePos_ = 0;
1039 } else {
1040 int64_t startTimePos = 0;
1041 double lastTotalDuration = totalDuration - hstTime;
1042 if (static_cast<uint64_t>(lastTotalDuration) < seekTime) {
1043 startTimePos = static_cast<int64_t>(seekTime) - static_cast<int64_t>(lastTotalDuration);
1044 if (startTimePos > (int64_t)(hstTime / HALF_DIVIDE) && (&item != &backPlayList_.back())) { // 2
1045 writeTsIndex_++;
1046 MEDIA_LOG_I("writeTsIndex, RequestNewTs update writeTsIndex " PUBLIC_LOG_U32, writeTsIndex_);
1047 return -1;
1048 }
1049 startTimePos = 0;
1050 }
1051 playInfo.startTimePos_ = startTimePos;
1052 }
1053 PushPlayInfo(playInfo);
1054 return 0;
1055 }
PushPlayInfo(PlayInfo playInfo)1056 void HlsMediaDownloader::PushPlayInfo(PlayInfo playInfo)
1057 {
1058 fragmentDownloadStart[playInfo.url_] = false;
1059 if (!isDownloadStarted_) {
1060 isDownloadStarted_ = true;
1061 // To avoid downloader potentially stopped by curl error caused by break readbuffer blocking in seeking
1062 OSAL::SleepFor(6); // sleep 6ms
1063 readOffset_ = SpliceOffset(writeTsIndex_, 0);
1064 writeOffset_ = readOffset_;
1065 readTsIndex_ = writeTsIndex_;
1066 {
1067 AutoLock lock(tsStorageInfoMutex_);
1068 if (tsStorageInfo_.count(writeTsIndex_) <= 0) {
1069 tsStorageInfo_[writeTsIndex_] = std::make_pair(0, false);
1070 } else {
1071 tsStorageInfo_[writeTsIndex_].first = 0;
1072 tsStorageInfo_[writeTsIndex_].second = false;
1073 }
1074 }
1075 PutRequestIntoDownloader(playInfo);
1076 } else {
1077 playList_->Push(playInfo);
1078 }
1079 }
1080
SeekToTsForRead(uint32_t currentTsIndex)1081 void HlsMediaDownloader::SeekToTsForRead(uint32_t currentTsIndex)
1082 {
1083 MEDIA_LOG_I("SeekToTimeForRead: currentTsIndex " PUBLIC_LOG_U32, currentTsIndex);
1084 FALSE_RETURN_MSG(cacheMediaBuffer_ != nullptr, "cacheMediaBuffer_ is nullptr");
1085 AutoLock lock(switchMutex_);
1086 isSeekingFlag = true;
1087 PrepareToSeek();
1088
1089 writeTsIndex_ = 0;
1090 isDownloadStarted_ = false;
1091 playList_->Clear();
1092 for (const auto &item : backPlayList_) {
1093 if (writeTsIndex_ < currentTsIndex) {
1094 writeTsIndex_++;
1095 continue;
1096 }
1097 if (RequestNewTsForRead(item) == -1) {
1098 seekFailedCount_++;
1099 MEDIA_LOG_D("Seek failed count: " PUBLIC_LOG_U32, seekFailedCount_);
1100 continue;
1101 }
1102 }
1103 MEDIA_LOG_I("SeekToTimeForRead end");
1104 isSeekingFlag = false;
1105 }
1106
RequestNewTsForRead(const PlayInfo & item)1107 int64_t HlsMediaDownloader::RequestNewTsForRead(const PlayInfo& item)
1108 {
1109 PlayInfo playInfo;
1110 playInfo.url_ = item.url_;
1111 playInfo.duration_ = item.duration_;
1112 playInfo.startTimePos_ = 0;
1113 PushPlayInfo(playInfo);
1114 return 0;
1115 }
1116
UpdateDownloadFinished(const std::string & url,const std::string & location)1117 void HlsMediaDownloader::UpdateDownloadFinished(const std::string &url, const std::string& location)
1118 {
1119 uint32_t bitRate = downloadRequest_->GetBitRate();
1120 {
1121 AutoLock lock(tsStorageInfoMutex_);
1122 tsStorageInfo_[writeTsIndex_].second = true;
1123 }
1124 if (!playList_->Empty()) {
1125 writeTsIndex_++;
1126 size_t fragmentSize = downloadRequest_->GetFileContentLength();
1127 double duration = downloadRequest_->GetDuration();
1128 CalculateBitRate(fragmentSize, duration);
1129 auto playInfo = playList_->Pop();
1130 PutRequestIntoDownloader(playInfo);
1131 } else {
1132 isDownloadStarted_ = false;
1133 isDownloadFinish_ = true;
1134 MEDIA_LOG_D("Download done, average download speed : " PUBLIC_LOG_D32 " bit/s", avgDownloadSpeed_);
1135 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
1136 auto downloadTime = (nowTime - startDownloadTime_) / 1000;
1137 MEDIA_LOG_D("Download done, data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
1138 totalBits_, downloadTime * 1000);
1139 HandleBuffering();
1140 }
1141
1142 // bitrate above 0, user is not selecting, auto seliect is not going, playlist is done, is not seeking
1143 if ((bitRate > 0) && !isSelectingBitrate_ && isAutoSelectBitrate_ &&
1144 playlistDownloader_ != nullptr && playlistDownloader_->IsParseAndNotifyFinished() && !isSeekingFlag) {
1145 AutoSelectBitrate(bitRate);
1146 }
1147 }
1148
SetReadBlockingFlag(bool isReadBlockingAllowed)1149 void HlsMediaDownloader::SetReadBlockingFlag(bool isReadBlockingAllowed)
1150 {
1151 MEDIA_LOG_D("SetReadBlockingFlag entered");
1152 }
1153
SetIsTriggerAutoMode(bool isAuto)1154 void HlsMediaDownloader::SetIsTriggerAutoMode(bool isAuto)
1155 {
1156 isAutoSelectBitrate_ = isAuto;
1157 }
1158
ReportVideoSizeChange()1159 void HlsMediaDownloader::ReportVideoSizeChange()
1160 {
1161 if (callback_ == nullptr) {
1162 MEDIA_LOG_I("HLS callback == nullptr dont report video size change");
1163 return;
1164 }
1165 FALSE_RETURN(playlistDownloader_ != nullptr);
1166 int32_t videoWidth = playlistDownloader_->GetVedioWidth();
1167 int32_t videoHeight = playlistDownloader_->GetVedioHeight();
1168 MEDIA_LOG_I("HLS ReportVideoSizeChange videoWidth : " PUBLIC_LOG_D32 "videoHeight: "
1169 PUBLIC_LOG_D32, videoWidth, videoHeight);
1170 changeBitRateCount_++;
1171 MEDIA_LOG_I("HLS Change bit rate count : " PUBLIC_LOG_U32, changeBitRateCount_);
1172 std::pair<int32_t, int32_t> videoSize {videoWidth, videoHeight};
1173 callback_->OnEvent({PluginEventType::VIDEO_SIZE_CHANGE, {videoSize}, "video_size_change"});
1174 }
1175
SetDemuxerState(int32_t streamId)1176 void HlsMediaDownloader::SetDemuxerState(int32_t streamId)
1177 {
1178 MEDIA_LOG_I("HLS SetDemuxerState");
1179 isReadFrame_ = true;
1180 isFirstFrameArrived_ = true;
1181 }
1182
SetDownloadErrorState()1183 void HlsMediaDownloader::SetDownloadErrorState()
1184 {
1185 MEDIA_LOG_I("HLS SetDownloadErrorState");
1186 downloadErrorState_ = true;
1187 if (callback_) {
1188 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "download"});
1189 }
1190 Close(true);
1191 }
1192
AutoSelectBitrate(uint32_t bitRate)1193 void HlsMediaDownloader::AutoSelectBitrate(uint32_t bitRate)
1194 {
1195 MEDIA_LOG_I("HLS AutoSelectBitrate download bitrate " PUBLIC_LOG_D32, bitRate);
1196 FALSE_RETURN(playlistDownloader_ != nullptr);
1197 std::vector<uint32_t> bitRates = playlistDownloader_->GetBitRates();
1198 if (bitRates.size() == 0) {
1199 return;
1200 }
1201 sort(bitRates.begin(), bitRates.end());
1202 uint32_t desBitRate = bitRates[0];
1203 for (const auto &item : bitRates) {
1204 if (item < bitRate * 0.8) { // 0.8
1205 desBitRate = item;
1206 } else {
1207 break;
1208 }
1209 }
1210 uint32_t curBitrate = playlistDownloader_->GetCurBitrate();
1211 if (desBitRate == curBitrate) {
1212 return;
1213 }
1214 uint32_t bufferLowSize = static_cast<uint32_t>(static_cast<double>(bitRate) / 8.0 * 0.3);
1215
1216 // switch to high bitrate,if buffersize less than lowsize, do not switch
1217 if (curBitrate < desBitRate && GetBufferSize() < bufferLowSize) {
1218 MEDIA_LOG_I("AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
1219 ", bufferLowSize " PUBLIC_LOG_D32, curBitrate, desBitRate, bufferLowSize);
1220 return;
1221 }
1222 uint32_t bufferHighSize = MIN_BUFFER_SIZE * 0.8; // high size: buffersize * 0.8
1223
1224 // switch to low bitrate, if buffersize more than highsize, do not switch
1225 if (curBitrate > desBitRate && GetBufferSize() > bufferHighSize) {
1226 MEDIA_LOG_I("HLS AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
1227 ", bufferHighSize " PUBLIC_LOG_D32, curBitrate, desBitRate, bufferHighSize);
1228 return;
1229 }
1230 MEDIA_LOG_I("HLS AutoSelectBitrate " PUBLIC_LOG_D32 " switch to " PUBLIC_LOG_D32, curBitrate, desBitRate);
1231 SelectBitRate(desBitRate);
1232 }
1233
CheckRiseBufferSize()1234 bool HlsMediaDownloader::CheckRiseBufferSize()
1235 {
1236 if (recordData_ == nullptr) {
1237 return false;
1238 }
1239 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
1240 bool isHistoryLow = false;
1241 std::shared_ptr<RecordData> search = recordData_;
1242 uint64_t playingBitrate = playlistDownloader_->GetCurrentBitRate();
1243 if (playingBitrate == 0) {
1244 playingBitrate = TransferSizeToBitRate(playlistDownloader_->GetVedioWidth());
1245 }
1246 if (search->downloadRate > playingBitrate) {
1247 MEDIA_LOG_I("HLS downloadRate: " PUBLIC_LOG_D64 "current bit rate: "
1248 PUBLIC_LOG_D64 ", increasing buffer size.", static_cast<uint64_t>(search->downloadRate), playingBitrate);
1249 isHistoryLow = true;
1250 }
1251 return isHistoryLow;
1252 }
1253
CheckPulldownBufferSize()1254 bool HlsMediaDownloader::CheckPulldownBufferSize()
1255 {
1256 if (recordData_ == nullptr) {
1257 return false;
1258 }
1259 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
1260 bool isPullDown = false;
1261 uint64_t playingBitrate = playlistDownloader_ -> GetCurrentBitRate();
1262 if (playingBitrate == 0) {
1263 playingBitrate = TransferSizeToBitRate(playlistDownloader_->GetVedioWidth());
1264 }
1265 std::shared_ptr<RecordData> search = recordData_;
1266 if (search->downloadRate < playingBitrate) {
1267 MEDIA_LOG_I("HLS downloadRate: " PUBLIC_LOG_D64 "current bit rate: "
1268 PUBLIC_LOG_D64 ", reducing buffer size.", static_cast<uint64_t>(search->downloadRate), playingBitrate);
1269 isPullDown = true;
1270 }
1271 return isPullDown;
1272 }
1273
RiseBufferSize()1274 void HlsMediaDownloader::RiseBufferSize()
1275 {
1276 if (totalBufferSize_ >= MAX_BUFFER_SIZE) {
1277 MEDIA_LOG_I("HLS increasing buffer size failed, already reach the max buffer size: "
1278 PUBLIC_LOG_D64 ", current buffer size: " PUBLIC_LOG_ZU, MAX_BUFFER_SIZE, totalBufferSize_);
1279 return;
1280 }
1281 size_t tmpBufferSize = totalBufferSize_ + 1 * 1024 * 1024;
1282 totalBufferSize_ = tmpBufferSize;
1283 MEDIA_LOG_I("HLS increasing buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
1284 }
1285
DownBufferSize()1286 void HlsMediaDownloader::DownBufferSize()
1287 {
1288 if (totalBufferSize_ <= MIN_BUFFER_SIZE) {
1289 MEDIA_LOG_I("HLS reducing buffer size failed, already reach the min buffer size: "
1290 PUBLIC_LOG_ZU ", current buffer size: " PUBLIC_LOG_ZU, MIN_BUFFER_SIZE, totalBufferSize_);
1291 return;
1292 }
1293 size_t tmpBufferSize = totalBufferSize_ - 1 * 1024 * 1024;
1294 totalBufferSize_ = tmpBufferSize;
1295 MEDIA_LOG_I("HLS reducing buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
1296 }
1297
OnReadBuffer(uint32_t len)1298 void HlsMediaDownloader::OnReadBuffer(uint32_t len)
1299 {
1300 static uint32_t minDuration = 0;
1301 uint64_t nowTime = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
1302 // Bytes to bit
1303 uint32_t duration = len * 8;
1304 if (duration >= bufferedDuration_) {
1305 bufferedDuration_ = 0;
1306 } else {
1307 bufferedDuration_ -= duration;
1308 }
1309
1310 if (minDuration == 0 || bufferedDuration_ < minDuration) {
1311 minDuration = bufferedDuration_;
1312 }
1313 if ((nowTime - lastReadTime_) >= SAMPLE_INTERVAL || bufferedDuration_ == 0) {
1314 BufferLeastRecord* record = new BufferLeastRecord();
1315 record->minDuration = minDuration;
1316 record->next = bufferLeastRecord_;
1317 bufferLeastRecord_ = record;
1318 lastReadTime_ = nowTime;
1319 minDuration = 0;
1320 // delete all after bufferLeastRecord_[MAX_RECORD_CT]
1321 BufferLeastRecord* tmpRecord = bufferLeastRecord_;
1322 for (int i = 0; i < MAX_RECORD_COUNT; i++) {
1323 if (tmpRecord->next) {
1324 tmpRecord = tmpRecord->next;
1325 } else {
1326 break;
1327 }
1328 }
1329 BufferLeastRecord* next = tmpRecord->next;
1330 tmpRecord->next = nullptr;
1331 tmpRecord = next;
1332 while (tmpRecord) {
1333 next = tmpRecord->next;
1334 delete tmpRecord;
1335 tmpRecord = next;
1336 }
1337 }
1338 }
1339
ActiveAutoBufferSize()1340 void HlsMediaDownloader::ActiveAutoBufferSize()
1341 {
1342 if (userDefinedBufferDuration_) {
1343 MEDIA_LOG_I("HLS User has already setted a buffersize, can not switch auto buffer size");
1344 return;
1345 }
1346 autoBufferSize_ = true;
1347 }
1348
InActiveAutoBufferSize()1349 void HlsMediaDownloader::InActiveAutoBufferSize()
1350 {
1351 autoBufferSize_ = false;
1352 }
1353
TransferSizeToBitRate(int width)1354 uint64_t HlsMediaDownloader::TransferSizeToBitRate(int width)
1355 {
1356 if (width <= MIN_WITDH) {
1357 return MIN_BUFFER_SIZE;
1358 } else if (width >= MIN_WITDH && width < SECOND_WITDH) {
1359 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_2;
1360 } else if (width >= SECOND_WITDH && width < THIRD_WITDH) {
1361 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_3;
1362 } else {
1363 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_4;
1364 }
1365 }
1366
GetTotalBufferSize()1367 size_t HlsMediaDownloader::GetTotalBufferSize()
1368 {
1369 return totalBufferSize_;
1370 }
1371
SetInterruptState(bool isInterruptNeeded)1372 void HlsMediaDownloader::SetInterruptState(bool isInterruptNeeded)
1373 {
1374 MEDIA_LOG_I("SetInterruptState: " PUBLIC_LOG_D32, isInterruptNeeded);
1375 {
1376 AutoLock lk(bufferingEndMutex_);
1377 isInterruptNeeded_ = isInterruptNeeded;
1378 if (isInterruptNeeded_) {
1379 MEDIA_LOG_I("SetInterruptState bufferingEndCond NotifyAll.");
1380 bufferingEndCond_.NotifyAll();
1381 }
1382 }
1383 if (playlistDownloader_ != nullptr) {
1384 playlistDownloader_->SetInterruptState(isInterruptNeeded);
1385 }
1386 if (downloader_ != nullptr) {
1387 downloader_->SetInterruptState(isInterruptNeeded);
1388 }
1389 }
1390
GetDownloadInfo(DownloadInfo & downloadInfo)1391 void HlsMediaDownloader::GetDownloadInfo(DownloadInfo& downloadInfo)
1392 {
1393 if (recordSpeedCount_ == 0) {
1394 MEDIA_LOG_E("HlsMediaDownloader is 0, can't get avgDownloadRate");
1395 downloadInfo.avgDownloadRate = 0;
1396 } else {
1397 downloadInfo.avgDownloadRate = avgSpeedSum_ / recordSpeedCount_;
1398 }
1399 downloadInfo.avgDownloadSpeed = avgDownloadSpeed_;
1400 downloadInfo.totalDownLoadBits = totalBits_;
1401 downloadInfo.isTimeOut = isTimeOut_;
1402 }
1403
GetPlaybackInfo(PlaybackInfo & playbackInfo)1404 void HlsMediaDownloader::GetPlaybackInfo(PlaybackInfo& playbackInfo)
1405 {
1406 if (downloader_ != nullptr) {
1407 downloader_->GetIp(playbackInfo.serverIpAddress);
1408 }
1409 double tmpDownloadTime = static_cast<double>(totalDownloadDuringTime_) / SECOND_TO_MILLIONSECOND;
1410 if (tmpDownloadTime > ZERO_THRESHOLD) {
1411 playbackInfo.averageDownloadRate = static_cast<int64_t>(totalBits_ / tmpDownloadTime);
1412 } else {
1413 playbackInfo.averageDownloadRate = 0;
1414 }
1415 playbackInfo.isDownloading = isDownloadFinish_ ? false : true;
1416 if (recordData_ != nullptr) {
1417 playbackInfo.downloadRate = static_cast<int64_t>(recordData_->downloadRate);
1418 size_t remainingBuffer = GetBufferSize();
1419 uint64_t bufferDuration = 0;
1420 if (currentBitrate_ > 0) {
1421 bufferDuration = static_cast<uint64_t>(remainingBuffer) / currentBitrate_;
1422 } else {
1423 bufferDuration = static_cast<uint64_t>(remainingBuffer) / CURRENT_BIT_RATE;
1424 }
1425 playbackInfo.bufferDuration = static_cast<int64_t>(bufferDuration);
1426 } else {
1427 playbackInfo.downloadRate = 0;
1428 playbackInfo.bufferDuration = 0;
1429 }
1430 }
1431
ReportBitrateStart(uint32_t bitRate)1432 void HlsMediaDownloader::ReportBitrateStart(uint32_t bitRate)
1433 {
1434 if (callback_ == nullptr) {
1435 MEDIA_LOG_I("HLS callback_ == nullptr dont report bitrate start");
1436 return;
1437 }
1438 MEDIA_LOG_I("HLS ReportBitrateStart bitRate : " PUBLIC_LOG_U32, bitRate);
1439 callback_->OnEvent({PluginEventType::SOURCE_BITRATE_START, {bitRate}, "source_bitrate_start"});
1440 }
1441
GetDownloadInfo()1442 std::pair<int32_t, int32_t> HlsMediaDownloader::GetDownloadInfo()
1443 {
1444 MEDIA_LOG_I("HlsMediaDownloader::GetDownloadInfo.");
1445 if (recordSpeedCount_ == 0) {
1446 MEDIA_LOG_E("recordSpeedCount_ is 0, can't get avgDownloadRate");
1447 return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1448 }
1449 auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1450 return rateAndSpeed;
1451 }
1452
GetDownloadRateAndSpeed()1453 std::pair<int32_t, int32_t> HlsMediaDownloader::GetDownloadRateAndSpeed()
1454 {
1455 MEDIA_LOG_I("HlsMediaDownloader::GetDownloadRateAndSpeed.");
1456 if (recordSpeedCount_ == 0) {
1457 MEDIA_LOG_E("recordSpeedCount_ is 0, can't get avgDownloadRate");
1458 return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1459 }
1460 auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1461 return rateAndSpeed;
1462 }
1463
SetCurrentBitRate(int32_t bitRate,int32_t streamID)1464 Status HlsMediaDownloader::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
1465 {
1466 MEDIA_LOG_I("HLS SetCurrentBitRate: " PUBLIC_LOG_D32, bitRate);
1467 if (bitRate <= 0) {
1468 currentBitRate_ = -1; // -1
1469 } else {
1470 uint32_t playlistBitrate = static_cast<uint32_t>(playlistDownloader_->GetCurBitrate());
1471 currentBitRate_ = std::max(playlistBitrate, static_cast<uint32_t>(bitRate));
1472 MEDIA_LOG_I("HLS playlistBitrate: " PUBLIC_LOG_D32 " currentBitRate: " PUBLIC_LOG_D32,
1473 playlistBitrate, currentBitRate_);
1474 }
1475 return Status::OK;
1476 }
1477
CalculateBitRate(size_t fragmentSize,double duration)1478 void HlsMediaDownloader::CalculateBitRate(size_t fragmentSize, double duration)
1479 {
1480 if (fragmentSize == 0 || duration == 0) {
1481 return;
1482 }
1483 uint32_t calculateBitRate = static_cast<uint32_t>(static_cast<uint32_t>(fragmentSize * BYTES_TO_BIT) / duration);
1484
1485 currentBitRate_ = (calculateBitRate >> 1) + (currentBitRate_ >> 1) + ((calculateBitRate | currentBitRate_) & 1);
1486 MEDIA_LOG_I("HLS Calculate avgBitRate: " PUBLIC_LOG_D32, currentBitRate_);
1487 }
1488
UpdateWaterLineAbove()1489 void HlsMediaDownloader::UpdateWaterLineAbove()
1490 {
1491 if (!isFirstFrameArrived_) {
1492 return;
1493 }
1494 if (currentBitRate_ == 0) {
1495 currentBitRate_ = static_cast<uint32_t>(playlistDownloader_->GetCurBitrate());
1496 MEDIA_LOG_I("HLS use playlist bitrate: " PUBLIC_LOG_D32, currentBitRate_);
1497 }
1498 size_t waterLineAbove = DEFAULT_WATER_LINE_ABOVE;
1499 if (currentBitRate_ > 0) {
1500 float cacheTime = 0;
1501 uint64_t writeBitrate = writeBitrateCaculator_->GetWriteBitrate();
1502 if (writeBitrate > 0) {
1503 float ratio = static_cast<float>(writeBitrate) /
1504 static_cast<float>(currentBitRate_);
1505 cacheTime = GetCacheDuration(ratio);
1506 } else {
1507 cacheTime = DEFAULT_CACHE_TIME;
1508 }
1509 waterLineAbove = static_cast<size_t>(cacheTime * currentBitRate_ / BYTES_TO_BIT);
1510 waterLineAbove = std::max(MIN_WATER_LINE_ABOVE, waterLineAbove);
1511 } else {
1512 MEDIA_LOG_D("HLS UpdateWaterLineAbove default: " PUBLIC_LOG_ZU, waterLineAbove);
1513 }
1514 waterLineAbove_ = std::min(waterLineAbove, static_cast<size_t>(totalBufferSize_ *
1515 WATER_LINE_ABOVE_LIMIT_RATIO));
1516 MEDIA_LOG_D("HLS UpdateWaterLineAbove: " PUBLIC_LOG_ZU " writeBitrate: " PUBLIC_LOG_U64 " avgDownloadSpeed: "
1517 PUBLIC_LOG_D32 " currentBitRate: " PUBLIC_LOG_D32,
1518 waterLineAbove_, writeBitrateCaculator_->GetWriteBitrate(), avgDownloadSpeed_, currentBitRate_);
1519 }
1520
HandleCachedDuration()1521 void HlsMediaDownloader::HandleCachedDuration()
1522 {
1523 if (currentBitRate_ <= 0 || callback_ == nullptr) {
1524 return;
1525 }
1526
1527 uint64_t cachedDuration = static_cast<uint64_t>((static_cast<int64_t>(GetBufferSize()) *
1528 BYTES_TO_BIT * SECOND_TO_MILLIONSECOND) / static_cast<int64_t>(currentBitRate_));
1529 if ((cachedDuration > lastDurationReacord_ &&
1530 cachedDuration - lastDurationReacord_ > DURATION_CHANGE_AMOUT_MILLIONSECOND) ||
1531 (lastDurationReacord_ > cachedDuration &&
1532 lastDurationReacord_ - cachedDuration > DURATION_CHANGE_AMOUT_MILLIONSECOND)) {
1533 MEDIA_LOG_I("HLS OnEvent cachedDuration: " PUBLIC_LOG_U64, cachedDuration);
1534 callback_->OnEvent({PluginEventType::CACHED_DURATION, {cachedDuration}, "buffering_duration"});
1535 lastDurationReacord_ = cachedDuration;
1536 }
1537 }
1538
UpdateCachedPercent(BufferingInfoType infoType)1539 void HlsMediaDownloader::UpdateCachedPercent(BufferingInfoType infoType)
1540 {
1541 if (waterLineAbove_ == 0 || callback_ == nullptr) {
1542 MEDIA_LOG_E("UpdateCachedPercent: ERROR");
1543 return;
1544 }
1545 if (infoType == BufferingInfoType::BUFFERING_START) {
1546 lastCachedSize_ = 0;
1547 isBufferingStart_ = true;
1548 return;
1549 }
1550 if (infoType == BufferingInfoType::BUFFERING_END) {
1551 bufferingTime_ = 0;
1552 lastCachedSize_ = 0;
1553 isBufferingStart_ = false;
1554 return;
1555 }
1556 if (infoType != BufferingInfoType::BUFFERING_PERCENT || !isBufferingStart_) {
1557 return;
1558 }
1559 int64_t bufferSize = static_cast<int64_t>(GetBufferSize());
1560 if (bufferSize < lastCachedSize_) {
1561 return;
1562 }
1563 int64_t deltaSize = bufferSize - lastCachedSize_;
1564 if (deltaSize >= static_cast<int64_t>(UPDATE_CACHE_STEP)) {
1565 int percent = (bufferSize >= static_cast<int64_t>(waterLineAbove_)) ?
1566 HUNDRED_PERCENTS : bufferSize * HUNDRED_PERCENTS / static_cast<int64_t>(waterLineAbove_);
1567 callback_->OnEvent({PluginEventType::EVENT_BUFFER_PROGRESS, {percent}, "buffer percent"});
1568 lastCachedSize_ = bufferSize;
1569 }
1570 }
1571
CheckBufferingOneSeconds()1572 bool HlsMediaDownloader::CheckBufferingOneSeconds()
1573 {
1574 MEDIA_LOG_I("HLS CheckBufferingOneSeconds in");
1575 int32_t sleepTime = 0;
1576 // return error again 1 time 1s, avoid ffmpeg error
1577 while (sleepTime < ONE_SECONDS && !isInterruptNeeded_.load()) {
1578 if (!isBuffering_) {
1579 break;
1580 }
1581 if (CheckBreakCondition()) {
1582 break;
1583 }
1584 OSAL::SleepFor(TEN_MILLISECONDS);
1585 sleepTime += TEN_MILLISECONDS;
1586 }
1587 MEDIA_LOG_I("HLS CheckBufferingOneSeconds out");
1588 return isBuffering_.load();
1589 }
1590
SetAppUid(int32_t appUid)1591 void HlsMediaDownloader::SetAppUid(int32_t appUid)
1592 {
1593 if (downloader_) {
1594 downloader_->SetAppUid(appUid);
1595 }
1596 if (playlistDownloader_) {
1597 playlistDownloader_->SetAppUid(appUid);
1598 }
1599 }
1600
GetCacheDuration(float ratio)1601 float HlsMediaDownloader::GetCacheDuration(float ratio)
1602 {
1603 if (ratio >= 1) {
1604 return CACHE_LEVEL_1;
1605 }
1606 return DEFAULT_CACHE_TIME;
1607 }
1608
GetBufferSize() const1609 size_t HlsMediaDownloader::GetBufferSize() const
1610 {
1611 size_t bufferSize = 0;
1612 if (cacheMediaBuffer_ != nullptr) {
1613 bufferSize = cacheMediaBuffer_->GetBufferSize(readOffset_);
1614 }
1615 return bufferSize;
1616 }
1617
GetCrossTsBuffersize()1618 size_t HlsMediaDownloader::GetCrossTsBuffersize()
1619 {
1620 size_t bufferSize = 0;
1621 if (cacheMediaBuffer_ == nullptr) {
1622 return bufferSize;
1623 }
1624 bufferSize = cacheMediaBuffer_->GetBufferSize(readOffset_);
1625 if (backPlayList_.size() > 0 && readTsIndex_ < backPlayList_.size() - 1) {
1626 size_t nextTsOffset = SpliceOffset(readTsIndex_ + 1, 0);
1627 size_t nextTsBuffersize = cacheMediaBuffer_->GetBufferSize(nextTsOffset);
1628 bufferSize += nextTsBuffersize;
1629 }
1630 return bufferSize;
1631 }
1632
GetPlayable()1633 bool HlsMediaDownloader::GetPlayable()
1634 {
1635 if (!isFirstFrameArrived_) {
1636 return false;
1637 }
1638 size_t wantedLength = wantedReadLength_;
1639 size_t waterLine = wantedLength > 0 ? std::max(PLAY_WATER_LINE, wantedLength) : 0;
1640 return waterLine == 0 ? GetBufferSize() > waterLine : GetBufferSize() >= waterLine;
1641 }
1642
GetBufferingTimeOut()1643 bool HlsMediaDownloader::GetBufferingTimeOut()
1644 {
1645 if (bufferingTime_ == 0) {
1646 return false;
1647 } else {
1648 size_t now = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1649 return now >= bufferingTime_ ? now - bufferingTime_ >= MAX_BUFFERING_TIME_OUT : false;
1650 }
1651 }
1652
GetSegmentOffset()1653 size_t HlsMediaDownloader::GetSegmentOffset()
1654 {
1655 if (playlistDownloader_) {
1656 return playlistDownloader_->GetSegmentOffset(readTsIndex_);
1657 }
1658 return 0;
1659 }
1660
GetHLSDiscontinuity()1661 bool HlsMediaDownloader::GetHLSDiscontinuity()
1662 {
1663 if (playlistDownloader_) {
1664 return playlistDownloader_->GetHLSDiscontinuity();
1665 }
1666 return false;
1667 }
1668
ClearChunksOfFragment()1669 bool HlsMediaDownloader::ClearChunksOfFragment()
1670 {
1671 bool res = false;
1672 uint64_t offsetBegin = SpliceOffset(readTsIndex_, 0);
1673 uint64_t diff = readOffset_ > offsetBegin ? readOffset_ - offsetBegin : 0;
1674 if (diff > READ_BACK_SAVE_SIZE) {
1675 MEDIA_LOG_D("HLS ClearChunksOfFragment: " PUBLIC_LOG_U64, readOffset_);
1676 res = cacheMediaBuffer_->ClearChunksOfFragment(readOffset_ - READ_BACK_SAVE_SIZE);
1677 }
1678 return res;
1679 }
1680
WaitForBufferingEnd()1681 void HlsMediaDownloader::WaitForBufferingEnd()
1682 {
1683 AutoLock lk(bufferingEndMutex_);
1684 FALSE_RETURN_MSG(isBuffering_.load(), "isBuffering false.");
1685 MEDIA_LOG_I("WaitForBufferingEnd");
1686 bufferingEndCond_.Wait(lk, [this]() {
1687 MEDIA_LOG_I("Wait in, isBuffering: " PUBLIC_LOG_D32 " isInterruptNeeded: " PUBLIC_LOG_D32,
1688 isBuffering_.load(), isInterruptNeeded_.load());
1689 return !isBuffering_.load() || isInterruptNeeded_.load();
1690 });
1691 }
1692 }
1693 }
1694 }
1695 }