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 }