• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define HST_LOG_TAG "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 }