已合并
新增AIHDR查询接口 #66
已合并
zhuyicheng666创建于 23 天前
14 个文件变更+927-13
@@ -56,7 +56,9 @@
56 "//foundation/multimedia/video_processing_engine/framework:videoprocessingengine",56 "//foundation/multimedia/video_processing_engine/framework:videoprocessingengine",
57 "//foundation/multimedia/video_processing_engine/services:video_processing_service_group",57 "//foundation/multimedia/video_processing_engine/services:video_processing_service_group",
58 "//foundation/multimedia/video_processing_engine/interfaces/kits/taihe:video_processing_engine_taihe_gen_only",58 "//foundation/multimedia/video_processing_engine/interfaces/kits/taihe:video_processing_engine_taihe_gen_only",
59- "//foundation/multimedia/video_processing_engine/interfaces/kits/taihe:video_processing_engine_taihe_group"59+ "//foundation/multimedia/video_processing_engine/interfaces/kits/taihe:video_processing_engine_taihe_group",
60+ "//foundation/multimedia/video_processing_engine/interfaces/kits/taihe:video_processing_taihe_group",
61+ "//foundation/multimedia/video_processing_engine/framework:videoprocessing_napi"
60 ],62 ],
61 "inner_kits": [63 "inner_kits": [
62 {64 {
@@ -536,3 +536,48 @@ ohos_shared_library("videoprocessingenginenapi") {
536 relative_install_dir = "module/multimedia"536 relative_install_dir = "module/multimedia"
537 part_name = "video_processing_engine"537 part_name = "video_processing_engine"
538}538}
539+ 
540+ohos_shared_library("videoprocessing_napi") {
541+ branch_protector_ret = "pac_ret"
542+ sanitize = {
543+ cfi = true
544+ cfi_cross_dso = true
545+ cfi_vcall_icall_only = true
546+ debug = false
547+ }
548+
549+ defines = [ ]
550+
551+ include_dirs = [
552+ "$DFX_DIR/include",
553+ "$INTERFACES_DIR/kits/js",
554+ "$INTERFACES_INNER_API_DIR",
555+ "$ALGORITHM_COMMON_DIR/include/",
556+ "$INTERFACES_CAPI_DIR",
557+ "$SERVICES_DIR/utils/include",
558+ ]
559+ sources = [
560+ "$INTERFACES_DIR/kits/js/native_module_ohos_video_processing.cpp",
561+ "$INTERFACES_DIR/kits/js/video_processor_napi.cpp",
562+ ]
563+
564+ deps = [
565+ ":videoprocessingengine",
566+ ]
567+
568+ cflags = VIDEO_PROCESSING_ENGINE_CFLAGS
569+ external_deps = [
570+ "c_utils:utils",
571+ "drivers_interface_display:libdisplay_commontype_proxy_2.1",
572+ "hilog:libhilog",
573+ "hitrace:hitrace_meter",
574+ "ipc:ipc_napi",
575+ "media_foundation:native_media_core",
576+ "media_foundation:media_foundation",
577+ "napi:ace_napi",
578+ ]
579+
580+ subsystem_name = "multimedia"
581+ relative_install_dir = "module/multimedia"
582+ part_name = "video_processing_engine"
583+}
@@ -41,6 +41,19 @@ std::unordered_map<uint32_t, std::function<bool(const OHOS::Media::Format& param
41 // Feature altorithm header isSupported begin41 // Feature altorithm header isSupported begin
42 // Feature altorithm header isSupported end42 // Feature altorithm header isSupported end
43};43};
44+ 
45+std::unordered_map<uint32_t, std::function<int32_t(VpeVideo::SettingsChangeCallback)>>
46+ g_registerSettingsChangeCallback = {
47+ // NOTE: Add feature altorithm GetParameter here. Every time a new client is created for communication
48+ // Feature altorithm header GetParameter begin
49+ // Feature altorithm header GetParameter end
50+};
51+
52+std::unordered_map<uint32_t, std::function<int32_t(void)>> g_unregisterSettingsChangeCallback = {
53+ // NOTE: Add feature altorithm GetParameter here. Every time a new client is created for communication
54+ // Feature altorithm header GetParameter begin
55+ // Feature altorithm header GetParameter end
56+};
44}57}
45 58 
46std::shared_ptr<VpeVideo> VpeVideo::Create(uint32_t type)59std::shared_ptr<VpeVideo> VpeVideo::Create(uint32_t type)
@@ -138,3 +151,23 @@ VPEAlgoErrCode VpeVideo::RenderOutputBufferAtTime([[maybe_unused]] uint32_t inde
138{151{
139 return VPE_ALGO_ERR_OK;152 return VPE_ALGO_ERR_OK;
140}153}
154+ 
155+int32_t VpeVideo::RegisterSettingsChangeCallback(uint32_t type, SettingsChangeCallback callback)
156+{
157+ auto it = g_registerSettingsChangeCallback.find(type);
158+ if (it == g_registerSettingsChangeCallback.end()) {
159+ VPE_LOGE("Unsupported type: 0x%{public}x", type);
160+ return VPE_ALGO_ERR_INVALID_PARAM;
161+ }
162+ return it->second(callback);
163+}
164+
165+int32_t VpeVideo::UnregisterSettingsChangeCallback(uint32_t type)
166+{
167+ auto it = g_unregisterSettingsChangeCallback.find(type);
168+ if (it == g_unregisterSettingsChangeCallback.end()) {
169+ VPE_LOGE("Unsupported type: 0x%{public}x", type);
170+ return VPE_ALGO_ERR_INVALID_PARAM;
171+ }
172+ return it->second();
173+}
@@ -31,6 +31,7 @@ namespace Media {
31namespace VideoProcessingEngine {31namespace VideoProcessingEngine {
32class __attribute__((visibility("default"))) VpeVideo {32class __attribute__((visibility("default"))) VpeVideo {
33public:33public:
34+ using SettingsChangeCallback = std::function<void(int32_t feature, int32_t tag, int32_t param)>;
34 /**35 /**
35 * @brief Create a VpeVideo object.36 * @brief Create a VpeVideo object.
36 * @param type Use VIDEO_TYPE_XXX to specify the processing type. For details, see {@link VpeVideoType}.37 * @param type Use VIDEO_TYPE_XXX to specify the processing type. For details, see {@link VpeVideoType}.
@@ -57,6 +58,9 @@ public:
57 */58 */
58 static bool IsSupported(void);59 static bool IsSupported(void);
59 60 
61+ static int32_t RegisterSettingsChangeCallback(uint32_t type, SettingsChangeCallback callback);
62+ static int32_t UnregisterSettingsChangeCallback(uint32_t type);
63+ 
60 /**64 /**
61 * @brief Register callback object.65 * @brief Register callback object.
62 * @param callback Callback object to be registered. For details, see {@link VpeVideoCallback}.66 * @param callback Callback object to be registered. For details, see {@link VpeVideoCallback}.
@@ -35,7 +35,7 @@ static napi_value Export(napi_env env, napi_value exports)
35/*35/*
36 * module define36 * module define
37 */37 */
38-static napi_module videoProcessingModule = {38+static napi_module videoProcessingEngineModule = {
39 .nm_version = 1,39 .nm_version = 1,
40 .nm_flags = 0,40 .nm_flags = 0,
41 .nm_filename = nullptr,41 .nm_filename = nullptr,
@@ -48,9 +48,9 @@ static napi_module videoProcessingModule = {
48/*48/*
49 * module register49 * module register
50 */50 */
51-extern "C" __attribute__((constructor)) void VideoProcessingModule(void)51+extern "C" __attribute__((constructor)) void RegisterVideoProcessingEngineModule(void)
52{52{
53- napi_module_register(&videoProcessingModule);53+ napi_module_register(&videoProcessingEngineModule);
54}54}
55} // namespace Media55} // namespace Media
56} // namespace OHOS56} // namespace OHOS
@@ -0,0 +1,51 @@
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 "native_module_ohos_video_processing.h"
17+#include "video_processor_napi.h"
18+
19+namespace OHOS {
20+namespace Media {
21+/*
22+* Function registering all props and functions of multimedia.videoProcessing module
23+*/
24+static napi_value Export(napi_env env, napi_value exports)
25+{
26+ VideoProcessorNapi::Init(env, exports);
27+ return exports;
28+}
29+
30+/*
31+ * module define
32+ */
33+static napi_module videoProcessingModule = {
34+ .nm_version = 1,
35+ .nm_flags = 0,
36+ .nm_filename = nullptr,
37+ .nm_register_func = Export,
38+ .nm_modname = "multimedia.videoProcessing",
39+ .nm_priv = nullptr,
40+ .reserved = {0},
41+};
42+
43+/*
44+ * module register
45+ */
46+extern "C" __attribute__((constructor)) void RegisterVideoProcessingModule(void)
47+{
48+ napi_module_register(&videoProcessingModule);
49+}
50+} // namespace Media
51+} // namespace OHOS
@@ -0,0 +1,22 @@
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+#ifndef NATIVE_MODULE_OHOS_VIDEO_PROCESSING_H
17+#define NATIVE_MODULE_OHOS_VIDEO_PROCESSING_H
18+
19+#include "napi/native_api.h"
20+#include "napi/native_node_api.h"
21+
22+#endif
@@ -0,0 +1,335 @@
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+#undef LOG_DOMAIN
17+#define LOG_DOMAIN 0xD002B3F
18+#undef LOG_TAG
19+#define LOG_TAG "VideoProcessorNapi"
20+
21+#include "video_processor_napi.h"
22+
23+#include <algorithm>
24+#include "algorithm_video.h"
25+#include "video_processing_types.h"
26+#include "vpe_log.h"
27+#include "vpe_trace.h"
28+
29+
30+namespace {
31+constexpr uint32_t NUM_1 = 1;
32+const char VIDEO_PROCESSOR_CLASS_NAME[] = "VideoProcessor";
33+}
34+
35+namespace OHOS {
36+namespace Media {
37+using namespace VideoProcessingEngine;
38+using namespace std::chrono;
39+thread_local napi_ref VideoProcessorNapi::constructor_ = nullptr;
40+std::vector<napi_ref> VideoProcessorNapi::g_statusCallbacks{};
41+std::mutex VideoProcessorNapi::g_statusCallbacksLock{};
42+napi_threadsafe_function VideoProcessorNapi::g_statusTsfn = nullptr;
43+
44+struct StatusCallbackData {
45+ bool aiHdrEnabled;
46+};
47+
48+void VideoProcessorNapi::ThrowExceptionError(napi_env env, const int32_t errCode, const std::string errMsg)
49+{
50+ std::string errCodeStr = std::to_string(errCode);
51+ napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
52+}
53+
54+napi_value VideoProcessorNapi::Constructor(napi_env env, napi_callback_info info)
55+{
56+ napi_status status;
57+ napi_value thisVar = nullptr;
58+ size_t argc = NUM_1;
59+ napi_value argv[NUM_1] = {0};
60+ status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
61+ if (status != napi_ok || thisVar == nullptr) {
62+ return nullptr;
63+ }
64+ VideoProcessorNapi* pVideoProcessorNapi = new VideoProcessorNapi();
65+ CHECK_AND_RETURN_RET_LOG(pVideoProcessorNapi != nullptr, nullptr, "pVideoProcessorNapi == nullptr");
66+ status = napi_wrap_with_size(env, thisVar, reinterpret_cast<void*>(pVideoProcessorNapi),
67+ VideoProcessorNapi::Destructor, nullptr, nullptr, static_cast<size_t>(sizeof(VideoProcessorNapi)));
68+ CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failure wrapping js to native napi");
69+ return thisVar;
70+}
71+
72+void VideoProcessorNapi::Destructor(napi_env env, void* nativeObject, void* finalize)
73+{
74+ if (nativeObject != nullptr) {
75+ delete reinterpret_cast<VideoProcessorNapi*>(nativeObject);
76+ nativeObject = nullptr;
77+ }
78+}
79+
80+static napi_value BuildStatusObject(napi_env env, bool aiHdrEnabled)
81+{
82+ napi_value jsStatus = nullptr;
83+ CHECK_AND_RETURN_RET_LOG(napi_create_object(env, &jsStatus) == napi_ok, nullptr,
84+ "BuildStatusObject: create jsStatus failed");
85+ napi_value jsAiHdrStatus;
86+ CHECK_AND_RETURN_RET_LOG(napi_create_object(env, &jsAiHdrStatus) == napi_ok, nullptr,
87+ "BuildStatusObject: create jsAiHdrStatus failed");
88+ napi_value jsAiHdrEnabled;
89+ CHECK_AND_RETURN_RET_LOG(napi_get_boolean(env, aiHdrEnabled, &jsAiHdrEnabled) == napi_ok, nullptr,
90+ "BuildStatusObject: get boolean failed");
91+ CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, jsAiHdrStatus, "enabled", jsAiHdrEnabled) == napi_ok, nullptr,
92+ "BuildStatusObject: set enabled failed");
93+ CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, jsStatus, "aiHdr", jsAiHdrStatus) == napi_ok, nullptr,
94+ "BuildStatusObject: set aiHdr failed");
95+ return jsStatus;
96+}
97+
98+static void InvokeCallback(napi_env env, napi_ref callbackRef, napi_value jsStatus)
99+{
100+ CHECK_AND_RETURN_LOG(jsStatus != nullptr, "jsStatus is nullptr");
101+ napi_value global;
102+ CHECK_AND_RETURN_LOG(napi_get_global(env, &global) == napi_ok, "InvokeCallback: get global failed");
103+ napi_value callbackFunc;
104+ CHECK_AND_RETURN_LOG(napi_get_reference_value(env, callbackRef, &callbackFunc) == napi_ok,
105+ "InvokeCallback: get reference value failed");
106+ napi_value argv[NUM_1] = {jsStatus};
107+ napi_value callbackResult;
108+ CHECK_AND_RETURN_LOG(napi_call_function(env, global, callbackFunc, NUM_1, argv, &callbackResult) == napi_ok,
109+ "InvokeCallback: call function failed");
110+}
111+
112+void VideoProcessorNapi::NotifyCallback(napi_env env, napi_ref callbackRef, bool aiHdrEnabled)
113+{
114+ napi_value jsStatus = BuildStatusObject(env, aiHdrEnabled);
115+ CHECK_AND_RETURN_LOG(jsStatus != nullptr, "NotifyCallback: jsStatus is nullptr");
116+ InvokeCallback(env, callbackRef, jsStatus);
117+ VPE_LOGI("NotifyCallback: aiHdrEnabled=%{public}d", aiHdrEnabled);
118+}
119+
120+void VideoProcessorNapi::StatusTsfnCallJs(napi_env env, napi_value jsCallback, void* context, void* data)
121+{
122+ std::unique_ptr<StatusCallbackData> callbackDataPtr;
123+ CHECK_AND_RETURN_LOG(data != nullptr, "StatusTsfnCallJs data is nullptr");
124+ callbackDataPtr.reset(static_cast<StatusCallbackData*>(data));
125+ napi_value jsStatus = BuildStatusObject(env, callbackDataPtr->aiHdrEnabled);
126+ CHECK_AND_RETURN_LOG(jsStatus != nullptr, "StatusTsfnCallJs: jsStatus is nullptr");
127+
128+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
129+ for (auto& callbackRef : g_statusCallbacks) {
130+ InvokeCallback(env, callbackRef, jsStatus);
131+ }
132+ VPE_LOGI("StatusTsfnCallJs: aiHdrEnabled=%{public}d, callbackCount=%{public}zu",
133+ callbackDataPtr->aiHdrEnabled, g_statusCallbacks.size());
134+}
135+
136+void VideoProcessorNapi::StatusTsfnFinalize(napi_env env, void* data, void* hint)
137+{
138+ VPE_LOGI("StatusTsfnFinalize");
139+}
140+
141+napi_value VideoProcessorNapi::GetStatus(napi_env env, napi_callback_info info)
142+{
143+ VPETrace vpeTrace("VideoProcessorNapi::GetStatus");
144+ napi_value result;
145+ napi_get_undefined(env, &result);
146+ napi_deferred deferred;
147+ napi_value promise;
148+ CHECK_AND_RETURN_RET_LOG(napi_create_promise(env, &deferred, &promise) == napi_ok, result,
149+ "GetStatus: create promise failed");
150+ napi_value jsStatus;
151+ CHECK_AND_RETURN_RET_LOG(napi_create_object(env, &jsStatus) == napi_ok, result,
152+ "GetStatus: create jsStatus failed");
153+ napi_value jsAiHdrStatus;
154+ CHECK_AND_RETURN_RET_LOG(napi_create_object(env, &jsAiHdrStatus) == napi_ok, result,
155+ "GetStatus: create jsAiHdrStatus failed");
156+ Media::Format parameter{};
157+ bool aiHdrEnabled = VpeVideo::IsSupported(VIDEO_TYPE_AIHDR_ENHANCER, parameter);
158+ napi_value jsAiHdrEnabled;
159+ CHECK_AND_RETURN_RET_LOG(napi_get_boolean(env, aiHdrEnabled, &jsAiHdrEnabled) == napi_ok, result,
160+ "GetStatus: get boolean failed");
161+ CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, jsAiHdrStatus, "enabled", jsAiHdrEnabled) == napi_ok, result,
162+ "GetStatus: set enabled failed");
163+ CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, jsStatus, "aiHdr", jsAiHdrStatus) == napi_ok, result,
164+ "GetStatus: set aiHdr failed");
165+ CHECK_AND_RETURN_RET_LOG(napi_resolve_deferred(env, deferred, jsStatus) == napi_ok, result,
166+ "GetStatus: resolve deferred failed");
167+ VPE_LOGI("GetStatus: aiHdrEnabled=%{public}d", aiHdrEnabled);
168+ return promise;
169+}
170+
171+bool VideoProcessorNapi::ValidateCallback(napi_env env, napi_value callbackValue)
172+{
173+ napi_valuetype callbackType;
174+ napi_typeof(env, callbackValue, &callbackType);
175+ if (callbackType != napi_function) {
176+ VPE_LOGE("Callback arg is not function");
177+ ThrowExceptionError(env, VIDEO_PROCESSING_ERROR_INVALID_VALUE, "Callback arg is not function");
178+ return false;
179+ }
180+ return true;
181+}
182+
183+void VideoProcessorNapi::RegisterObserver(napi_env env)
184+{
185+ CHECK_AND_RETURN_LOG(g_statusTsfn == nullptr, "RegisterObserver: already registered");
186+ napi_value cbName;
187+ std::string callbackName = "StatusChange";
188+ CHECK_AND_RETURN_LOG(napi_create_string_utf8(env, callbackName.c_str(), callbackName.length(), &cbName) == napi_ok,
189+ "RegisterObserverIf: create string failed");
190+ CHECK_AND_RETURN_LOG(napi_create_threadsafe_function(env, nullptr, nullptr, cbName, 0,
191+ 1, nullptr, StatusTsfnFinalize, nullptr, StatusTsfnCallJs, &g_statusTsfn) == napi_ok,
192+ "RegisterObserverIf: create threadsafe function failed");
193+ napi_threadsafe_function tsfnCopy = g_statusTsfn;
194+ VpeVideo::RegisterSettingsChangeCallback(VIDEO_TYPE_AIHDR_ENHANCER,
195+ [tsfnCopy](int32_t feature, int32_t tag, int32_t param) {
196+ VPE_LOGI("Settings changed, calling TSFN");
197+ auto* callbackData = new StatusCallbackData{(param != 0)};
198+ if (tsfnCopy != nullptr) {
199+ napi_call_threadsafe_function(tsfnCopy, callbackData, napi_tsfn_blocking);
200+ }
201+ });
202+}
203+
204+void VideoProcessorNapi::UnregisterObserver()
205+{
206+ if (g_statusCallbacks.empty()) {
207+ VpeVideo::UnregisterSettingsChangeCallback(VIDEO_TYPE_AIHDR_ENHANCER);
208+ if (g_statusTsfn != nullptr) {
209+ napi_release_threadsafe_function(g_statusTsfn, napi_tsfn_release);
210+ g_statusTsfn = nullptr;
211+ }
212+ }
213+}
214+
215+napi_value VideoProcessorNapi::OnStatusChange(napi_env env, napi_callback_info info)
216+{
217+ VPETrace vpeTrace("VideoProcessorNapi::OnStatusChange");
218+ napi_value result;
219+ napi_get_undefined(env, &result);
220+ size_t argc = NUM_1;
221+ napi_value argv[NUM_1] = {0};
222+ napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
223+ if (argc != NUM_1 || !ValidateCallback(env, argv[0])) {
224+ return result;
225+ }
226+
227+ napi_ref callbackRef = nullptr;
228+ if (napi_create_reference(env, argv[0], 1, &callbackRef) != napi_ok) {
229+ VPE_LOGE("Create callback reference failed");
230+ ThrowExceptionError(env, VIDEO_PROCESSING_ERROR_INVALID_VALUE, "Create callback reference failed");
231+ return result;
232+ }
233+ size_t callbackSize = 0;
234+ {
235+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
236+ if (g_statusCallbacks.empty()) {
237+ RegisterObserver(env);
238+ }
239+ g_statusCallbacks.push_back(callbackRef);
240+ callbackSize = g_statusCallbacks.size();
241+ }
242+ Media::Format parameter{};
243+ bool aiHdrEnabled = VpeVideo::IsSupported(VIDEO_TYPE_AIHDR_ENHANCER, parameter);
244+ NotifyCallback(env, callbackRef, aiHdrEnabled);
245+ VPE_LOGI("OnStatusChange done, callbackCount=%{public}zu", callbackSize);
246+ return result;
247+}
248+
249+void VideoProcessorNapi::RemoveCallbackRef(napi_env env, napi_value callback)
250+{
251+ auto it = std::find_if(g_statusCallbacks.begin(), g_statusCallbacks.end(),
252+ [env, callback](napi_ref ref) {
253+ napi_value refFunc;
254+ CHECK_AND_RETURN_RET_LOG(napi_get_reference_value(env, ref, &refFunc) == napi_ok, false,
255+ "RemoveCallbackRef: get reference value failed");
256+ bool isEqual = false;
257+ CHECK_AND_RETURN_RET_LOG(napi_strict_equals(env, callback, refFunc, &isEqual) == napi_ok, false,
258+ "RemoveCallbackRef: strict equals failed");
259+ return isEqual;
260+ });
261+ CHECK_AND_RETURN_LOG(it != g_statusCallbacks.end(), "RemoveCallbackRef: callback not found");
262+ CHECK_AND_RETURN_LOG(napi_delete_reference(env, *it) == napi_ok,
263+ "RemoveCallbackRef: delete reference failed");
264+ g_statusCallbacks.erase(it);
265+}
266+
267+napi_value VideoProcessorNapi::OffStatusChange(napi_env env, napi_callback_info info)
268+{
269+ VPETrace vpeTrace("VideoProcessorNapi::OffStatusChange");
270+ napi_value result;
271+ napi_get_undefined(env, &result);
272+ size_t argc = NUM_1;
273+ napi_value argv[NUM_1] = {0};
274+ napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
275+ if (argc > NUM_1) {
276+ VPE_LOGE("Invalid args count %{public}zu", argc);
277+ ThrowExceptionError(env, VIDEO_PROCESSING_ERROR_INVALID_VALUE, "Invalid args count");
278+ return result;
279+ }
280+
281+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
282+ if (argc == NUM_1) {
283+ if (!ValidateCallback(env, argv[0])) {
284+ return result;
285+ }
286+ RemoveCallbackRef(env, argv[0]);
287+ } else {
288+ for (auto& ref : g_statusCallbacks) {
289+ napi_delete_reference(env, ref);
290+ }
291+ g_statusCallbacks.clear();
292+ }
293+ UnregisterObserver();
294+ VPE_LOGI("OffStatusChange done, remainingCallbacks=%{public}zu", g_statusCallbacks.size());
295+ return result;
296+}
297+
298+napi_value VideoProcessorNapi::Init(napi_env env, napi_value exports)
299+{
300+ napi_property_descriptor props[] = {
301+ DECLARE_NAPI_FUNCTION("getStatus", VideoProcessorNapi::GetStatus),
302+ DECLARE_NAPI_FUNCTION("onStatusChange", VideoProcessorNapi::OnStatusChange),
303+ DECLARE_NAPI_FUNCTION("offStatusChange", VideoProcessorNapi::OffStatusChange)
304+ };
305+
306+ napi_value constructor = nullptr;
307+ CHECK_AND_RETURN_RET_LOG(napi_define_class(env, VIDEO_PROCESSOR_CLASS_NAME, sizeof(VIDEO_PROCESSOR_CLASS_NAME),
308+ VideoProcessorNapi::Constructor, nullptr, sizeof(props) / sizeof(props[0]), props, &constructor) == napi_ok,
309+ nullptr, "define class fail");
310+ CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, exports, VIDEO_PROCESSOR_CLASS_NAME, constructor) == napi_ok,
311+ nullptr, "set named property fail");
312+ CHECK_AND_RETURN_RET_LOG(napi_create_reference(env, constructor, 1, &constructor_) == napi_ok,
313+ nullptr, "create reference fail");
314+ napi_property_descriptor moduleFuncs[] = {
315+ DECLARE_NAPI_FUNCTION("createVideoProcessor", VideoProcessorNapi::CreateVideoProcessor),
316+ };
317+ napi_define_properties(env, exports, sizeof(moduleFuncs) / sizeof(moduleFuncs[0]), moduleFuncs);
318+ return exports;
319+}
320+
321+napi_value VideoProcessorNapi::CreateVideoProcessor(napi_env env, napi_callback_info info)
322+{
323+ napi_value result = nullptr;
324+ napi_value constructor = nullptr;
325+ CHECK_AND_RETURN_RET_LOG(napi_get_reference_value(env, constructor_, &constructor) == napi_ok,
326+ nullptr, "CreateVideoProcessor: get constructor failed");
327+ size_t argc = NUM_1;
328+ napi_value argv[NUM_1] = {0};
329+ CHECK_AND_RETURN_RET_LOG(napi_new_instance(env, constructor, argc, argv, &result) == napi_ok,
330+ nullptr, "CreateVideoProcessor: new instance failed");
331+ VPE_LOGI("create done");
332+ return result;
333+}
334+}
335+}
@@ -0,0 +1,58 @@
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+#ifndef VIDEO_PROCESSOR_NAPI_H
17+#define VIDEO_PROCESSOR_NAPI_H
18+
19+#include "algorithm_video.h"
20+#include "napi/native_api.h"
21+#include "napi/native_node_api.h"
22+
23+namespace OHOS {
24+namespace Media {
25+
26+class VideoProcessorNapi {
27+public:
28+ VideoProcessorNapi() = default;
29+ ~VideoProcessorNapi() = default;
30+
31+ static napi_value Init(napi_env env, napi_value exports);
32+ static napi_value CreateVideoProcessor(napi_env env, napi_callback_info info);
33+ static napi_value GetStatus(napi_env env, napi_callback_info info);
34+ static napi_value OnStatusChange(napi_env env, napi_callback_info info);
35+ static napi_value OffStatusChange(napi_env env, napi_callback_info info);
36+
37+private:
38+ static thread_local napi_ref constructor_;
39+ static std::vector<napi_ref> g_statusCallbacks;
40+ static std::mutex g_statusCallbacksLock;
41+ static napi_threadsafe_function g_statusTsfn;
42+
43+ static napi_value Constructor(napi_env env, napi_callback_info info);
44+ static void Destructor(napi_env env, void* nativeObject, void* finalize);
45+ static void ThrowExceptionError(napi_env env, const int32_t errCode, const std::string errMsg);
46+ static void NotifyCallback(napi_env env, napi_ref callbackRef, bool aiHdrEnabled);
47+ static void StatusTsfnCallJs(napi_env env, napi_value jsCallback, void* context, void* data);
48+ static void StatusTsfnFinalize(napi_env env, void* data, void* hint);
49+
50+ static bool ValidateCallback(napi_env env, napi_value callbackValue);
51+ static void RegisterObserver(napi_env env);
52+ static void UnregisterObserver();
53+ static void RemoveCallbackRef(napi_env env, napi_value callback);
54+};
55+}
56+}
57+
58+#endif
@@ -18,8 +18,10 @@ import("//foundation/multimedia/video_processing_engine/config.gni")
18 18 
19subsystem_name = "multimedia"19subsystem_name = "multimedia"
20part_name = "video_processing_engine"20part_name = "video_processing_engine"
21-taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name"
22 21 
22+# =============== videoProcessingEngine Module ===============
23+videoProcessingEngine = "videoProcessingEngine"
24+video_processing_engine_taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name/$videoProcessingEngine"
23config("video_processing_engine_taihe_config") {25config("video_processing_engine_taihe_config") {
24 visibility = [ ":*" ]26 visibility = [ ":*" ]
25 include_dirs = [ "include" ]27 include_dirs = [ "include" ]
@@ -36,17 +38,17 @@ copy_taihe_idl("copy_video_processing_engine_taihe") {
36}38}
37 39 
38ohos_taihe("run_taihe") {40ohos_taihe("run_taihe") {
39- taihe_generated_file_path = "$taihe_generated_file_path"41+ taihe_generated_file_path = "$video_processing_engine_taihe_generated_file_path"
40 deps = [ ":copy_video_processing_engine_taihe" ]42 deps = [ ":copy_video_processing_engine_taihe" ]
41 outputs = [43 outputs = [
42- "$taihe_generated_file_path/src/ohos.multimedia.videoProcessingEngine.ani.cpp",44+ "$video_processing_engine_taihe_generated_file_path/src/ohos.multimedia.videoProcessingEngine.ani.cpp",
43- "$taihe_generated_file_path/src/ohos.multimedia.videoProcessingEngine.abi.c",45+ "$video_processing_engine_taihe_generated_file_path/src/ohos.multimedia.videoProcessingEngine.abi.c",
44 ]46 ]
45}47}
46 48 
47generate_static_abc("video_processing_engine_taihe_abc") {49generate_static_abc("video_processing_engine_taihe_abc") {
48- base_url = "$taihe_generated_file_path"50+ base_url = "$video_processing_engine_taihe_generated_file_path"
49- files = [ "$taihe_generated_file_path/@ohos.multimedia.videoProcessingEngine.ets" ]51+ files = [ "$video_processing_engine_taihe_generated_file_path/@ohos.multimedia.videoProcessingEngine.ets" ]
50 is_boot_abc = "True"52 is_boot_abc = "True"
51 device_dst_file = "/system/framework/video_processing_engine_taihe_abc.abc"53 device_dst_file = "/system/framework/video_processing_engine_taihe_abc.abc"
52 dependencies = [ ":run_taihe" ]54 dependencies = [ ":run_taihe" ]
@@ -72,7 +74,7 @@ group("video_processing_engine_taihe_gen_only") {
72}74}
73 75 
74taihe_shared_library("video_processing_engine_taihe") {76taihe_shared_library("video_processing_engine_taihe") {
75- taihe_generated_file_path = "$taihe_generated_file_path"77+ taihe_generated_file_path = "$video_processing_engine_taihe_generated_file_path"
76 subsystem_name = "$subsystem_name"78 subsystem_name = "$subsystem_name"
77 part_name = "$part_name"79 part_name = "$part_name"
78 80 
@@ -113,6 +115,7 @@ taihe_shared_library("video_processing_engine_taihe") {
113 "media_foundation:native_media_core",115 "media_foundation:native_media_core",
114 "media_foundation:media_foundation",116 "media_foundation:media_foundation",
115 "runtime_core:ani_helpers",117 "runtime_core:ani_helpers",
118+ "napi:ace_napi",
116 ]119 ]
117 120 
118 cflags = [121 cflags = [
@@ -131,7 +134,7 @@ taihe_shared_library("video_processing_engine_taihe") {
131}134}
132 135 
133taihe_shared_library("video_processing_engine_taihe_core") {136taihe_shared_library("video_processing_engine_taihe_core") {
134- taihe_generated_file_path = "$taihe_generated_file_path"137+ taihe_generated_file_path = "$video_processing_engine_taihe_generated_file_path"
135 subsystem_name = "$subsystem_name"138 subsystem_name = "$subsystem_name"
136 part_name = "$part_name"139 part_name = "$part_name"
137 shlib_type = "ani"140 shlib_type = "ani"
@@ -147,4 +150,108 @@ taihe_shared_library("video_processing_engine_taihe_core") {
147 ubsan = true150 ubsan = true
148 debug = false151 debug = false
149 }152 }
150-}153+}
154+ 
155+# =============== videoProcessing Module ===============
156+videoProcessing = "videoProcessing"
157+video_processing_taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name/$videoProcessing"
158+config("video_processing_taihe_config") {
159+ visibility = [ ":*" ]
160+ include_dirs = [ "include" ]
161+}
162+ 
163+copy_taihe_idl("copy_video_processing_taihe") {
164+ sources = [
165+ "$INTERFACES_DIR/kits/taihe/idl/ohos.multimedia.videoProcessing.taihe",
166+ ]
167+}
168+ 
169+ohos_taihe("run_taihe_video_processing") {
170+ taihe_generated_file_path = "$video_processing_taihe_generated_file_path"
171+ deps = [ ":copy_video_processing_taihe" ]
172+ outputs = [
173+ "$video_processing_taihe_generated_file_path/src/ohos.multimedia.videoProcessing.ani.cpp",
174+ "$video_processing_taihe_generated_file_path/src/ohos.multimedia.videoProcessing.abi.c",
175+ ]
176+}
177+ 
178+generate_static_abc("video_processing_taihe_abc") {
179+ base_url = "$video_processing_taihe_generated_file_path"
180+ files = [ "$video_processing_taihe_generated_file_path/@ohos.multimedia.videoProcessing.ets" ]
181+ is_boot_abc = "True"
182+ device_dst_file = "/system/framework/video_processing_taihe_abc.abc"
183+ dependencies = [ ":run_taihe_video_processing" ]
184+}
185+ 
186+ohos_prebuilt_etc("video_processing_etc") {
187+ source = "$target_out_dir/video_processing_taihe_abc.abc"
188+ module_install_dir = "framework"
189+ part_name = "$part_name"
190+ subsystem_name = "$subsystem_name"
191+ deps = [ ":video_processing_taihe_abc" ]
192+}
193+ 
194+group("video_processing_taihe_gen_only") {
195+ deps = [ ":run_taihe_video_processing" ]
196+}
197+ 
198+group("video_processing_taihe_group") {
199+ deps = [
200+ ":video_processing_etc",
201+ ":video_processing_taihe_native",
202+ ]
203+}
204+ 
205+taihe_shared_library("video_processing_taihe_native") {
206+ taihe_generated_file_path = "$video_processing_taihe_generated_file_path"
207+ subsystem_name = "$subsystem_name"
208+ part_name = "$part_name"
209+ public_configs = [ ":video_processing_taihe_config" ]
210+ 
211+ include_dirs = [
212+ "include",
213+ "$DFX_DIR/include",
214+ "$INTERFACES_DIR/kits/js",
215+ "$INTERFACES_INNER_API_DIR",
216+ "$CAPI_DIR/image_processing/include/",
217+ "$ALGORITHM_COMMON_DIR/include/",
218+ "$INTERFACES_CAPI_DIR",
219+ ]
220+ 
221+ sources = get_target_outputs(":run_taihe_video_processing")
222+ sources += [
223+ "src/video_processing_taihe.cpp",
224+ "src/video_processing_ani_constructor.cpp",
225+ ]
226+ 
227+ deps = [
228+ ":run_taihe_video_processing",
229+ "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/framework:videoprocessingengine",
230+ ]
231+ 
232+ external_deps = [
233+ "c_utils:utils",
234+ "drivers_interface_display:libdisplay_commontype_proxy_2.1",
235+ "hilog:libhilog",
236+ "hitrace:hitrace_meter",
237+ "ipc:ipc_napi",
238+ "media_foundation:native_media_core",
239+ "media_foundation:media_foundation",
240+ "runtime_core:ani_helpers",
241+ "napi:ace_napi",
242+ ]
243+ 
244+ cflags = [
245+ "-DIMAGE_DEBUG_FLAG",
246+ "-DIMAGE_COLORSPACE_FLAG",
247+ ]
248+ 
249+ sanitize = {
250+ boundary_sanitize = true
251+ cfi = true
252+ cfi_cross_dso = true
253+ integer_overflow = true
254+ ubsan = true
255+ debug = false
256+ }
257+}
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright (C) 2026 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+@!namespace("@ohos.multimedia.videoProcessing", "videoProcessing")
17+@!sts_export_default
18+@!sts_inject("""
19+static { loadLibraryWithPermissionCheck("video_processing_taihe_native.z", "@ohos.multimedia.videoProcessing"); }
20+""")
21+ 
22+struct VideoProcessorAiHdrStatus {
23+ @optional enabled: Optional<bool>;
24+}
25+ 
26+struct VideoProcessorStatus {
27+ @optional aiHdr: Optional<VideoProcessorAiHdrStatus>;
28+}
29+ 
30+interface VideoProcessor {
31+ @rename("getStatus") @promise GetStatus(): VideoProcessorStatus;
32+ @rename("onStatusChange") OnStatusChange(callback: (status: VideoProcessorStatus) => void): void;
33+ @rename("offStatusChange") OffStatusChange(@optional callback: Optional<(status: VideoProcessorStatus) => void>): void;
34+}
35+ 
36+function createVideoProcessor(): VideoProcessor;
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2026 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+#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_VIDEO_PROCESSING_TAIHE_H
17+#define FRAMEWORKS_KITS_TAIHE_INCLUDE_VIDEO_PROCESSING_TAIHE_H
18+ 
19+#include "ohos.multimedia.videoProcessing.impl.hpp"
20+#include "ohos.multimedia.videoProcessing.proj.hpp"
21+#include <mutex>
22+#include <vector>
23+#include <functional>
24+ 
25+#include "taihe/runtime.hpp"
26+ 
27+namespace ANI::Vp {
28+using namespace taihe;
29+namespace taiheVp = ::ohos::multimedia::videoProcessing;
30+ 
31+class VideoProcessorImpl {
32+public:
33+ VideoProcessorImpl() = default;
34+ ~VideoProcessorImpl() = default;
35+ 
36+ taiheVp::VideoProcessorStatus GetStatus();
37+ void OnStatusChange(
38+ taihe::callback_view<void(const taiheVp::VideoProcessorStatus&)> callback);
39+ void OffStatusChange(
40+ taihe::optional_view<taihe::callback<void(const taiheVp::VideoProcessorStatus&)>> callback);
41+ 
42+private:
43+ bool GetCurrentAiHdrEnabled();
44+ void TriggerSingleCallback(const taihe::callback<void(const taiheVp::VideoProcessorStatus&)>& callback,
45+ bool aiHdrEnabled);
46+ void StatusChangeCallback(int32_t feature, int32_t tag, int32_t param);
47+ 
48+ static std::vector<taihe::callback<void(const taiheVp::VideoProcessorStatus&)>> g_statusCallbacks;
49+ static std::mutex g_statusCallbacksLock;
50+ static bool g_isListenerRegistered;
51+};
52+ 
53+}
54+#endif
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2026 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 "ohos.multimedia.videoProcessing.ani.hpp"
17+#if __has_include(<ani.h>)
18+#include <ani.h>
19+#elif __has_include(<ani/ani.h>)
20+#include <ani/ani.h>
21+#else
22+#error "ani.h not found. Please ensure the Ani SDK is correctly installed."
23+#endif
24+ 
25+ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
26+{
27+ ani_env* env;
28+ if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
29+ return ANI_ERROR;
30+ }
31+ ani_status status = ANI_OK;
32+ if (ANI_OK != ohos::multimedia::videoProcessing::ANIRegister(env)) {
33+ std::cerr << "Error from ohos::multimedia::videoProcessing::ANIRegister" << std::endl;
34+ status = ANI_ERROR;
35+ }
36+ *result = ANI_VERSION_1;
37+ return status;
38+}
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright (C) 2026 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_taihe.h"
17+#include "algorithm_video.h"
18+#include "vpe_log.h"
19+#include "vpe_trace.h"
20+#include "taihe/runtime.hpp"
21+ 
22+using namespace taihe;
23+using namespace OHOS::Media::VideoProcessingEngine;
24+using namespace ANI;
25+using namespace ANI::Vp;
26+ 
27+namespace ANI::Vp {
28+std::vector<taihe::callback<void(const taiheVp::VideoProcessorStatus&)>> VideoProcessorImpl::g_statusCallbacks;
29+std::mutex VideoProcessorImpl::g_statusCallbacksLock;
30+ 
31+taiheVp::VideoProcessor createVideoProcessor()
32+{
33+ return taihe::make_holder<VideoProcessorImpl, taiheVp::VideoProcessor>();
34+}
35+}
36+ 
37+bool VideoProcessorImpl::GetCurrentAiHdrEnabled()
38+{
39+ OHOS::Media::Format parameter;
40+ return VpeVideo::IsSupported(VIDEO_TYPE_AIHDR_ENHANCER, parameter);
41+}
42+ 
43+void VideoProcessorImpl::StatusChangeCallback(int32_t feature, int32_t tag, int32_t param)
44+{
45+ VPE_LOGI("StatusChangeCallback: feature=%{public}d, param=%{public}d", feature, param);
46+ bool aiHdrEnabled = (param != 0);
47+
48+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
49+ taiheVp::VideoProcessorAiHdrStatus aiHdrStatus;
50+ aiHdrStatus.enabled.emplace(aiHdrEnabled);
51+ taiheVp::VideoProcessorStatus status;
52+ status.aiHdr.emplace(aiHdrStatus);
53+ for (auto& callback : g_statusCallbacks) {
54+ callback(status);
55+ }
56+ VPE_LOGI("StatusChangeCallback: notified %{public}zu callbacks, aiHdrEnabled=%{public}d",
57+ g_statusCallbacks.size(), aiHdrEnabled);
58+}
59+ 
60+void VideoProcessorImpl::TriggerSingleCallback(
61+ const taihe::callback<void(const taiheVp::VideoProcessorStatus&)>& callback, bool aiHdrEnabled)
62+{
63+ taiheVp::VideoProcessorAiHdrStatus aiHdrStatus;
64+ aiHdrStatus.enabled.emplace(aiHdrEnabled);
65+ taiheVp::VideoProcessorStatus status;
66+ status.aiHdr.emplace(aiHdrStatus);
67+ callback(status);
68+ VPE_LOGI("TriggerSingleCallback: aiHdrEnabled=%{public}d", aiHdrEnabled);
69+}
70+ 
71+taiheVp::VideoProcessorStatus VideoProcessorImpl::GetStatus()
72+{
73+ taiheVp::VideoProcessorAiHdrStatus aiHdrStatus;
74+ bool aiHdrEnabled = GetCurrentAiHdrEnabled();
75+ aiHdrStatus.enabled.emplace(aiHdrEnabled);
76+ taiheVp::VideoProcessorStatus status;
77+ status.aiHdr.emplace(aiHdrStatus);
78+ VPE_LOGI("GetStatus: aiHdrEnabled=%{public}d", aiHdrEnabled);
79+ return status;
80+}
81+ 
82+void VideoProcessorImpl::OnStatusChange(
83+ taihe::callback_view<void(const taiheVp::VideoProcessorStatus&)> callback)
84+{
85+ VPETrace vpeTrace("VideoProcessorImpl::OnStatusChange");
86+ size_t callbackSize = 0;
87+ {
88+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
89+ if (g_statusCallbacks.empty()) {
90+ VpeVideo::RegisterSettingsChangeCallback(VIDEO_TYPE_AIHDR_ENHANCER,
91+ [this](int32_t feature, int32_t tag, int32_t param) {
92+ StatusChangeCallback(feature, tag, param);
93+ });
94+ }
95+ g_statusCallbacks.push_back(callback);
96+ callbackSize = g_statusCallbacks.size();
97+ }
98+
99+ bool aiHdrEnabled = GetCurrentAiHdrEnabled();
100+ TriggerSingleCallback(callback, aiHdrEnabled);
101+ VPE_LOGI("OnStatusChange done, callbackCount=%{public}zu", callbackSize);
102+}
103+ 
104+void VideoProcessorImpl::OffStatusChange(
105+ taihe::optional_view<taihe::callback<void(const taiheVp::VideoProcessorStatus&)>> callback)
106+{
107+ VPETrace vpeTrace("VideoProcessorImpl::OffStatusChange");
108+ std::lock_guard<std::mutex> lock(g_statusCallbacksLock);
109+ if (callback.has_value()) {
110+ auto it = std::find_if(g_statusCallbacks.begin(), g_statusCallbacks.end(),
111+ [&callback](const taihe::callback<void(const taiheVp::VideoProcessorStatus&)>& item) {
112+ return item == callback.value();
113+ });
114+ if (it != g_statusCallbacks.end()) {
115+ g_statusCallbacks.erase(it);
116+ }
117+ } else {
118+ g_statusCallbacks.clear();
119+ }
120+
121+ if (g_statusCallbacks.empty()) {
122+ VpeVideo::UnregisterSettingsChangeCallback(VIDEO_TYPE_AIHDR_ENHANCER);
123+ }
124+ VPE_LOGI("OffStatusChange done, remainingCallbacks=%{public}zu", g_statusCallbacks.size());
125+}
126+ 
127+// NOLINTBEGIN
128+TH_EXPORT_CPP_API_createVideoProcessor(createVideoProcessor);
129+// NOLINTEND