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_WIDTH = 480;
39 constexpr int SECOND_WIDTH = 720;
40 constexpr int THIRD_WIDTH = 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_INTERVAL = 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; // Determine whether it is downloading
49 constexpr size_t DEFAULT_WATER_LINE_ABOVE = 512 * 1024;
50 constexpr uint32_t DURATION_CHANGE_AMOUT_MILLISECONDS = 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 = 2;
60 constexpr float 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 size_t MAX_BUFFERING_TIME_OUT_DELAY = 60 * 1000;
67 constexpr int32_t HUNDRED_PERCENTS = 100;
68 constexpr int32_t HALF_DIVIDE = 2;
69 constexpr uint64_t READ_BACK_SAVE_SIZE = 1 * 1024 * 1024;
70 constexpr int32_t SAVE_DATA_LOG_FREQUENCY = 50;
71 constexpr uint32_t KILO = 1024;
72 constexpr int32_t ONE_HUNDRED_MILLIONSECOND = 100;
73 constexpr uint64_t RESUME_FREE_SIZE_THRESHOLD = 2 * 1024 * 1024;
74 constexpr size_t STORP_WRITE_BUFFER_REDUNDANCY = 1 * 1024 * 1024;
75 constexpr int MAX_RETRY = 10;
76 }
77
78 // hls manifest, m3u8 --- content get from m3u8 url, we get play list from the content
79 // fragment --- one item in play list, download media data according to the fragment address.
HlsMediaDownloader(int expectBufferDuration,const std::map<std::string,std::string> & httpHeader,std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)80 HlsMediaDownloader::HlsMediaDownloader(int expectBufferDuration, const std::map<std::string, std::string>& httpHeader,
81 std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)
82 {
83 expectDuration_ = static_cast<uint64_t>(expectBufferDuration);
84 userDefinedBufferDuration_ = true;
85 totalBufferSize_ = expectDuration_ * CURRENT_BIT_RATE;
86 httpHeader_ = httpHeader;
87 timeoutInterval_ = MAX_BUFFERING_TIME_OUT;
88 MEDIA_LOG_I("HLS user define buffer duration.");
89 MEDIA_LOG_I("HLS setting buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
90 HlsInit(sourceLoader);
91 }
92
HlsMediaDownloader(std::string mimeType,const std::map<std::string,std::string> & httpHeader)93 HlsMediaDownloader::HlsMediaDownloader(std::string mimeType,
94 const std::map<std::string, std::string>& httpHeader)
95 {
96 mimeType_ = mimeType;
97 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
98 httpHeader_ = httpHeader;
99 timeoutInterval_ = MAX_BUFFERING_TIME_OUT;
100 cacheMediaBuffer_->Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE);
101 totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
102 MEDIA_LOG_I("HLS setting buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
103 HlsInit(nullptr);
104 }
105
HlsInit(std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)106 void HlsMediaDownloader::HlsInit(std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)
107 {
108 if (sourceLoader != nullptr) {
109 sourceLoader_ = sourceLoader;
110 downloader_ = std::make_shared<Downloader>("hlsMedia", sourceLoader);
111 MEDIA_LOG_I("HLS app download.");
112 } else {
113 downloader_ = std::make_shared<Downloader>("hlsMedia");
114 }
115 playList_ = std::make_shared<BlockingQueue<PlayInfo>>("PlayList");
116 dataSave_ = [this] (uint8_t*&& data, uint32_t&& len, bool&& notBlock) {
117 return SaveData(std::forward<decltype(data)>(data), std::forward<decltype(len)>(len),
118 std::forward<decltype(notBlock)>(notBlock));
119 };
120 if (sourceLoader != nullptr) {
121 playlistDownloader_ = std::make_shared<HlsPlayListDownloader>(httpHeader_, sourceLoader);
122 } else {
123 playlistDownloader_ = std::make_shared<HlsPlayListDownloader>(httpHeader_, nullptr);
124 }
125 playlistDownloader_->SetPlayListCallback(this);
126 writeBitrateCaculator_ = std::make_shared<WriteBitrateCaculator>();
127 waterLineAbove_ = PLAY_WATER_LINE;
128 steadyClock_.Reset();
129 loopInterruptClock_.Reset();
130 aesKey_.rounds = 0;
131 for (size_t i = 0; i < sizeof(aesKey_.rd_key) / sizeof(aesKey_.rd_key[0]); ++i) {
132 aesKey_.rd_key[i] = 0;
133 }
134 }
135
~HlsMediaDownloader()136 HlsMediaDownloader::~HlsMediaDownloader()
137 {
138 MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~HlsMediaDownloader dtor in", FAKE_POINTER(this));
139 if (downloader_ != nullptr) {
140 downloader_->Stop(false);
141 }
142 cacheMediaBuffer_ = nullptr;
143 if (playlistDownloader_ != nullptr) {
144 playlistDownloader_ = nullptr;
145 }
146 MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~HlsMediaDownloader dtor out", FAKE_POINTER(this));
147 }
148
SpliceOffset(uint32_t tsIndex,uint32_t offset32)149 size_t SpliceOffset(uint32_t tsIndex, uint32_t offset32)
150 {
151 uint64_t offset64 = 0;
152 offset64 = tsIndex;
153 offset64 = (offset64 << 32); // 32
154 offset64 |= offset32;
155 return static_cast<size_t>(offset64);
156 }
157
PutRequestIntoDownloader(const PlayInfo & playInfo)158 void HlsMediaDownloader::PutRequestIntoDownloader(const PlayInfo& playInfo)
159 {
160 if (fragmentDownloadStart[playInfo.url_]) {
161 writeTsIndex_ > 0 ? writeTsIndex_-- : 0;
162 return;
163 }
164 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
165 std::shared_ptr<DownloadRequest>& request) {
166 statusCallback_(status, downloader_, std::forward<decltype(request)>(request));
167 };
168 auto downloadDoneCallback = [this] (const std::string &url, const std::string& location) {
169 UpdateDownloadFinished(url, location);
170 };
171 RequestInfo requestInfo;
172 requestInfo.url = playInfo.rangeUrl_.empty() ? playInfo.url_ : playInfo.rangeUrl_;
173 requestInfo.httpHeader = httpHeader_;
174 bool isRequestWholeFile = playInfo.rangeUrl_.empty() ? true : playInfo.length_ <= 0;
175 downloadRequest_ = std::make_shared<DownloadRequest>(playInfo.duration_, dataSave_,
176 realStatusCallback, requestInfo, isRequestWholeFile);
177 fragmentDownloadStart[playInfo.url_] = true;
178 int64_t startTimePos = playInfo.startTimePos_;
179 curUrl_ = playInfo.rangeUrl_.empty() ? playInfo.url_ : playInfo.rangeUrl_;
180 if (writeTsIndex_ == 0) {
181 readOffset_ = SpliceOffset(writeTsIndex_, 0);
182 MEDIA_LOG_I("HLS PutRequestIntoDownloader init readOffset." PUBLIC_LOG_U64, readOffset_);
183 readTsIndex_ = writeTsIndex_;
184 uint32_t readTsIndexTempValue = readTsIndex_.load();
185 MEDIA_LOG_I("readTsIndex_, PutRequestIntoDownloader init readTsIndex_." PUBLIC_LOG_U32, readTsIndexTempValue);
186 }
187 writeOffset_ = SpliceOffset(writeTsIndex_, 0);
188 MEDIA_LOG_I("HLS PutRequestIntoDwonloader update writeOffset_: " PUBLIC_LOG_U64 " writeTsIndex_: " PUBLIC_LOG_U32,
189 writeOffset_, writeTsIndex_);
190 {
191 AutoLock lock(tsStorageInfoMutex_);
192 if (tsStorageInfo_.find(writeTsIndex_) == tsStorageInfo_.end()) {
193 tsStorageInfo_[writeTsIndex_] = std::make_pair(0, false);
194 }
195 }
196 if (!playInfo.rangeUrl_.empty()) {
197 tsStreamIdInfo_[writeTsIndex_] = playInfo.streamId_;
198 if (!isRequestWholeFile) {
199 downloadRequest_->SetRangePos(playInfo.offset_, playInfo.offset_ + playInfo.length_ - 1); // 1
200 }
201 }
202 downloadRequest_->SetRequestProtocolType(RequestProtocolType::HLS);
203 downloadRequest_->SetDownloadDoneCb(downloadDoneCallback);
204 downloadRequest_->SetStartTimePos(startTimePos);
205 downloader_->Download(downloadRequest_, -1); // -1
206 downloader_->Start();
207 }
208
SaveHttpHeader(const std::map<std::string,std::string> & httpHeader)209 void HlsMediaDownloader::SaveHttpHeader(const std::map<std::string, std::string>& httpHeader)
210 {
211 httpHeader_ = httpHeader;
212 }
213
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)214 bool HlsMediaDownloader::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
215 {
216 isDownloadFinish_ = false;
217 SaveHttpHeader(httpHeader);
218 writeBitrateCaculator_->StartClock();
219 playlistDownloader_->SetMimeType(mimeType_);
220 playlistDownloader_->Open(url, httpHeader);
221 steadyClock_.Reset();
222 openTime_ = steadyClock_.ElapsedMilliseconds();
223 if (userDefinedBufferDuration_) {
224 MEDIA_LOG_I("HLS User setting buffer duration playListDownloader_ opened.");
225 totalBufferSize_ = expectDuration_ * CURRENT_BIT_RATE;
226 if (totalBufferSize_ < MIN_BUFFER_SIZE) {
227 MEDIA_LOG_I("HLS Failed setting buffer size: " PUBLIC_LOG_ZU ". already lower than the min buffer size: "
228 PUBLIC_LOG_ZU ", setting buffer size: " PUBLIC_LOG_ZU ". ",
229 totalBufferSize_, MIN_BUFFER_SIZE, MIN_BUFFER_SIZE);
230 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
231 cacheMediaBuffer_->Init(MIN_BUFFER_SIZE, CHUNK_SIZE);
232 totalBufferSize_ = MIN_BUFFER_SIZE;
233 } else if (totalBufferSize_ > MAX_CACHE_BUFFER_SIZE) {
234 MEDIA_LOG_I("HLS Failed setting buffer size: " PUBLIC_LOG_ZU ". already exceed the max buffer size: "
235 PUBLIC_LOG_U64 ", setting buffer size: " PUBLIC_LOG_U64 ". ",
236 totalBufferSize_, MAX_CACHE_BUFFER_SIZE, MAX_CACHE_BUFFER_SIZE);
237 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
238 cacheMediaBuffer_->Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE);
239 totalBufferSize_ = MAX_CACHE_BUFFER_SIZE;
240 } else {
241 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
242 cacheMediaBuffer_->Init(totalBufferSize_, CHUNK_SIZE);
243 MEDIA_LOG_I("HLS Success setted buffer size: " PUBLIC_LOG_ZU ". ", totalBufferSize_);
244 }
245 }
246 return true;
247 }
248
Close(bool isAsync)249 void HlsMediaDownloader::Close(bool isAsync)
250 {
251 MEDIA_LOG_I("0x%{public}06" PRIXPTR " HLS Close enter", FAKE_POINTER(this));
252 isInterrupt_ = true;
253 if (playList_) {
254 playList_->SetActive(false);
255 }
256 if (playlistDownloader_) {
257 playlistDownloader_->Close();
258 }
259 if (downloader_) {
260 downloader_->Stop(isAsync);
261 }
262 isStopped = true;
263 if (!isDownloadFinish_) {
264 MEDIA_LOG_D("HLS Download close, average download speed: " PUBLIC_LOG_D32 " bit/s", avgDownloadSpeed_);
265 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
266 auto downloadTime = nowTime - startDownloadTime_;
267 MEDIA_LOG_D("HLS Download close, Data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
268 totalBits_, downloadTime);
269 }
270 }
271
Pause()272 void HlsMediaDownloader::Pause()
273 {
274 MEDIA_LOG_I("HLS Pause enter");
275 playlistDownloader_->Pause();
276 }
277
Resume()278 void HlsMediaDownloader::Resume()
279 {
280 MEDIA_LOG_I("HLS Resume enter");
281 playlistDownloader_->Resume();
282 }
283
CheckReadStatus()284 bool HlsMediaDownloader::CheckReadStatus()
285 {
286 // eos:palylist is empty, request is finished, hls is vod, do not select bitrate
287 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
288 FALSE_RETURN_V(downloadRequest_ != nullptr, false);
289 bool isEos = playList_->Empty() && (downloadRequest_ != nullptr) &&
290 downloadRequest_->IsEos() && playlistDownloader_ != nullptr &&
291 (playlistDownloader_->GetDuration() > 0) &&
292 playlistDownloader_->IsParseAndNotifyFinished();
293 if (isEos) {
294 MEDIA_LOG_I("HLS download done.");
295 return true;
296 }
297 if (playlistDownloader_->GetDuration() > 0 && playlistDownloader_->IsParseAndNotifyFinished() &&
298 static_cast<int64_t>(seekTime_) >= playlistDownloader_->GetDuration()) {
299 MEDIA_LOG_I("HLS seek to tail.");
300 return true;
301 }
302 return false;
303 }
304
CheckBreakCondition()305 bool HlsMediaDownloader::CheckBreakCondition()
306 {
307 if (downloadErrorState_) {
308 MEDIA_LOG_I("HLS downloadErrorState break");
309 return true;
310 }
311 if (CheckReadStatus()) {
312 MEDIA_LOG_I("HLS download complete break");
313 return true;
314 }
315 return false;
316 }
317
HandleBuffering()318 bool HlsMediaDownloader::HandleBuffering()
319 {
320 if (isBuffering_ && GetBufferingTimeOut() && callback_) {
321 MEDIA_LOG_I("HTTP cachebuffer buffering time out.");
322 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "buffering"});
323 isTimeoutErrorNotified_.store(true);
324 isBuffering_ = false;
325 return false;
326 }
327 if (IsNeedBufferForPlaying() || !isBuffering_.load()) {
328 return false;
329 }
330 if (isFirstFrameArrived_) {
331 UpdateWaterLineAbove();
332 UpdateCachedPercent(BufferingInfoType::BUFFERING_PERCENT);
333 }
334 {
335 AutoLock lk(bufferingEndMutex_);
336 if (!canWrite_) {
337 MEDIA_LOG_I("HLS canWrite false");
338 }
339 {
340 AutoLock lock(tsStorageInfoMutex_);
341 if (tsStorageInfo_.find(readTsIndex_) != tsStorageInfo_.end() &&
342 tsStorageInfo_[readTsIndex_].second &&
343 !backPlayList_.empty() && readTsIndex_ >= backPlayList_.size() - 1) {
344 MEDIA_LOG_I("HLS readTS download complete.");
345 isBuffering_ = false;
346 }
347 }
348 HandleWaterLine();
349 }
350 if (!isBuffering_ && !isFirstFrameArrived_) {
351 bufferingTime_ = 0;
352 }
353 if (!isBuffering_ && isFirstFrameArrived_ && callback_ != nullptr) {
354 MEDIA_LOG_I("HLS CacheData onEvent BUFFERING_END, waterLineAbove: " PUBLIC_LOG_ZU " readOffset: "
355 PUBLIC_LOG_U64 " writeOffset: " PUBLIC_LOG_U64 " writeTsIndex: " PUBLIC_LOG_U32 " bufferSize: "
356 PUBLIC_LOG_ZU, waterLineAbove_, readOffset_, writeOffset_, writeTsIndex_, GetCrossTsBuffersize());
357 UpdateCachedPercent(BufferingInfoType::BUFFERING_END);
358 callback_->OnEvent({PluginEventType::BUFFERING_END, {BufferingInfoType::BUFFERING_END}, "end"});
359 bufferingTime_ = 0;
360 }
361 return isBuffering_.load();
362 }
363
HandleWaterLine()364 void HlsMediaDownloader::HandleWaterLine()
365 {
366 size_t currentWaterLine = waterLineAbove_;
367 size_t currentOffset = readOffset_;
368 {
369 AutoLock lock(initCacheMutex_);
370 if (initCacheSize_.load() != -1) {
371 currentWaterLine = static_cast<size_t>(initCacheSize_.load());
372 currentOffset = static_cast<size_t>(expectOffset_.load());
373 MEDIA_LOG_I("currentOffset:" PUBLIC_LOG_ZU, currentOffset);
374 }
375 if (GetCrossTsBuffersize() >= currentWaterLine || CheckBreakCondition() ||
376 (tsStorageInfo_.find(readTsIndex_ + 1) != tsStorageInfo_.end() &&
377 tsStorageInfo_[readTsIndex_ + 1].second)) {
378 MEDIA_LOG_I("HLS CheckBreakCondition true, waterLineAbove: " PUBLIC_LOG_ZU " bufferSize: " PUBLIC_LOG_ZU,
379 waterLineAbove_, GetCrossTsBuffersize());
380 if (initCacheSize_.load() != -1) {
381 initCacheSize_.store(-1);
382 expectOffset_.store(-1);
383 callback_->OnEvent({PluginEventType::INITIAL_BUFFER_SUCCESS,
384 {BufferingInfoType::BUFFERING_END}, "end"});
385 }
386 isBuffering_ = false;
387 }
388 }
389 if (!isBuffering_) {
390 MEDIA_LOG_I("HandleBuffering bufferingEndCond NotifyAll.");
391 bufferingEndCond_.NotifyAll();
392 }
393 }
394
HandleCache()395 bool HlsMediaDownloader::HandleCache()
396 {
397 size_t waterLine = 0;
398 if (isFirstFrameArrived_) {
399 waterLine = wantedReadLength_ > 0 ?
400 std::max(PLAY_WATER_LINE, static_cast<size_t>(wantedReadLength_)) : 0;
401 } else {
402 waterLine = wantedReadLength_;
403 waterLineAbove_ = waterLine;
404 }
405 bool isAboveLine = GetCrossTsBuffersize() >= waterLine;
406 bool isNextTsReady = true;
407 if (!backPlayList_.empty() && readTsIndex_ >= backPlayList_.size() - 1) {
408 isNextTsReady = tsStorageInfo_[readTsIndex_].second;
409 } else {
410 isNextTsReady = tsStorageInfo_[readTsIndex_ + 1].second;
411 }
412 if (isBuffering_ || callback_ == nullptr || !canWrite_ || isAboveLine || isNextTsReady) {
413 return false;
414 }
415 isBuffering_ = true;
416 bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
417 if (isFirstFrameArrived_) {
418 callback_->OnEvent({PluginEventType::BUFFERING_START, {BufferingInfoType::BUFFERING_START}, "start"});
419 UpdateCachedPercent(BufferingInfoType::BUFFERING_START);
420 MEDIA_LOG_I("HLS CacheData onEvent BUFFERING_START, waterLineAbove: " PUBLIC_LOG_ZU " readOffset: "
421 PUBLIC_LOG_U64 " writeOffset: " PUBLIC_LOG_U64 " writeTsIndex: " PUBLIC_LOG_U32 " bufferSize: "
422 PUBLIC_LOG_ZU, waterLineAbove_, readOffset_, writeOffset_, writeTsIndex_, GetCrossTsBuffersize());
423 }
424 return true;
425 }
426
HandleFfmpegReadback(uint64_t ffmpegOffset)427 void HlsMediaDownloader::HandleFfmpegReadback(uint64_t ffmpegOffset)
428 {
429 if (curStreamId_ > 0 && isNeedResetOffset_.load()) {
430 ffmpegOffset_ = ffmpegOffset;
431 return;
432 }
433 if (ffmpegOffset_ <= ffmpegOffset) {
434 return;
435 }
436 MEDIA_LOG_D("HLS Read back, ffmpegOffset: " PUBLIC_LOG_U64 " ffmpegOffset: " PUBLIC_LOG_U64,
437 ffmpegOffset_, ffmpegOffset);
438 uint64_t readBack = ffmpegOffset_ - ffmpegOffset;
439 uint64_t curTsHaveRead = readOffset_ > SpliceOffset(readTsIndex_, 0) ?
440 readOffset_ - SpliceOffset(readTsIndex_, 0) : 0;
441 AutoLock lock(tsStorageInfoMutex_);
442 if (curTsHaveRead >= readBack) {
443 readOffset_ -= readBack;
444 MEDIA_LOG_D("HLS Read back, current ts, update readOffset: " PUBLIC_LOG_U64, readOffset_);
445 } else {
446 if (readTsIndex_ == 0) {
447 readOffset_ = 0; // Cross ts readback, but this is the first ts, so reset readOffset.
448 MEDIA_LOG_W("HLS Read back, this is the first ts: " PUBLIC_LOG_U64, readOffset_);
449 return;
450 }
451 if (tsStorageInfo_.find(readTsIndex_ - 1) == tsStorageInfo_.end()) {
452 readOffset_ = readOffset_ > curTsHaveRead ? readOffset_ - curTsHaveRead : 0;
453 MEDIA_LOG_W("HLS Read back, last ts is not ready, update readOffset to readTsIndex head: "
454 PUBLIC_LOG_U64, readOffset_);
455 return;
456 }
457 readTsIndex_--;
458 uint64_t lastTsReadBack = readBack - curTsHaveRead;
459 uint32_t readTsIndexTempValue = readTsIndex_.load();
460 uint32_t offset32 = 0;
461 if (tsStorageInfo_.find(readTsIndex_) != tsStorageInfo_.end()) {
462 offset32 = tsStorageInfo_[readTsIndex_].first >= lastTsReadBack ?
463 tsStorageInfo_[readTsIndex_].first - lastTsReadBack : 0;
464 readOffset_ = SpliceOffset(readTsIndex_, offset32);
465 MEDIA_LOG_I("HLS Read back, last ts, update readTsIndex: " PUBLIC_LOG_U32
466 " update readOffset: " PUBLIC_LOG_U64, readTsIndexTempValue, readOffset_);
467 }
468 }
469 }
470
CheckDataIntegrity()471 bool HlsMediaDownloader::CheckDataIntegrity()
472 {
473 AutoLock lock(tsStorageInfoMutex_);
474 if (tsStorageInfo_.find(readTsIndex_) != tsStorageInfo_.end() &&
475 !tsStorageInfo_[readTsIndex_].second) {
476 return readTsIndex_ == writeTsIndex_;
477 } else {
478 uint64_t head = SpliceOffset(readTsIndex_, 0);
479 uint64_t hasRead = readOffset_ >= head ? readOffset_ - head : 0;
480 size_t bufferSize = tsStorageInfo_[readTsIndex_].first >= hasRead ?
481 tsStorageInfo_[readTsIndex_].first - hasRead : 0;
482 return bufferSize == GetBufferSize();
483 }
484 }
485
CheckPlaylist(unsigned char * buff,ReadDataInfo & readDataInfo)486 Status HlsMediaDownloader::CheckPlaylist(unsigned char* buff, ReadDataInfo& readDataInfo)
487 {
488 bool isFinishedPlay = CheckReadStatus() || isStopped;
489 if (downloadRequest_ != nullptr) {
490 readDataInfo.isEos_ = downloadRequest_->IsEos();
491 }
492 if (isFinishedPlay && readTsIndex_ + 1 < backPlayList_.size()) {
493 return Status::ERROR_UNKNOWN;
494 }
495 if (isFinishedPlay && GetBufferSize() > 0) {
496 if (ReadHeaderData(buff, readDataInfo)) {
497 return Status::OK;
498 }
499 size_t readLen = std::min(GetBufferSize(), static_cast<size_t>(readDataInfo.wantReadLength_));
500 readDataInfo.realReadLength_ = cacheMediaBuffer_->Read(buff, readOffset_, readLen);
501 readOffset_ += readDataInfo.realReadLength_;
502 ffmpegOffset_ = readDataInfo.ffmpegOffset + readDataInfo.realReadLength_;
503 canWrite_ = true;
504 OnReadBuffer(readDataInfo.realReadLength_);
505 uint32_t readTsIndexTempValue = readTsIndex_.load();
506 timeoutInterval_ = MAX_BUFFERING_TIME_OUT;
507 MEDIA_LOG_D("HLS Read Success: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
508 PUBLIC_LOG_D32 " readOffset_ " PUBLIC_LOG_U64 " readTsIndex_ " PUBLIC_LOG_U32, readDataInfo.wantReadLength_,
509 readDataInfo.realReadLength_, readDataInfo.isEos_, readOffset_, readTsIndexTempValue);
510 return Status::OK;
511 }
512 if (isFinishedPlay && GetBufferSize() == 0 && GetSeekable() == Seekable::SEEKABLE &&
513 tsStorageInfo_.find(writeTsIndex_) != tsStorageInfo_.end() &&
514 tsStorageInfo_[writeTsIndex_].second) {
515 readDataInfo.realReadLength_ = 0;
516 MEDIA_LOG_I("HLS CheckPlaylist, eos.");
517 return Status::END_OF_STREAM;
518 }
519 return Status::ERROR_UNKNOWN;
520 }
521
ReadDelegate(unsigned char * buff,ReadDataInfo & readDataInfo)522 Status HlsMediaDownloader::ReadDelegate(unsigned char* buff, ReadDataInfo& readDataInfo)
523 {
524 FALSE_RETURN_V_MSG(cacheMediaBuffer_ != nullptr, Status::END_OF_STREAM, "eos, cacheMediaBuffer_ is nullptr");
525 FALSE_RETURN_V_MSG(!isInterruptNeeded_.load(), Status::END_OF_STREAM, "eos, isInterruptNeeded");
526 MediaAVCodec::AVCodecTrace trace("HLS ReadDelegate, expectedLen: " +
527 std::to_string(readDataInfo.wantReadLength_) + ", bufferSize: " + std::to_string(GetBufferSize()));
528 MEDIA_LOG_D("HLS Read in: wantReadLength " PUBLIC_LOG_D32 ", readOffset: " PUBLIC_LOG_U64 " readTsIndex: "
529 PUBLIC_LOG_U32 " bufferSize: " PUBLIC_LOG_ZU, readDataInfo.wantReadLength_, readOffset_,
530 readTsIndex_.load(), GetCrossTsBuffersize());
531 readDataInfo.isEos_ = CheckReadStatus();
532 if (readDataInfo.isEos_ && GetBufferSize() == 0 && readTsIndex_ + 1 == backPlayList_.size() &&
533 tsStorageInfo_.find(readTsIndex_) != tsStorageInfo_.end() &&
534 tsStorageInfo_[readTsIndex_].second) {
535 readDataInfo.realReadLength_ = 0;
536 MEDIA_LOG_I("HLS buffer is empty, eos.");
537 return Status::END_OF_STREAM;
538 }
539 if (isBuffering_ && GetBufferingTimeOut() && callback_ && !isReportedErrorCode_) {
540 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "read"});
541 isTimeoutErrorNotified_.store(true);
542 MEDIA_LOG_D("HLS return END_OF_STREAM.");
543 return Status::END_OF_STREAM;
544 }
545 if (isBuffering_ && CheckBufferingOneSeconds()) {
546 MEDIA_LOG_I("HLS read return error again.");
547 return Status::ERROR_AGAIN;
548 }
549 wantedReadLength_ = static_cast<size_t>(readDataInfo.wantReadLength_);
550 if (!CheckBreakCondition() && HandleCache()) {
551 MEDIA_LOG_D("HLS read return error again.");
552 return Status::ERROR_AGAIN;
553 }
554 Status tmpRes = CheckPlaylist(buff, readDataInfo);
555 if (tmpRes != Status::ERROR_UNKNOWN) {
556 MEDIA_LOG_D("HLS read return tmpRes.");
557 return tmpRes;
558 }
559
560 FALSE_RETURN_V_MSG(readDataInfo.wantReadLength_ > 0, Status::END_OF_STREAM, "eos, wantReadLength_ <= 0");
561 ReadCacheBuffer(buff, readDataInfo);
562 MEDIA_LOG_D("HLS Read success: wantReadLength " PUBLIC_LOG_D32 " realReadLen: " PUBLIC_LOG_D32 " readOffset: "
563 PUBLIC_LOG_U64 " readTsIndex: " PUBLIC_LOG_U32 " bufferSize: " PUBLIC_LOG_ZU, readDataInfo.wantReadLength_,
564 readDataInfo.realReadLength_, readOffset_, readTsIndex_.load(), GetCrossTsBuffersize());
565 return Status::OK;
566 }
567
ReadHeaderData(unsigned char * buff,ReadDataInfo & readDataInfo)568 bool HlsMediaDownloader::ReadHeaderData(unsigned char* buff, ReadDataInfo& readDataInfo)
569 {
570 if (playlistDownloader_ == nullptr || (playlistDownloader_ && !playlistDownloader_->IsHlsFmp4())) {
571 return false;
572 }
573 if (curStreamId_ <= 0 && readDataInfo.streamId_ > 0) {
574 curStreamId_ = static_cast<uint32_t>(readDataInfo.streamId_);
575 isNeedReadHeader_.store(true);
576 MEDIA_LOG_D("HLS read curStreamId_ " PUBLIC_LOG_U32, curStreamId_);
577 } else if (readDataInfo.streamId_ > 0 && readDataInfo.streamId_ != static_cast<int32_t>(curStreamId_)) {
578 readDataInfo.nextStreamId_ = static_cast<int32_t>(curStreamId_);
579 isNeedReadHeader_.store(true);
580 MEDIA_LOG_I("HLS read curStreamId_ " PUBLIC_LOG_U32 " curStreamId_ " PUBLIC_LOG_U32,
581 curStreamId_, readDataInfo.streamId_);
582 return true;
583 }
584 if (readDataInfo.streamId_ > 0 && curStreamId_ == static_cast<uint32_t>(readDataInfo.streamId_) &&
585 isNeedReadHeader_.load()) {
586 playlistDownloader_->ReadFmp4Header(buff, readDataInfo.realReadLength_, readDataInfo.streamId_);
587 isNeedReadHeader_.store(false);
588 MEDIA_LOG_I("HLS read fmp4 header.");
589 return true;
590 }
591 return false;
592 }
593
ReadCacheBuffer(unsigned char * buff,ReadDataInfo & readDataInfo)594 void HlsMediaDownloader::ReadCacheBuffer(unsigned char* buff, ReadDataInfo& readDataInfo)
595 {
596 if (ReadHeaderData(buff, readDataInfo)) {
597 return;
598 }
599 readDataInfo.realReadLength_ = cacheMediaBuffer_->Read(buff, readOffset_, readDataInfo.wantReadLength_);
600 readOffset_ += readDataInfo.realReadLength_;
601 ffmpegOffset_ = readDataInfo.ffmpegOffset + readDataInfo.realReadLength_;
602 if ((IsHlsFmp4() && readDataInfo.streamId_ > 0) || IsPureByteRange()) {
603 size_t remain = cacheMediaBuffer_->GetBufferSize(readOffset_);
604 if (remain > 0 && remain < DECRYPT_UNIT_LEN && keyLen_ > 0) {
605 size_t readRemain = cacheMediaBuffer_->Read(buff, readOffset_, readDataInfo.wantReadLength_);
606 readOffset_ += readRemain;
607 ffmpegOffset_ += readRemain;
608 readDataInfo.realReadLength_ += readRemain;
609 }
610 }
611 if (tsStorageInfo_.find(readTsIndex_) != tsStorageInfo_.end() &&
612 tsStorageInfo_[readTsIndex_].second == true) {
613 size_t tsEndOffset = SpliceOffset(readTsIndex_, tsStorageInfo_[readTsIndex_].first);
614 if (readOffset_ >= tsEndOffset) {
615 RemoveFmp4PaddingData(buff, readDataInfo);
616 cacheMediaBuffer_->ClearFragmentBeforeOffset(SpliceOffset(readTsIndex_, 0));
617 readTsIndex_++;
618 readOffset_ = SpliceOffset(readTsIndex_, 0);
619 if (playlistDownloader_->IsHlsFmp4() && tsStreamIdInfo_.find(readTsIndex_) != tsStreamIdInfo_.end() &&
620 readDataInfo.streamId_ > 0 &&
621 readDataInfo.streamId_ != static_cast<int32_t>(tsStreamIdInfo_[readTsIndex_])) {
622 curStreamId_ = tsStreamIdInfo_[readTsIndex_];
623 isNeedResetOffset_.store(true);
624 MEDIA_LOG_D("HLS read readTsIndex_ " PUBLIC_LOG_U32, readTsIndex_.load());
625 return;
626 }
627 }
628 if (readDataInfo.realReadLength_ < readDataInfo.wantReadLength_ && readTsIndex_ != backPlayList_.size()) {
629 uint32_t crossFragLen = readDataInfo.wantReadLength_ - readDataInfo.realReadLength_;
630 uint32_t crossReadLen = cacheMediaBuffer_->Read(buff + readDataInfo.realReadLength_, readOffset_,
631 crossFragLen);
632 readDataInfo.realReadLength_ = readDataInfo.realReadLength_ + crossReadLen;
633 ffmpegOffset_ += crossReadLen;
634 readOffset_ += crossReadLen;
635 }
636 }
637 canWrite_ = true;
638 }
639
RemoveFmp4PaddingData(unsigned char * buff,ReadDataInfo & readDataInfo)640 void HlsMediaDownloader::RemoveFmp4PaddingData(unsigned char* buff, ReadDataInfo& readDataInfo)
641 {
642 if (keyLen_ <= 0 || readDataInfo.realReadLength_ < 1) {
643 return;
644 }
645 if ((IsHlsFmp4() && readDataInfo.streamId_ > 0) || IsPureByteRange()) {
646 size_t endValue = buff[readDataInfo.realReadLength_ - 1];
647 size_t paddingStart = readDataInfo.realReadLength_ > endValue ?
648 readDataInfo.realReadLength_ - endValue : 0;
649 if (buff[paddingStart] == endValue) {
650 readOffset_ -= endValue;
651 ffmpegOffset_ -= endValue;
652 readDataInfo.realReadLength_ -= endValue;
653 }
654 }
655 }
656
Read(unsigned char * buff,ReadDataInfo & readDataInfo)657 Status HlsMediaDownloader::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
658 {
659 FALSE_RETURN_V(cacheMediaBuffer_ != nullptr, Status::ERROR_AGAIN);
660 uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
661 readTime_ = now;
662 if (isBuffering_ && !canWrite_) {
663 MEDIA_LOG_I("HLS can not write and buffering.");
664 SeekToTsForRead(readTsIndex_);
665 return Status::ERROR_AGAIN;
666 }
667 if (!CheckDataIntegrity()) {
668 MEDIA_LOG_W("HLS Read in, fix download.");
669 SeekToTsForRead(readTsIndex_);
670 return Status::ERROR_AGAIN;
671 }
672
673 HandleFfmpegReadback(readDataInfo.ffmpegOffset);
674
675 auto ret = ReadDelegate(buff, readDataInfo);
676
677 uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
678 if (freeSize > RESUME_FREE_SIZE_THRESHOLD && isNeedResume_.load()) {
679 downloader_->Resume();
680 isNeedResume_.store(false);
681 MEDIA_LOG_D("HLS downloader resume.");
682 }
683
684 readTotalBytes_ += readDataInfo.realReadLength_;
685 if (now > lastReadCheckTime_ && now - lastReadCheckTime_ > SAMPLE_INTERVAL) {
686 readRecordDuringTime_ = now - lastReadCheckTime_;
687 double readDuration = static_cast<double>(readRecordDuringTime_) / SECOND_TO_MILLISECONDS;
688 if (readDuration > ZERO_THRESHOLD) {
689 double readSpeed = readTotalBytes_ * BYTES_TO_BIT / readDuration; // bps
690 currentBitrate_ = static_cast<uint32_t>(readSpeed); // bps
691 MEDIA_LOG_D("Current read speed: " PUBLIC_LOG_D32 " Kbit/s,Current buffer size: " PUBLIC_LOG_U64
692 " KByte", static_cast<int32_t>(readSpeed / KILO), static_cast<uint64_t>(GetBufferSize() / KILO));
693 MediaAVCodec::AVCodecTrace trace("HlsMediaDownloader::Read, read speed: " +
694 std::to_string(readSpeed) + " bit/s, bufferSize: " + std::to_string(GetBufferSize()) + " Byte");
695 readTotalBytes_ = 0;
696 }
697 lastReadCheckTime_ = now;
698 readRecordDuringTime_ = 0;
699 }
700 return ret;
701 }
702
PrepareToSeek()703 void HlsMediaDownloader::PrepareToSeek()
704 {
705 int32_t retry {0};
706 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
707 do {
708 if (CheckLoopTimeout(loopStartTime)) {
709 break;
710 }
711 retry++;
712 FALSE_RETURN_MSG(!isInterruptNeeded_, "HLS Seek return, isInterruptNeeded_.");
713 if (retry >= SEEK_STATUS_RETRY_TIMES) { // 100 means retry times
714 MEDIA_LOG_I("HLS Seek may be failed");
715 break;
716 }
717 OSAL::SleepFor(SEEK_STATUS_SLEEP_TIME); // 50 means sleep time pre retry
718 } while (!playlistDownloader_->IsParseAndNotifyFinished());
719
720 playList_->Clear();
721 downloader_->Cancel();
722
723 cacheMediaBuffer_.reset();
724 cacheMediaBuffer_ = std::make_shared<CacheMediaChunkBufferHlsImpl>();
725 cacheMediaBuffer_->Init(totalBufferSize_, CHUNK_SIZE);
726 canWrite_ = true;
727
728 AutoLock lock(tsStorageInfoMutex_);
729 tsStorageInfo_.clear();
730 if (playlistDownloader_->IsHlsFmp4()) {
731 tsStreamIdInfo_.clear();
732 }
733
734 memset_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, 0x00, DECRYPT_UNIT_LEN);
735 memset_s(decryptCache_, MIN_BUFFER_SIZE, 0x00, MIN_BUFFER_SIZE);
736 memset_s(decryptBuffer_, MIN_BUFFER_SIZE, 0x00, MIN_BUFFER_SIZE);
737 auto ret = memcpy_s(iv_, DECRYPT_UNIT_LEN, initIv_, DECRYPT_UNIT_LEN);
738 if (ret != 0) {
739 MEDIA_LOG_E("iv copy error.");
740 }
741 afterAlignRemainedLength_ = 0;
742 isLastDecryptWriteError_ = false;
743 }
744
SeekToTime(int64_t seekTime,SeekMode mode)745 bool HlsMediaDownloader::SeekToTime(int64_t seekTime, SeekMode mode)
746 {
747 MEDIA_LOG_I("HLS Seek: buffer size " PUBLIC_LOG_ZU ", seekTime " PUBLIC_LOG_D64 " mode: " PUBLIC_LOG_D32,
748 GetBufferSize(), seekTime, mode);
749 AutoLock lock(switchMutex_);
750 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
751 FALSE_RETURN_V(cacheMediaBuffer_ != nullptr, false);
752 if (GetBufferSize() == 0 && seekTime == 0) {
753 NotifyInitSuccess();
754 }
755 isSeekingFlag = true;
756 seekTime_ = static_cast<uint64_t>(seekTime);
757 bufferingTime_ = 0;
758 PrepareToSeek();
759 FALSE_RETURN_V_MSG(!isInterruptNeeded_, true, "HLS Seek return, isInterruptNeeded_.");
760 if (seekTime_ < static_cast<uint64_t>(playlistDownloader_->GetDuration())) {
761 if (playlistDownloader_->IsHlsFmp4()) {
762 isNeedReadHeader_.store(true);
763 }
764 SeekToTs(seekTime, mode);
765 } else {
766 readTsIndex_ = !backPlayList_.empty() ? backPlayList_.size() - 1 : 0; // 0
767 tsStorageInfo_[readTsIndex_].second = true;
768 }
769 HandleSeekReady(MediaAVCodec::MediaType::MEDIA_TYPE_VID, curStreamId_, CheckBreakCondition());
770 MEDIA_LOG_I("HLS SeekToTime end\n");
771 isSeekingFlag = false;
772 return true;
773 }
774
GetContentLength() const775 size_t HlsMediaDownloader::GetContentLength() const
776 {
777 return 0;
778 }
779
GetDuration() const780 int64_t HlsMediaDownloader::GetDuration() const
781 {
782 FALSE_RETURN_V(playlistDownloader_ != nullptr, 0);
783 MEDIA_LOG_I("HLS GetDuration " PUBLIC_LOG_D64, playlistDownloader_->GetDuration());
784 return playlistDownloader_->GetDuration();
785 }
786
GetSeekable() const787 Seekable HlsMediaDownloader::GetSeekable() const
788 {
789 FALSE_RETURN_V(playlistDownloader_ != nullptr, Seekable::INVALID);
790 return playlistDownloader_->GetSeekable();
791 }
792
SetCallback(Callback * cb)793 void HlsMediaDownloader::SetCallback(Callback* cb)
794 {
795 FALSE_RETURN(playlistDownloader_ != nullptr);
796 callback_ = cb;
797 playlistDownloader_->SetCallback(cb);
798 }
799
ResetPlaylistCapacity(size_t size)800 void HlsMediaDownloader::ResetPlaylistCapacity(size_t size)
801 {
802 size_t remainCapacity = playList_->Capacity() - playList_->Size();
803 if (remainCapacity >= size) {
804 return;
805 }
806 size_t newCapacity = playList_->Size() + size;
807 playList_->ResetCapacity(newCapacity);
808 }
809
PlaylistBackup(const PlayInfo & fragment)810 void HlsMediaDownloader::PlaylistBackup(const PlayInfo& fragment)
811 {
812 FALSE_RETURN(playlistDownloader_ != nullptr);
813 if (playlistDownloader_->IsParseFinished() && (GetSeekable() == Seekable::UNSEEKABLE)) {
814 if (backPlayList_.size() > 0) {
815 backPlayList_.clear();
816 }
817 return;
818 }
819 if (playlistDownloader_->IsParseFinished()) {
820 backPlayList_.push_back(fragment);
821 }
822 }
823
OnPlayListChanged(const std::vector<PlayInfo> & playList)824 void HlsMediaDownloader::OnPlayListChanged(const std::vector<PlayInfo>& playList)
825 {
826 ResetPlaylistCapacity(static_cast<size_t>(playList.size()));
827 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
828 for (uint32_t i = 0; i < static_cast<uint32_t>(playList.size()); i++) {
829 if (CheckLoopTimeout(loopStartTime)) {
830 break;
831 }
832 if (isInterruptNeeded_.load()) {
833 MEDIA_LOG_I("HLS OnPlayListChanged isInterruptNeeded.");
834 break;
835 }
836 auto fragment = playList[i];
837 PlaylistBackup(fragment);
838 if (isSelectingBitrate_ && (GetSeekable() == Seekable::SEEKABLE)) {
839 if (writeTsIndex_ == i) {
840 MEDIA_LOG_I("HLS Switch bitrate");
841 isSelectingBitrate_ = false;
842 fragmentDownloadStart[fragment.url_] = true;
843 } else {
844 fragmentDownloadStart[fragment.url_] = true;
845 continue;
846 }
847 }
848 if (!fragmentDownloadStart[fragment.url_] && !fragmentPushed[fragment.url_]) {
849 playList_->Push(fragment);
850 fragmentPushed[fragment.url_] = true;
851 }
852 }
853 if (!isDownloadStarted_ && !playList_->Empty() && !isInterruptNeeded_.load()) {
854 auto playInfo = playList_->Pop();
855 std::string url = playInfo.url_;
856 isDownloadStarted_ = true;
857 writeTsIndex_ > 0 ? writeTsIndex_++ : 0;
858 PutRequestIntoDownloader(playInfo);
859 }
860 }
861
GetStartedStatus()862 bool HlsMediaDownloader::GetStartedStatus()
863 {
864 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
865 return playlistDownloader_->GetPlayListDownloadStatus() && startedPlayStatus_;
866 }
867
CacheBufferFullLoop()868 bool HlsMediaDownloader::CacheBufferFullLoop()
869 {
870 {
871 AutoLock lock(initCacheMutex_);
872 if (initCacheSize_.load() != -1) {
873 if (IsCachedInitSizeReady(initCacheSize_.load())) {
874 callback_->OnEvent({PluginEventType::INITIAL_BUFFER_SUCCESS,
875 {BufferingInfoType::BUFFERING_END}, "end"});
876 initCacheSize_.store(-1);
877 expectOffset_.store(-1);
878 }
879 }
880 }
881
882 MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCY, "HLS CacheMediaBuffer full, waiting seek or read");
883 if (isSeekingFlag.load()) {
884 MEDIA_LOG_I("HLS CacheMediaBuffer full, isSeeking, return true.");
885 return true;
886 }
887 OSAL::SleepFor(SLEEP_TIME_100);
888 return false;
889 }
890
SaveCacheBufferDataNotblock(uint8_t * data,uint32_t len)891 uint32_t HlsMediaDownloader::SaveCacheBufferDataNotblock(uint8_t* data, uint32_t len)
892 {
893 uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
894 if (freeSize <= (len + STORP_WRITE_BUFFER_REDUNDANCY) && !isNeedResume_.load()) {
895 isNeedResume_.store(true);
896 MEDIA_LOG_I("HLS stop write, freeSize: " PUBLIC_LOG_U64 " len: " PUBLIC_LOG_U32, freeSize, len);
897 return 0;
898 }
899
900 size_t res = cacheMediaBuffer_->Write(data, writeOffset_, len);
901 writeOffset_ += res;
902 MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCY, "SaveCacheBufferDataNotblock writeOffset " PUBLIC_LOG_U64 " res "
903 PUBLIC_LOG_ZU " len: " PUBLIC_LOG_U32, writeOffset_, res, len);
904 {
905 AutoLock lock(tsStorageInfoMutex_);
906 if (tsStorageInfo_.find(writeTsIndex_) != tsStorageInfo_.end()) {
907 tsStorageInfo_[writeTsIndex_].first += res;
908 }
909 }
910
911 writeBitrateCaculator_->UpdateWriteBytes(res);
912 ClearChunksOfFragment();
913 HandleCachedDuration();
914 writeBitrateCaculator_->StartClock();
915 uint64_t writeTime = writeBitrateCaculator_->GetWriteTime() / SECOND_TO_MILLISECONDS;
916 if (writeTime > ONE_SECONDS) {
917 writeBitrateCaculator_->ResetClock();
918 }
919 return res;
920 }
921
SaveCacheBufferData(uint8_t * data,uint32_t len,bool notBlock)922 uint32_t HlsMediaDownloader::SaveCacheBufferData(uint8_t* data, uint32_t len, bool notBlock)
923 {
924 if (notBlock) {
925 return SaveCacheBufferDataNotblock(data, len);
926 }
927 size_t hasWriteSize = 0;
928 while (hasWriteSize < len && !isInterruptNeeded_.load() && !isInterrupt_) {
929 size_t res = cacheMediaBuffer_->Write(data + hasWriteSize, writeOffset_, len - hasWriteSize);
930 writeOffset_ += res;
931 hasWriteSize += res;
932 {
933 AutoLock lock(tsStorageInfoMutex_);
934 if (tsStorageInfo_.find(writeTsIndex_) != tsStorageInfo_.end()) {
935 tsStorageInfo_[writeTsIndex_].first += res;
936 }
937 }
938 writeBitrateCaculator_->UpdateWriteBytes(res);
939 MEDIA_LOGI_LIMIT(SAVE_DATA_LOG_FREQUENCY, "writeOffset " PUBLIC_LOG_U64 " res "
940 PUBLIC_LOG_ZU, writeOffset_, res);
941 ClearChunksOfFragment();
942 if (res > 0 || hasWriteSize == len) {
943 HandleCachedDuration();
944 writeBitrateCaculator_->StartClock();
945 uint64_t writeTime = writeBitrateCaculator_->GetWriteTime() / SECOND_TO_MILLISECONDS;
946 if (writeTime > ONE_SECONDS) {
947 writeBitrateCaculator_->ResetClock();
948 }
949 continue;
950 }
951 writeBitrateCaculator_->StopClock();
952 MEDIA_LOG_W("HLS CacheMediaBuffer full.");
953 canWrite_ = false;
954 HandleBuffering();
955 while (!isInterrupt_ && !canWrite_.load() && !isInterruptNeeded_.load()) {
956 if (CacheBufferFullLoop()) {
957 return len;
958 }
959 }
960 canWrite_ = true;
961 }
962 if (isInterruptNeeded_.load() || isInterrupt_) {
963 MEDIA_LOG_I("HLS isInterruptNeeded true, return false.");
964 return 0;
965 }
966 return hasWriteSize;
967 }
968
SaveData(uint8_t * data,uint32_t len,bool notBlock)969 uint32_t HlsMediaDownloader::SaveData(uint8_t* data, uint32_t len, bool notBlock)
970 {
971 if (cacheMediaBuffer_ == nullptr) {
972 return 0;
973 }
974 OnWriteCacheBuffer(len);
975 if (isSeekingFlag.load()) {
976 return len;
977 }
978 startedPlayStatus_ = true;
979 uint32_t res = 0;
980 if (keyLen_ == 0) {
981 res = SaveCacheBufferData(data, len, notBlock);
982 } else {
983 res = SaveEncryptData(data, len, notBlock);
984 }
985 HandleBuffering();
986
987 uint64_t freeSize = cacheMediaBuffer_->GetFreeSize();
988 MEDIA_LOG_D("HLS free size: " PUBLIC_LOG_U64, freeSize);
989 return res;
990 }
991
GetDecrptyRealLen(uint8_t * writeDataPoint,uint32_t waitLen,uint32_t writeLen)992 uint32_t HlsMediaDownloader::GetDecrptyRealLen(uint8_t* writeDataPoint, uint32_t waitLen, uint32_t writeLen)
993 {
994 uint32_t realLen;
995 errno_t err {0};
996 if (afterAlignRemainedLength_ > 0) {
997 err = memcpy_s(decryptBuffer_, afterAlignRemainedLength_,
998 afterAlignRemainedBuffer_, afterAlignRemainedLength_);
999 if (err != 0) {
1000 MEDIA_LOG_D("afterAlignRemainedLength_: " PUBLIC_LOG_D64, afterAlignRemainedLength_);
1001 }
1002 }
1003 uint32_t minWriteLen = (MIN_BUFFER_SIZE - afterAlignRemainedLength_) > writeLen ?
1004 writeLen : MIN_BUFFER_SIZE - afterAlignRemainedLength_;
1005 if (minWriteLen > MIN_BUFFER_SIZE) {
1006 return 0;
1007 }
1008 err = memcpy_s(decryptBuffer_ + afterAlignRemainedLength_,
1009 minWriteLen, writeDataPoint, minWriteLen);
1010 if (err != 0) {
1011 MEDIA_LOG_D("minWriteLen: " PUBLIC_LOG_D32, minWriteLen);
1012 }
1013 realLen = minWriteLen + afterAlignRemainedLength_;
1014 AES_cbc_encrypt(decryptBuffer_, decryptCache_, realLen, &aesKey_, iv_, AES_DECRYPT);
1015 return realLen;
1016 }
1017
SaveEncryptData(uint8_t * data,uint32_t len,bool notBlock)1018 uint32_t HlsMediaDownloader::SaveEncryptData(uint8_t* data, uint32_t len, bool notBlock)
1019 {
1020 uint32_t writeLen = 0;
1021 uint8_t *writeDataPoint = data;
1022 uint32_t waitLen = len;
1023 errno_t err {0};
1024 uint32_t realLen;
1025 if ((waitLen + afterAlignRemainedLength_) < DECRYPT_UNIT_LEN && waitLen <= len) {
1026 err = memcpy_s(afterAlignRemainedBuffer_ + afterAlignRemainedLength_,
1027 DECRYPT_UNIT_LEN - afterAlignRemainedLength_,
1028 writeDataPoint, waitLen);
1029 if (err != 0) {
1030 MEDIA_LOG_E("afterAlignRemainedLength_: " PUBLIC_LOG_D64,
1031 DECRYPT_UNIT_LEN - afterAlignRemainedLength_);
1032 }
1033 afterAlignRemainedLength_ += waitLen;
1034 return len;
1035 }
1036 writeLen = ((waitLen + afterAlignRemainedLength_) / DECRYPT_UNIT_LEN) *
1037 DECRYPT_UNIT_LEN - afterAlignRemainedLength_;
1038 realLen = GetDecrptyRealLen(writeDataPoint, waitLen, writeLen);
1039 totalLen_ += realLen;
1040
1041 uint32_t writeSuccessLen = SaveCacheBufferData(decryptCache_, realLen, notBlock);
1042
1043 err = memset_s(decryptCache_, realLen, 0x00, realLen);
1044 if (err != 0) {
1045 MEDIA_LOG_E("realLen: " PUBLIC_LOG_D32, realLen);
1046 }
1047 if (writeSuccessLen == realLen) {
1048 afterAlignRemainedLength_ = 0;
1049 err = memset_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, 0x00, DECRYPT_UNIT_LEN);
1050 if (err != 0) {
1051 MEDIA_LOG_E("DECRYPT_UNIT_LEN: " PUBLIC_LOG_D64, DECRYPT_UNIT_LEN);
1052 }
1053 }
1054 if (writeLen > len) {
1055 MEDIA_LOG_D("writeLen: " PUBLIC_LOG_D32, writeLen);
1056 }
1057 writeDataPoint += writeLen;
1058 waitLen -= writeLen;
1059 if (waitLen > 0 && writeSuccessLen == realLen) {
1060 afterAlignRemainedLength_ = waitLen;
1061 err = memcpy_s(afterAlignRemainedBuffer_, DECRYPT_UNIT_LEN, writeDataPoint, waitLen);
1062 if (err != 0) {
1063 MEDIA_LOG_D("waitLen: " PUBLIC_LOG_D32, waitLen);
1064 }
1065 }
1066 MEDIA_LOG_D("SaveEncryptData, return len " PUBLIC_LOG_D32, len);
1067 return writeSuccessLen == realLen ? len : writeSuccessLen;
1068 }
1069
DownloadRecordHistory(int64_t nowTime)1070 void HlsMediaDownloader::DownloadRecordHistory(int64_t nowTime)
1071 {
1072 if ((static_cast<uint64_t>(nowTime) - lastWriteTime_) >= SAMPLE_INTERVAL) {
1073 MEDIA_LOG_I("HLS OnWriteRingBuffer nowTime: " PUBLIC_LOG_D64
1074 " lastWriteTime:" PUBLIC_LOG_D64 ".\n", nowTime, lastWriteTime_);
1075 BufferDownRecord* record = new BufferDownRecord();
1076 record->dataBits = lastWriteBit_;
1077 record->timeoff = static_cast<uint64_t>(nowTime) - lastWriteTime_;
1078 record->next = bufferDownRecord_;
1079 bufferDownRecord_ = record;
1080 lastWriteBit_ = 0;
1081 lastWriteTime_ = static_cast<uint64_t>(nowTime);
1082 BufferDownRecord* tmpRecord = bufferDownRecord_;
1083 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1084 for (int i = 0; i < MAX_RECORD_COUNT; i++) {
1085 if (CheckLoopTimeout(loopStartTime)) {
1086 break;
1087 }
1088 if (tmpRecord->next) {
1089 tmpRecord = tmpRecord->next;
1090 } else {
1091 break;
1092 }
1093 }
1094 BufferDownRecord* next = tmpRecord->next;
1095 tmpRecord->next = nullptr;
1096 tmpRecord = next;
1097 loopStartTime = loopInterruptClock_.ElapsedSeconds();
1098 while (tmpRecord) {
1099 if (CheckLoopTimeout(loopStartTime)) {
1100 break;
1101 }
1102 next = tmpRecord->next;
1103 delete tmpRecord;
1104 tmpRecord = next;
1105 }
1106 if (autoBufferSize_ && !userDefinedBufferDuration_) {
1107 if (CheckRiseBufferSize()) {
1108 RiseBufferSize();
1109 } else if (CheckPulldownBufferSize()) {
1110 DownBufferSize();
1111 }
1112 }
1113 }
1114 }
1115
OnWriteCacheBuffer(uint32_t len)1116 void HlsMediaDownloader::OnWriteCacheBuffer(uint32_t len)
1117 {
1118 {
1119 AutoLock lock(initCacheMutex_);
1120 if (initCacheSize_.load() != -1) {
1121 if (IsCachedInitSizeReady(initCacheSize_.load())) {
1122 callback_->OnEvent({PluginEventType::INITIAL_BUFFER_SUCCESS,
1123 {BufferingInfoType::BUFFERING_END}, "end"});
1124 initCacheSize_.store(-1);
1125 expectOffset_.store(-1);
1126 }
1127 }
1128 }
1129 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
1130 if (startDownloadTime_ == 0) {
1131 startDownloadTime_ = nowTime;
1132 lastReportUsageTime_ = nowTime;
1133 }
1134 uint32_t writeBits = len * BYTES_TO_BIT; // bit
1135 bufferedDuration_ += writeBits;
1136 totalBits_ += writeBits;
1137 lastWriteBit_ += writeBits;
1138 dataUsage_ += writeBits;
1139 if ((totalBits_ > START_PLAY_WATER_LINE) && (playDelayTime_ == 0)) {
1140 auto startPlayTime = steadyClock_.ElapsedMilliseconds();
1141 playDelayTime_ = startPlayTime - openTime_;
1142 MEDIA_LOG_D("Start play delay time: " PUBLIC_LOG_D64, playDelayTime_);
1143 }
1144 DownloadRecordHistory(nowTime);
1145 DownloadReport();
1146 }
1147
CalculateCurrentDownloadSpeed()1148 double HlsMediaDownloader::CalculateCurrentDownloadSpeed()
1149 {
1150 double downloadRate = 0;
1151 double tmpNumerator = static_cast<double>(downloadBits_);
1152 double tmpDenominator = static_cast<double>(downloadDuringTime_) / SECOND_TO_MILLISECONDS;
1153 if (tmpDenominator > ZERO_THRESHOLD) {
1154 downloadRate = tmpNumerator / tmpDenominator;
1155 avgDownloadSpeed_ = downloadRate;
1156 downloadDuringTime_ = 0;
1157 downloadBits_ = 0;
1158 }
1159
1160 return downloadRate;
1161 }
1162
DownloadReport()1163 void HlsMediaDownloader::DownloadReport()
1164 {
1165 uint64_t now = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
1166 if (now > lastCheckTime_ && now - lastCheckTime_ > SAMPLE_INTERVAL) {
1167 uint64_t curDownloadBits = totalBits_ - lastBits_;
1168 if (curDownloadBits >= IS_DOWNLOAD_MIN_BIT) {
1169 downloadDuringTime_ = now - lastCheckTime_;
1170 downloadBits_ = curDownloadBits;
1171 totalDownloadDuringTime_ += downloadDuringTime_;
1172
1173 std::shared_ptr<RecordData> recordBuff = std::make_shared<RecordData>();
1174 double downloadRate = CalculateCurrentDownloadSpeed();
1175 recordBuff->downloadRate = downloadRate;
1176 size_t remainingBuffer = GetBufferSize();
1177 MEDIA_LOG_D("Current download speed : " PUBLIC_LOG_D32 " Kbit/s,Current buffer size : " PUBLIC_LOG_U64
1178 " KByte", static_cast<int32_t>(downloadRate / KILO), static_cast<uint64_t>(remainingBuffer / KILO));
1179 MediaAVCodec::AVCodecTrace trace("HlsMediaDownloader::DownloadReport, download speed: " +
1180 std::to_string(downloadRate) + " bit/s, bufferSize: " + std::to_string(remainingBuffer) + " Byte");
1181 // Remaining playable time: s
1182 uint64_t bufferDuration = 0;
1183 if (currentBitrate_ > 0) {
1184 bufferDuration = bufferedDuration_ / static_cast<uint64_t>(currentBitrate_);
1185 } else {
1186 bufferDuration = bufferedDuration_ / CURRENT_BIT_RATE;
1187 }
1188 recordBuff->bufferDuring = bufferDuration;
1189 recordData_ = recordBuff;
1190 recordCount_++;
1191 }
1192 // Total amount of downloaded data
1193 lastBits_ = totalBits_;
1194 lastCheckTime_ = now;
1195 }
1196 if (!isDownloadFinish_ && (static_cast<int64_t>(now) - lastReportUsageTime_) > DATA_USAGE_INTERVAL) {
1197 MEDIA_LOG_D("Data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D32 "ms", dataUsage_, DATA_USAGE_INTERVAL);
1198 dataUsage_ = 0;
1199 lastReportUsageTime_ = static_cast<int64_t>(now);
1200 }
1201 }
1202
OnSourceKeyChange(const uint8_t * key,size_t keyLen,const uint8_t * iv)1203 void HlsMediaDownloader::OnSourceKeyChange(const uint8_t *key, size_t keyLen, const uint8_t *iv)
1204 {
1205 keyLen_ = keyLen;
1206 if (keyLen == 0) {
1207 return;
1208 }
1209 NZERO_LOG(memcpy_s(iv_, DECRYPT_UNIT_LEN, iv, DECRYPT_UNIT_LEN));
1210 NZERO_LOG(memcpy_s(initIv_, DECRYPT_UNIT_LEN, iv, DECRYPT_UNIT_LEN));
1211 NZERO_LOG(memcpy_s(key_, DECRYPT_UNIT_LEN, key, keyLen));
1212 AES_set_decrypt_key(key_, DECRYPT_COPY_LEN, &aesKey_);
1213 }
1214
OnDrmInfoChanged(const std::multimap<std::string,std::vector<uint8_t>> & drmInfos)1215 void HlsMediaDownloader::OnDrmInfoChanged(const std::multimap<std::string, std::vector<uint8_t>>& drmInfos)
1216 {
1217 if (callback_ != nullptr) {
1218 callback_->OnEvent({PluginEventType::SOURCE_DRM_INFO_UPDATE, {drmInfos}, "drm_info_update"});
1219 }
1220 }
1221
SetStatusCallback(StatusCallbackFunc cb)1222 void HlsMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
1223 {
1224 FALSE_RETURN(playlistDownloader_ != nullptr);
1225 statusCallback_ = cb;
1226 playlistDownloader_->SetStatusCallback(cb);
1227 }
1228
GetBitRates()1229 std::vector<uint32_t> HlsMediaDownloader::GetBitRates()
1230 {
1231 FALSE_RETURN_V(playlistDownloader_ != nullptr, std::vector<uint32_t>());
1232 return playlistDownloader_->GetBitRates();
1233 }
1234
SelectBitRate(uint32_t bitRate)1235 bool HlsMediaDownloader::SelectBitRate(uint32_t bitRate)
1236 {
1237 AutoLock lock(switchMutex_);
1238 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
1239 FALSE_RETURN_V(playList_ != nullptr, false);
1240 if (playlistDownloader_->IsBitrateSame(bitRate)) {
1241 return true;
1242 }
1243 if (playlistDownloader_->IsHlsFmp4() && callback_ && isAutoSelectBitrate_ && !CheckReadStatus()) {
1244 bool switchFlag = true;
1245 switchFlag = callback_->CanAutoSelectBitRate();
1246 if (!switchFlag) {
1247 return true;
1248 }
1249 callback_->SetSelectBitRateFlag(true, bitRate);
1250 }
1251 // report change bitrate start
1252 ReportBitrateStart(bitRate);
1253
1254 playlistDownloader_->Cancel();
1255
1256 // clear request queue
1257 playList_->SetActive(false, true);
1258 playList_->SetActive(true);
1259 fragmentDownloadStart.clear();
1260 fragmentPushed.clear();
1261 backPlayList_.clear();
1262
1263 // switch to des bitrate
1264 playlistDownloader_->SelectBitRate(bitRate);
1265 playlistDownloader_->Start();
1266 isSelectingBitrate_ = true;
1267 playlistDownloader_->UpdateManifest();
1268 return true;
1269 }
1270
SeekToTs(uint64_t seekTime,SeekMode mode)1271 void HlsMediaDownloader::SeekToTs(uint64_t seekTime, SeekMode mode)
1272 {
1273 MEDIA_LOG_I("SeekToTs: in.");
1274 writeTsIndex_ = 0;
1275 double totalDuration = 0;
1276 isDownloadStarted_ = false;
1277 playList_->Clear();
1278 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1279 for (const auto &item : backPlayList_) {
1280 if (CheckLoopTimeout(loopStartTime)) {
1281 break;
1282 }
1283 double hstTime = item.duration_ * HST_SECOND;
1284 totalDuration += hstTime / HST_NSECOND;
1285 if (seekTime >= static_cast<uint64_t>(totalDuration)) {
1286 writeTsIndex_++;
1287 continue;
1288 }
1289 if (RequestNewTs(seekTime, mode, totalDuration, hstTime, item) == -1) {
1290 seekFailedCount_ ++;
1291 MEDIA_LOG_D("Seek failed count: " PUBLIC_LOG_D32, seekFailedCount_);
1292 continue;
1293 }
1294 }
1295 }
1296
RequestNewTs(uint64_t seekTime,SeekMode mode,double totalDuration,double hstTime,const PlayInfo & item)1297 int64_t HlsMediaDownloader::RequestNewTs(uint64_t seekTime, SeekMode mode, double totalDuration,
1298 double hstTime, const PlayInfo& item)
1299 {
1300 PlayInfo playInfo;
1301 playInfo.url_ = item.url_;
1302 playInfo.rangeUrl_ = item.rangeUrl_;
1303 playInfo.streamId_ = item.streamId_;
1304 playInfo.duration_ = item.duration_;
1305 playInfo.offset_ = item.offset_;
1306 playInfo.length_ = item.length_;
1307 if (mode == SeekMode::SEEK_PREVIOUS_SYNC) {
1308 playInfo.startTimePos_ = 0;
1309 } else {
1310 int64_t startTimePos = 0;
1311 double lastTotalDuration = totalDuration - hstTime;
1312 if (static_cast<uint64_t>(lastTotalDuration) < seekTime) {
1313 startTimePos = static_cast<int64_t>(seekTime) - static_cast<int64_t>(lastTotalDuration);
1314 if (startTimePos > (int64_t)(hstTime / HALF_DIVIDE) && (&item != &backPlayList_.back())) { // 2
1315 writeTsIndex_++;
1316 MEDIA_LOG_I("writeTsIndex, RequestNewTs update writeTsIndex " PUBLIC_LOG_U32, writeTsIndex_);
1317 return -1;
1318 }
1319 startTimePos = 0;
1320 }
1321 playInfo.startTimePos_ = startTimePos;
1322 }
1323 PushPlayInfo(playInfo);
1324 return 0;
1325 }
PushPlayInfo(PlayInfo playInfo)1326 void HlsMediaDownloader::PushPlayInfo(PlayInfo playInfo)
1327 {
1328 fragmentDownloadStart[playInfo.url_] = false;
1329 if (playlistDownloader_ && playlistDownloader_->IsHlsFmp4()) {
1330 curStreamId_ = playInfo.streamId_;
1331 }
1332 if (!isDownloadStarted_) {
1333 isDownloadStarted_ = true;
1334 // To avoid downloader potentially stopped by curl error caused by break readbuffer blocking in seeking
1335 OSAL::SleepFor(6); // sleep 6ms
1336 readOffset_ = SpliceOffset(writeTsIndex_, 0);
1337 writeOffset_ = readOffset_;
1338 readTsIndex_ = writeTsIndex_;
1339 {
1340 AutoLock lock(tsStorageInfoMutex_);
1341 if (tsStorageInfo_.find(writeTsIndex_) != tsStorageInfo_.end()) {
1342 tsStorageInfo_[writeTsIndex_] = std::make_pair(0, false);
1343 } else {
1344 tsStorageInfo_[writeTsIndex_].first = 0;
1345 tsStorageInfo_[writeTsIndex_].second = false;
1346 }
1347 }
1348 PutRequestIntoDownloader(playInfo);
1349 } else {
1350 playList_->Push(playInfo);
1351 }
1352 }
1353
SeekToTsForRead(uint32_t currentTsIndex)1354 void HlsMediaDownloader::SeekToTsForRead(uint32_t currentTsIndex)
1355 {
1356 MEDIA_LOG_I("SeekToTimeForRead: currentTsIndex " PUBLIC_LOG_U32, currentTsIndex);
1357 FALSE_RETURN_MSG(cacheMediaBuffer_ != nullptr, "cacheMediaBuffer_ is nullptr");
1358 AutoLock lock(switchMutex_);
1359 isSeekingFlag = true;
1360 PrepareToSeek();
1361
1362 writeTsIndex_ = 0;
1363 isDownloadStarted_ = false;
1364 playList_->Clear();
1365 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1366 for (const auto &item : backPlayList_) {
1367 if (CheckLoopTimeout(loopStartTime)) {
1368 break;
1369 }
1370 if (writeTsIndex_ < currentTsIndex) {
1371 writeTsIndex_++;
1372 continue;
1373 }
1374 if (RequestNewTsForRead(item) == -1) {
1375 seekFailedCount_++;
1376 MEDIA_LOG_D("Seek failed count: " PUBLIC_LOG_U32, seekFailedCount_);
1377 continue;
1378 }
1379 }
1380 MEDIA_LOG_I("SeekToTimeForRead end");
1381 isSeekingFlag = false;
1382 }
1383
RequestNewTsForRead(const PlayInfo & item)1384 int64_t HlsMediaDownloader::RequestNewTsForRead(const PlayInfo& item)
1385 {
1386 PlayInfo playInfo;
1387 playInfo.url_ = item.url_;
1388 playInfo.rangeUrl_ = item.rangeUrl_;
1389 playInfo.streamId_ = item.streamId_;
1390 playInfo.duration_ = item.duration_;
1391 playInfo.offset_ = item.offset_;
1392 playInfo.length_ = item.length_;
1393 playInfo.startTimePos_ = 0;
1394 PushPlayInfo(playInfo);
1395 return 0;
1396 }
1397
UpdateDownloadFinished(const std::string & url,const std::string & location)1398 void HlsMediaDownloader::UpdateDownloadFinished(const std::string &url, const std::string& location)
1399 {
1400 uint32_t bitRate = downloadRequest_->GetBitRate();
1401 {
1402 AutoLock lock(tsStorageInfoMutex_);
1403 tsStorageInfo_[writeTsIndex_].second = true;
1404 }
1405 if (keyLen_ > 0) {
1406 NZERO_LOG(memcpy_s(iv_, DECRYPT_UNIT_LEN, initIv_, DECRYPT_UNIT_LEN));
1407 }
1408 if (!playList_->Empty()) {
1409 writeTsIndex_++;
1410 size_t fragmentSize = downloadRequest_->GetFileContentLength();
1411 double duration = downloadRequest_->GetDuration();
1412 CalculateBitRate(fragmentSize, duration);
1413 auto playInfo = playList_->Pop();
1414 PutRequestIntoDownloader(playInfo);
1415 } else {
1416 isDownloadStarted_ = false;
1417 if (isSeekingFlag) {
1418 return;
1419 }
1420 isDownloadFinish_ = true;
1421 MEDIA_LOG_D("Download done, average download speed : " PUBLIC_LOG_D32 " bit/s", avgDownloadSpeed_);
1422 int64_t nowTime = steadyClock_.ElapsedMilliseconds();
1423 auto downloadTime = (nowTime - startDownloadTime_) / 1000;
1424 MEDIA_LOG_D("Download done, data usage: " PUBLIC_LOG_U64 " bits in " PUBLIC_LOG_D64 "ms",
1425 totalBits_, downloadTime * 1000);
1426 HandleBuffering();
1427 }
1428
1429 // bitrate above 0, user is not selecting, auto seliect is not going, playlist is done, is not seeking
1430 if ((bitRate > 0) && !isSelectingBitrate_ && isAutoSelectBitrate_ &&
1431 playlistDownloader_ != nullptr && playlistDownloader_->IsParseAndNotifyFinished() && !isSeekingFlag) {
1432 AutoSelectBitrate(bitRate);
1433 }
1434 }
1435
SetReadBlockingFlag(bool isReadBlockingAllowed)1436 void HlsMediaDownloader::SetReadBlockingFlag(bool isReadBlockingAllowed)
1437 {
1438 MEDIA_LOG_D("SetReadBlockingFlag entered");
1439 }
1440
SetIsTriggerAutoMode(bool isAuto)1441 void HlsMediaDownloader::SetIsTriggerAutoMode(bool isAuto)
1442 {
1443 isAutoSelectBitrate_ = isAuto;
1444 }
1445
ReportVideoSizeChange()1446 void HlsMediaDownloader::ReportVideoSizeChange()
1447 {
1448 if (callback_ == nullptr) {
1449 MEDIA_LOG_I("HLS callback == nullptr dont report video size change");
1450 return;
1451 }
1452 FALSE_RETURN(playlistDownloader_ != nullptr);
1453 int32_t videoWidth = playlistDownloader_->GetVideoWidth();
1454 int32_t videoHeight = playlistDownloader_->GetVideoHeight();
1455 MEDIA_LOG_I("HLS ReportVideoSizeChange videoWidth : " PUBLIC_LOG_D32 "videoHeight: "
1456 PUBLIC_LOG_D32, videoWidth, videoHeight);
1457 changeBitRateCount_++;
1458 MEDIA_LOG_I("HLS Change bit rate count : " PUBLIC_LOG_U32, changeBitRateCount_);
1459 std::pair<int32_t, int32_t> videoSize {videoWidth, videoHeight};
1460 callback_->OnEvent({PluginEventType::VIDEO_SIZE_CHANGE, {videoSize}, "video_size_change"});
1461 }
1462
SetDemuxerState(int32_t streamId)1463 void HlsMediaDownloader::SetDemuxerState(int32_t streamId)
1464 {
1465 MEDIA_LOG_I("HLS SetDemuxerState");
1466 isReadFrame_ = true;
1467 isFirstFrameArrived_ = true;
1468 }
1469
SetDownloadErrorState()1470 void HlsMediaDownloader::SetDownloadErrorState()
1471 {
1472 MEDIA_LOG_I("HLS SetDownloadErrorState");
1473 downloadErrorState_ = true;
1474 if (callback_ != nullptr && !isReportedErrorCode_) {
1475 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT}, "download"});
1476 isTimeoutErrorNotified_.store(true);
1477 }
1478 Close(true);
1479 }
1480
AutoSelectBitrate(uint32_t bitRate)1481 void HlsMediaDownloader::AutoSelectBitrate(uint32_t bitRate)
1482 {
1483 MEDIA_LOG_I("HLS AutoSelectBitrate download bitrate " PUBLIC_LOG_D32, bitRate);
1484 FALSE_RETURN(playlistDownloader_ != nullptr);
1485 std::vector<uint32_t> bitRates = playlistDownloader_->GetBitRates();
1486 if (bitRates.size() == 0) {
1487 return;
1488 }
1489 sort(bitRates.begin(), bitRates.end());
1490 uint32_t desBitRate = bitRates[0];
1491 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1492 for (const auto &item : bitRates) {
1493 if (CheckLoopTimeout(loopStartTime)) {
1494 break;
1495 }
1496 if (item < bitRate * 0.8) { // 0.8
1497 desBitRate = item;
1498 } else {
1499 break;
1500 }
1501 }
1502 uint32_t curBitrate = playlistDownloader_->GetCurBitrate();
1503 if (desBitRate == curBitrate) {
1504 return;
1505 }
1506 uint32_t bufferLowSize = static_cast<uint32_t>(static_cast<double>(bitRate) / 8.0 * 0.3);
1507
1508 // switch to high bitrate,if buffersize less than lowsize, do not switch
1509 if (curBitrate < desBitRate && GetBufferSize() < bufferLowSize) {
1510 MEDIA_LOG_I("AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
1511 ", bufferLowSize " PUBLIC_LOG_D32, curBitrate, desBitRate, bufferLowSize);
1512 return;
1513 }
1514 uint32_t bufferHighSize = MIN_BUFFER_SIZE * 0.8; // high size: buffersize * 0.8
1515
1516 // switch to low bitrate, if buffersize more than highsize, do not switch
1517 if (curBitrate > desBitRate && GetBufferSize() > bufferHighSize) {
1518 MEDIA_LOG_I("HLS AutoSelectBitrate curBitrate " PUBLIC_LOG_D32 ", desBitRate " PUBLIC_LOG_D32
1519 ", bufferHighSize " PUBLIC_LOG_D32, curBitrate, desBitRate, bufferHighSize);
1520 return;
1521 }
1522 MEDIA_LOG_I("HLS AutoSelectBitrate " PUBLIC_LOG_D32 " switch to " PUBLIC_LOG_D32, curBitrate, desBitRate);
1523 SelectBitRate(desBitRate);
1524 }
1525
CheckRiseBufferSize()1526 bool HlsMediaDownloader::CheckRiseBufferSize()
1527 {
1528 if (recordData_ == nullptr) {
1529 return false;
1530 }
1531 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
1532 bool isHistoryLow = false;
1533 std::shared_ptr<RecordData> search = recordData_;
1534 uint64_t playingBitrate = playlistDownloader_->GetCurrentBitRate();
1535 if (playingBitrate == 0) {
1536 playingBitrate = TransferSizeToBitRate(playlistDownloader_->GetVideoWidth());
1537 }
1538 if (search->downloadRate > playingBitrate) {
1539 MEDIA_LOG_I("HLS downloadRate: " PUBLIC_LOG_D64 "current bit rate: "
1540 PUBLIC_LOG_D64 ", increasing buffer size.", static_cast<uint64_t>(search->downloadRate), playingBitrate);
1541 isHistoryLow = true;
1542 }
1543 return isHistoryLow;
1544 }
1545
CheckPulldownBufferSize()1546 bool HlsMediaDownloader::CheckPulldownBufferSize()
1547 {
1548 FALSE_RETURN_V(recordData_ != nullptr, false);
1549 FALSE_RETURN_V(playlistDownloader_ != nullptr, false);
1550 bool isPullDown = false;
1551 uint64_t playingBitrate = playlistDownloader_ -> GetCurrentBitRate();
1552 if (playingBitrate == 0) {
1553 playingBitrate = TransferSizeToBitRate(playlistDownloader_->GetVideoWidth());
1554 }
1555 std::shared_ptr<RecordData> search = recordData_;
1556 if (search->downloadRate < playingBitrate) {
1557 MEDIA_LOG_I("HLS downloadRate: " PUBLIC_LOG_D64 "current bit rate: "
1558 PUBLIC_LOG_D64 ", reducing buffer size.", static_cast<uint64_t>(search->downloadRate), playingBitrate);
1559 isPullDown = true;
1560 }
1561 return isPullDown;
1562 }
1563
RiseBufferSize()1564 void HlsMediaDownloader::RiseBufferSize()
1565 {
1566 if (totalBufferSize_ >= MAX_BUFFER_SIZE) {
1567 MEDIA_LOG_I("HLS increasing buffer size failed, already reach the max buffer size: "
1568 PUBLIC_LOG_D64 ", current buffer size: " PUBLIC_LOG_ZU, MAX_BUFFER_SIZE, totalBufferSize_);
1569 return;
1570 }
1571 size_t tmpBufferSize = totalBufferSize_ + 1 * 1024 * 1024;
1572 totalBufferSize_ = tmpBufferSize;
1573 MEDIA_LOG_I("HLS increasing buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
1574 }
1575
DownBufferSize()1576 void HlsMediaDownloader::DownBufferSize()
1577 {
1578 if (totalBufferSize_ <= MIN_BUFFER_SIZE) {
1579 MEDIA_LOG_I("HLS reducing buffer size failed, already reach the min buffer size: "
1580 PUBLIC_LOG_ZU ", current buffer size: " PUBLIC_LOG_ZU, MIN_BUFFER_SIZE, totalBufferSize_);
1581 return;
1582 }
1583 size_t tmpBufferSize = totalBufferSize_ - 1 * 1024 * 1024;
1584 totalBufferSize_ = tmpBufferSize;
1585 MEDIA_LOG_I("HLS reducing buffer size: " PUBLIC_LOG_ZU, totalBufferSize_);
1586 }
1587
OnReadBuffer(uint32_t len)1588 void HlsMediaDownloader::OnReadBuffer(uint32_t len)
1589 {
1590 static uint32_t minDuration = 0;
1591 uint64_t nowTime = static_cast<uint64_t>(steadyClock_.ElapsedMilliseconds());
1592 // Bytes to bit
1593 uint32_t duration = len * 8;
1594 if (duration >= bufferedDuration_) {
1595 bufferedDuration_ = 0;
1596 } else {
1597 bufferedDuration_ -= duration;
1598 }
1599
1600 if (minDuration == 0 || bufferedDuration_ < minDuration) {
1601 minDuration = bufferedDuration_;
1602 }
1603 if ((nowTime - lastReadTime_) >= SAMPLE_INTERVAL || bufferedDuration_ == 0) {
1604 BufferLeastRecord* record = new BufferLeastRecord();
1605 record->minDuration = minDuration;
1606 record->next = bufferLeastRecord_;
1607 bufferLeastRecord_ = record;
1608 lastReadTime_ = nowTime;
1609 minDuration = 0;
1610 // delete all after bufferLeastRecord_[MAX_RECORD_CT]
1611 BufferLeastRecord* tmpRecord = bufferLeastRecord_;
1612 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1613 for (int i = 0; i < MAX_RECORD_COUNT; i++) {
1614 if (CheckLoopTimeout(loopStartTime)) {
1615 break;
1616 }
1617 if (tmpRecord->next) {
1618 tmpRecord = tmpRecord->next;
1619 } else {
1620 break;
1621 }
1622 }
1623 BufferLeastRecord* next = tmpRecord->next;
1624 tmpRecord->next = nullptr;
1625 tmpRecord = next;
1626 loopStartTime = loopInterruptClock_.ElapsedSeconds();
1627 while (tmpRecord) {
1628 if (CheckLoopTimeout(loopStartTime)) {
1629 break;
1630 }
1631 next = tmpRecord->next;
1632 delete tmpRecord;
1633 tmpRecord = next;
1634 }
1635 }
1636 }
1637
ActiveAutoBufferSize()1638 void HlsMediaDownloader::ActiveAutoBufferSize()
1639 {
1640 if (userDefinedBufferDuration_) {
1641 MEDIA_LOG_I("HLS User has already setted a buffersize, can not switch auto buffer size");
1642 return;
1643 }
1644 autoBufferSize_ = true;
1645 }
1646
InActiveAutoBufferSize()1647 void HlsMediaDownloader::InActiveAutoBufferSize()
1648 {
1649 autoBufferSize_ = false;
1650 }
1651
TransferSizeToBitRate(int width)1652 uint64_t HlsMediaDownloader::TransferSizeToBitRate(int width)
1653 {
1654 if (width <= MIN_WIDTH) {
1655 return MIN_BUFFER_SIZE;
1656 } else if (width >= MIN_WIDTH && width < SECOND_WIDTH) {
1657 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_2;
1658 } else if (width >= SECOND_WIDTH && width < THIRD_WIDTH) {
1659 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_3;
1660 } else {
1661 return MIN_BUFFER_SIZE * TRANSFER_SIZE_RATE_4;
1662 }
1663 }
1664
GetTotalBufferSize()1665 size_t HlsMediaDownloader::GetTotalBufferSize()
1666 {
1667 return totalBufferSize_;
1668 }
1669
SetInterruptState(bool isInterruptNeeded)1670 void HlsMediaDownloader::SetInterruptState(bool isInterruptNeeded)
1671 {
1672 MEDIA_LOG_I("SetInterruptState: " PUBLIC_LOG_D32, isInterruptNeeded);
1673 {
1674 AutoLock lk(bufferingEndMutex_);
1675 isInterruptNeeded_ = isInterruptNeeded;
1676 if (isInterruptNeeded_) {
1677 MEDIA_LOG_I("SetInterruptState bufferingEndCond NotifyAll.");
1678 bufferingEndCond_.NotifyAll();
1679 }
1680 }
1681 if (playlistDownloader_ != nullptr) {
1682 playlistDownloader_->SetInterruptState(isInterruptNeeded);
1683 }
1684 if (downloader_ != nullptr) {
1685 downloader_->SetInterruptState(isInterruptNeeded);
1686 }
1687 }
1688
GetDownloadInfo(DownloadInfo & downloadInfo)1689 void HlsMediaDownloader::GetDownloadInfo(DownloadInfo& downloadInfo)
1690 {
1691 if (recordSpeedCount_ == 0) {
1692 MEDIA_LOG_E("HlsMediaDownloader is 0, can't get avgDownloadRate");
1693 downloadInfo.avgDownloadRate = 0;
1694 } else {
1695 downloadInfo.avgDownloadRate = avgSpeedSum_ / recordSpeedCount_;
1696 }
1697 downloadInfo.avgDownloadSpeed = avgDownloadSpeed_;
1698 downloadInfo.totalDownLoadBits = totalBits_;
1699 downloadInfo.isTimeOut = isTimeOut_;
1700 }
1701
GetPlaybackInfo(PlaybackInfo & playbackInfo)1702 void HlsMediaDownloader::GetPlaybackInfo(PlaybackInfo& playbackInfo)
1703 {
1704 if (downloader_ != nullptr) {
1705 downloader_->GetIp(playbackInfo.serverIpAddress);
1706 }
1707 double tmpDownloadTime = static_cast<double>(totalDownloadDuringTime_) / SECOND_TO_MILLISECONDS;
1708 if (tmpDownloadTime > ZERO_THRESHOLD) {
1709 playbackInfo.averageDownloadRate = static_cast<int64_t>(totalBits_ / tmpDownloadTime);
1710 } else {
1711 playbackInfo.averageDownloadRate = 0;
1712 }
1713 playbackInfo.isDownloading = isDownloadFinish_ ? false : true;
1714 if (recordData_ != nullptr) {
1715 playbackInfo.downloadRate = static_cast<int64_t>(recordData_->downloadRate);
1716 size_t remainingBuffer = GetBufferSize();
1717 uint64_t bufferDuration = 0;
1718 if (currentBitrate_ > 0) {
1719 bufferDuration = static_cast<uint64_t>(remainingBuffer) /
1720 static_cast<uint64_t>(currentBitrate_);
1721 } else {
1722 bufferDuration = static_cast<uint64_t>(remainingBuffer) / CURRENT_BIT_RATE;
1723 }
1724 playbackInfo.bufferDuration = static_cast<int64_t>(bufferDuration);
1725 } else {
1726 playbackInfo.downloadRate = 0;
1727 playbackInfo.bufferDuration = 0;
1728 }
1729 }
1730
ReportBitrateStart(uint32_t bitRate)1731 void HlsMediaDownloader::ReportBitrateStart(uint32_t bitRate)
1732 {
1733 if (callback_ == nullptr) {
1734 MEDIA_LOG_I("HLS callback_ == nullptr dont report bitrate start");
1735 return;
1736 }
1737 MEDIA_LOG_I("HLS ReportBitrateStart bitRate : " PUBLIC_LOG_U32, bitRate);
1738 callback_->OnEvent({PluginEventType::SOURCE_BITRATE_START, {bitRate}, "source_bitrate_start"});
1739 }
1740
GetDownloadInfo()1741 std::pair<int32_t, int32_t> HlsMediaDownloader::GetDownloadInfo()
1742 {
1743 MEDIA_LOG_I("HlsMediaDownloader::GetDownloadInfo.");
1744 if (recordSpeedCount_ == 0) {
1745 MEDIA_LOG_E("recordSpeedCount_ is 0, can't get avgDownloadRate");
1746 return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1747 }
1748 auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1749 return rateAndSpeed;
1750 }
1751
GetDownloadRateAndSpeed()1752 std::pair<int32_t, int32_t> HlsMediaDownloader::GetDownloadRateAndSpeed()
1753 {
1754 MEDIA_LOG_I("HlsMediaDownloader::GetDownloadRateAndSpeed.");
1755 if (recordSpeedCount_ == 0) {
1756 MEDIA_LOG_E("recordSpeedCount_ is 0, can't get avgDownloadRate");
1757 return std::make_pair(0, static_cast<int32_t>(avgDownloadSpeed_));
1758 }
1759 auto rateAndSpeed = std::make_pair(avgSpeedSum_ / recordSpeedCount_, static_cast<int32_t>(avgDownloadSpeed_));
1760 return rateAndSpeed;
1761 }
1762
SetCurrentBitRate(int32_t bitRate,int32_t streamID)1763 Status HlsMediaDownloader::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
1764 {
1765 MEDIA_LOG_I("HLS SetCurrentBitRate: " PUBLIC_LOG_D32, bitRate);
1766 if (bitRate <= 0) {
1767 currentBitRate_ = -1; // -1
1768 } else {
1769 int32_t playlistBitrate = static_cast<int32_t>(playlistDownloader_->GetCurBitrate());
1770 currentBitRate_ = std::max(playlistBitrate, static_cast<int32_t>(bitRate));
1771 MEDIA_LOG_I("HLS playlistBitrate: " PUBLIC_LOG_D32 " currentBitRate: " PUBLIC_LOG_D32,
1772 playlistBitrate, currentBitRate_);
1773 }
1774 if (bufferDurationForPlaying_ > 0 && currentBitRate_ > 0) {
1775 waterlineForPlaying_ = static_cast<uint64_t>(static_cast<double>(currentBitRate_) /
1776 static_cast<double>(BYTES_TO_BIT) * bufferDurationForPlaying_);
1777 }
1778 return Status::OK;
1779 }
1780
CalculateBitRate(size_t fragmentSize,double duration)1781 void HlsMediaDownloader::CalculateBitRate(size_t fragmentSize, double duration)
1782 {
1783 if (fragmentSize == 0 || duration < ZERO_THRESHOLD) {
1784 return;
1785 }
1786 double divisorFragmentSize = (static_cast<double>(fragmentSize) / static_cast<double>(ONE_SECONDS))
1787 * static_cast<double>(BYTES_TO_BIT);
1788 double dividendDuration = static_cast<double>(duration) / static_cast<double>(ONE_SECONDS);
1789 uint32_t calculateBitRate = static_cast<uint32_t>(divisorFragmentSize / dividendDuration);
1790 uint32_t tmpBitRate = static_cast<uint32_t>(currentBitRate_);
1791 tmpBitRate = (calculateBitRate >> 1) + (tmpBitRate >> 1) + ((calculateBitRate | tmpBitRate) & 1);
1792 currentBitRate_ = static_cast<int32_t>(tmpBitRate);
1793 MEDIA_LOG_I("HLS Calculate avgBitRate: " PUBLIC_LOG_D32, currentBitRate_);
1794 }
1795
UpdateWaterLineAbove()1796 void HlsMediaDownloader::UpdateWaterLineAbove()
1797 {
1798 if (!isFirstFrameArrived_) {
1799 return;
1800 }
1801 if (currentBitRate_ == 0) {
1802 currentBitRate_ = static_cast<int32_t>(playlistDownloader_->GetCurBitrate());
1803 MEDIA_LOG_I("HLS use playlist bitrate: " PUBLIC_LOG_D32, currentBitRate_);
1804 }
1805 size_t waterLineAbove = DEFAULT_WATER_LINE_ABOVE;
1806 if (currentBitRate_ > 0) {
1807 float cacheTime = 0;
1808 uint64_t writeBitrate = writeBitrateCaculator_->GetWriteBitrate();
1809 if (writeBitrate > 0) {
1810 float ratio = static_cast<float>(writeBitrate) /
1811 static_cast<float>(currentBitRate_);
1812 cacheTime = GetCacheDuration(ratio);
1813 } else {
1814 cacheTime = DEFAULT_CACHE_TIME;
1815 }
1816 waterLineAbove = static_cast<size_t>(cacheTime * currentBitRate_ / BYTES_TO_BIT);
1817 waterLineAbove = std::max(MIN_WATER_LINE_ABOVE, waterLineAbove);
1818 } else {
1819 MEDIA_LOG_D("HLS UpdateWaterLineAbove default: " PUBLIC_LOG_ZU, waterLineAbove);
1820 }
1821 waterLineAbove_ = std::min(waterLineAbove, static_cast<size_t>(totalBufferSize_ *
1822 WATER_LINE_ABOVE_LIMIT_RATIO));
1823 MEDIA_LOG_D("HLS UpdateWaterLineAbove: " PUBLIC_LOG_ZU " writeBitrate: " PUBLIC_LOG_U64 " avgDownloadSpeed: "
1824 PUBLIC_LOG_D32 " currentBitRate: " PUBLIC_LOG_D32,
1825 waterLineAbove_, writeBitrateCaculator_->GetWriteBitrate(), avgDownloadSpeed_, currentBitRate_);
1826 }
1827
HandleCachedDuration()1828 void HlsMediaDownloader::HandleCachedDuration()
1829 {
1830 if (currentBitRate_ <= 0 || callback_ == nullptr) {
1831 return;
1832 }
1833 cachedDuration_ = static_cast<uint64_t>((static_cast<int64_t>(GetBufferSize()) *
1834 BYTES_TO_BIT * SECOND_TO_MILLISECONDS) / static_cast<int64_t>(currentBitRate_));
1835 if ((cachedDuration_ > lastDurationReacord_ &&
1836 cachedDuration_ - lastDurationReacord_ > DURATION_CHANGE_AMOUT_MILLISECONDS) ||
1837 (lastDurationReacord_ > cachedDuration_ &&
1838 lastDurationReacord_ - cachedDuration_ > DURATION_CHANGE_AMOUT_MILLISECONDS)) {
1839 MEDIA_LOG_D("HLS OnEvent cachedDuration: " PUBLIC_LOG_U64, cachedDuration_);
1840 callback_->OnEvent({PluginEventType::CACHED_DURATION, {cachedDuration_}, "buffering_duration"});
1841 lastDurationReacord_ = cachedDuration_;
1842 }
1843 }
1844
UpdateCachedPercent(BufferingInfoType infoType)1845 void HlsMediaDownloader::UpdateCachedPercent(BufferingInfoType infoType)
1846 {
1847 if (waterLineAbove_ == 0 || callback_ == nullptr) {
1848 MEDIA_LOG_E("HLS UpdateCachedPercent: ERROR");
1849 return;
1850 }
1851 if (infoType == BufferingInfoType::BUFFERING_START) {
1852 lastCachedSize_ = 0;
1853 isBufferingStart_ = true;
1854 return;
1855 }
1856 if (infoType == BufferingInfoType::BUFFERING_END) {
1857 bufferingTime_ = 0;
1858 lastCachedSize_ = 0;
1859 isBufferingStart_ = false;
1860 return;
1861 }
1862 if (infoType != BufferingInfoType::BUFFERING_PERCENT || !isBufferingStart_) {
1863 return;
1864 }
1865 int64_t bufferSize = static_cast<int64_t>(GetBufferSize());
1866 if (bufferSize < lastCachedSize_) {
1867 return;
1868 }
1869 int64_t deltaSize = bufferSize - lastCachedSize_;
1870 if (deltaSize >= static_cast<int64_t>(UPDATE_CACHE_STEP)) {
1871 int percent = (bufferSize >= static_cast<int64_t>(waterLineAbove_)) ?
1872 HUNDRED_PERCENTS : bufferSize * HUNDRED_PERCENTS / static_cast<int64_t>(waterLineAbove_);
1873 callback_->OnEvent({PluginEventType::EVENT_BUFFER_PROGRESS, {percent}, "buffer percent"});
1874 lastCachedSize_ = bufferSize;
1875 }
1876 }
1877
CheckBufferingOneSeconds()1878 bool HlsMediaDownloader::CheckBufferingOneSeconds()
1879 {
1880 MEDIA_LOG_I("HLS CheckBufferingOneSeconds in");
1881 int32_t sleepTime = 0;
1882 // return error again 1 time 1s, avoid ffmpeg error
1883 int64_t loopStartTime = loopInterruptClock_.ElapsedSeconds();
1884 while (sleepTime < (isFirstFrameArrived_ ? ONE_SECONDS : ONE_HUNDRED_MILLIONSECOND) &&
1885 !isInterruptNeeded_.load()) {
1886 if (CheckLoopTimeout(loopStartTime)) {
1887 break;
1888 }
1889 if (!isBuffering_) {
1890 break;
1891 }
1892 if (CheckBreakCondition()) {
1893 break;
1894 }
1895 OSAL::SleepFor(TEN_MILLISECONDS);
1896 sleepTime += TEN_MILLISECONDS;
1897 }
1898 MEDIA_LOG_I("HLS CheckBufferingOneSeconds out");
1899 return isBuffering_.load();
1900 }
1901
SetAppUid(int32_t appUid)1902 void HlsMediaDownloader::SetAppUid(int32_t appUid)
1903 {
1904 if (downloader_) {
1905 downloader_->SetAppUid(appUid);
1906 }
1907 if (playlistDownloader_) {
1908 playlistDownloader_->SetAppUid(appUid);
1909 }
1910 }
1911
GetCacheDuration(float ratio)1912 float HlsMediaDownloader::GetCacheDuration(float ratio)
1913 {
1914 if (ratio >= 1) {
1915 return CACHE_LEVEL_1;
1916 }
1917 return DEFAULT_CACHE_TIME;
1918 }
1919
GetBufferSize() const1920 size_t HlsMediaDownloader::GetBufferSize() const
1921 {
1922 size_t bufferSize = 0;
1923 if (cacheMediaBuffer_ != nullptr) {
1924 bufferSize = cacheMediaBuffer_->GetBufferSize(readOffset_);
1925 }
1926 return bufferSize;
1927 }
1928
GetCrossTsBuffersize()1929 size_t HlsMediaDownloader::GetCrossTsBuffersize()
1930 {
1931 size_t bufferSize = 0;
1932 if (cacheMediaBuffer_ == nullptr) {
1933 return bufferSize;
1934 }
1935 bufferSize = cacheMediaBuffer_->GetBufferSize(readOffset_);
1936 if (!backPlayList_.empty() && readTsIndex_ < backPlayList_.size() - 1) {
1937 size_t nextTsOffset = SpliceOffset(readTsIndex_ + 1, 0);
1938 size_t nextTsBuffersize = cacheMediaBuffer_->GetBufferSize(nextTsOffset);
1939 bufferSize += nextTsBuffersize;
1940 }
1941 return bufferSize;
1942 }
1943
IsCachedInitSizeReady(int32_t wantInitSize)1944 bool HlsMediaDownloader::IsCachedInitSizeReady(int32_t wantInitSize)
1945 {
1946 if (wantInitSize < 0) {
1947 return false;
1948 }
1949 size_t bufferSize = 0;
1950 if (cacheMediaBuffer_ == nullptr) {
1951 return false;
1952 }
1953 size_t listSize = backPlayList_.size();
1954 for (size_t i = 0; i < listSize; i++) {
1955 if (i + 1 == listSize) {
1956 return true;
1957 }
1958 if (tsStorageInfo_.find(i) == tsStorageInfo_.end()) {
1959 break;
1960 } else {
1961 size_t currentTsStart = SpliceOffset(i, 0);
1962 bufferSize += cacheMediaBuffer_->GetBufferSize(currentTsStart);
1963 if (bufferSize >= static_cast<size_t>(wantInitSize)) {
1964 return true;
1965 }
1966 if (!tsStorageInfo_[i].second) {
1967 break;
1968 }
1969 }
1970 }
1971 return false;
1972 }
1973
GetPlayable()1974 bool HlsMediaDownloader::GetPlayable()
1975 {
1976 if (isBuffering_) {
1977 return false;
1978 }
1979 if (!isFirstFrameArrived_) {
1980 return false;
1981 }
1982 size_t wantedLength = wantedReadLength_;
1983 size_t waterLine = wantedLength > 0 ? std::max(PLAY_WATER_LINE, wantedLength) : 0;
1984 return waterLine == 0 ? GetBufferSize() > waterLine : GetBufferSize() >= waterLine;
1985 }
1986
GetBufferingTimeOut()1987 bool HlsMediaDownloader::GetBufferingTimeOut()
1988 {
1989 if (bufferingTime_ == 0) {
1990 return false;
1991 } else {
1992 size_t now = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
1993 return now >= bufferingTime_ ? now - bufferingTime_ >= timeoutInterval_ : false;
1994 }
1995 }
1996
GetReadTimeOut(bool isDelay)1997 bool HlsMediaDownloader::GetReadTimeOut(bool isDelay)
1998 {
1999 size_t now = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
2000 if (isDelay) { // NOT_READY
2001 timeoutInterval_ = MAX_BUFFERING_TIME_OUT_DELAY;
2002 }
2003 return (now >= readTime_) ? (now - readTime_ >= timeoutInterval_) : false;
2004 }
2005
GetSegmentOffset()2006 size_t HlsMediaDownloader::GetSegmentOffset()
2007 {
2008 if (playlistDownloader_) {
2009 return playlistDownloader_->GetSegmentOffset(readTsIndex_);
2010 }
2011 return 0;
2012 }
2013
GetHLSDiscontinuity()2014 bool HlsMediaDownloader::GetHLSDiscontinuity()
2015 {
2016 if (playlistDownloader_) {
2017 return playlistDownloader_->GetHLSDiscontinuity();
2018 }
2019 return false;
2020 }
2021
StopBufferring(bool isAppBackground)2022 Status HlsMediaDownloader::StopBufferring(bool isAppBackground)
2023 {
2024 MEDIA_LOG_I("HlsMediaDownloader:StopBufferring enter");
2025 if (cacheMediaBuffer_ == nullptr || downloader_ == nullptr || playlistDownloader_ == nullptr) {
2026 MEDIA_LOG_E("StopBufferring error.");
2027 return Status::ERROR_NULL_POINTER;
2028 }
2029 downloader_->SetAppState(isAppBackground);
2030 if (isAppBackground) {
2031 isInterrupt_ = true;
2032 } else {
2033 isInterrupt_ = false;
2034 }
2035 downloader_->StopBufferring();
2036 playlistDownloader_->StopBufferring(isAppBackground);
2037 MEDIA_LOG_I("HlsMediaDownloader:StopBufferring out");
2038 return Status::OK;
2039 }
2040
ClearChunksOfFragment()2041 bool HlsMediaDownloader::ClearChunksOfFragment()
2042 {
2043 bool res = false;
2044 uint64_t offsetBegin = SpliceOffset(readTsIndex_, 0);
2045 uint64_t diff = readOffset_ > offsetBegin ? readOffset_ - offsetBegin : 0;
2046 if (diff > READ_BACK_SAVE_SIZE) {
2047 MEDIA_LOG_D("HLS ClearChunksOfFragment: " PUBLIC_LOG_U64, readOffset_);
2048 res = cacheMediaBuffer_->ClearChunksOfFragment(readOffset_ - READ_BACK_SAVE_SIZE);
2049 }
2050 return res;
2051 }
2052
WaitForBufferingEnd()2053 void HlsMediaDownloader::WaitForBufferingEnd()
2054 {
2055 AutoLock lk(bufferingEndMutex_);
2056 FALSE_RETURN_MSG(isBuffering_.load(), "isBuffering false.");
2057 MEDIA_LOG_I("WaitForBufferingEnd");
2058 bufferingEndCond_.Wait(lk, [this]() {
2059 MEDIA_LOG_I("Wait in, isBuffering: " PUBLIC_LOG_D32 " isInterruptNeeded: " PUBLIC_LOG_D32,
2060 isBuffering_.load(), isInterruptNeeded_.load());
2061 return !isBuffering_.load() || isInterruptNeeded_.load();
2062 });
2063 }
2064
SetIsReportedErrorCode()2065 void HlsMediaDownloader::SetIsReportedErrorCode()
2066 {
2067 isReportedErrorCode_ = true;
2068 }
2069
SetInitialBufferSize(int32_t offset,int32_t size)2070 bool HlsMediaDownloader::SetInitialBufferSize(int32_t offset, int32_t size)
2071 {
2072 AutoLock lock(initCacheMutex_);
2073 bool isInitBufferSizeOk = IsCachedInitSizeReady(size) >= size || CheckBreakCondition();
2074 if (isInitBufferSizeOk || !downloader_ || !downloadRequest_ || isTimeoutErrorNotified_.load()) {
2075 MEDIA_LOG_I("HLS SetInitialBufferSize initCacheSize ok.");
2076 return false;
2077 }
2078 MEDIA_LOG_I("HLS SetInitialBufferSize initCacheSize " PUBLIC_LOG_U32, size);
2079 if (!isBuffering_.load()) {
2080 isBuffering_.store(true);
2081 }
2082 bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
2083 expectOffset_.store(offset);
2084 initCacheSize_.store(size);
2085 return true;
2086 }
2087
SetPlayStrategy(const std::shared_ptr<PlayStrategy> & playStrategy)2088 void HlsMediaDownloader::SetPlayStrategy(const std::shared_ptr<PlayStrategy>& playStrategy)
2089 {
2090 if (playlistDownloader_ == nullptr || playStrategy == nullptr) {
2091 MEDIA_LOG_E("SetPlayStrategy error.");
2092 return;
2093 }
2094 if (playStrategy->width > 0 && playStrategy->height > 0) {
2095 playlistDownloader_->SetInitResolution(playStrategy->width, playStrategy->height);
2096 }
2097 if (playStrategy->bufferDurationForPlaying > 0) {
2098 bufferDurationForPlaying_ = playStrategy->bufferDurationForPlaying;
2099 waterlineForPlaying_ = static_cast<uint64_t>(static_cast<double>(CURRENT_BIT_RATE) /
2100 static_cast<double>(BYTES_TO_BIT) * bufferDurationForPlaying_);
2101 MEDIA_LOG_I("HLS buffer duration for playing : " PUBLIC_LOG ".3f", bufferDurationForPlaying_);
2102 }
2103 }
2104
IsNeedBufferForPlaying()2105 bool HlsMediaDownloader::IsNeedBufferForPlaying()
2106 {
2107 if (bufferDurationForPlaying_ <= 0 || !isDemuxerInitSuccess_.load() || !isBuffering_.load()) {
2108 return false;
2109 }
2110 if (GetBufferingTimeOut()) {
2111 callback_->OnEvent({PluginEventType::CLIENT_ERROR, {NetworkClientErrorCode::ERROR_TIME_OUT},
2112 "buffer for playing"});
2113 isTimeoutErrorNotified_.store(true);
2114 isBuffering_.store(false);
2115 isDemuxerInitSuccess_.store(false);
2116 bufferingTime_ = 0;
2117 return false;
2118 }
2119 if (GetCrossTsBuffersize() >= waterlineForPlaying_ || CheckBreakCondition() ||
2120 (tsStorageInfo_.find(readTsIndex_ + 1) != tsStorageInfo_.end() &&
2121 tsStorageInfo_[readTsIndex_ + 1].second)) {
2122 MEDIA_LOG_I("HLS buffer duration for playing is enough, buffersize: " PUBLIC_LOG_ZU " waterLineAbove: "
2123 PUBLIC_LOG_U64, GetCrossTsBuffersize(), waterlineForPlaying_);
2124 isBuffering_.store(false);
2125 isDemuxerInitSuccess_.store(false);
2126 bufferingTime_ = 0;
2127 return false;
2128 }
2129 return true;
2130 }
2131
NotifyInitSuccess()2132 void HlsMediaDownloader::NotifyInitSuccess()
2133 {
2134 MEDIA_LOG_I("HLS NotifyInitSuccess in");
2135 isDemuxerInitSuccess_.store(true);
2136 if (bufferDurationForPlaying_ <= 0) {
2137 return;
2138 }
2139 uint32_t playlistBitrate = 0;
2140 if (playlistDownloader_ != nullptr) {
2141 playlistBitrate = static_cast<uint32_t>(playlistDownloader_->GetCurBitrate());
2142 }
2143 if (playlistBitrate > 0) {
2144 waterlineForPlaying_ = static_cast<uint64_t>(static_cast<double>(playlistBitrate) /
2145 static_cast<double>(BYTES_TO_BIT) * bufferDurationForPlaying_);
2146 }
2147 isBuffering_.store(true);
2148 bufferingTime_ = static_cast<size_t>(steadyClock_.ElapsedMilliseconds());
2149 }
2150
CheckLoopTimeout(int64_t loopStartTime)2151 bool HlsMediaDownloader::CheckLoopTimeout(int64_t loopStartTime)
2152 {
2153 int64_t now = loopInterruptClock_.ElapsedSeconds();
2154 int64_t loopDuration = now > loopStartTime ? now - loopStartTime : 0;
2155 bool isLoopTimeout = loopDuration > LOOP_TIMEOUT;
2156 if (isLoopTimeout) {
2157 SetDownloadErrorState();
2158 MEDIA_LOG_E("loop timeout.");
2159 }
2160 return isLoopTimeout;
2161 }
2162
GetCachedDuration()2163 uint64_t HlsMediaDownloader::GetCachedDuration()
2164 {
2165 MEDIA_LOG_I("HLS GetCachedDuration: " PUBLIC_LOG_U64, cachedDuration_);
2166 return cachedDuration_;
2167 }
2168
GetStreamInfo(std::vector<StreamInfo> & streams)2169 Status HlsMediaDownloader::GetStreamInfo(std::vector<StreamInfo>& streams)
2170 {
2171 Seekable seekable = Seekable::INVALID;
2172 int retry = 0;
2173 do {
2174 seekable = GetSeekable();
2175 retry++;
2176 if (seekable == Seekable::INVALID) {
2177 if (retry >= MAX_RETRY) {
2178 break;
2179 }
2180 }
2181 } while (seekable == Seekable::INVALID && !isInterruptNeeded_.load());
2182
2183 if (playlistDownloader_) {
2184 playlistDownloader_->GetStreamInfo(streams);
2185 MEDIA_LOG_I("HLS GetStreamInfo " PUBLIC_LOG_ZU, streams.size());
2186 }
2187 return Status::OK;
2188 }
2189
IsHlsFmp4()2190 bool HlsMediaDownloader::IsHlsFmp4()
2191 {
2192 if (playlistDownloader_) {
2193 return playlistDownloader_->IsHlsFmp4();
2194 }
2195 return false;
2196 }
2197
IsPureByteRange()2198 bool HlsMediaDownloader::IsPureByteRange()
2199 {
2200 if (playlistDownloader_) {
2201 return playlistDownloader_->IsPureByteRange();
2202 }
2203 return false;
2204 }
2205
HandleSeekReady(int32_t streamType,int32_t streamId,int32_t isEos)2206 void HlsMediaDownloader::HandleSeekReady(int32_t streamType, int32_t streamId, int32_t isEos)
2207 {
2208 if (playlistDownloader_ && !playlistDownloader_->IsHlsFmp4()) {
2209 return;
2210 }
2211 Format seekReadyInfo {};
2212 seekReadyInfo.PutIntValue("currentStreamType", streamType);
2213 seekReadyInfo.PutIntValue("currentStreamId", streamId);
2214 seekReadyInfo.PutIntValue("isEOS", isEos);
2215 MEDIA_LOG_D("StreamType: " PUBLIC_LOG_D32 " StreamId: " PUBLIC_LOG_D32 " isEOS: " PUBLIC_LOG_D32,
2216 streamType, streamId, isEos);
2217 if (callback_ != nullptr) {
2218 callback_->OnEvent({PluginEventType::HLS_SEEK_READY, seekReadyInfo, "hls_seek_ready"});
2219 }
2220 }
2221 }
2222 }
2223 }
2224 }