• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 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 "HttpLiteSourcePlugin"
16 #include "http_lite_source_plugin.h"
17 #include "foundation/log.h"
18 #include "plugin/common/plugin_types.h"
19 #include "plugin/core/plugin_manager.h"
20 #include "utils/util.h"
21 
22 namespace OHOS {
23 namespace Media {
24 namespace Plugin {
25 namespace HttpLitePlugin {
26 namespace {
27 constexpr int DEFAULT_BUFFER_SIZE = 200 * 1024;
28 }
29 
HttpSourcePluginCreater(const std::string & name)30 std::shared_ptr<SourcePlugin> HttpSourcePluginCreater(const std::string &name)
31 {
32     return std::make_shared<HttpSourcePlugin>(name);
33 }
34 
HttpSourceRegister(std::shared_ptr<Register> reg)35 const Status HttpSourceRegister(std::shared_ptr<Register> reg)
36 {
37     SourcePluginDef definition;
38     definition.name = "HttpLiteSource";
39     definition.description = "Http lite source";
40     definition.rank = 100; // 100
41     definition.protocol.emplace_back(ProtocolType::HTTP);
42     definition.protocol.emplace_back(ProtocolType::HTTPS);
43     definition.creator = HttpSourcePluginCreater;
44     return reg->AddPlugin(definition);
45 }
__anon7ae7e8ad0202null46 PLUGIN_DEFINITION(HttpLiteSource, LicenseType::APACHE_V2, HttpSourceRegister, [] {});
47 
Alloc(size_t size)48 void* HttpSourceAllocator::Alloc(size_t size)
49 {
50     if (size == 0) {
51         return nullptr;
52     }
53     return reinterpret_cast<void*>(new (std::nothrow) uint8_t[size]); // NOLINT: cast
54 }
55 
Free(void * ptr)56 void HttpSourceAllocator::Free(void* ptr) // NOLINT: void*
57 {
58     if (ptr != nullptr) {
59         delete[](uint8_t*) ptr;
60     }
61 }
62 
HttpSourcePlugin(const std::string name)63 HttpSourcePlugin::HttpSourcePlugin(const std::string name) noexcept
64     : SourcePlugin(std::move(name)),
65       url_(""),
66       certFile_(""),
67       needExit_(false),
68       isSeekable_(false),
69       bufferSize_(DEFAULT_BUFFER_SIZE),
70       position_(0),
71       waterline_(0),
72       fileSize_(-1),
73       httpHandle_(nullptr),
74       mAllocator_(nullptr),
75       httpMutex_()
76 {
77     MEDIA_LOG_D("HttpSourcePlugin IN");
78 }
79 
~HttpSourcePlugin()80 HttpSourcePlugin::~HttpSourcePlugin()
81 {
82     MEDIA_LOG_D("~HttpSourcePlugin IN");
83 }
84 
Init()85 Status HttpSourcePlugin::Init()
86 {
87     OSAL::ScopedLock lock(httpMutex_);
88     MEDIA_LOG_D("Init IN");
89     httpHandle_ = std::make_shared<HttpLiteManager>();
90     if (httpHandle_ == nullptr) {
91         MEDIA_LOG_E("httpHandle_ create error");
92         return Status::ERROR_UNKNOWN;
93     }
94     mAllocator_ = std::make_shared<HttpSourceAllocator>();
95     if (mAllocator_ == nullptr) {
96         MEDIA_LOG_E("mAllocator_ create error");
97         return Status::ERROR_UNKNOWN;
98     }
99     MEDIA_LOG_D("Init OUT");
100     return Status::OK;
101 }
102 
Deinit()103 Status HttpSourcePlugin::Deinit()
104 {
105     OSAL::ScopedLock lock(httpMutex_);
106     MEDIA_LOG_D("IN");
107     CloseUri();
108     return Status::OK;
109 }
110 
Prepare()111 Status HttpSourcePlugin::Prepare()
112 {
113     OSAL::ScopedLock lock(httpMutex_);
114     MEDIA_LOG_D("IN");
115     return Status::OK;
116 }
117 
Reset()118 Status HttpSourcePlugin::Reset()
119 {
120     needExit_ = true;
121     {
122         OSAL::ScopedLock lock(httpMutex_);
123         needExit_ = false;
124         MEDIA_LOG_D("IN");
125         CloseUri();
126         return Status::OK;
127     }
128 }
129 
Start()130 Status HttpSourcePlugin::Start()
131 {
132     OSAL::ScopedLock lock(httpMutex_);
133     MEDIA_LOG_D("IN");
134     if (isSeekable_ && httpHandle_ != nullptr) {
135         waterline_ = 20; // 20
136         httpHandle_->SetWaterline(waterline_, 0);
137     }
138     MEDIA_LOG_D("OUT");
139     return Status::OK;
140 }
141 
Stop()142 Status HttpSourcePlugin::Stop()
143 {
144     needExit_ = true;
145     {
146         MEDIA_LOG_D("IN");
147         OSAL::ScopedLock lock(httpMutex_);
148         needExit_ = false;
149         if (httpHandle_ != nullptr) {
150             httpHandle_->HttpClose();
151             httpHandle_ = nullptr;
152         }
153         MEDIA_LOG_D("OUT");
154         return Status::ERROR_UNKNOWN;
155     }
156 }
157 
IsParameterSupported(Tag tag)158 bool HttpSourcePlugin::IsParameterSupported(Tag tag)
159 {
160     MEDIA_LOG_D("IN");
161     if (tag == Tag::BUFFERING_SIZE || tag == Tag::WATERLINE_HIGH) {
162         return true;
163     }
164     return false;
165 }
166 
GetParameter(Tag tag,ValueType & value)167 Status HttpSourcePlugin::GetParameter(Tag tag, ValueType &value)
168 {
169     OSAL::ScopedLock lock(httpMutex_);
170     MEDIA_LOG_D("IN");
171     switch (tag) {
172         case Tag::BUFFERING_SIZE:
173             value = bufferSize_;
174             return Status::OK;
175         case Tag::WATERLINE_HIGH:
176             value = waterline_;
177             return Status::OK;
178         default:
179             return Status::ERROR_INVALID_PARAMETER;
180     }
181 }
182 
SetParameter(Tag tag,const ValueType & value)183 Status HttpSourcePlugin::SetParameter(Tag tag, const ValueType &value)
184 {
185     OSAL::ScopedLock lock(httpMutex_);
186     MEDIA_LOG_D("IN");
187     switch (tag) {
188         case Tag::BUFFERING_SIZE:
189             bufferSize_ = AnyCast<uint32_t>(value);
190             return Status::OK;
191         case Tag::WATERLINE_HIGH:
192             waterline_ = AnyCast<uint32_t>(value);
193             return Status::OK;
194         default:
195             return Status::ERROR_INVALID_PARAMETER;
196     }
197 }
198 
SetCallback(Callback * cb)199 Status HttpSourcePlugin::SetCallback(Callback* cb)
200 {
201     MEDIA_LOG_D("IN");
202     callback_ = cb;
203     return Status::OK;
204 }
205 
SetSource(std::shared_ptr<MediaSource> source)206 Status HttpSourcePlugin::SetSource(std::shared_ptr<MediaSource> source)
207 {
208     OSAL::ScopedLock lock(httpMutex_);
209     MEDIA_LOG_D("SetSource IN");
210     if (httpHandle_ == nullptr) {
211         MEDIA_LOG_D("httpHandle_ null error");
212         return Status::ERROR_UNKNOWN;
213     }
214     auto uri = source->GetSourceUri();
215     MEDIA_LOG_D("%" PUBLIC_LOG "s", uri.c_str());
216     Status ret = OpenUri(uri);
217     if (ret != Status::OK) {
218         MEDIA_LOG_D("OpenUri error");
219         return ret;
220     }
221     MEDIA_LOG_D("OpenUri success");
222     unsigned int downloadPos = 0;
223     httpHandle_->GetHttpBufferRange(&position_, &downloadPos);
224     MEDIA_LOG_D("position_ %" PUBLIC_LOG "d downloadPos %" PUBLIC_LOG "d",
225                 (uint32_t)position_, (uint32_t)downloadPos);
226     int8_t retryTimes = 0;
227     while (!needExit_ && position_ == downloadPos && retryTimes < 60) { // 60
228         OHOS::Media::OSAL::SleepFor(200); // 200
229         httpHandle_->GetHttpBufferRange(&position_, &downloadPos);
230         retryTimes++;
231     }
232     MEDIA_LOG_D("position_ %" PUBLIC_LOG "d downloadPos %" PUBLIC_LOG "d", position_, downloadPos);
233     if (position_ == downloadPos) {
234         MEDIA_LOG_D("position_ == downloadPos");
235         httpHandle_->HttpClose();
236         return Status::ERROR_UNKNOWN;
237     }
238     isSeekable_ = httpHandle_->IsStreaming();
239     fileSize_ = isSeekable_ ? httpHandle_->GetContentLength() : -1;
240     MEDIA_LOG_D("SetSource OUT fileSize_ %" PUBLIC_LOG "d", fileSize_);
241     return Status::OK;
242 }
243 
GetAllocator()244 std::shared_ptr<Allocator> HttpSourcePlugin::GetAllocator()
245 {
246     MEDIA_LOG_D("GetAllocator IN");
247     return mAllocator_;
248 }
249 
OnError(int httpError,int localError,void * param,int support_retry)250 void HttpSourcePlugin::OnError(int httpError, int localError, void *param, int support_retry)
251 {
252     MEDIA_LOG_D("httpError %" PUBLIC_LOG "d localError %" PUBLIC_LOG "d", httpError, localError);
253     auto plugin = reinterpret_cast<HttpSourcePlugin *>(param);
254     if (plugin == nullptr) {
255         return;
256     }
257     plugin->needExit_ = true;
258     plugin->OnHttpEvent(param, httpError, localError);
259 }
260 
OnHttpEvent(void * priv,int errorType,int32_t errorCode)261 Status HttpSourcePlugin::OnHttpEvent(void *priv, int errorType, int32_t errorCode)
262 {
263     if (priv == nullptr) {
264         MEDIA_LOG_D("priv null error");
265         return Status::ERROR_UNKNOWN;
266     }
267     auto plugin = reinterpret_cast<HttpSourcePlugin *>(priv);
268     plugin->callback_->OnEvent(
269         PluginEvent{PluginEventType::OTHER_ERROR, errorCode, "http lite error"});
270     return Status::OK;
271 }
272 
Read(std::shared_ptr<Buffer> & buffer,size_t expectedLen)273 Status HttpSourcePlugin::Read(std::shared_ptr<Buffer> &buffer, size_t expectedLen)
274 {
275     MEDIA_LOG_D("Read in");
276     if (httpHandle_ == nullptr || buffer == nullptr) {
277         MEDIA_LOG_D("Read error");
278         return Status::ERROR_INVALID_PARAMETER;
279     }
280     {
281         OSAL::ScopedLock lock(httpMutex_);
282         std::shared_ptr<Memory>bufData;
283 
284         if (buffer->IsEmpty()) {
285             bufData = buffer->AllocMemory(GetAllocator(), expectedLen);
286         } else {
287             bufData = buffer->GetMemory();
288         }
289         unsigned int read = 0;
290         unsigned int write = 0;
291         unsigned int realReadSize = 0;
292         bool isEos = false;
293 
294         httpHandle_->GetHttpBufferRange(&read, &write);
295 
296         MEDIA_LOG_I("read pos %" PUBLIC_LOG "d write pos %" PUBLIC_LOG "d expectedLen %" PUBLIC_LOG "d",
297                     read, write, expectedLen);
298 
299         expectedLen = std::min(static_cast<size_t>(write - read), expectedLen);
300         expectedLen = std::min(bufData->GetCapacity(), expectedLen);
301 
302         MEDIA_LOG_I("bufData->GetCapacity() %" PUBLIC_LOG "d", bufData->GetCapacity());
303         httpHandle_->HttpRead(bufData->GetWritableAddr(expectedLen), expectedLen, realReadSize, isEos);
304         bufData->UpdateDataSize(realReadSize);
305         httpHandle_->GetHttpBufferRange(&position_, &write);
306         MEDIA_LOG_D("position_ : %" PUBLIC_LOG "d, readSize = %" PUBLIC_LOG "d, isEos %" PUBLIC_LOG "d",
307                     position_, bufData->GetSize(), isEos);
308         return Status::OK;
309     }
310 }
311 
GetSize(size_t & size)312 Status HttpSourcePlugin::GetSize(size_t &size)
313 {
314     OSAL::ScopedLock lock(httpMutex_);
315     MEDIA_LOG_D("IN");
316     size = fileSize_;
317     return Status::OK;
318 }
319 
IsSeekable()320 bool HttpSourcePlugin::IsSeekable()
321 {
322     OSAL::ScopedLock lock(httpMutex_);
323     MEDIA_LOG_D("IN");
324     return isSeekable_;
325 }
326 
SeekTo(uint64_t offset)327 Status HttpSourcePlugin::SeekTo(uint64_t offset)
328 {
329     OSAL::ScopedLock lock(httpMutex_);
330     unsigned int readPos = 0;
331     unsigned int writePos = 0;
332     uint32_t readLength;
333     uint8_t tmpBuf;
334     bool sourceFlag;
335     if ((httpHandle_ == nullptr) || (!isSeekable_) || (position_ == offset) || (offset > fileSize_)) {
336         MEDIA_LOG_E("Invalid operation");
337         return Status::ERROR_INVALID_PARAMETER;
338     }
339     if (!httpHandle_->HttpSeek(offset)) {
340         MEDIA_LOG_D("seek to position_ %" PUBLIC_LOG "d failed", position_);
341         return Status::ERROR_UNKNOWN;
342     }
343     position_ = static_cast<unsigned int>(offset);
344     httpHandle_->GetHttpBufferRange(&readPos, &writePos);
345     MEDIA_LOG_D("offset = %" PUBLIC_LOG "d, after SeekTo readPos = %" PUBLIC_LOG "d, writePos = %" PUBLIC_LOG
346                 "d", static_cast<uint32_t>(offset), readPos, writePos);
347     MEDIA_LOG_D("seek to position_ %" PUBLIC_LOG "d success", position_);
348     return Status::OK;
349 }
350 
OpenUri(std::string & url)351 Status HttpSourcePlugin::OpenUri(std::string &url)
352 {
353     MEDIA_LOG_D("OpenUri IN");
354     if (httpHandle_ == nullptr) {
355         return Status::ERROR_UNIMPLEMENTED;
356     }
357     httpHandle_->HttpClose();
358     HttpLiteAttr httpAttr;
359     httpAttr.certFile = certFile_;
360     httpAttr.priority = -1;
361     httpAttr.bufferSize = bufferSize_;
362     httpAttr.pluginHandle = this;
363     httpAttr.callbackFunc = OnError;
364     MEDIA_LOG_D("OpenUri httpAttr.pluginHandle %" PUBLIC_LOG "p httpAttr.callbackFunc %" PUBLIC_LOG "p",
365                 httpAttr.pluginHandle, httpAttr.callbackFunc);
366     return httpHandle_->HttpOpen(url, httpAttr) ? Status::OK : Status::ERROR_UNKNOWN;
367 }
368 
CloseUri()369 void HttpSourcePlugin::CloseUri()
370 {
371     if (httpHandle_ != nullptr) {
372         MEDIA_LOG_D("close uri");
373         httpHandle_->HttpClose();
374         httpHandle_ = nullptr;
375     }
376 }
377 } // namespace HttpLitePlugin
378 } // namespace Plugin
379 } // namespace Media
380 } // namespace OHOS