• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 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 "HttpMediaDownloader"
16 
17 #include "http_media_downloader.h"
18 
19 namespace OHOS {
20 namespace Media {
21 namespace Plugin {
22 namespace HttpPlugin {
23 namespace {
24 #ifdef OHOS_LITE
25 constexpr int RING_BUFFER_SIZE = 5 * 48 * 1024;
26 constexpr int WATER_LINE = RING_BUFFER_SIZE / 30; //30  WATER_LINE:8192
27 #else
28 constexpr int RING_BUFFER_SIZE = 5 * 1024 * 1024;
29 constexpr int WATER_LINE = 8192; //  WATER_LINE:8192
30 #endif
31 }
32 
HttpMediaDownloader()33 HttpMediaDownloader::HttpMediaDownloader() noexcept
34 {
35     buffer_ = std::make_shared<RingBuffer>(RING_BUFFER_SIZE);
36     buffer_->Init();
37 
38     downloader_ = std::make_shared<Downloader>("http");
39 }
40 
Open(const std::string & url)41 bool HttpMediaDownloader::Open(const std::string& url)
42 {
43     MEDIA_LOG_I("Open download " PUBLIC_LOG_S, url.c_str());
44     auto saveData =  [this] (uint8_t*&& data, uint32_t&& len, int64_t&& offset) {
45         return SaveData(std::forward<decltype(data)>(data), std::forward<decltype(len)>(len),
46                         std::forward<decltype(offset)>(offset));
47     };
48     FALSE_RETURN_V(statusCallback_ != nullptr, false);
49     auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
50                                   std::shared_ptr<DownloadRequest>& request) {
51         statusCallback_(status, downloader_, std::forward<decltype(request)>(request));
52     };
53     downloadRequest_ = std::make_shared<DownloadRequest>(url, saveData, realStatusCallback);
54     downloader_->Download(downloadRequest_, -1); // -1
55     downloader_->Start();
56     return true;
57 }
58 
Close()59 void HttpMediaDownloader::Close()
60 {
61     buffer_->SetActive(false);
62     downloader_->Stop();
63 }
64 
Pause()65 void HttpMediaDownloader::Pause()
66 {
67     bool cleanData = GetSeekable() != Seekable::SEEKABLE;
68     buffer_->SetActive(false, cleanData);
69     downloader_->Pause();
70 }
71 
Resume()72 void HttpMediaDownloader::Resume()
73 {
74     buffer_->SetActive(true);
75     downloader_->Resume();
76 }
77 
Read(unsigned char * buff,unsigned int wantReadLength,unsigned int & realReadLength,bool & isEos)78 bool HttpMediaDownloader::Read(unsigned char* buff, unsigned int wantReadLength,
79                                unsigned int& realReadLength, bool& isEos)
80 {
81     FALSE_RETURN_V(buffer_ != nullptr, false);
82     isEos = false;
83     while (buffer_->GetSize() == 0) {
84         if (downloadRequest_->IsEos()) {
85             MEDIA_LOG_D("HttpMediaDownloader read return because of EOS");
86             isEos = true;
87             realReadLength = 0;
88             return false;
89         }
90         OSAL::SleepFor(5); // 5
91     }
92     realReadLength = buffer_->ReadBuffer(buff, wantReadLength, 2); // wait 2 times
93     MEDIA_LOG_D("Read: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
94                 PUBLIC_LOG_D32, wantReadLength, realReadLength, isEos);
95     return true;
96 }
97 
Seek(int offset)98 bool HttpMediaDownloader::Seek(int offset)
99 {
100     FALSE_RETURN_V(buffer_ != nullptr, false);
101     MEDIA_LOG_I("Seek: buffer size " PUBLIC_LOG_ZU ", offset " PUBLIC_LOG_D32, buffer_->GetSize(), offset);
102     if (buffer_->Seek(offset)) {
103         return true;
104     }
105     buffer_->Clear(); // First clear buffer, avoid no available buffer then task pause never exit.
106     downloader_->Pause();
107     buffer_->Clear();
108     downloader_->Seek(offset);
109     downloader_->Resume();
110     return true;
111 }
112 
GetContentLength() const113 size_t HttpMediaDownloader::GetContentLength() const
114 {
115     return downloadRequest_->GetFileContentLength();
116 }
117 
GetDuration() const118 double HttpMediaDownloader::GetDuration() const
119 {
120     return 0;
121 }
122 
GetSeekable() const123 Seekable HttpMediaDownloader::GetSeekable() const
124 {
125     return downloadRequest_->IsChunked() ? Seekable::UNSEEKABLE : Seekable::SEEKABLE;
126 }
127 
SetCallback(Callback * cb)128 void HttpMediaDownloader::SetCallback(Callback* cb)
129 {
130     callback_ = cb;
131 }
132 
SetStatusCallback(StatusCallbackFunc cb)133 void HttpMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
134 {
135     statusCallback_ = cb;
136 }
137 
GetStartedStatus()138 bool HttpMediaDownloader::GetStartedStatus()
139 {
140     return startedPlayStatus_;
141 }
142 
SaveData(uint8_t * data,uint32_t len,int64_t offset)143 bool HttpMediaDownloader::SaveData(uint8_t* data, uint32_t len, int64_t offset)
144 {
145     FALSE_RETURN_V(buffer_->WriteBuffer(data, len, offset), false);
146     size_t bufferSize = buffer_->GetSize();
147     double ratio = (static_cast<double>(bufferSize)) / RING_BUFFER_SIZE;
148     if ((bufferSize >= WATER_LINE ||
149         bufferSize >= downloadRequest_->GetFileContentLength() / 2) && !aboveWaterline_) { // 2
150         aboveWaterline_ = true;
151         MEDIA_LOG_I("Send http aboveWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
152         callback_->OnEvent({PluginEventType::ABOVE_LOW_WATERLINE, {ratio}, "http"});
153         startedPlayStatus_ = true;
154     } else if (bufferSize < WATER_LINE && aboveWaterline_) {
155         aboveWaterline_ = false;
156         MEDIA_LOG_I("Send http belowWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
157         callback_->OnEvent({PluginEventType::BELOW_LOW_WATERLINE, {ratio}, "http"});
158     }
159     return true;
160 }
161 }
162 }
163 }
164 }