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