• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define HST_LOG_TAG "DownloadMonitor"
16 
17 #include "monitor/download_monitor.h"
18 #include "cpp_ext/algorithm_ext.h"
19 
20 namespace OHOS {
21 namespace Media {
22 namespace Plugins {
23 namespace HttpPlugin {
24 namespace {
25     constexpr int RETRY_TIMES_TO_REPORT_ERROR = 10;
26     constexpr int APP_DOWNLOAD_RETRY_TIMES = 60;
27     constexpr int SERVER_ERROR_THRESHOLD = 500;
28     constexpr int32_t READ_LOG_FEQUENCE = 50;
29     constexpr int64_t MICROSECONDS_TO_MILLISECOND = 1000;
30     constexpr int64_t RETRY_SEG = 50;
31     constexpr int32_t REDIRECT_CODE = 302;
32     const std::set<int32_t> CLIENT_NOT_RETRY_ERROR_CODES = {
33         992,
34     };
35     const std::set<int32_t> CLIENT_RETRY_ERROR_CODES = {
36         -1, // Application resource not ready for access
37         23, // notBlock
38         25, // Upload faild.
39         26, // Faild to open/read local data from file/application.
40         28, // Timeout was reached.
41         56,
42         18,
43         0,
44     };
45     const std::set<int32_t> SERVER_RETRY_ERROR_CODES = {
46         300,
47         301,
48         302,
49         303,
50         304,
51         305,
52         403,
53         500,
54         0,
55     };
56 }
57 
DownloadMonitor(std::shared_ptr<MediaDownloader> downloader)58 DownloadMonitor::DownloadMonitor(std::shared_ptr<MediaDownloader> downloader) noexcept
59     : downloader_(std::move(downloader))
60 {
61     auto statusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
62         std::shared_ptr<DownloadRequest>& request) {
63         if (isClosed_) {
64             MEDIA_LOG_W("Downloader monitor is already closed.");
65             return;
66         }
67         OnDownloadStatus(std::forward<decltype(downloader)>(downloader), std::forward<decltype(request)>(request));
68     };
69     downloader_->SetStatusCallback(statusCallback);
70     task_ = std::make_shared<Task>(std::string("OS_HttpMonitor"));
71     task_->RegisterJob([this] { return HttpMonitorLoop(); });
72     task_->Start();
73 }
74 
HttpMonitorLoop()75 int64_t DownloadMonitor::HttpMonitorLoop()
76 {
77     RetryRequest task;
78     {
79         AutoLock lock(taskMutex_);
80         if (!retryTasks_.empty()) {
81             task = retryTasks_.front();
82             retryTasks_.pop_front();
83         }
84     }
85     if (task.request && task.function) {
86         task.function();
87     }
88     return RETRY_SEG * MICROSECONDS_TO_MILLISECOND; // retry after 50ms
89 }
90 
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)91 bool DownloadMonitor::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
92 {
93     isPlaying_ = true;
94     {
95         AutoLock lock(taskMutex_);
96         retryTasks_.clear();
97     }
98     return downloader_->Open(url, httpHeader);
99 }
100 
Pause()101 void DownloadMonitor::Pause()
102 {
103     if (downloader_ != nullptr) {
104         downloader_->Pause();
105     }
106 }
107 
Resume()108 void DownloadMonitor::Resume()
109 {
110     if (downloader_ != nullptr) {
111         downloader_->Resume();
112     }
113 }
114 
Close(bool isAsync)115 void DownloadMonitor::Close(bool isAsync)
116 {
117     isClosed_ = true;
118     {
119         AutoLock lock(taskMutex_);
120         retryTasks_.clear();
121     }
122     if (isAsync) {
123         downloader_->Close(true);
124         task_->Stop();
125     } else {
126         task_->Stop();
127         downloader_->Close(false);
128     }
129     isPlaying_ = false;
130 }
131 
Read(unsigned char * buff,ReadDataInfo & readDataInfo)132 Status DownloadMonitor::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
133 {
134     auto ret = downloader_->Read(buff, readDataInfo);
135     time(&lastReadTime_);
136     if (ULLONG_MAX - haveReadData_ > readDataInfo.realReadLength_) {
137         haveReadData_ += readDataInfo.realReadLength_;
138     }
139     MEDIA_LOGI_LIMIT(READ_LOG_FEQUENCE, "DownloadMonitor: haveReadData " PUBLIC_LOG_U64, haveReadData_);
140     if (readDataInfo.isEos_ && ret == Status::END_OF_STREAM) {
141         MEDIA_LOG_I("buffer is empty, read eos." PUBLIC_LOG_U64, haveReadData_);
142     }
143     return ret;
144 }
145 
SeekToPos(int64_t offset,bool & isSeekHIt)146 bool DownloadMonitor::SeekToPos(int64_t offset, bool& isSeekHIt)
147 {
148     isPlaying_ = true;
149     bool isSeekHit = false;
150     bool res = downloader_->SeekToPos(offset, isSeekHit);
151     if (!isSeekHit) {
152         AutoLock lock(taskMutex_);
153         retryTasks_.clear();
154     }
155     return res;
156 }
157 
GetContentLength() const158 size_t DownloadMonitor::GetContentLength() const
159 {
160     return downloader_->GetContentLength();
161 }
162 
GetDuration() const163 int64_t DownloadMonitor::GetDuration() const
164 {
165     return downloader_->GetDuration();
166 }
167 
GetSeekable() const168 Seekable DownloadMonitor::GetSeekable() const
169 {
170     return downloader_->GetSeekable();
171 }
172 
SeekToTime(int64_t seekTime,SeekMode mode)173 bool DownloadMonitor::SeekToTime(int64_t seekTime, SeekMode mode)
174 {
175     isPlaying_ = true;
176     {
177         AutoLock lock(taskMutex_);
178         retryTasks_.clear();
179     }
180     return downloader_->SeekToTime(seekTime, mode);
181 }
182 
GetBitRates()183 std::vector<uint32_t> DownloadMonitor::GetBitRates()
184 {
185     return downloader_->GetBitRates();
186 }
187 
SelectBitRate(uint32_t bitRate)188 bool DownloadMonitor::SelectBitRate(uint32_t bitRate)
189 {
190     return downloader_->SelectBitRate(bitRate);
191 }
192 
AutoSelectBitRate(uint32_t bitRate)193 bool DownloadMonitor::AutoSelectBitRate(uint32_t bitRate)
194 {
195     return downloader_->AutoSelectBitRate(bitRate);
196 }
197 
SetCallback(Callback * cb)198 void DownloadMonitor::SetCallback(Callback* cb)
199 {
200     callback_ = cb;
201     downloader_->SetCallback(cb);
202 }
203 
SetStatusCallback(StatusCallbackFunc cb)204 void DownloadMonitor::SetStatusCallback(StatusCallbackFunc cb)
205 {
206 }
207 
GetStartedStatus()208 bool DownloadMonitor::GetStartedStatus()
209 {
210     return downloader_->GetStartedStatus();
211 }
212 
213 // Notify client and server error.
NotifyError(int32_t clientErrorCode,int32_t serverErrorCode)214 void DownloadMonitor::NotifyError(int32_t clientErrorCode, int32_t serverErrorCode)
215 {
216     if (callback_ == nullptr) {
217         MEDIA_LOG_E("callback_ is nullptr, notify error failed.");
218         return;
219     }
220     if (clientErrorCode != 0) {
221         int32_t errorCode = MediaServiceErrCode::MSERR_DATA_SOURCE_IO_ERROR;
222         GetClientMediaServiceErrorCode(clientErrorCode, errorCode);
223         if (downloader_ != nullptr) {
224             downloader_->SetIsReportedErrorCode();
225         }
226         callback_->OnEvent({PluginEventType::SERVER_ERROR, {errorCode}, "client error"});
227         MEDIA_LOG_E("Notify http client error, code " PUBLIC_LOG_D32, clientErrorCode);
228     }
229     if (serverErrorCode != 0) {
230         int32_t errorCode = MediaServiceErrCode::MSERR_DATA_SOURCE_IO_ERROR;
231         GetServerMediaServiceErrorCode(serverErrorCode, errorCode);
232         if (downloader_ != nullptr) {
233             downloader_->SetIsReportedErrorCode();
234         }
235         callback_->OnEvent({PluginEventType::SERVER_ERROR, {errorCode}, "server error"});
236         MEDIA_LOG_E("Notify http server error, code " PUBLIC_LOG_D32, serverErrorCode);
237     }
238 }
239 
NeedRetry(const std::shared_ptr<DownloadRequest> & request)240 bool DownloadMonitor::NeedRetry(const std::shared_ptr<DownloadRequest>& request)
241 {
242     auto clientError = request->GetClientError();
243     int serverError = request->GetServerError();
244     auto retryTimes = request->GetRetryTimes();
245     isNeedClearBuffer_ = serverError == REDIRECT_CODE;
246     MEDIA_LOG_I("NeedRetry: clientError = " PUBLIC_LOG_D32 ", serverError = " PUBLIC_LOG_D32
247         ", retryTimes = " PUBLIC_LOG_D32 ",", clientError, serverError, retryTimes);
248     if (CLIENT_NOT_RETRY_ERROR_CODES.find(static_cast<int32_t>(clientError)) != CLIENT_NOT_RETRY_ERROR_CODES.end()) {
249         MEDIA_LOG_I("Client error code is 23 or 992, not retry.");
250         return false;
251     }
252 
253     if (downloader_ != nullptr && downloader_->IsNotRetry(request)) { // flv living
254         NotifyError(clientError, serverError);
255         downloader_->SetDownloadErrorState();
256         return false;
257     }
258 
259     if (clientError == 0 && serverError == 0) {
260         return false;
261     }
262     if ((GetPlayable() && !GetReadTimeOut(clientError == -1))) { // -1: NOT_READY
263         return true;
264     }
265 
266     if (CLIENT_RETRY_ERROR_CODES.find(clientError) == CLIENT_RETRY_ERROR_CODES.end() ||
267         SERVER_RETRY_ERROR_CODES.find(serverError) == SERVER_RETRY_ERROR_CODES.end() ||
268         serverError > SERVER_ERROR_THRESHOLD) {
269         MEDIA_LOG_I("error code dont't need to retry.");
270         NotifyError(clientError, serverError);
271         if (downloader_ != nullptr) {
272             downloader_->SetDownloadErrorState();
273         }
274         request->Close();
275         return false;
276     }
277 
278     int retryTimesTmp = clientError == -1 ? APP_DOWNLOAD_RETRY_TIMES : RETRY_TIMES_TO_REPORT_ERROR;
279     if (retryTimes > retryTimesTmp) { // Report error to upper layer
280         MEDIA_LOG_I("Retry times readches the upper limit.");
281         NotifyError(clientError, serverError);
282         if (downloader_ != nullptr) {
283             downloader_->SetDownloadErrorState();
284         }
285         return false;
286     }
287     return true;
288 }
289 
OnDownloadStatus(std::shared_ptr<Downloader> & downloader,std::shared_ptr<DownloadRequest> & request)290 void DownloadMonitor::OnDownloadStatus(std::shared_ptr<Downloader>& downloader,
291                                        std::shared_ptr<DownloadRequest>& request)
292 {
293     FALSE_RETURN_MSG(downloader != nullptr, "downloader is nullptr.");
294     if (NeedRetry(request)) {
295         if (isNeedClearBuffer_) {
296             downloader_->ClearBuffer();
297         }
298         AutoLock lock(taskMutex_);
299         bool exists = CppExt::AnyOf(retryTasks_.begin(), retryTasks_.end(), [&](const RetryRequest& item) {
300             return item.request->IsSame(request);
301         });
302         if (!exists) {
303             RetryRequest retryRequest {request, [downloader, request] { downloader->Retry(request); }};
304             retryTasks_.emplace_back(std::move(retryRequest));
305         }
306     }
307 }
308 
SetIsTriggerAutoMode(bool isAuto)309 void DownloadMonitor::SetIsTriggerAutoMode(bool isAuto)
310 {
311     downloader_->SetIsTriggerAutoMode(isAuto);
312 }
313 
SetDemuxerState(int32_t streamId)314 void DownloadMonitor::SetDemuxerState(int32_t streamId)
315 {
316     downloader_->SetDemuxerState(streamId);
317 }
318 
SetReadBlockingFlag(bool isReadBlockingAllowed)319 void DownloadMonitor::SetReadBlockingFlag(bool isReadBlockingAllowed)
320 {
321     FALSE_RETURN_MSG(downloader_ != nullptr, "SetReadBlockingFlag downloader is null");
322     downloader_->SetReadBlockingFlag(isReadBlockingAllowed);
323 }
324 
SetPlayStrategy(const std::shared_ptr<PlayStrategy> & playStrategy)325 void DownloadMonitor::SetPlayStrategy(const std::shared_ptr<PlayStrategy>& playStrategy)
326 {
327     if (downloader_ != nullptr) {
328         downloader_->SetPlayStrategy(playStrategy);
329     }
330 }
331 
SetInterruptState(bool isInterruptNeeded)332 void DownloadMonitor::SetInterruptState(bool isInterruptNeeded)
333 {
334     if (downloader_ != nullptr) {
335         downloader_->SetInterruptState(isInterruptNeeded);
336     }
337 }
338 
GetStreamInfo(std::vector<StreamInfo> & streams)339 Status DownloadMonitor::GetStreamInfo(std::vector<StreamInfo>& streams)
340 {
341     return downloader_->GetStreamInfo(streams);
342 }
343 
SelectStream(int32_t streamId)344 Status DownloadMonitor::SelectStream(int32_t streamId)
345 {
346     return downloader_->SelectStream(streamId);
347 }
348 
GetDownloadInfo(DownloadInfo & downloadInfo)349 void DownloadMonitor::GetDownloadInfo(DownloadInfo& downloadInfo)
350 {
351     if (downloader_ != nullptr) {
352         MEDIA_LOG_I("DownloadMonitor GetDownloadInfo");
353         downloader_->GetDownloadInfo(downloadInfo);
354     }
355 }
356 
GetDownloadInfo()357 std::pair<int32_t, int32_t> DownloadMonitor::GetDownloadInfo()
358 {
359     MEDIA_LOG_I("DownloadMonitor GetDownloadInfo");
360     if (downloader_ == nullptr) {
361         return std::make_pair(0, 0);
362     }
363     return downloader_->GetDownloadInfo();
364 }
365 
GetPlaybackInfo(PlaybackInfo & playbackInfo)366 void DownloadMonitor::GetPlaybackInfo(PlaybackInfo& playbackInfo)
367 {
368     if (downloader_ != nullptr) {
369         MEDIA_LOG_I("DownloadMonitor GetPlaybackInfo");
370         downloader_->GetPlaybackInfo(playbackInfo);
371     }
372 }
373 
GetBufferSize() const374 size_t DownloadMonitor::GetBufferSize() const
375 {
376     FALSE_RETURN_V(downloader_ != nullptr, 0);
377     return downloader_->GetBufferSize();
378 }
379 
SetCurrentBitRate(int32_t bitRate,int32_t streamID)380 Status DownloadMonitor::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
381 {
382     MEDIA_LOG_I("SetCurrentBitRate");
383     if (downloader_ == nullptr) {
384         MEDIA_LOG_E("SetCurrentBitRate failed, downloader_ is nullptr");
385         return Status::ERROR_INVALID_OPERATION;
386     }
387     return downloader_->SetCurrentBitRate(bitRate, streamID);
388 }
389 
SetAppUid(int32_t appUid)390 void DownloadMonitor::SetAppUid(int32_t appUid)
391 {
392     if (downloader_) {
393         downloader_->SetAppUid(appUid);
394     }
395 }
396 
GetPlayable()397 bool DownloadMonitor::GetPlayable()
398 {
399     if (downloader_) {
400         return downloader_->GetPlayable();
401     }
402     return false;
403 }
404 
GetBufferingTimeOut()405 bool DownloadMonitor::GetBufferingTimeOut()
406 {
407     if (downloader_) {
408         return downloader_->GetBufferingTimeOut();
409     } else {
410         return false;
411     }
412 }
413 
GetReadTimeOut(bool isDelay)414 bool DownloadMonitor::GetReadTimeOut(bool isDelay)
415 {
416     if (downloader_) {
417         return downloader_->GetReadTimeOut(isDelay);
418     }
419     return false;
420 }
421 
GetSegmentOffset()422 size_t DownloadMonitor::GetSegmentOffset()
423 {
424     if (downloader_) {
425         return downloader_->GetSegmentOffset();
426     }
427     return 0;
428 }
429 
GetHLSDiscontinuity()430 bool DownloadMonitor::GetHLSDiscontinuity()
431 {
432     if (downloader_) {
433         return downloader_->GetHLSDiscontinuity();
434     }
435     return false;
436 }
437 
StopBufferring(bool isAppBackground)438 Status DownloadMonitor::StopBufferring(bool isAppBackground)
439 {
440     MEDIA_LOG_I("DownloadMonitor::StopBufferring");
441     if (downloader_ == nullptr) {
442         MEDIA_LOG_E("StopBufferring failed, downloader_ is nullptr");
443         return Status::ERROR_NULL_POINTER;
444     }
445     return downloader_->StopBufferring(isAppBackground);
446 }
447 
WaitForBufferingEnd()448 void DownloadMonitor::WaitForBufferingEnd()
449 {
450     FALSE_RETURN_MSG(downloader_ != nullptr, "WaitForBufferingEnd downloader is nullptr");
451     downloader_->WaitForBufferingEnd();
452 }
453 
GetServerMediaServiceErrorCode(int32_t errorCode,int32_t & serverCode)454 void DownloadMonitor::GetServerMediaServiceErrorCode(int32_t errorCode, int32_t& serverCode)
455 {
456     if (serverErrorCodeMap_.find(errorCode) == serverErrorCodeMap_.end()) {
457         MEDIA_LOG_W("Unknown server error code.");
458     } else {
459         serverCode = serverErrorCodeMap_[errorCode];
460         MEDIA_LOG_D("serverCode: " PUBLIC_LOG_D32, static_cast<int32_t>(serverCode));
461     }
462 }
463 
GetClientMediaServiceErrorCode(int32_t errorCode,int32_t & clientCode)464 void DownloadMonitor::GetClientMediaServiceErrorCode(int32_t errorCode, int32_t& clientCode)
465 {
466     if (clientErrorCodeMap_.find(errorCode) == clientErrorCodeMap_.end()) {
467         MEDIA_LOG_W("Unknown client error code.");
468     } else {
469         clientCode = clientErrorCodeMap_[errorCode];
470         MEDIA_LOG_D("clientCode: " PUBLIC_LOG_D32, static_cast<int32_t>(clientCode));
471     }
472 }
473 
SetInitialBufferSize(int32_t offset,int32_t size)474 bool DownloadMonitor::SetInitialBufferSize(int32_t offset, int32_t size)
475 {
476     return downloader_->SetInitialBufferSize(offset, size);
477 }
478 
NotifyInitSuccess()479 void DownloadMonitor::NotifyInitSuccess()
480 {
481     FALSE_RETURN_MSG(downloader_ != nullptr, "NotifyInitSuccess downloader is nullptr");
482     downloader_->NotifyInitSuccess();
483 }
484 
GetCachedDuration()485 uint64_t DownloadMonitor::GetCachedDuration()
486 {
487     FALSE_RETURN_V_MSG_E(downloader_ != nullptr, 0, "downloader_ is nullptr");
488     return downloader_->GetCachedDuration();
489 }
490 
RestartAndClearBuffer()491 void DownloadMonitor::RestartAndClearBuffer()
492 {
493     FALSE_RETURN_MSG(downloader_ != nullptr, "downloader_ is nullptr");
494     return downloader_->RestartAndClearBuffer();
495 }
496 
IsFlvLive()497 bool DownloadMonitor::IsFlvLive()
498 {
499     FALSE_RETURN_V_MSG_E(downloader_ != nullptr, false, "downloader_ is nullptr");
500     return downloader_->IsFlvLive();
501 }
502 
SetStartPts(int64_t startPts)503 void DownloadMonitor::SetStartPts(int64_t startPts)
504 {
505     if (downloader_) {
506         downloader_->SetStartPts(startPts);
507     }
508 }
509 
SetExtraCache(uint64_t cacheDuration)510 void DownloadMonitor::SetExtraCache(uint64_t cacheDuration)
511 {
512     if (downloader_) {
513         downloader_->SetExtraCache(cacheDuration);
514     }
515 }
516 
SetMediaStreams(const MediaStreamList & mediaStreams)517 void DownloadMonitor::SetMediaStreams(const MediaStreamList& mediaStreams)
518 {
519     if (downloader_) {
520         downloader_->SetMediaStreams(mediaStreams);
521     }
522 }
523 
IsHlsFmp4()524 bool DownloadMonitor::IsHlsFmp4()
525 {
526     FALSE_RETURN_V_MSG_E(downloader_ != nullptr, false, "downloader_ is nullptr");
527     return downloader_->IsHlsFmp4();
528 }
529 
GetContentType()530 std::string DownloadMonitor::GetContentType()
531 {
532     FALSE_RETURN_V(downloader_ != nullptr, "");
533     return downloader_->GetContentType();
534 }
535 
GetMemorySize()536 uint64_t DownloadMonitor::GetMemorySize()
537 {
538     FALSE_RETURN_V_MSG_E(downloader_ != nullptr, 0, "downloader_ is nullptr");
539     return downloader_->GetMemorySize();
540 }
541 
GetCurUrl()542 std::string DownloadMonitor::GetCurUrl()
543 {
544     FALSE_RETURN_V(downloader_ != nullptr, "");
545     return downloader_->GetCurUrl();
546 }
547 }
548 }
549 }
550 }