• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_native_base.h"
17 
18 #include "common/native_mfmagic.h"
19 #include "native_window.h"
20 
21 #include "video_environment_native.h"
22 #include "video_processing_callback_impl.h"
23 #include "vpe_log.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Media::VideoProcessingEngine;
27 
VideoProcessingNativeBase(OH_VideoProcessing * context)28 VideoProcessingNativeBase::VideoProcessingNativeBase(OH_VideoProcessing* context) : context_(context)
29 {
30 }
31 
Initialize()32 VideoProcessing_ErrorCode VideoProcessingNativeBase::Initialize()
33 {
34     CHECK_AND_RETURN_RET_LOG(!isInitialized_.load(), VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
35         "Already init!");
36     std::lock_guard<std::mutex> lock(lock_);
37     CHECK_AND_RETURN_RET_LOG(!isInitialized_.load(), VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
38         "Already init!");
39     auto result = InitializeInner();
40     isInitialized_ = true;
41     return result;
42 }
43 
Deinitialize()44 VideoProcessing_ErrorCode VideoProcessingNativeBase::Deinitialize()
45 {
46     CHECK_AND_RETURN_RET_LOG(isInitialized_.load(), VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
47         "Already deinit!");
48     std::lock_guard<std::mutex> lock(lock_);
49     CHECK_AND_RETURN_RET_LOG(isInitialized_.load(), VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
50         "Already deinit!");
51     isInitialized_ = false;
52     auto result = DeinitializeInner();
53     return result;
54 }
55 
RegisterCallback(const VideoProcessing_Callback * callback,void * userData)56 VideoProcessing_ErrorCode VideoProcessingNativeBase::RegisterCallback(const VideoProcessing_Callback* callback,
57     void* userData)
58 {
59     CHECK_AND_RETURN_RET_LOG(callback != nullptr, VIDEO_PROCESSING_ERROR_INVALID_PARAMETER, "Callback is null!");
60     CHECK_AND_RETURN_RET_LOG(callback->GetInnerCallback() != nullptr && callback->GetInnerCallback()->IsValid(),
61         VIDEO_PROCESSING_ERROR_INVALID_VALUE, "Callback is empty!");
62 
63     return ExecuteWhenIdle([this, &callback, &userData]() {
64         std::lock_guard<std::mutex> lock(callbackLock_);
65         VideoProcessing_ErrorCode errorCode = PrepareRegistrationLocked();
66         if (errorCode != VIDEO_PROCESSING_SUCCESS) {
67             return errorCode;
68         }
69         auto [it, result]  = callbacks_.insert({ callback->GetInnerCallback(), userData });
70         CHECK_AND_RETURN_RET_LOG(result, VIDEO_PROCESSING_ERROR_PROCESS_FAILED, "Add callback failed!");
71         hasCallback_ = true;
72         if (callback->GetInnerCallback()->HasOnNewOutputBuffer()) {
73             hasOnRenderOutputBuffer_ = true;
74         }
75         return VIDEO_PROCESSING_SUCCESS;
76     }, "Registration during running is not allowed!");
77 }
78 
SetSurface(const OHNativeWindow * window)79 VideoProcessing_ErrorCode VideoProcessingNativeBase::SetSurface(const OHNativeWindow* window)
80 {
81     CHECK_AND_RETURN_RET_LOG(window != nullptr && window->surface != nullptr, VIDEO_PROCESSING_ERROR_INVALID_PARAMETER,
82         "window is null or surface buffer is null!");
83 
84     std::lock_guard<std::mutex> lock(lock_);
85     auto result = SetSurface(window->surface, *window);
86     hasOutputSurface_ = (result == VIDEO_PROCESSING_SUCCESS);
87     return result;
88 }
89 
GetSurface(OHNativeWindow ** window)90 VideoProcessing_ErrorCode VideoProcessingNativeBase::GetSurface(OHNativeWindow** window)
91 {
92     CHECK_AND_RETURN_RET_LOG(window != nullptr, VIDEO_PROCESSING_ERROR_INVALID_PARAMETER, "window is null!");
93     return ExecuteWhenIdle([this, &window]() {
94         if (hasInputSurface_.load()) {
95             VPE_LOGE("Input surface is already created!");
96             return VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED;
97         }
98 
99         sptr<Surface> surface = GetSurface();
100         CHECK_AND_RETURN_RET_LOG(surface != nullptr, VIDEO_PROCESSING_ERROR_CREATE_FAILED, "get surface failed!");
101         *window = CreateNativeWindowFromSurface(&surface);
102         CHECK_AND_RETURN_RET_LOG(*window != nullptr, VIDEO_PROCESSING_ERROR_CREATE_FAILED, "create window failed!");
103         hasInputSurface_ = true;
104         return VIDEO_PROCESSING_SUCCESS;
105     }, "Surface getting during running is not allowed!");
106 }
107 
SetParameter(const OH_AVFormat * parameter)108 VideoProcessing_ErrorCode VideoProcessingNativeBase::SetParameter(const OH_AVFormat* parameter)
109 {
110     CHECK_AND_RETURN_RET_LOG(parameter != nullptr, VIDEO_PROCESSING_ERROR_INVALID_PARAMETER, "parameter is null!");
111     return SetParameter(parameter->format_);
112 }
113 
GetParameter(OH_AVFormat * parameter)114 VideoProcessing_ErrorCode VideoProcessingNativeBase::GetParameter(OH_AVFormat* parameter)
115 {
116     CHECK_AND_RETURN_RET_LOG(parameter != nullptr, VIDEO_PROCESSING_ERROR_INVALID_PARAMETER, "parameter is null!");
117     return GetParameter(parameter->format_);
118 }
119 
Start()120 VideoProcessing_ErrorCode VideoProcessingNativeBase::Start()
121 {
122     return ExecuteWhenIdle([this]() {
123         CHECK_AND_RETURN_RET_LOG(hasInputSurface_.load() && hasOutputSurface_.load() && hasCallback_.load(),
124             VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
125             "Input/Output surface is not ready or the callback is not registered!");
126 
127         TraverseCallbacksLocked([](std::shared_ptr<VideoProcessingCallbackNative>& cb, void*) { cb->LockModifiers(); });
128         isRunning_ = true;
129         return OnStart();
130     }, "Already start!");
131 }
132 
Stop()133 VideoProcessing_ErrorCode VideoProcessingNativeBase::Stop()
134 {
135     return ExecuteWhenRunning([this]() {
136         TraverseCallbacksLocked(
137             [](std::shared_ptr<VideoProcessingCallbackNative>& cb, void*) { cb->UnlockModifiers(); });
138         isRunning_ = false;
139         return OnStop();
140     }, "Already stop!");
141 }
142 
RenderOutputBuffer(uint32_t index)143 VideoProcessing_ErrorCode VideoProcessingNativeBase::RenderOutputBuffer(uint32_t index)
144 {
145     CHECK_AND_RETURN_RET_LOG(hasOnRenderOutputBuffer_.load(), VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED,
146         "The operation is not permitted without binding OnRenderOutputBuffer!");
147     if (isOnNewOutputBuffer_.load()) {
148         return OnRenderOutputBuffer(index);
149     }
150     return ExecuteWhenRunning([this, &index]() {
151         return OnRenderOutputBuffer(index);
152     }, "RenderOutputBuffer must be called during running!");
153 }
154 
InitializeInner()155 VideoProcessing_ErrorCode VideoProcessingNativeBase::InitializeInner()
156 {
157     return VideoEnvironmentNative::Get().InitializeByDefault();
158 }
159 
DeinitializeInner()160 VideoProcessing_ErrorCode VideoProcessingNativeBase::DeinitializeInner()
161 {
162     return VideoEnvironmentNative::Get().DeinitializeByDefault();
163 }
164 
RegisterCallback()165 VideoProcessing_ErrorCode VideoProcessingNativeBase::RegisterCallback()
166 {
167     return VIDEO_PROCESSING_SUCCESS;
168 }
169 
SetSurface(const sptr<Surface> & surface,const OHNativeWindow & window)170 VideoProcessing_ErrorCode VideoProcessingNativeBase::SetSurface(const sptr<Surface>& surface,
171     [[maybe_unused]] const OHNativeWindow& window)
172 {
173     return SetSurface(surface);
174 }
175 
SetSurface(const sptr<Surface> & surface)176 VideoProcessing_ErrorCode VideoProcessingNativeBase::SetSurface([[maybe_unused]] const sptr<Surface>& surface)
177 {
178     return VIDEO_PROCESSING_SUCCESS;
179 }
180 
GetSurface()181 sptr<Surface> VideoProcessingNativeBase::GetSurface()
182 {
183     return nullptr;
184 }
185 
SetParameter(const OHOS::Media::Format & parameter)186 VideoProcessing_ErrorCode VideoProcessingNativeBase::SetParameter([[maybe_unused]] const OHOS::Media::Format& parameter)
187 {
188     return VIDEO_PROCESSING_SUCCESS;
189 }
190 
GetParameter(OHOS::Media::Format & parameter)191 VideoProcessing_ErrorCode VideoProcessingNativeBase::GetParameter([[maybe_unused]] OHOS::Media::Format& parameter)
192 {
193     return VIDEO_PROCESSING_SUCCESS;
194 }
195 
OnStart()196 VideoProcessing_ErrorCode VideoProcessingNativeBase::OnStart()
197 {
198     return VIDEO_PROCESSING_SUCCESS;
199 }
200 
OnStop()201 VideoProcessing_ErrorCode VideoProcessingNativeBase::OnStop()
202 {
203     return VIDEO_PROCESSING_SUCCESS;
204 }
205 
OnRenderOutputBuffer(uint32_t index)206 VideoProcessing_ErrorCode VideoProcessingNativeBase::OnRenderOutputBuffer([[maybe_unused]] uint32_t index)
207 {
208     return VIDEO_PROCESSING_SUCCESS;
209 }
210 
OnError(VideoProcessing_ErrorCode errorCode)211 void VideoProcessingNativeBase::OnError(VideoProcessing_ErrorCode errorCode)
212 {
213     OnCallback([this, &errorCode](std::shared_ptr<VideoProcessingCallbackNative>& callback, void* userData) {
214         callback->OnError(context_, errorCode, userData);
215     }, "OnError");
216 }
217 
OnState(VideoProcessing_State state)218 void VideoProcessingNativeBase::OnState(VideoProcessing_State state)
219 {
220     OnCallback([this, &state](std::shared_ptr<VideoProcessingCallbackNative>& callback, void* userData) {
221         callback->OnState(context_, state, userData);
222     }, "OnState");
223 }
224 
OnNewOutputBuffer(uint32_t index)225 void VideoProcessingNativeBase::OnNewOutputBuffer(uint32_t index)
226 {
227     if (!isInitialized_.load()) {
228         VPE_LOGI("Skip index:%{public}u buffer because VPE has been deinitialized.", index);
229         return;
230     }
231     OnCallback([this, &index](std::shared_ptr<VideoProcessingCallbackNative>& callback, void* userData) {
232         if (callback->HasOnNewOutputBuffer()) {
233             isOnNewOutputBuffer_ = true;
234             callback->OnNewOutputBuffer(context_, index, userData);
235             isOnNewOutputBuffer_ = false;
236         } else {
237             OnRenderOutputBuffer(index);
238         }
239     }, "OnNewOutputBuffer");
240 }
241 
ExecuteWhenIdle(std::function<VideoProcessing_ErrorCode (void)> && task,const std::string & errLog)242 VideoProcessing_ErrorCode VideoProcessingNativeBase::ExecuteWhenIdle(
243     std::function<VideoProcessing_ErrorCode(void)>&& task, const std::string& errLog)
244 {
245     if (isRunning_.load()) {
246         VPE_LOGW("%{public}s", errLog.c_str());
247         return VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED;
248     }
249 
250     std::lock_guard<std::mutex> lock(lock_);
251     if (isRunning_.load()) {
252         VPE_LOGW("%{public}s", errLog.c_str());
253         return VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED;
254     }
255     return task();
256 }
257 
ExecuteWhenRunning(std::function<VideoProcessing_ErrorCode (void)> && task,const std::string & errLog)258 VideoProcessing_ErrorCode VideoProcessingNativeBase::ExecuteWhenRunning(
259     std::function<VideoProcessing_ErrorCode(void)>&& task, const std::string& errLog)
260 {
261     if (!isRunning_.load()) {
262         VPE_LOGW("%{public}s", errLog.c_str());
263         return VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED;
264     }
265 
266     std::lock_guard<std::mutex> lock(lock_);
267     if (!isRunning_.load()) {
268         VPE_LOGW("%{public}s", errLog.c_str());
269         return VIDEO_PROCESSING_ERROR_OPERATION_NOT_PERMITTED;
270     }
271     return task();
272 }
273 
OnCallback(std::function<void (std::shared_ptr<VideoProcessingCallbackNative> &,void *)> && task,const std::string & name)274 void VideoProcessingNativeBase::OnCallback(
275     std::function<void(std::shared_ptr<VideoProcessingCallbackNative>&, void*)>&& task,
276     const std::string& name)
277 {
278     std::lock_guard<std::mutex> lock(callbackLock_);
279     TraverseCallbacksLocked(std::move(task));
280 }
281 
TraverseCallbacksLocked(std::function<void (std::shared_ptr<VideoProcessingCallbackNative> &,void *)> && task)282 void VideoProcessingNativeBase::TraverseCallbacksLocked(
283     std::function<void(std::shared_ptr<VideoProcessingCallbackNative>&, void*)>&& task)
284 {
285     TraverseCallbacksExLocked([&task](std::shared_ptr<VideoProcessingCallbackNative>& cb, void* userData) {
286         task(cb, userData);
287         return false;
288     });
289 }
290 
TraverseCallbacksExLocked(std::function<bool (std::shared_ptr<VideoProcessingCallbackNative> &,void *)> && task)291 void VideoProcessingNativeBase::TraverseCallbacksExLocked(
292     std::function<bool(std::shared_ptr<VideoProcessingCallbackNative>&, void*)>&& task)
293 {
294     for (auto& callback : callbacks_) {
295         std::shared_ptr<VideoProcessingCallbackNative> cb = callback.callback;
296         if (cb == nullptr) [[unlikely]] {
297             VPE_LOGW("callback is null!");
298             continue;
299         }
300         if (task(cb, callback.userData)) {
301             break;
302         }
303     }
304 }
305 
PrepareRegistrationLocked()306 VideoProcessing_ErrorCode VideoProcessingNativeBase::PrepareRegistrationLocked()
307 {
308     if (isInnerCallbackReady_) {
309         return VIDEO_PROCESSING_SUCCESS;
310     }
311     VideoProcessing_ErrorCode errorCode = RegisterCallback();
312     if (errorCode == VIDEO_PROCESSING_SUCCESS) {
313         VPE_LOGD("Inner RegisterCallback success.");
314         isInnerCallbackReady_ = true;
315     }
316     return errorCode;
317 }
318