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