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 "HttpSourcePlugin"
16
17 #include "http_source_plugin.h"
18 #include "download/http_curl_client.h"
19 #include "foundation/log.h"
20 #include "hls/hls_media_downloader.h"
21 #include "http/http_media_downloader.h"
22 #include "monitor/download_monitor.h"
23 #undef ERROR_INVALID_OPERATION
24
25 namespace OHOS {
26 namespace Media {
27 namespace Plugin {
28 namespace HttpPlugin {
29 namespace {
30 constexpr int DEFAULT_BUFFER_SIZE = 200 * 1024;
31 }
32
HttpSourcePluginCreater(const std::string & name)33 std::shared_ptr<SourcePlugin> HttpSourcePluginCreater(const std::string& name)
34 {
35 return std::make_shared<HttpSourcePlugin>(name);
36 }
37
HttpSourceRegister(std::shared_ptr<Register> reg)38 Status HttpSourceRegister(std::shared_ptr<Register> reg)
39 {
40 SourcePluginDef definition;
41 definition.name = "HttpSource";
42 definition.description = "Http source";
43 definition.rank = 100; // 100
44 definition.protocol.emplace_back(ProtocolType::HTTP);
45 definition.protocol.emplace_back(ProtocolType::HTTPS);
46 definition.creator = HttpSourcePluginCreater;
47 return reg->AddPlugin(definition);
48 }
__anon3c11fdee0202null49 PLUGIN_DEFINITION(HttpSource, LicenseType::APACHE_V2, HttpSourceRegister, [] {});
50
HttpSourcePlugin(std::string name)51 HttpSourcePlugin::HttpSourcePlugin(std::string name) noexcept
52 : SourcePlugin(std::move(name)),
53 bufferSize_(DEFAULT_BUFFER_SIZE),
54 waterline_(0),
55 downloader_(nullptr)
56 {
57 MEDIA_LOG_D("HttpSourcePlugin IN");
58 }
59
~HttpSourcePlugin()60 HttpSourcePlugin::~HttpSourcePlugin()
61 {
62 MEDIA_LOG_D("~HttpSourcePlugin IN");
63 CloseUri();
64 }
65
Init()66 Status HttpSourcePlugin::Init()
67 {
68 MEDIA_LOG_D("Init IN");
69 return Status::OK;
70 }
71
Deinit()72 Status HttpSourcePlugin::Deinit()
73 {
74 MEDIA_LOG_D("IN");
75 CloseUri();
76 return Status::OK;
77 }
78
Prepare()79 Status HttpSourcePlugin::Prepare()
80 {
81 MEDIA_LOG_D("IN");
82 if (delayReady) {
83 return Status::ERROR_DELAY_READY;
84 }
85 return Status::OK;
86 }
87
Reset()88 Status HttpSourcePlugin::Reset()
89 {
90 MEDIA_LOG_D("IN");
91 CloseUri();
92 return Status::OK;
93 }
94
Start()95 Status HttpSourcePlugin::Start()
96 {
97 MEDIA_LOG_D("IN");
98 return Status::OK;
99 }
100
Stop()101 Status HttpSourcePlugin::Stop()
102 {
103 MEDIA_LOG_I("IN");
104 CloseUri();
105 return Status::OK;
106 }
107
108 #undef ERROR_INVALID_PARAMETER
109
GetParameter(Tag tag,ValueType & value)110 Status HttpSourcePlugin::GetParameter(Tag tag, ValueType& value)
111 {
112 MEDIA_LOG_D("IN");
113 switch (tag) {
114 case Tag::BUFFERING_SIZE:
115 value = bufferSize_;
116 return Status::OK;
117 case Tag::WATERLINE_HIGH:
118 value = waterline_;
119 return Status::OK;
120 default:
121 return Status::ERROR_INVALID_PARAMETER;
122 }
123 }
124
SetParameter(Tag tag,const ValueType & value)125 Status HttpSourcePlugin::SetParameter(Tag tag, const ValueType& value)
126 {
127 MEDIA_LOG_D("IN");
128 switch (tag) {
129 case Tag::BUFFERING_SIZE:
130 bufferSize_ = AnyCast<uint32_t>(value);
131 return Status::OK;
132 case Tag::WATERLINE_HIGH:
133 waterline_ = AnyCast<uint32_t>(value);
134 return Status::OK;
135 default:
136 return Status::ERROR_INVALID_PARAMETER;
137 }
138 }
139
SetCallback(Callback * cb)140 Status HttpSourcePlugin::SetCallback(Callback* cb)
141 {
142 MEDIA_LOG_D("IN");
143 callback_ = cb;
144 OSAL::ScopedLock lock(mutex_);
145 if (downloader_ != nullptr) {
146 downloader_->SetCallback(cb);
147 }
148 return Status::OK;
149 }
150
SetSource(std::shared_ptr<MediaSource> source)151 Status HttpSourcePlugin::SetSource(std::shared_ptr<MediaSource> source)
152 {
153 MEDIA_LOG_D("SetSource IN");
154 OSAL::ScopedLock lock(mutex_);
155 auto uri = source->GetSourceUri();
156 if (uri.find(".m3u8") != std::string::npos) {
157 downloader_ = std::make_shared<DownloadMonitor>(std::make_shared<HlsMediaDownloader>());
158 delayReady = false;
159 } else if (uri.compare(0, 4, "http") == 0) { // 0 : position, 4: count
160 downloader_ = std::make_shared<DownloadMonitor>(std::make_shared<HttpMediaDownloader>());
161 }
162 FALSE_RETURN_V(downloader_ != nullptr, Status::ERROR_NULL_POINTER);
163
164 if (callback_ != nullptr) {
165 downloader_->SetCallback(callback_);
166 }
167
168 MEDIA_LOG_I("SetSource: " PUBLIC_LOG_S, uri.c_str());
169 FALSE_RETURN_V(downloader_->Open(uri), Status::ERROR_UNKNOWN);
170 return Status::OK;
171 }
172
GetAllocator()173 std::shared_ptr<Allocator> HttpSourcePlugin::GetAllocator()
174 {
175 MEDIA_LOG_D("GetAllocator IN");
176 return nullptr;
177 }
178
Read(std::shared_ptr<Buffer> & buffer,size_t expectedLen)179 Status HttpSourcePlugin::Read(std::shared_ptr<Buffer>& buffer, size_t expectedLen)
180 {
181 MEDIA_LOG_D("Read in");
182 OSAL::ScopedLock lock(mutex_);
183 FALSE_RETURN_V(downloader_ != nullptr, Status::ERROR_NULL_POINTER);
184
185 if (buffer == nullptr) {
186 buffer = std::make_shared<Buffer>();
187 }
188
189 std::shared_ptr<Memory>bufData;
190 if (buffer->IsEmpty()) {
191 bufData = buffer->AllocMemory(GetAllocator(), expectedLen);
192 } else {
193 bufData = buffer->GetMemory();
194 }
195
196 bool isEos = false;
197 unsigned int realReadSize = 0;
198 bool result = downloader_->Read(bufData->GetWritableAddr(expectedLen), expectedLen, realReadSize, isEos);
199 bufData->UpdateDataSize(realReadSize);
200 MEDIA_LOG_D("Read finished, read size = " PUBLIC_LOG_ZU ", isEos " PUBLIC_LOG_D32, bufData->GetSize(), isEos);
201 return result ? Status::OK : Status::END_OF_STREAM;
202 }
203
GetSize(size_t & size)204 Status HttpSourcePlugin::GetSize(size_t& size)
205 {
206 MEDIA_LOG_D("IN");
207 OSAL::ScopedLock lock(mutex_);
208 FALSE_RETURN_V(downloader_ != nullptr, Status::ERROR_NULL_POINTER);
209 size = downloader_->GetContentLength();
210 return Status::OK;
211 }
212
GetSeekable()213 Seekable HttpSourcePlugin::GetSeekable()
214 {
215 MEDIA_LOG_D("IN");
216 OSAL::ScopedLock lock(mutex_);
217 FALSE_RETURN_V(downloader_ != nullptr, Seekable::INVALID);
218 return downloader_->GetSeekable();
219 }
220
SeekTo(uint64_t offset)221 Status HttpSourcePlugin::SeekTo(uint64_t offset)
222 {
223 OSAL::ScopedLock lock(mutex_);
224 FALSE_RETURN_V(downloader_ != nullptr, Status::ERROR_NULL_POINTER);
225 FALSE_RETURN_V(downloader_->GetSeekable() == Seekable::SEEKABLE, Status::ERROR_INVALID_OPERATION);
226 FALSE_RETURN_V(offset <= downloader_->GetContentLength(), Status::ERROR_INVALID_PARAMETER);
227 FALSE_RETURN_V(downloader_->Seek(offset), Status::ERROR_UNKNOWN);
228 return Status::OK;
229 }
230
CloseUri()231 void HttpSourcePlugin::CloseUri()
232 {
233 OSAL::ScopedLock lock(mutex_);
234 if (downloader_ != nullptr) {
235 MEDIA_LOG_D("Close uri");
236 downloader_->Close();
237 downloader_ = nullptr;
238 }
239 }
240 }
241 }
242 }
243 }