1 /*
2  * Copyright (c) 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 
16 #include "core/components/video/resource/resource.h"
17 
18 #include <sstream>
19 
20 #include "base/log/log.h"
21 
22 namespace OHOS::Ace {
23 
24 const char PARAM_NONE[] = "";
25 const char PARAM_AND[] = "#HWJS-&-#";
26 const char PARAM_VALUE[] = "value";
27 const char PARAM_EQUALS[] = "#HWJS-=-#";
28 const char PARAM_BEGIN[] = "#HWJS-?-#";
29 const char METHOD[] = "method";
30 const char EVENT[] = "event";
31 const char RESULT_FAIL[] = "fail";
32 
Release(const std::function<void (bool)> & onRelease)33 void Resource::Release(const std::function<void(bool)>& onRelease)
34 {
35     if (id_ == INVALID_ID) {
36         return;
37     }
38 
39     auto context = context_.Upgrade();
40     if (!context) {
41         LOGE("fail to release resource due to context is null");
42         return;
43     }
44 
45     auto resRegister = context->GetPlatformResRegister();
46     auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
47     auto weakRes = AceType::WeakClaim(AceType::RawPtr(resRegister));
48     auto releaseTask = [weak = AceType::WeakClaim(this), weakRes, onRelease] {
49         auto resource = weak.Upgrade();
50         auto resRegister = weakRes.Upgrade();
51         if (resource == nullptr || resRegister == nullptr) {
52             LOGE("resource or resRegister is nullptr");
53             return;
54         }
55         bool ret = resRegister->ReleaseResource(resource->hash_);
56         if (ret) {
57             resource->id_ = INVALID_ID;
58             resource->hash_.clear();
59         }
60         if (onRelease) {
61             onRelease(ret);
62         }
63     };
64     if (platformTaskExecutor.IsRunOnCurrentThread()) {
65         releaseTask();
66     } else {
67         platformTaskExecutor.PostTask(releaseTask, "ArkUIVideoResourceRelease");
68     }
69 }
70 
GetDoubleParam(const std::string & param,const std::string & name) const71 double Resource::GetDoubleParam(const std::string& param, const std::string& name) const
72 {
73     size_t len = name.length();
74     size_t pos = param.find(name);
75     double result = 0.0;
76 
77     if (pos != std::string::npos) {
78         std::stringstream ss;
79 
80         ss << param.substr(pos + 1 + len);
81         ss >> result;
82     }
83 
84     return result;
85 }
86 
GetIntParam(const std::string & param,const std::string & name) const87 int32_t Resource::GetIntParam(const std::string& param, const std::string& name) const
88 {
89     size_t len = name.length();
90     size_t pos = param.find(name);
91     int32_t result = 0;
92 
93     if (pos != std::string::npos) {
94         std::stringstream ss;
95 
96         ss << param.substr(pos + 1 + len);
97         ss >> result;
98     }
99 
100     return result;
101 }
102 
GetInt64Param(const std::string & param,const std::string & name) const103 int64_t Resource::GetInt64Param(const std::string& param, const std::string& name) const
104 {
105     size_t len = name.length();
106     size_t pos = param.find(name);
107     int64_t result = 0;
108 
109     if (pos != std::string::npos) {
110         std::stringstream ss;
111         ss << param.substr(pos + 1 + len);
112         ss >> result;
113     }
114 
115     return result;
116 }
117 
GetFloatArrayParam(const std::string & param,const std::string & name,std::vector<float> & matrix) const118 void Resource::GetFloatArrayParam(const std::string& param, const std::string& name, std::vector<float>& matrix) const
119 {
120     size_t len = name.length();
121     size_t pos = param.find(name);
122     matrix.clear();
123     if (pos == std::string::npos) {
124         return;
125     }
126     std::string data = param.substr(pos + 1 + len);
127     pos = data.find("[");
128     if (pos == std::string::npos) {
129         return;
130     }
131     do {
132         std::stringstream ss;
133         ss << data.substr(pos + 1);
134         float tmp = 0;
135         ss >> tmp;
136         matrix.emplace_back(tmp);
137         data = data.substr(pos + 1);
138         pos = data.find(",");
139         if (pos == std::string::npos) {
140             return;
141         }
142     } while (1);
143     return;
144 }
145 
ParseMapFromString(const std::string & param)146 std::map<std::string, std::string> Resource::ParseMapFromString(const std::string& param)
147 {
148     size_t equalsLen = sizeof(PARAM_EQUALS) - 1;
149     size_t andLen = sizeof(PARAM_EQUALS) - 1;
150     size_t totalLen = param.length();
151     size_t index = 0;
152     std::map<std::string, std::string> result;
153     while (index < totalLen) {
154         size_t end = param.find(PARAM_AND, index);
155         if (end == std::string::npos) {
156             end = totalLen;
157         }
158 
159         size_t mid = param.find(PARAM_EQUALS, index);
160         if (mid == std::string::npos) {
161             index = end + andLen;
162             continue;
163         }
164         std::string key = param.substr(index, mid - index);
165         std::string value = param.substr(mid + equalsLen, end - mid - equalsLen);
166         result[key] = value;
167         index = end + andLen;
168     }
169     return result;
170 }
171 
MakeResourceHash() const172 std::string Resource::MakeResourceHash() const
173 {
174     std::stringstream hashCode;
175     hashCode << type_ << "@" << id_;
176 
177     return hashCode.str();
178 }
179 
MakeEventHash(const std::string & event) const180 std::string Resource::MakeEventHash(const std::string& event) const
181 {
182     std::string eventHash = hash_;
183 
184     eventHash += std::string(EVENT);
185     eventHash += std::string(PARAM_EQUALS);
186     eventHash += event;
187     eventHash += std::string(PARAM_BEGIN);
188 
189     return eventHash;
190 }
191 
MakeMethodHash(const std::string & method) const192 std::string Resource::MakeMethodHash(const std::string& method) const
193 {
194     std::string methodHash = hash_;
195 
196     methodHash += std::string(METHOD);
197     methodHash += std::string(PARAM_EQUALS);
198     methodHash += method;
199     methodHash += std::string(PARAM_BEGIN);
200 
201     return methodHash;
202 }
203 
IsResultSuccess(const std::string & result) const204 bool Resource::IsResultSuccess(const std::string& result) const
205 {
206     size_t pos = result.find(RESULT_FAIL);
207 
208     return pos != 0;
209 }
210 
OnError(const std::string & errorCode,const std::string & errorMsg)211 void Resource::OnError(const std::string& errorCode, const std::string& errorMsg)
212 {
213     if (onError_) {
214         onError_(errorCode, errorMsg);
215     }
216 }
217 
CallResRegisterMethod(const std::string & method,const std::string & param,const std::function<void (std::string &)> & callback)218 void Resource::CallResRegisterMethod(
219     const std::string& method, const std::string& param, const std::function<void(std::string&)>& callback)
220 {
221     if (method.empty()) {
222         return;
223     }
224 
225     auto context = context_.Upgrade();
226     if (!context) {
227         LOGE("fail to get context to call res register method");
228         return;
229     }
230 
231     auto resRegister = context->GetPlatformResRegister();
232     auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
233     auto weakRes = AceType::WeakClaim(AceType::RawPtr(resRegister));
234     platformTaskExecutor.PostTask([method, param, weakRes, callback] {
235         auto resRegister = weakRes.Upgrade();
236         if (resRegister == nullptr) {
237             LOGE("resRegister is nullptr");
238             return;
239         }
240         std::string result;
241         resRegister->OnMethodCall(method, param, result);
242         if (callback) {
243             callback(result);
244         }
245     }, "ArkUIVideoCallResRegisterMethod");
246 }
247 
CallSyncResRegisterMethod(const Method & method,const std::string & param,const std::function<void (std::string &)> & callback)248 void Resource::CallSyncResRegisterMethod(
249     const Method& method, const std::string& param, const std::function<void(std::string&)>& callback)
250 {
251     if (method.empty()) {
252         return;
253     }
254 
255     auto context = context_.Upgrade();
256     if (!context) {
257         LOGE("fail to get context to call res register method");
258         return;
259     }
260 
261     auto resRegister = context->GetPlatformResRegister();
262     std::string result;
263     if (!resRegister) {
264         LOGE("fail to get resRegister to call res register method");
265         return;
266     }
267     resRegister->OnMethodCall(method, param, result);
268     if (callback) {
269         callback(result);
270     }
271 }
272 
273 } // namespace OHOS::Ace