• 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 
~HttpMediaDownloader()41 HttpMediaDownloader::~HttpMediaDownloader()
42 {
43     MEDIA_LOG_I("~HttpMediaDownloader dtor");
44     Close(false);
45 }
46 
Open(const std::string & url)47 bool HttpMediaDownloader::Open(const std::string& url)
48 {
49     MEDIA_LOG_I("Open download " PUBLIC_LOG_S, url.c_str());
50     auto saveData =  [this] (uint8_t*&& data, uint32_t&& len) {
51         return SaveData(std::forward<decltype(data)>(data), std::forward<decltype(len)>(len));
52     };
53     FALSE_RETURN_V(statusCallback_ != nullptr, false);
54     auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
55                                   std::shared_ptr<DownloadRequest>& request) {
56         statusCallback_(status, downloader_, std::forward<decltype(request)>(request));
57     };
58     downloadRequest_ = std::make_shared<DownloadRequest>(url, saveData, realStatusCallback);
59     downloader_->Download(downloadRequest_, -1); // -1
60     buffer_->SetMediaOffset(0);
61     downloader_->Start();
62     return true;
63 }
64 
Close(bool isAsync)65 void HttpMediaDownloader::Close(bool isAsync)
66 {
67     buffer_->SetActive(false);
68     downloader_->Stop(isAsync);
69     cvReadWrite_.NotifyOne();
70 }
71 
Pause()72 void HttpMediaDownloader::Pause()
73 {
74     bool cleanData = GetSeekable() != Seekable::SEEKABLE;
75     buffer_->SetActive(false, cleanData);
76     downloader_->Pause();
77     cvReadWrite_.NotifyOne();
78 }
79 
Resume()80 void HttpMediaDownloader::Resume()
81 {
82     buffer_->SetActive(true);
83     downloader_->Resume();
84     cvReadWrite_.NotifyOne();
85 }
86 
Read(unsigned char * buff,unsigned int wantReadLength,unsigned int & realReadLength,bool & isEos)87 bool HttpMediaDownloader::Read(unsigned char* buff, unsigned int wantReadLength,
88                                unsigned int& realReadLength, bool& isEos)
89 {
90     FALSE_RETURN_V(buffer_ != nullptr, false);
91     isEos = false;
92     while (buffer_->GetSize() == 0) {
93         isEos = downloadRequest_->IsEos();
94         bool isClosed = downloadRequest_->IsClosed();
95         if (isEos || isClosed) {
96             MEDIA_LOG_D("HttpMediaDownloader read return, isEos: " PUBLIC_LOG_D32 ", isClosed: "
97                 PUBLIC_LOG_D32, isEos, isClosed);
98             realReadLength = 0;
99             return false;
100         }
101         OSAL::SleepFor(5); // 5
102     }
103     if (buffer_->GetMediaOffset() + wantReadLength <= downloadRequest_->GetFileContentLength() &&
104         (buffer_->GetSize() < wantReadLength)) {
105         MEDIA_LOG_D("wantReadLength larger than available, wait for write");
106         OSAL::ScopedLock lock(mutex_);
107         cvReadWrite_.Wait(lock, [this, wantReadLength] {
108             return buffer_->GetSize() >= wantReadLength || downloadRequest_->IsEos() || downloadRequest_->IsClosed();
109         });
110     }
111     realReadLength = buffer_->ReadBuffer(buff, wantReadLength, 2); // wait 2 times
112     MEDIA_LOG_D("Read: wantReadLength " PUBLIC_LOG_D32 ", realReadLength " PUBLIC_LOG_D32 ", isEos "
113                 PUBLIC_LOG_D32, wantReadLength, realReadLength, isEos);
114     return true;
115 }
116 
Seek(int offset)117 bool HttpMediaDownloader::Seek(int offset)
118 {
119     FALSE_RETURN_V(buffer_ != nullptr, false);
120     MEDIA_LOG_I("Seek: buffer size " PUBLIC_LOG_ZU ", offset " PUBLIC_LOG_D32, buffer_->GetSize(), offset);
121     if (buffer_->Seek(offset)) {
122         return true;
123     }
124     buffer_->SetActive(false); // First clear buffer, avoid no available buffer then task pause never exit.
125     downloader_->Pause();
126     buffer_->Clear();
127     buffer_->SetActive(true);
128     bool result = downloader_->Seek(offset);
129     if (result) {
130         buffer_->SetMediaOffset(offset);
131     }
132     downloader_->Resume();
133     return result;
134 }
135 
GetContentLength() const136 size_t HttpMediaDownloader::GetContentLength() const
137 {
138     return downloadRequest_->GetFileContentLength();
139 }
140 
GetDuration() const141 double HttpMediaDownloader::GetDuration() const
142 {
143     return 0;
144 }
145 
GetSeekable() const146 Seekable HttpMediaDownloader::GetSeekable() const
147 {
148     return downloadRequest_->IsChunked() ? Seekable::UNSEEKABLE : Seekable::SEEKABLE;
149 }
150 
SetCallback(Callback * cb)151 void HttpMediaDownloader::SetCallback(Callback* cb)
152 {
153     callback_ = cb;
154 }
155 
SetStatusCallback(StatusCallbackFunc cb)156 void HttpMediaDownloader::SetStatusCallback(StatusCallbackFunc cb)
157 {
158     statusCallback_ = cb;
159 }
160 
GetStartedStatus()161 bool HttpMediaDownloader::GetStartedStatus()
162 {
163     return startedPlayStatus_;
164 }
165 
SaveData(uint8_t * data,uint32_t len)166 bool HttpMediaDownloader::SaveData(uint8_t* data, uint32_t len)
167 {
168     FALSE_RETURN_V(buffer_->WriteBuffer(data, len), false);
169     cvReadWrite_.NotifyOne();
170     size_t bufferSize = buffer_->GetSize();
171     double ratio = (static_cast<double>(bufferSize)) / RING_BUFFER_SIZE;
172     if ((bufferSize >= WATER_LINE ||
173         bufferSize >= downloadRequest_->GetFileContentLength() / 2) && !aboveWaterline_) { // 2
174         aboveWaterline_ = true;
175         MEDIA_LOG_I("Send http aboveWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
176         if (callback_ != nullptr) {
177             callback_->OnEvent({PluginEventType::ABOVE_LOW_WATERLINE, {ratio}, "http"});
178         }
179         startedPlayStatus_ = true;
180     } else if (bufferSize < WATER_LINE && aboveWaterline_) {
181         aboveWaterline_ = false;
182         MEDIA_LOG_I("Send http belowWaterline event, ringbuffer ratio " PUBLIC_LOG_F, ratio);
183         if (callback_ != nullptr) {
184             callback_->OnEvent({PluginEventType::BELOW_LOW_WATERLINE, {ratio}, "http"});
185         }
186     }
187     return true;
188 }
189 }
190 }
191 }
192 }