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