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