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
16 #define MEDIA_PLUGIN
17 #define HST_LOG_TAG "Downloader"
18
19 #include "avcodec_trace.h"
20 #include "downloader.h"
21 #include "osal/utils/steady_clock.h"
22 #include "securec.h"
23 #include "plugin/plugin_time.h"
24 #include "syspara/parameter.h"
25
26 namespace OHOS {
27 namespace Media {
28 namespace Plugins {
29 namespace HttpPlugin {
30 namespace {
31 constexpr int PER_REQUEST_SIZE = 48 * 1024 * 10;
32 constexpr unsigned int SLEEP_TIME = 5; // Sleep 5ms
33 constexpr size_t RETRY_TIMES = 6000; // Retry 6000 times
34 constexpr size_t REQUEST_QUEUE_SIZE = 50;
35 constexpr long LIVE_CONTENT_LENGTH = 2147483646;
36 constexpr int32_t DOWNLOAD_LOG_FEQUENCE = 10;
37 constexpr int32_t LOOP_TIMES = 5;
38 constexpr int32_t MAX_LEN = 128;
39 const std::string USER_AGENT = "User-Agent";
40 const std::string DISPLAYVERSION = "const.product.software.version";
41 constexpr int FIRST_REQUEST_SIZE = 8 * 1024;
42 constexpr int MIN_REQUEST_SIZE = 2;
43 constexpr int SERVER_RANGE_ERROR_CODE = 416;
44 constexpr int32_t LOOP_LOG_FEQUENCE = 50;
45 constexpr int REQUEST_OFTEN_ERROR_CODE = 500;
46 constexpr int SLEEP_TEN_MICRO_SEC = 10; // 10ms
47 constexpr int APP_OPEN_RETRY_TIMES = 10;
48 }
49
DownloadRequest(const std::string & url,DataSaveFunc saveData,StatusCallbackFunc statusCallback,bool requestWholeFile)50 DownloadRequest::DownloadRequest(const std::string& url, DataSaveFunc saveData, StatusCallbackFunc statusCallback,
51 bool requestWholeFile)
52 : url_(url), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
53 requestWholeFile_(requestWholeFile)
54 {
55 (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
56 headerInfo_.fileContentLen = 0;
57 headerInfo_.contentLen = 0;
58 }
59
DownloadRequest(const std::string & url,double duration,DataSaveFunc saveData,StatusCallbackFunc statusCallback,bool requestWholeFile)60 DownloadRequest::DownloadRequest(const std::string& url,
61 double duration,
62 DataSaveFunc saveData,
63 StatusCallbackFunc statusCallback,
64 bool requestWholeFile)
65 : url_(url), duration_(duration), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
66 requestWholeFile_(requestWholeFile)
67 {
68 (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
69 headerInfo_.fileContentLen = 0;
70 headerInfo_.contentLen = 0;
71 }
72
DownloadRequest(DataSaveFunc saveData,StatusCallbackFunc statusCallback,RequestInfo requestInfo,bool requestWholeFile)73 DownloadRequest::DownloadRequest(DataSaveFunc saveData, StatusCallbackFunc statusCallback, RequestInfo requestInfo,
74 bool requestWholeFile)
75 : saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)), requestInfo_(requestInfo),
76 requestWholeFile_(requestWholeFile)
77 {
78 (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
79 headerInfo_.fileContentLen = 0;
80 headerInfo_.contentLen = 0;
81 url_ = requestInfo.url;
82 httpHeader_ = requestInfo.httpHeader;
83 }
84
DownloadRequest(double duration,DataSaveFunc saveData,StatusCallbackFunc statusCallback,RequestInfo requestInfo,bool requestWholeFile)85 DownloadRequest::DownloadRequest(double duration,
86 DataSaveFunc saveData,
87 StatusCallbackFunc statusCallback,
88 RequestInfo requestInfo,
89 bool requestWholeFile)
90 : duration_(duration), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
91 requestInfo_(requestInfo), requestWholeFile_(requestWholeFile)
92 {
93 (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
94 headerInfo_.fileContentLen = 0;
95 headerInfo_.contentLen = 0;
96 url_ = requestInfo.url;
97 httpHeader_ = requestInfo.httpHeader;
98 }
99
GetFileContentLength() const100 size_t DownloadRequest::GetFileContentLength() const
101 {
102 WaitHeaderUpdated();
103 return headerInfo_.GetFileContentLength();
104 }
105
GetFileContentLengthNoWait() const106 size_t DownloadRequest::GetFileContentLengthNoWait() const
107 {
108 return headerInfo_.fileContentLen;
109 }
110
SaveHeader(const HeaderInfo * header)111 void DownloadRequest::SaveHeader(const HeaderInfo* header)
112 {
113 MediaAVCodec::AVCodecTrace trace("DownloadRequest::SaveHeader");
114 headerInfo_.Update(header);
115 isHeaderUpdated_ = true;
116 }
117
IsChunked(bool isInterruptNeeded)118 Seekable DownloadRequest::IsChunked(bool isInterruptNeeded)
119 {
120 isInterruptNeeded_ = isInterruptNeeded;
121 WaitHeaderUpdated();
122 if (isInterruptNeeded) {
123 MEDIA_LOG_I("Canceled");
124 return Seekable::INVALID;
125 }
126 if (headerInfo_.isChunked) {
127 return GetFileContentLength() == LIVE_CONTENT_LENGTH ? Seekable::SEEKABLE : Seekable::UNSEEKABLE;
128 } else {
129 return Seekable::SEEKABLE;
130 }
131 };
132
IsEos() const133 bool DownloadRequest::IsEos() const
134 {
135 return isEos_;
136 }
137
GetRetryTimes() const138 int DownloadRequest::GetRetryTimes() const
139 {
140 return retryTimes_;
141 }
142
GetClientError() const143 int32_t DownloadRequest::GetClientError() const
144 {
145 return clientError_;
146 }
147
GetServerError() const148 int32_t DownloadRequest::GetServerError() const
149 {
150 return serverError_;
151 }
152
IsClosed() const153 bool DownloadRequest::IsClosed() const
154 {
155 return headerInfo_.isClosed;
156 }
157
Close()158 void DownloadRequest::Close()
159 {
160 headerInfo_.isClosed = true;
161 }
162
WaitHeaderUpdated() const163 void DownloadRequest::WaitHeaderUpdated() const
164 {
165 isHeaderUpdating_ = true;
166 MediaAVCodec::AVCodecTrace trace("DownloadRequest::WaitHeaderUpdated");
167 // Wait Header(fileContentLen etc.) updated
168 while (!isHeaderUpdated_ && times_ < RETRY_TIMES && !isInterruptNeeded_ && !headerInfo_.isClosed) {
169 Task::SleepInTask(SLEEP_TIME);
170 times_++;
171 }
172 MEDIA_LOG_D("isHeaderUpdated_ " PUBLIC_LOG_D32 ", times " PUBLIC_LOG_ZU ", isClosed " PUBLIC_LOG_D32,
173 isHeaderUpdated_.load(), times_.load(), headerInfo_.isClosed.load());
174 isHeaderUpdating_ = false;
175 }
176
GetDuration() const177 double DownloadRequest::GetDuration() const
178 {
179 return duration_;
180 }
181
SetStartTimePos(int64_t startTimePos)182 void DownloadRequest::SetStartTimePos(int64_t startTimePos)
183 {
184 startTimePos_ = startTimePos;
185 if (startTimePos_ > 0) {
186 shouldSaveData_ = false;
187 }
188 }
189
SetRangePos(int64_t startPos,int64_t endPos)190 void DownloadRequest::SetRangePos(int64_t startPos, int64_t endPos)
191 {
192 startPos_ = startPos;
193 endPos_ = endPos;
194 }
195
SetDownloadDoneCb(DownloadDoneCbFunc downloadDoneCallback)196 void DownloadRequest::SetDownloadDoneCb(DownloadDoneCbFunc downloadDoneCallback)
197 {
198 downloadDoneCallback_ = downloadDoneCallback;
199 }
200
GetNowTime()201 int64_t DownloadRequest::GetNowTime()
202 {
203 return std::chrono::duration_cast<std::chrono::milliseconds>
204 (std::chrono::system_clock::now().time_since_epoch()).count();
205 }
206
GetBitRate() const207 uint32_t DownloadRequest::GetBitRate() const
208 {
209 if ((downloadDoneTime_ == 0) || (downloadStartTime_ == 0) || (realRecvContentLen_ == 0)) {
210 return 0;
211 }
212 int64_t timeGap = downloadDoneTime_ - downloadStartTime_;
213 if (timeGap == 0) {
214 return 0;
215 }
216 uint32_t bitRate = static_cast<uint32_t>(realRecvContentLen_ * 1000 *
217 1 * 8 / timeGap); // 1000:ms to sec 1:weight 8:byte to bit
218 return bitRate;
219 }
220
IsChunkedVod() const221 bool DownloadRequest::IsChunkedVod() const
222 {
223 return headerInfo_.isChunked && headerInfo_.GetFileContentLength() == LIVE_CONTENT_LENGTH;
224 }
225
IsM3u8Request() const226 bool DownloadRequest::IsM3u8Request() const
227 {
228 return protocolType_ == RequestProtocolType::HLS;
229 }
230
SetRequestProtocolType(RequestProtocolType protocolType)231 void DownloadRequest::SetRequestProtocolType(RequestProtocolType protocolType)
232 {
233 protocolType_ = protocolType;
234 }
235
IsServerAcceptRange() const236 bool DownloadRequest::IsServerAcceptRange() const
237 {
238 if (headerInfo_.isChunked) {
239 return false;
240 }
241 return headerInfo_.isServerAcceptRange;
242 }
243
~DownloadRequest()244 DownloadRequest::~DownloadRequest()
245 {
246 MEDIA_LOG_D("~DownloadRequest dtor in.");
247 int sleepTmpTime = 0;
248 while (isHeaderUpdating_.load() && sleepTmpTime < RETRY_TIMES) {
249 Task::SleepInTask(SLEEP_TIME);
250 sleepTmpTime++;
251 }
252 }
253
GetLocation(std::string & location) const254 void DownloadRequest::GetLocation(std::string& location) const
255 {
256 location = location_;
257 }
258
Downloader(const std::string & name)259 Downloader::Downloader(const std::string& name) noexcept : name_(std::move(name))
260 {
261 shouldStartNextRequest = true;
262
263 client_ = NetworkClient::GetInstance(&RxHeaderData, &RxBodyData, this);
264 DonwloaderInit(name);
265 }
266
DonwloaderInit(const std::string & name)267 void Downloader::DonwloaderInit(const std::string& name)
268 {
269 client_->Init();
270 requestQue_ = std::make_shared<BlockingQueue<std::shared_ptr<DownloadRequest>>>(name_ + "RequestQue",
271 REQUEST_QUEUE_SIZE);
272 task_ = std::make_shared<Task>(std::string("OS_" + name_ + "Downloader"));
273 task_->RegisterJob([this] {
274 {
275 AutoLock lk(loopPauseMutex_);
276 if (loopStatus_ == LoopStatus::PAUSE) {
277 MEDIA_LOG_I("0x%{public}06" PRIXPTR " loopStatus PAUSE to START", FAKE_POINTER(this));
278 }
279 loopStatus_ = LoopStatus::START;
280 }
281 HttpDownloadLoop();
282 NotifyLoopPause();
283 return 0;
284 });
285 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader ctor", FAKE_POINTER(this));
286 }
287
Downloader(const std::string & name,std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)288 Downloader::Downloader(const std::string& name, std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader) noexcept
289 {
290 name_ = name;
291 shouldStartNextRequest = true;
292 if (sourceLoader != nullptr) {
293 isNotBlock_ = true;
294 sourceLoader_ = sourceLoader;
295 client_ = NetworkClient::GetAppInstance(&RxHeaderData, &RxBodyData, this);
296 client_->SetLoader(sourceLoader->loader_);
297 MEDIA_LOG_I("0x%{public}06" PRIXPTR "Get app instance success", FAKE_POINTER(this));
298 } else {
299 MEDIA_LOG_I("0x%{public}06" PRIXPTR "Get libcurl instance success", FAKE_POINTER(this));
300 client_ = NetworkClient::GetInstance(&RxHeaderData, &RxBodyData, this);
301 }
302 DonwloaderInit(name);
303 }
304
~Downloader()305 Downloader::~Downloader()
306 {
307 isDestructor_ = true;
308 MEDIA_LOG_I("~Downloader In");
309 {
310 AutoLock lock(closeMutex_);
311 if (sourceLoader_ != nullptr) {
312 sourceLoader_->Close(uuid_);
313 sourceLoader_ = nullptr;
314 }
315 }
316 Stop(false);
317 if (task_ != nullptr) {
318 task_ = nullptr;
319 }
320 if (client_ != nullptr) {
321 client_->Deinit();
322 client_ = nullptr;
323 }
324 MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~Downloader dtor", FAKE_POINTER(this));
325 }
326
Download(const std::shared_ptr<DownloadRequest> & request,int32_t waitMs)327 bool Downloader::Download(const std::shared_ptr<DownloadRequest>& request, int32_t waitMs)
328 {
329 MEDIA_LOG_I("In");
330 if (isInterruptNeeded_) {
331 request->isInterruptNeeded_ = true;
332 }
333 requestQue_->SetActive(true);
334 if (waitMs == -1) { // wait until push success
335 requestQue_->Push(request);
336 return true;
337 }
338 return requestQue_->Push(request, static_cast<int>(waitMs));
339 }
340
Start()341 void Downloader::Start()
342 {
343 MediaAVCodec::AVCodecTrace trace("Downloader::Start");
344 MEDIA_LOG_I("start Begin");
345 requestQue_->SetActive(true);
346 task_->Start();
347 MEDIA_LOG_I("start End");
348 }
349
Pause(bool isAsync)350 void Downloader::Pause(bool isAsync)
351 {
352 MediaAVCodec::AVCodecTrace trace("Downloader::Pause");
353 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Pause Begin", FAKE_POINTER(this));
354 requestQue_->SetActive(false, false);
355 if (client_ != nullptr) {
356 isClientClose_ = true;
357 client_->Close(isAsync);
358 }
359 PauseLoop(true);
360 if (!isAsync) {
361 WaitLoopPause();
362 }
363 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Pause End", FAKE_POINTER(this));
364 }
365
Cancel()366 void Downloader::Cancel()
367 {
368 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Cancel Begin", FAKE_POINTER(this));
369 if (currentRequest_ != nullptr && currentRequest_->retryTimes_ > 0) {
370 currentRequest_->retryTimes_ = 0;
371 }
372 requestQue_->SetActive(false, true);
373 shouldStartNextRequest = true;
374 if (client_ != nullptr) {
375 client_->Close(false);
376 }
377 PauseLoop(true);
378 WaitLoopPause();
379 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Cancel End", FAKE_POINTER(this));
380 }
381
382
Resume()383 void Downloader::Resume()
384 {
385 MediaAVCodec::AVCodecTrace trace("Downloader::Resume");
386 FALSE_RETURN_MSG(!isDestructor_ && !isInterruptNeeded_, "not Resume. is Destructor or InterruptNeeded");
387 {
388 AutoLock lock(operatorMutex_);
389 MEDIA_LOG_I("resume Begin");
390 if (isClientClose_ && client_ != nullptr && currentRequest_ != nullptr) {
391 isClientClose_ = false;
392 client_->Open(currentRequest_->url_, currentRequest_->httpHeader_, currentRequest_->requestInfo_.timeoutMs);
393 }
394 requestQue_->SetActive(true);
395 if (currentRequest_ != nullptr) {
396 currentRequest_->isEos_ = false;
397
398 int64_t fileLength = static_cast<int64_t>(currentRequest_->GetFileContentLength());
399 if (currentRequest_->startPos_ + currentRequest_->requestSize_ > fileLength) {
400 int correctRequestSize = fileLength - currentRequest_->startPos_;
401 MEDIA_LOG_E("resume error startPos = " PUBLIC_LOG_D64 ", requestSize = " PUBLIC_LOG_D32
402 ", fileLength = " PUBLIC_LOG_D64 ", correct requestSize = " PUBLIC_LOG_D32,
403 currentRequest_->startPos_, currentRequest_->requestSize_, fileLength, correctRequestSize);
404 if (currentRequest_->startPos_ < fileLength) {
405 currentRequest_->requestSize_ = correctRequestSize;
406 }
407 }
408 }
409 }
410 Start();
411 MEDIA_LOG_I("resume End");
412 }
413
Stop(bool isAsync)414 void Downloader::Stop(bool isAsync)
415 {
416 MediaAVCodec::AVCodecTrace trace("Downloader::Stop");
417 MEDIA_LOG_I("Stop Begin");
418 isDestructor_ = true;
419 if (requestQue_ != nullptr) {
420 requestQue_->SetActive(false);
421 }
422 if (currentRequest_ != nullptr) {
423 currentRequest_->isInterruptNeeded_ = true;
424 currentRequest_->Close();
425 }
426 if (client_ != nullptr) {
427 client_->Close(isAsync);
428 if (!isAsync) {
429 client_->Deinit();
430 }
431 }
432 shouldStartNextRequest = true;
433 if (task_ != nullptr) {
434 if (isAsync) {
435 task_->StopAsync();
436 } else {
437 task_->Stop();
438 }
439 }
440 MEDIA_LOG_I("Stop End");
441 }
442
Seek(int64_t offset)443 bool Downloader::Seek(int64_t offset)
444 {
445 MediaAVCodec::AVCodecTrace trace("Downloader::Seek, offset: " + std::to_string(offset));
446 FALSE_RETURN_V_MSG(!isDestructor_ && !isInterruptNeeded_, false, "Seek fail, is Destructor or InterruptNeeded");
447 AutoLock lock(operatorMutex_);
448 FALSE_RETURN_V_MSG(currentRequest_ != nullptr, false, "Seek fail, currentRequest nullptr");
449 size_t contentLength = currentRequest_->GetFileContentLength();
450 MEDIA_LOG_I("Seek Begin, offset = " PUBLIC_LOG_D64 ", contentLength = " PUBLIC_LOG_ZU, offset, contentLength);
451 if (offset >= 0 && offset < static_cast<int64_t>(contentLength)) {
452 currentRequest_->startPos_ = offset;
453 }
454 size_t temp = currentRequest_->GetFileContentLength() - static_cast<size_t>(currentRequest_->startPos_);
455 currentRequest_->requestSize_ = static_cast<int>(std::min(temp, static_cast<size_t>(PER_REQUEST_SIZE)));
456 if (downloadRequestSize_ > 0) {
457 currentRequest_->requestSize_ = std::min(currentRequest_->requestSize_,
458 static_cast<int>(downloadRequestSize_));
459 downloadRequestSize_ = 0;
460 }
461 currentRequest_->isEos_ = false;
462 shouldStartNextRequest = false; // Reuse last request when seek
463 if (currentRequest_->retryTimes_ > 0) {
464 currentRequest_->retryTimes_ = 0;
465 }
466 return true;
467 }
468
SetRequestSize(size_t downloadRequestSize)469 void Downloader::SetRequestSize(size_t downloadRequestSize)
470 {
471 downloadRequestSize_ = downloadRequestSize;
472 }
473
GetIp(std::string & ip)474 void Downloader::GetIp(std::string &ip)
475 {
476 if (client_ != nullptr) {
477 client_->GetIp(ip);
478 }
479 }
480
481 // Pause download thread before use currentRequest_
Retry(const std::shared_ptr<DownloadRequest> & request)482 bool Downloader::Retry(const std::shared_ptr<DownloadRequest>& request)
483 {
484 FALSE_RETURN_V_MSG(client_ != nullptr && !isDestructor_ && !isInterruptNeeded_, false,
485 "not Retry, client null or isDestructor or isInterruptNeeded");
486 if (isAppBackground_) {
487 Pause(true);
488 MEDIA_LOG_I("Retry avoid, forground to background.");
489 return true;
490 }
491 {
492 AutoLock lock(operatorMutex_);
493 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Retry Begin", FAKE_POINTER(this));
494 FALSE_RETURN_V(client_ != nullptr && !shouldStartNextRequest && !isDestructor_ && !isInterruptNeeded_, false);
495 requestQue_->SetActive(false, false);
496 }
497 PauseLoop(true);
498 WaitLoopPause();
499 {
500 AutoLock lock(operatorMutex_);
501 FALSE_RETURN_V(client_ != nullptr && !shouldStartNextRequest && !isDestructor_ && !isInterruptNeeded_, false);
502 client_->Close(false);
503 if (currentRequest_ != nullptr) {
504 if (currentRequest_->IsSame(request) && !shouldStartNextRequest) {
505 currentRequest_->retryTimes_++;
506 currentRequest_->retryOnGoing_ = true;
507 currentRequest_->dropedDataLen_ = 0;
508 }
509 client_->Open(currentRequest_->url_, currentRequest_->httpHeader_, currentRequest_->requestInfo_.timeoutMs);
510 requestQue_->SetActive(true);
511 currentRequest_->isEos_ = false;
512 if (currentRequest_->endPos_ > 0 && currentRequest_->startPos_ >= 0 &&
513 currentRequest_->endPos_ >= currentRequest_->startPos_) {
514 currentRequest_->requestSize_ = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
515 }
516 }
517 }
518 task_->Start();
519 MEDIA_LOG_I("Do retry.");
520 return true;
521 }
522
GetSystemParam(const std::string & key)523 std::string GetSystemParam(const std::string &key)
524 {
525 char value[MAX_LEN] = {0};
526 int32_t ret = GetParameter(key.c_str(), "", value, MAX_LEN);
527 if (ret < 0) {
528 return "";
529 }
530 return std::string(value);
531 }
532
GetUserAgent()533 std::string GetUserAgent()
534 {
535 std::string displayVersion = GetSystemParam(DISPLAYVERSION);
536 std::string userAgent = " AVPlayerLib " + displayVersion;
537 return userAgent;
538 }
539
BeginDownload()540 bool Downloader::BeginDownload()
541 {
542 MEDIA_LOG_I("BeginDownload");
543 std::string url = currentRequest_->url_;
544 std::map<std::string, std::string> httpHeader = currentRequest_->httpHeader_;
545
546 if (currentRequest_->httpHeader_.count(USER_AGENT) <= 0) {
547 currentRequest_->httpHeader_[USER_AGENT] = GetUserAgent();
548 httpHeader[USER_AGENT] = GetUserAgent();
549 MEDIA_LOG_I("Set default UA.");
550 }
551
552 int32_t timeoutMs = currentRequest_->requestInfo_.timeoutMs;
553 FALSE_RETURN_V(!url.empty(), false);
554 if (client_) {
555 client_->Open(url, httpHeader, timeoutMs);
556 }
557
558 if (currentRequest_->endPos_ <= 0) {
559 currentRequest_->startPos_ = 0;
560 currentRequest_->requestSize_ = FIRST_REQUEST_SIZE;
561 } else {
562 int64_t temp = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
563 currentRequest_->requestSize_ = static_cast<int>(std::min(temp, static_cast<int64_t>(PER_REQUEST_SIZE)));
564 }
565 currentRequest_->isEos_ = false;
566 currentRequest_->retryTimes_ = 0;
567 currentRequest_->downloadStartTime_ = currentRequest_->GetNowTime();
568 MEDIA_LOG_I("End");
569 return true;
570 }
571
HttpDownloadLoop()572 void Downloader::HttpDownloadLoop()
573 {
574 AutoLock lock(operatorMutex_);
575 MEDIA_LOGI_LIMIT(LOOP_LOG_FEQUENCE, "Downloader loop shouldStartNextRequest %{public}d",
576 shouldStartNextRequest.load());
577 if (shouldStartNextRequest) {
578 std::shared_ptr<DownloadRequest> tempRequest = requestQue_->Pop(1000); // 1000ms timeout limit.
579 if (!tempRequest) {
580 MEDIA_LOG_W("HttpDownloadLoop tempRequest is null.");
581 noTaskLoopTimes_++;
582 if (noTaskLoopTimes_ >= LOOP_TIMES) {
583 PauseLoop(true);
584 }
585 return;
586 }
587 noTaskLoopTimes_ = 0;
588 currentRequest_ = tempRequest;
589 if (isInterruptNeeded_) {
590 currentRequest_->isInterruptNeeded_ = true;
591 }
592 BeginDownload();
593 shouldStartNextRequest = currentRequest_->IsClosed();
594 }
595 if (currentRequest_ == nullptr || client_ == nullptr) {
596 MEDIA_LOG_I("currentRequest_ %{public}d client_ %{public}d nullptr",
597 currentRequest_ != nullptr, client_ != nullptr);
598 PauseLoop(true);
599 return;
600 }
601 RequestData();
602 return;
603 }
604
OpenAppUri()605 void Downloader::OpenAppUri()
606 {
607 {
608 AutoLock lock(closeMutex_);
609 appPreviousRequestUrl_ = currentRequest_->GetUrl();
610 if (sourceLoader_ != nullptr && currentRequest_ != nullptr) {
611 if (uuid_ != 0) {
612 sourceLoader_->Close(uuid_);
613 MEDIA_LOG_D("0x%{public}06" PRIXPTR "LoaderCombinations Close uuid " PUBLIC_LOG_D64,
614 FAKE_POINTER(this), uuid_);
615 }
616
617 int64_t uuid = 0;
618 for (int i = 0; i < APP_OPEN_RETRY_TIMES; i++) {
619 uuid = sourceLoader_->Open(appPreviousRequestUrl_, currentRequest_->GetHttpHeader(), client_);
620 if (uuid > 0) {
621 break;
622 }
623 MEDIA_LOG_D("0x%{public}06" PRIXPTR "Open retry " PUBLIC_LOG_D64 " retryTimes: " PUBLIC_LOG_D32,
624 FAKE_POINTER(this), uuid, i);
625 }
626 MEDIA_LOG_I("0x%{public}06" PRIXPTR "LoaderCombinations Open uuid " PUBLIC_LOG_D64,
627 FAKE_POINTER(this), uuid);
628 if (uuid != 0) {
629 client_->SetUuid(uuid);
630 uuid_ = uuid;
631 } else {
632 MEDIA_LOG_E("0x%{public}06" PRIXPTR "Open faild, uuid " PUBLIC_LOG_D64,
633 FAKE_POINTER(this), uuid);
634 std::shared_ptr<Downloader> unused;
635 currentRequest_->statusCallback_(DownloadStatus::PARTTAL_DOWNLOAD, unused, currentRequest_);
636 }
637 }
638 }
639 }
640
RequestData()641 void Downloader::RequestData()
642 {
643 MediaAVCodec::AVCodecTrace trace("Downloader::HttpDownloadLoop, startPos: "
644 + std::to_string(currentRequest_->startPos_) + ", reqSize: " + std::to_string(currentRequest_->requestSize_));
645 int64_t startPos = currentRequest_->startPos_;
646 if (currentRequest_->requestWholeFile_ && currentRequest_->shouldSaveData_) {
647 startPos = -1;
648 }
649 RequestInfo sourceInfo;
650 sourceInfo.url = currentRequest_->url_;
651 sourceInfo.httpHeader = currentRequest_->httpHeader_;
652 sourceInfo.timeoutMs = currentRequest_->requestInfo_.timeoutMs;
653
654 if ((currentRequest_->protocolType_ == RequestProtocolType::HTTP && uuid_ == 0) ||
655 currentRequest_->protocolType_ == RequestProtocolType::HLS ||
656 currentRequest_->protocolType_ == RequestProtocolType::DASH) {
657 OpenAppUri();
658 }
659
660 auto handleResponseCb = [this](int32_t clientCode, int32_t serverCode, Status ret) {
661 currentRequest_->clientError_ = clientCode;
662 currentRequest_->serverError_ = serverCode;
663 if (isDestructor_) {
664 return;
665 }
666 if (currentRequest_->requestSize_ == FIRST_REQUEST_SIZE && !currentRequest_->isFirstRangeRequestReady_
667 && currentRequest_->serverError_ == SERVER_RANGE_ERROR_CODE) {
668 MEDIA_LOG_I("first request is above filesize, need retry.");
669 currentRequest_->startPos_ = 0;
670 currentRequest_->requestSize_ = MIN_REQUEST_SIZE;
671 currentRequest_->isHeaderUpdated_ = false;
672 currentRequest_->isFirstRangeRequestReady_ = true;
673 currentRequest_->headerInfo_.fileContentLen = 0;
674 return;
675 }
676 if (ret == Status::OK) {
677 HandleRetOK();
678 } else {
679 PauseLoop(true);
680 MEDIA_LOG_E("Client request data failed. ret = " PUBLIC_LOG_D32 ", clientCode = " PUBLIC_LOG_D32
681 ",request queue size: " PUBLIC_LOG_U64, static_cast<int32_t>(ret),
682 static_cast<int32_t>(clientCode), static_cast<int64_t>(requestQue_->Size()));
683 HandleRetErrorCode();
684 std::shared_ptr<Downloader> unused;
685 currentRequest_->statusCallback_(DownloadStatus::PARTTAL_DOWNLOAD, unused, currentRequest_);
686 }
687 };
688 MEDIA_LOG_I("0x%{public}06" PRIXPTR " RequestData enter.", FAKE_POINTER(this));
689 client_->RequestData(startPos, currentRequest_->requestSize_, sourceInfo, handleResponseCb);
690 MEDIA_LOG_I("0x%{public}06" PRIXPTR " RequestData end.", FAKE_POINTER(this));
691 }
692
HandleRetErrorCode()693 void Downloader::HandleRetErrorCode()
694 {
695 if (currentRequest_ && currentRequest_->serverError_ == REQUEST_OFTEN_ERROR_CODE) {
696 int sleepTime = 0;
697 while (!isInterruptNeeded_ && sleepTime <= 1000) { // 1000:sleep 1s
698 Task::SleepInTask(SLEEP_TEN_MICRO_SEC);
699 sleepTime += SLEEP_TEN_MICRO_SEC;
700 }
701 }
702 }
HandlePlayingFinish()703 void Downloader::HandlePlayingFinish()
704 {
705 if (requestQue_->Empty()) {
706 PauseLoop(true);
707 }
708 shouldStartNextRequest = true;
709 if (currentRequest_->downloadDoneCallback_ && !isDestructor_) {
710 currentRequest_->downloadDoneTime_ = currentRequest_->GetNowTime();
711 currentRequest_->downloadDoneCallback_(currentRequest_->GetUrl(), currentRequest_->location_);
712 currentRequest_->isFirstRangeRequestReady_ = false;
713 }
714 }
715
HandleRetOK()716 void Downloader::HandleRetOK()
717 {
718 if (currentRequest_->retryTimes_ > 0) {
719 currentRequest_->retryTimes_ = 0;
720 }
721 if (currentRequest_->headerInfo_.isChunked && requestQue_->Empty()) {
722 currentRequest_->isEos_ = true;
723 PauseLoop(true);
724 return;
725 }
726
727 int64_t remaining = 0;
728 if (currentRequest_->endPos_ <= 0) {
729 remaining = static_cast<int64_t>(currentRequest_->headerInfo_.fileContentLen) -
730 currentRequest_->startPos_;
731 } else {
732 remaining = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
733 }
734 if (currentRequest_->headerInfo_.fileContentLen > 0 && remaining <= 0) { // Check whether the playback ends.
735 MEDIA_LOG_I("http transfer reach end, startPos_ " PUBLIC_LOG_D64, currentRequest_->startPos_);
736 currentRequest_->isEos_ = true;
737 HandlePlayingFinish();
738 return;
739 }
740 if (currentRequest_->headerInfo_.fileContentLen == 0 && remaining <= 0) {
741 currentRequest_->isEos_ = true;
742 currentRequest_->Close();
743 HandlePlayingFinish();
744 return;
745 }
746 if (remaining < PER_REQUEST_SIZE) {
747 currentRequest_->requestSize_ = remaining;
748 } else {
749 currentRequest_->requestSize_ = PER_REQUEST_SIZE;
750 }
751 }
752
UpdateHeaderInfo(Downloader * mediaDownloader)753 void Downloader::UpdateHeaderInfo(Downloader* mediaDownloader)
754 {
755 if (mediaDownloader->currentRequest_->isHeaderUpdated_) {
756 return;
757 }
758 MEDIA_LOG_I("UpdateHeaderInfo enter.");
759 HeaderInfo* info = &(mediaDownloader->currentRequest_->headerInfo_);
760 if (info->contentLen > 0 && info->contentLen < LIVE_CONTENT_LENGTH) {
761 info->isChunked = false;
762 }
763 if (info->contentLen <= 0 && !mediaDownloader->currentRequest_->IsM3u8Request()) {
764 info->isChunked = true;
765 }
766 if (info->fileContentLen > 0 && info->isChunked && !mediaDownloader->currentRequest_->IsM3u8Request()) {
767 info->isChunked = false;
768 }
769 mediaDownloader->currentRequest_->SaveHeader(info);
770 }
771
IsDropDataRetryRequest(Downloader * mediaDownloader)772 bool Downloader::IsDropDataRetryRequest(Downloader* mediaDownloader)
773 {
774 bool isWholeFileRetry = mediaDownloader->currentRequest_->requestWholeFile_ &&
775 mediaDownloader->currentRequest_->shouldSaveData_ &&
776 mediaDownloader->currentRequest_->retryOnGoing_;
777 if (!isWholeFileRetry) {
778 return false;
779 }
780 if (mediaDownloader->currentRequest_->startPos_ > 0) {
781 return true;
782 } else {
783 mediaDownloader->currentRequest_->retryOnGoing_ = false;
784 return false;
785 }
786 }
787
DropRetryData(void * buffer,size_t dataLen,Downloader * mediaDownloader)788 size_t Downloader::DropRetryData(void* buffer, size_t dataLen, Downloader* mediaDownloader)
789 {
790 auto currentRequest_ = mediaDownloader->currentRequest_;
791 int64_t writeOffSet = -1;
792 if (currentRequest_->startPos_ > 0) {
793 writeOffSet = currentRequest_->startPos_ >= static_cast<int64_t>(dataLen) ?
794 0 : currentRequest_->startPos_; // 0:drop all
795 }
796 bool dropRet = false;
797 uint32_t writeLen = 0;
798 if (writeOffSet > 0) {
799 int64_t secondParam = static_cast<int64_t>(dataLen) - writeOffSet;
800 if (secondParam < 0) {
801 secondParam = 0;
802 }
803 writeLen = currentRequest_->saveData_(static_cast<uint8_t *>(buffer) + writeOffSet,
804 static_cast<uint32_t>(secondParam), mediaDownloader->isNotBlock_);
805 dropRet = writeLen == secondParam;
806 currentRequest_->dropedDataLen_ = currentRequest_->dropedDataLen_ + writeOffSet;
807 MEDIA_LOG_D("DropRetryData: last drop, droped len " PUBLIC_LOG_D64 ", startPos_ " PUBLIC_LOG_D64,
808 currentRequest_->dropedDataLen_, currentRequest_->startPos_);
809 } else if (writeOffSet == 0) {
810 currentRequest_->dropedDataLen_ += static_cast<int64_t>(dataLen);
811 dropRet = true;
812 MEDIA_LOG_D("DropRetryData: drop, droped len " PUBLIC_LOG_D64 ", startPos_ " PUBLIC_LOG_D64,
813 currentRequest_->dropedDataLen_, currentRequest_->startPos_);
814 } else {
815 MEDIA_LOG_E("drop data error");
816 }
817 if (dropRet && currentRequest_->startPos_ == currentRequest_->dropedDataLen_) {
818 currentRequest_->retryOnGoing_ = false;
819 currentRequest_->dropedDataLen_ = 0;
820 if (writeOffSet > 0) {
821 currentRequest_->startPos_ += static_cast<int64_t>(dataLen) - writeOffSet;
822 }
823 MEDIA_LOG_I("drop data finished, startPos_ " PUBLIC_LOG_D64, currentRequest_->startPos_);
824 }
825 if (!dropRet && mediaDownloader->sourceLoader_ != nullptr) {
826 mediaDownloader->currentRequest_->startPos_ += static_cast<int64_t>(writeLen);
827 mediaDownloader->PauseLoop(true);
828 mediaDownloader->currentRequest_->retryOnGoing_ = true;
829 mediaDownloader->currentRequest_->dropedDataLen_ = 0;
830 }
831 return dropRet ? dataLen : 0; // 0:save data failed or drop error
832 }
833
UpdateCurRequest(Downloader * mediaDownloader,HeaderInfo * header)834 void Downloader::UpdateCurRequest(Downloader* mediaDownloader, HeaderInfo* header)
835 {
836 int64_t hstTime = 0;
837 Sec2HstTime(mediaDownloader->currentRequest_->GetDuration(), hstTime);
838 int64_t startTimePos = mediaDownloader->currentRequest_->startTimePos_;
839 int64_t contenLen = static_cast<int64_t>(header->fileContentLen);
840 int64_t startPos = 0;
841 if (hstTime != 0) {
842 startPos = contenLen * startTimePos / (HstTime2Ns(hstTime));
843 }
844 mediaDownloader->currentRequest_->startPos_ = startPos;
845 mediaDownloader->currentRequest_->shouldSaveData_ = true;
846 mediaDownloader->currentRequest_->requestWholeFile_ = false;
847 mediaDownloader->currentRequest_->requestSize_ = PER_REQUEST_SIZE;
848 mediaDownloader->currentRequest_->startTimePos_ = 0;
849 }
850
HandleFileContentLen(HeaderInfo * header)851 void Downloader::HandleFileContentLen(HeaderInfo* header)
852 {
853 if (header->fileContentLen == 0) {
854 if (header->contentLen > 0) {
855 MEDIA_LOG_W("Unsupported range, use content length as content file length, contentLen: " PUBLIC_LOG_D32,
856 static_cast<int32_t>(header->contentLen));
857 header->fileContentLen = static_cast<size_t>(header->contentLen);
858 } else {
859 MEDIA_LOG_D("fileContentLen and contentLen are both zero.");
860 }
861 }
862 }
863
RxBodyData(void * buffer,size_t size,size_t nitems,void * userParam)864 size_t Downloader::RxBodyData(void* buffer, size_t size, size_t nitems, void* userParam)
865 {
866 auto mediaDownloader = static_cast<Downloader *>(userParam);
867 size_t dataLen = size * nitems;
868 int64_t curLen = mediaDownloader->currentRequest_->realRecvContentLen_;
869 int64_t realRecvContentLen = static_cast<int64_t>(dataLen) + curLen;
870 UpdateHeaderInfo(mediaDownloader);
871 MediaAVCodec::AVCodecTrace trace("Downloader::RxBodyData, dataLen: " + std::to_string(dataLen)
872 + ", realRecvContentLen: " + std::to_string(realRecvContentLen));
873 mediaDownloader->currentRequest_->realRecvContentLen_ = realRecvContentLen;
874
875 if (IsDropDataRetryRequest(mediaDownloader) && !mediaDownloader->currentRequest_->IsIndexM3u8Request()) {
876 return DropRetryData(buffer, dataLen, mediaDownloader);
877 }
878 HeaderInfo* header = &(mediaDownloader->currentRequest_->headerInfo_);
879 if (!mediaDownloader->currentRequest_->shouldSaveData_) {
880 UpdateCurRequest(mediaDownloader, header);
881 return dataLen;
882 }
883 HandleFileContentLen(header);
884 if (!mediaDownloader->currentRequest_->isDownloading_) {
885 mediaDownloader->currentRequest_->isDownloading_ = true;
886 }
887 uint32_t writeLen = mediaDownloader->currentRequest_->saveData_(static_cast<uint8_t *>(buffer),
888 static_cast<uint32_t>(dataLen), mediaDownloader->isNotBlock_);
889 MEDIA_LOGI_LIMIT(DOWNLOAD_LOG_FEQUENCE, "RxBodyData: dataLen " PUBLIC_LOG_ZU ", startPos_ " PUBLIC_LOG_D64, dataLen,
890 mediaDownloader->currentRequest_->startPos_);
891 mediaDownloader->currentRequest_->startPos_ = mediaDownloader->currentRequest_->startPos_ +
892 static_cast<int64_t>(writeLen);
893
894 int64_t remaining = 0;
895 if (mediaDownloader->currentRequest_->endPos_ <= 0) {
896 remaining = static_cast<int64_t>(mediaDownloader->currentRequest_->headerInfo_.fileContentLen) -
897 mediaDownloader->currentRequest_->startPos_;
898 } else {
899 remaining = mediaDownloader->currentRequest_->endPos_ - mediaDownloader->currentRequest_->startPos_ + 1;
900 }
901
902 mediaDownloader->currentRequest_->requestSize_ = remaining < PER_REQUEST_SIZE ? remaining : PER_REQUEST_SIZE;
903
904 if (writeLen != dataLen) {
905 if (mediaDownloader->sourceLoader_ != nullptr) {
906 mediaDownloader->PauseLoop(true);
907 mediaDownloader->currentRequest_->retryOnGoing_ = true;
908 mediaDownloader->currentRequest_->dropedDataLen_ = 0;
909 }
910 MEDIA_LOG_W("Save data failed.");
911 return 0; // save data failed, make perform finished.
912 }
913
914 mediaDownloader->currentRequest_->isDownloading_ = false;
915 return dataLen;
916 }
917
918 namespace {
StringTrim(char * str)919 char* StringTrim(char* str)
920 {
921 if (str == nullptr) {
922 return nullptr;
923 }
924 char* p = str;
925 char* p1 = p + strlen(str) - 1;
926
927 while (*p && isspace(static_cast<int>(*p))) {
928 p++;
929 }
930 while (p1 > p && isspace(static_cast<int>(*p1))) {
931 *p1-- = 0;
932 }
933 return p;
934 }
935 }
936
HandleContentRange(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)937 bool Downloader::HandleContentRange(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
938 {
939 if (!strncmp(key, "Content-Range", strlen("Content-Range")) ||
940 !strncmp(key, "content-range", strlen("content-range"))) {
941 char* token = strtok_s(nullptr, ":", &next);
942 FALSE_RETURN_V(token != nullptr, false);
943 char* strRange = StringTrim(token);
944 size_t start;
945 size_t end;
946 size_t fileLen;
947 FALSE_LOG_MSG(sscanf_s(strRange, "bytes %lu-%lu/%lu", &start, &end, &fileLen) != -1,
948 "sscanf get range failed");
949 if (info->fileContentLen > 0 && info->fileContentLen != fileLen) {
950 MEDIA_LOG_E("FileContentLen doesn't equal to fileLen");
951 }
952 if (info->fileContentLen == 0) {
953 info->fileContentLen = fileLen;
954 }
955 }
956 return true;
957 }
958
HandleContentType(HeaderInfo * info,char * key,char * next,size_t headerSize,Downloader * mediaDownloader)959 bool Downloader::HandleContentType(HeaderInfo* info, char* key, char* next, size_t headerSize,
960 Downloader* mediaDownloader)
961 {
962 if (!strncmp(key, "Content-Type", strlen("Content-Type"))) {
963 char* token = strtok_s(nullptr, ":", &next);
964 FALSE_RETURN_V(token != nullptr, false);
965 char* type = StringTrim(token);
966 std::string tokenStr = (std::string)token;
967 MEDIA_LOG_I("Content-Type: " PUBLIC_LOG_S, tokenStr.c_str());
968 NZERO_LOG(memcpy_s(info->contentType, sizeof(info->contentType), type, strlen(type)));
969 }
970 return true;
971 }
972
HandleContentEncode(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)973 bool Downloader::HandleContentEncode(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
974 {
975 if (!strncmp(key, "Content-Encode", strlen("Content-Encode")) ||
976 !strncmp(key, "content-encode", strlen("content-encode"))) {
977 char* token = strtok_s(nullptr, ":", &next);
978 FALSE_RETURN_V(token != nullptr, false);
979 std::string tokenStr = (std::string)token;
980 MEDIA_LOG_I("Content-Encode: " PUBLIC_LOG_S, tokenStr.c_str());
981 }
982 return true;
983 }
984
HandleContentLength(HeaderInfo * info,char * key,char * next,Downloader * mediaDownloader)985 bool Downloader::HandleContentLength(HeaderInfo* info, char* key, char* next, Downloader* mediaDownloader)
986 {
987 FALSE_RETURN_V(key != nullptr, false);
988 if (!strncmp(key, "Content-Length", strlen("Content-Length")) ||
989 !strncmp(key, "content-length", strlen("content-length"))) {
990 FALSE_RETURN_V(next != nullptr, false);
991 char* token = strtok_s(nullptr, ":", &next);
992 FALSE_RETURN_V(token != nullptr, false);
993 if (info != nullptr && mediaDownloader != nullptr) {
994 info->contentLen = atol(StringTrim(token));
995 if (info->contentLen <= 0 && !mediaDownloader->currentRequest_->IsM3u8Request()) {
996 info->isChunked = true;
997 }
998 }
999 }
1000 return true;
1001 }
1002
1003 // Check if this server supports range download. (HTTP)
HandleRange(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)1004 bool Downloader::HandleRange(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
1005 {
1006 if (!strncmp(key, "Accept-Ranges", strlen("Accept-Ranges")) ||
1007 !strncmp(key, "accept-ranges", strlen("accept-ranges"))) {
1008 char* token = strtok_s(nullptr, ":", &next);
1009 FALSE_RETURN_V(token != nullptr, false);
1010 if (!strncmp(StringTrim(token), "bytes", strlen("bytes"))) {
1011 info->isServerAcceptRange = true;
1012 MEDIA_LOG_I("Accept-Ranges: bytes");
1013 }
1014 }
1015 if (!strncmp(key, "Content-Range", strlen("Content-Range")) ||
1016 !strncmp(key, "content-range", strlen("content-range"))) {
1017 char* token = strtok_s(nullptr, ":", &next);
1018 FALSE_RETURN_V(token != nullptr, false);
1019 std::string tokenStr = (std::string)token;
1020 if (tokenStr.find("bytes") != std::string::npos) {
1021 info->isServerAcceptRange = true;
1022 MEDIA_LOG_I("Content-Range: " PUBLIC_LOG_S, tokenStr.c_str());
1023 }
1024 }
1025 return true;
1026 }
1027
RxHeaderData(void * buffer,size_t size,size_t nitems,void * userParam)1028 size_t Downloader::RxHeaderData(void* buffer, size_t size, size_t nitems, void* userParam)
1029 {
1030 MediaAVCodec::AVCodecTrace trace("Downloader::RxHeaderData");
1031 auto mediaDownloader = static_cast<Downloader *>(userParam);
1032 HeaderInfo* info = &(mediaDownloader->currentRequest_->headerInfo_);
1033 if (mediaDownloader->currentRequest_->isHeaderUpdated_) {
1034 return size * nitems;
1035 }
1036 char* next = nullptr;
1037 char* key = strtok_s(reinterpret_cast<char*>(buffer), ":", &next);
1038 FALSE_RETURN_V(key != nullptr, size * nitems);
1039
1040 if (!strncmp(key, "Transfer-Encoding", strlen("Transfer-Encoding")) ||
1041 !strncmp(key, "transfer-encoding", strlen("transfer-encoding"))) {
1042 char* token = strtok_s(nullptr, ":", &next);
1043 FALSE_RETURN_V(token != nullptr, size * nitems);
1044 if (!strncmp(StringTrim(token), "chunked", strlen("chunked")) &&
1045 !mediaDownloader->currentRequest_->IsM3u8Request()) {
1046 info->isChunked = true;
1047 if (static_cast<int32_t>(mediaDownloader->currentRequest_->url_.find(".flv") == std::string::npos)) {
1048 info->contentLen = LIVE_CONTENT_LENGTH;
1049 } else {
1050 info->contentLen = 0;
1051 }
1052 std::string tokenStr = (std::string)token;
1053 MEDIA_LOG_I("Transfer-Encoding: " PUBLIC_LOG_S, tokenStr.c_str());
1054 }
1055 }
1056 if (!strncmp(key, "Location", strlen("Location")) ||
1057 !strncmp(key, "location", strlen("location"))) {
1058 FALSE_RETURN_V(next != nullptr, size * nitems);
1059 char* location = StringTrim(next);
1060 mediaDownloader->currentRequest_->location_ = location;
1061 }
1062
1063 if (!HandleContentRange(info, key, next, size, nitems) ||
1064 !HandleContentType(info, key, next, size * nitems, mediaDownloader) ||
1065 !HandleContentEncode(info, key, next, size, nitems) ||
1066 !HandleContentLength(info, key, next, mediaDownloader) ||
1067 !HandleRange(info, key, next, size, nitems)) {
1068 return size * nitems;
1069 }
1070
1071 return size * nitems;
1072 }
1073
PauseLoop(bool isAsync)1074 void Downloader::PauseLoop(bool isAsync)
1075 {
1076 if (task_ == nullptr) {
1077 return;
1078 }
1079 if (isAsync) {
1080 task_->PauseAsync();
1081 } else {
1082 task_->Pause();
1083 }
1084 }
1085
SetAppUid(int32_t appUid)1086 void Downloader::SetAppUid(int32_t appUid)
1087 {
1088 if (client_) {
1089 client_->SetAppUid(appUid);
1090 }
1091 }
1092
GetCurrentRequest()1093 const std::shared_ptr<DownloadRequest>& Downloader::GetCurrentRequest()
1094 {
1095 return currentRequest_;
1096 }
1097
SetInterruptState(bool isInterruptNeeded)1098 void Downloader::SetInterruptState(bool isInterruptNeeded)
1099 {
1100 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader SetInterruptState %{public}d",
1101 FAKE_POINTER(this), isInterruptNeeded);
1102 isInterruptNeeded_ = isInterruptNeeded;
1103 if (currentRequest_ != nullptr) {
1104 currentRequest_->isInterruptNeeded_ = isInterruptNeeded;
1105 }
1106 if (sourceLoader_ != nullptr) {
1107 client_->Close(false);
1108 }
1109 NotifyLoopPause();
1110 }
1111
NotifyLoopPause()1112 void Downloader::NotifyLoopPause()
1113 {
1114 AutoLock lk(loopPauseMutex_);
1115 if (loopStatus_ == LoopStatus::PAUSE || isInterruptNeeded_) {
1116 MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader NotifyLoopPause", FAKE_POINTER(this));
1117 loopStatus_ = LoopStatus::IDLE;
1118 loopPauseCond_.NotifyAll();
1119 } else {
1120 loopStatus_ = LoopStatus::IDLE;
1121 MEDIA_LOG_I("Downloader not NotifyLoopPause loopStatus %{public}d isInterruptNeeded %{public}d",
1122 loopStatus_.load(), isInterruptNeeded_.load());
1123 }
1124 }
1125
WaitLoopPause()1126 void Downloader::WaitLoopPause()
1127 {
1128 AutoLock lk(loopPauseMutex_);
1129 if (loopStatus_ == LoopStatus::IDLE) {
1130 MEDIA_LOG_I("0x%{public}06" PRIXPTR "Downloader not WaitLoopPause loopStatus is idle", FAKE_POINTER(this));
1131 return;
1132 }
1133 MEDIA_LOG_I("0x%{public}06" PRIXPTR "Downloader WaitLoopPause task loopStatus_ %{public}d",
1134 FAKE_POINTER(this), loopStatus_.load());
1135 loopStatus_ = LoopStatus::PAUSE;
1136 loopPauseCond_.Wait(lk, [this]() {
1137 MEDIA_LOG_I("0x%{public}06" PRIXPTR " WaitLoopPause wake loopStatus %{public}d",
1138 FAKE_POINTER(this), loopStatus_.load());
1139 return loopStatus_ != LoopStatus::PAUSE || isInterruptNeeded_;
1140 });
1141 }
1142
SetAppState(bool isAppBackground)1143 void Downloader::SetAppState(bool isAppBackground)
1144 {
1145 isAppBackground_ = isAppBackground;
1146 }
1147
StopBufferring()1148 void Downloader::StopBufferring()
1149 {
1150 MediaAVCodec::AVCodecTrace trace("Downloader::StopBufferring");
1151 if (task_ == nullptr || currentRequest_ == nullptr) {
1152 MEDIA_LOG_E("Downloader StopBufferring error.");
1153 return;
1154 }
1155 if (isAppBackground_) {
1156 if (!task_->IsTaskRunning() && client_ != nullptr) {
1157 MEDIA_LOG_I("StopBufferring: is task not running.");
1158 client_->Close(false);
1159 }
1160 } else {
1161 if (currentRequest_ != nullptr && !shouldStartNextRequest) {
1162 int64_t lastStartPos = currentRequest_->startPos_; // downlaod from last pos
1163 BeginDownload();
1164 currentRequest_->startPos_ = lastStartPos;
1165 if (currentRequest_->startPos_ > 0) {
1166 currentRequest_->retryOnGoing_ = true;
1167 currentRequest_->dropedDataLen_ = 0;
1168 }
1169 MEDIA_LOG_I("StopBufferring: begin pos " PUBLIC_LOG_U64, currentRequest_->startPos_);
1170 }
1171 Start();
1172 }
1173 }
1174 }
1175 }
1176 }
1177 }
1178