1 /*
2 * Copyright (c) 2025 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 "video_processing_client.h"
17
18 #include "iservice_registry.h"
19 #include "video_processing_load_callback.h"
20 #include "vpe_sa_constants.h"
21
22 using namespace OHOS::Media::VideoProcessingEngine;
23 using namespace OHOS;
24 using namespace std::chrono_literals;
25 using namespace std::placeholders;
26
27 using VpeSa = IVideoProcessingServiceManager;
28
29 namespace {
30 std::mutex g_proxyLock;
31 constexpr int ERROR_DEAD_REPLY = 29189;
32 constexpr int DEAD_RETRY_COUNT = 5;
33 }
34
GetInstance()35 VideoProcessingManager& VideoProcessingManager::GetInstance()
36 {
37 static VideoProcessingManager instance;
38 return instance;
39 }
40
Connect()41 void VideoProcessingManager::Connect()
42 {
43 VPE_LOGD("call GetService");
44 GetService();
45 }
46
Disconnect()47 void VideoProcessingManager::Disconnect()
48 {
49 VPE_LOGD("VideoProcessingManager Disconnect!");
50 return;
51 }
52
LoadInfo(int32_t key,SurfaceBufferInfo & bufferInfo)53 ErrCode VideoProcessingManager::LoadInfo(int32_t key, SurfaceBufferInfo& bufferInfo)
54 {
55 std::lock_guard<std::mutex> lock(g_proxyLock);
56 return Execute([&key, &bufferInfo](sptr<VpeSa>& proxy) { return proxy->LoadInfo(key, bufferInfo); }, VPE_LOG_INFO);
57 }
58
LoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)59 void VideoProcessingManager::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
60 {
61 VPE_LOGI("Get VideoProcessingService SA success!");
62 std::unique_lock<std::mutex> lock(g_proxyLock);
63 if (remoteObject != nullptr) {
64 VPE_LOGD("remoteObject is not null.");
65 proxy_ = iface_cast<IVideoProcessingServiceManager>(remoteObject);
66 cvProxy_.notify_one();
67 }
68 }
69
LoadSystemAbilityFail()70 void VideoProcessingManager::LoadSystemAbilityFail()
71 {
72 VPE_LOGE("Get VideoProcessingService SA failed!");
73 std::unique_lock<std::mutex> lock(g_proxyLock);
74 proxy_ = nullptr;
75 }
76
Create(const std::string & feature,const std::string & clientName,uint32_t & clientID)77 VPEAlgoErrCode VideoProcessingManager::Create(const std::string& feature, const std::string& clientName,
78 uint32_t& clientID)
79 {
80 int id;
81 auto ret = Execute(std::bind(&VpeSa::Create, _1, feature, clientName, std::ref(id)), VPE_LOG_INFO);
82 if (ret == ERR_NONE) {
83 clientID = static_cast<uint32_t>(id);
84 VPE_LOGD("feature:%{public}s client:%{public}s -> ID:%{public}d", feature.c_str(), clientName.c_str(), id);
85 } else {
86 VPE_LOGE("feature:%{public}s client:%{public}s failed! ret:%{public}d", feature.c_str(), clientName.c_str(),
87 ret);
88 }
89 return ret;
90 }
91
Destroy(uint32_t clientID)92 VPEAlgoErrCode VideoProcessingManager::Destroy(uint32_t clientID)
93 {
94 return Execute(std::bind(&VpeSa::Destroy, _1, clientID), VPE_LOG_INFO);
95 }
96
SetParameter(uint32_t clientID,int32_t tag,const std::vector<uint8_t> & parameter)97 VPEAlgoErrCode VideoProcessingManager::SetParameter(uint32_t clientID, int32_t tag,
98 const std::vector<uint8_t>& parameter)
99 {
100 return Execute(std::bind(&VpeSa::SetParameter, _1, clientID, tag, parameter), VPE_LOG_INFO);
101 }
102
SetParameter(uint32_t clientID,int32_t tag)103 VPEAlgoErrCode VideoProcessingManager::SetParameter(uint32_t clientID, int32_t tag)
104 {
105 std::vector<uint8_t> param;
106 return SetParameter(clientID, tag, param);
107 }
108
GetParameter(uint32_t clientID,int32_t tag,std::vector<uint8_t> & parameter)109 VPEAlgoErrCode VideoProcessingManager::GetParameter(uint32_t clientID, int32_t tag, std::vector<uint8_t>& parameter)
110 {
111 return Execute(std::bind(&VpeSa::GetParameter, _1, clientID, tag, parameter), VPE_LOG_INFO);
112 }
113
UpdateMetadata(uint32_t clientID,SurfaceBufferInfo & image)114 VPEAlgoErrCode VideoProcessingManager::UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
115 {
116 return Execute(std::bind(&VpeSa::UpdateMetadata, _1, clientID, image), VPE_LOG_INFO);
117 }
118
Process(uint32_t clientID,const SurfaceBufferInfo & input,SurfaceBufferInfo & output)119 VPEAlgoErrCode VideoProcessingManager::Process(uint32_t clientID, const SurfaceBufferInfo& input,
120 SurfaceBufferInfo& output)
121 {
122 return Execute(std::bind(&VpeSa::Process, _1, clientID, input, output), VPE_LOG_INFO);
123 }
124
ComposeImage(uint32_t clientID,const SurfaceBufferInfo & inputSdrImage,const SurfaceBufferInfo & inputGainmap,SurfaceBufferInfo & outputHdrImage,bool legacy)125 VPEAlgoErrCode VideoProcessingManager::ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
126 const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy)
127 {
128 return Execute(std::bind(&VpeSa::ComposeImage, _1, clientID, inputSdrImage, inputGainmap, outputHdrImage, legacy),
129 VPE_LOG_INFO);
130 }
131
DecomposeImage(uint32_t clientID,const SurfaceBufferInfo & inputImage,SurfaceBufferInfo & outputSdrImage,SurfaceBufferInfo & outputGainmap)132 VPEAlgoErrCode VideoProcessingManager::DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
133 SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap)
134 {
135 return Execute(std::bind(&VpeSa::DecomposeImage, _1, clientID, inputImage, outputSdrImage, outputGainmap),
136 VPE_LOG_INFO);
137 }
138
GetService()139 sptr<IVideoProcessingServiceManager> VideoProcessingManager::GetService()
140 {
141 do {
142 std::lock_guard<std::mutex> lock(lock_);
143 if (proxy_ != nullptr) {
144 if (proxy_->AsObject() != nullptr && !proxy_->AsObject()->IsObjectDead()) [[likely]] {
145 return proxy_;
146 }
147 VPE_LOGD("SA remote died.");
148 ClearSaLocked();
149 }
150
151 if (isLoading_.load()) {
152 VPE_LOGD("SA is loading, so wait for the result directly .");
153 break;
154 }
155
156 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
157 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "Failed to GetSystemAbilityManager!");
158 VPE_LOGD("Try to check VPE SA.");
159 auto object = samgr->CheckSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID);
160 if (object != nullptr) {
161 proxy_ = iface_cast<IVideoProcessingServiceManager>(object);
162 VPE_LOGD("SA is already start");
163 return proxy_;
164 }
165
166 sptr<LoadCallback> loadCallback = new(std::nothrow) LoadCallback(
167 std::bind(&VideoProcessingManager::OnSaLoad, this, _1),
168 std::bind(&VideoProcessingManager::OnSaLoad, this, nullptr));
169 CHECK_AND_RETURN_RET_LOG(loadCallback != nullptr, nullptr, "Failed to create LoadCallback!");
170 VPE_LOGD("Loading VPE SA...");
171 CHECK_AND_RETURN_RET_LOG(samgr->LoadSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID, loadCallback) == ERR_OK,
172 nullptr, "Failed to load VPE SA!");
173 isLoading_ = true;
174 } while (false);
175
176 std::unique_lock lock(lock_);
177 CHECK_AND_RETURN_RET_LOG(cvProxy_.wait_for(lock, 1s, [this] { return !isLoading_.load(); }), nullptr,
178 "load SA timeout!");
179 if (proxy_ != nullptr) {
180 VPE_LOGD("Finish loading VPE SA success.");
181 } else {
182 VPE_LOGE("Finish loading VPE SA fail!");
183 }
184 return proxy_;
185 }
186
OnSaLoad(const sptr<IRemoteObject> & remoteObject)187 void VideoProcessingManager::OnSaLoad(const sptr<IRemoteObject>& remoteObject)
188 {
189 {
190 std::lock_guard<std::mutex> lock(lock_);
191 if (remoteObject != nullptr) {
192 sptr<DeathObserver> observer = new(std::nothrow) DeathObserver(
193 std::bind(&VideoProcessingManager::OnSaDied, this, _1));
194 CHECK_AND_RETURN_LOG(observer != nullptr, "Failed to create DeathObserver!");
195 CHECK_AND_RETURN_LOG(remoteObject->AddDeathRecipient(observer), "Failed to AddDeathRecipient!");
196 VPE_LOGD("AddDeathRecipient success.");
197 proxy_ = iface_cast<IVideoProcessingServiceManager>(remoteObject);
198 VPE_LOGI("SA load success.");
199 } else {
200 proxy_ = nullptr;
201 VPE_LOGE("SA load fail!");
202 }
203 isLoading_ = false;
204 }
205 cvProxy_.notify_all();
206 }
207
OnSaDied(const wptr<IRemoteObject> & remoteObject)208 void VideoProcessingManager::OnSaDied([[maybe_unused]] const wptr<IRemoteObject>& remoteObject)
209 {
210 std::lock_guard<std::mutex> lock(lock_);
211 proxy_ = nullptr;
212 }
213
Execute(std::function<ErrCode (sptr<IVideoProcessingServiceManager> &)> && operation,const LogInfo & logInfo)214 VPEAlgoErrCode VideoProcessingManager::Execute(
215 std::function<ErrCode(sptr<IVideoProcessingServiceManager>&)>&& operation, const LogInfo& logInfo)
216 {
217 auto proxy = GetService();
218 if (proxy == nullptr) [[unlikely]] {
219 VPE_ORG_LOGE(logInfo, "proxy is null!");
220 return VPE_ALGO_ERR_INVALID_STATE;
221 }
222 auto err = static_cast<VPEAlgoErrCode>(operation(proxy));
223 if (err == ERROR_DEAD_REPLY) {
224 ClearSa();
225 if (deadRetryCount_.load() < DEAD_RETRY_COUNT) {
226 deadRetryCount_++;
227 VPE_ORG_LOGD(logInfo, "<%{public}d> Retry to check SA again for dead reply.", deadRetryCount_.load());
228 return Execute(std::move(operation), logInfo);
229 }
230 } else {
231 deadRetryCount_.store(0);
232 }
233 return err;
234 }
235
ClearSa()236 void VideoProcessingManager::ClearSa()
237 {
238 std::lock_guard<std::mutex> lock(lock_);
239 ClearSaLocked();
240 }
241
ClearSaLocked()242 void VideoProcessingManager::ClearSaLocked()
243 {
244 proxy_ = nullptr;
245 isLoading_ = false;
246 }
247
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)248 void VideoProcessingManager::LoadCallback::OnLoadSystemAbilitySuccess([[maybe_unused]] int32_t systemAbilityId,
249 const sptr<IRemoteObject>& remoteObject)
250 {
251 onSuccess_(remoteObject);
252 }
253
OnLoadSystemAbilityFail(int32_t systemAbilityId)254 void VideoProcessingManager::LoadCallback::OnLoadSystemAbilityFail([[maybe_unused]] int32_t systemAbilityId)
255 {
256 onFail_();
257 }
258
OnRemoteDied(const wptr<IRemoteObject> & remoteObject)259 void VideoProcessingManager::DeathObserver::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
260 {
261 onRemoteDied_(remoteObject);
262 }