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 "VpeNapi"
20
21 #include "detail_enhance_napi_formal.h"
22
23 #include <algorithm>
24
25 #include "image_napi_utils.h"
26 #include "media_errors.h"
27 #include "memory_manager.h"
28 #include "native_avformat.h"
29 #include "pixelmap_native_impl.h"
30 #include "pixelmap_native.h"
31
32 #include "detail_enhancer_common.h"
33 #include "vpe_log.h"
34 #include "vpe_trace.h"
35 #include "vpe_utils.h"
36
37 namespace {
38 constexpr uint32_t NUM_0 = 0;
39 constexpr uint32_t NUM_1 = 1;
40 constexpr uint32_t NUM_2 = 2;
41 constexpr uint32_t NUM_3 = 3;
42 constexpr uint32_t NUM_4 = 4;
43 constexpr uint32_t NUM_5 = 5;
44 constexpr uint32_t NUM_6 = 6;
45 constexpr uint32_t NUM_7 = 7;
46 constexpr uint32_t NUM_8 = 8;
47 constexpr uint32_t NUM_9 = 9;
48 constexpr int32_t NEW_INSTANCE_ARGC = 1;
49 constexpr int32_t MIN_WIDTH_CONTRAST = 720; // min support width 720, consistent with fwk
50 constexpr int32_t MIN_HEIGHT_CONTRAST = 720; // min support height 720, consistent with fwk
51 constexpr int32_t MAX_RESOLUTION_CONTRAST = 20000; // max support resolution 20000, consistent with fwk
52 constexpr int32_t MIN_RESOLUTION_DETAIL = 32; // min support resolution 32, consistent with fwk
53 constexpr int32_t MAX_RESOLUTION_DETAIL = 8192; // max support resolution 8192, consistent with fwk
54 constexpr float ROUNDING_OPERATOR = 0.5;
55 const std::string CLASS_NAME = "ImageProcessor";
56 static std::mutex g_imageProcessorMutex{std::mutex()};
57 static std::mutex g_contrastLock{std::mutex()};
58 }
59
60 namespace OHOS {
61 namespace Media {
62 using namespace VideoProcessingEngine;
63 using namespace std::chrono;
64 thread_local napi_ref VpeNapi::constructor_ = nullptr;
65 thread_local napi_ref VpeNapi::qualityLevelTypeRef_ = nullptr;
66 thread_local std::shared_ptr<VpeNapi::DetailEnhanceContext> VpeNapi::detailContext_ = nullptr;
67 thread_local std::shared_ptr<VpeNapi::ContrastEnhanceContext> VpeNapi::contrastContext_ = nullptr;
68 static std::shared_ptr<DetailEnhancerImage> g_detailEnh{};
69 static std::shared_ptr<ContrastEnhancerImage> g_contrastEnh{};
70
71 struct QualityLevelEnum {
72 std::string name;
73 int32_t numVal;
74 std::string strVal;
75 };
76 static std::vector<struct QualityLevelEnum> g_qualityLevels = {
77 {"NONE", OHOS::Media::VideoProcessingEngine::DETAIL_ENH_LEVEL_NONE, ""},
78 {"LOW", OHOS::Media::VideoProcessingEngine::DETAIL_ENH_LEVEL_LOW, ""},
79 {"MEDIUM", OHOS::Media::VideoProcessingEngine::DETAIL_ENH_LEVEL_MEDIUM, ""},
80 {"HIGH", OHOS::Media::VideoProcessingEngine::DETAIL_ENH_LEVEL_HIGH, ""},
81 };
82
ThrowExceptionError(napi_env env,const int32_t errCode,const std::string errMsg)83 void VpeNapi::ThrowExceptionError(napi_env env, const int32_t errCode, const std::string errMsg)
84 {
85 std::string errCodeStr = std::to_string(errCode);
86 napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
87 }
88
PrepareNapiEnv(napi_env env,napi_callback_info info,NapiValues * nVal)89 bool VpeNapi::PrepareNapiEnv(napi_env env, napi_callback_info info, NapiValues* nVal)
90 {
91 CHECK_AND_RETURN_RET_LOG(nVal != nullptr, false, "nVal == nullptr");
92 if (napi_get_undefined(env, &(nVal->result)) != napi_ok) {
93 VPE_LOGE("Get undefined result failed");
94 return false;
95 }
96 nVal->status = napi_get_cb_info(env, info, &(nVal->argc), nVal->argv, &(nVal->thisVar), nullptr);
97 if (nVal->status != napi_ok) {
98 VPE_LOGE("fail to napi_get_cb_info");
99 return false;
100 }
101 return true;
102 }
103
ParserImageType(napi_env env,napi_value argv)104 ImageType VpeNapi::ParserImageType(napi_env env, napi_value argv)
105 {
106 napi_value constructor = nullptr;
107 napi_value global = nullptr;
108 napi_status ret = napi_invalid_arg;
109 napi_get_global(env, &global);
110 ret = napi_get_named_property(env, global, "PixelMap", &constructor);
111 if (ret != napi_ok) {
112 VPE_LOGI("Get VpeNapi property failed!");
113 return ImageType::TYPE_UNKNOWN;
114 }
115 bool isInstance = false;
116 ret = napi_instanceof(env, argv, constructor, &isInstance);
117 if (ret == napi_ok && isInstance) {
118 return ImageType::TYPE_PIXEL_MAP;
119 }
120 return ImageType::TYPE_UNKNOWN;
121 }
122
ConfigResolutionBasedOnRatio(napi_env env,napi_value & nVal,std::shared_ptr<VpeNapi::DetailEnhanceContext> context)123 bool VpeNapi::ConfigResolutionBasedOnRatio(napi_env env, napi_value& nVal,
124 std::shared_ptr<VpeNapi::DetailEnhanceContext> context)
125 {
126 CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context == nullptr");
127 double zoomRatio;
128 if (napi_ok != napi_get_value_double(env, nVal, &zoomRatio)) {
129 VPE_LOGE("Arg 1 type mismatch");
130 return false;
131 }
132 CHECK_AND_RETURN_RET_LOG(context->inputPixelMap != nullptr, false, "context->inputPixelMap == nullptr");
133 context->xArg = zoomRatio * context->inputPixelMap->GetWidth();
134 context->yArg = zoomRatio * context->inputPixelMap->GetHeight();
135 VPE_LOGE("config resolution with ratio :%{public}d, %{public}d",
136 static_cast<int>(context->xArg), static_cast<int>(context->yArg));
137 return true;
138 }
139
ConfigResolution(napi_env env,napi_value & width,napi_value & height,std::shared_ptr<VpeNapi::DetailEnhanceContext> context)140 bool VpeNapi::ConfigResolution(napi_env env, napi_value& width, napi_value& height,
141 std::shared_ptr<VpeNapi::DetailEnhanceContext> context)
142 {
143 CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context == nullptr");
144 CHECK_AND_RETURN_RET_LOG(napi_ok == napi_get_value_double(env, width, &(context->xArg)),
145 false, "Arg 1 type mismatch");
146 CHECK_AND_RETURN_RET_LOG(napi_ok == napi_get_value_double(env, height, &(context->yArg)),
147 false, "Arg 2 type mismatch");
148 return true;
149 }
150
ParseDetailEnhanceParameter(napi_env env,napi_callback_info info)151 bool VpeNapi::ParseDetailEnhanceParameter(napi_env env, napi_callback_info info)
152 {
153 VPETrace vpeTrace("VpeNapi::DetailEnhanceParseParameter");
154 CHECK_AND_RETURN_RET_LOG(detailContext_ != nullptr, false, "detailContext_ == nullptr");
155 NapiValues nVal;
156 nVal.argc = NUM_4; // Use the maximum value to initialize argc before executing PrepareNapiEnv
157 napi_value argValue[NUM_4] = {0};
158 nVal.argv = argValue;
159 CHECK_AND_RETURN_RET_LOG(PrepareNapiEnv(env, info, &nVal), false, "PrepareNapiEnv failed");
160 if (nVal.argc != NUM_2 && nVal.argc != NUM_3 && nVal.argc != NUM_4) {
161 VPE_LOGE("Invalid args count %{public}zu", nVal.argc);
162 return false;
163 }
164 if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP) {
165 detailContext_->inputPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
166 } else {
167 VPE_LOGE("args0 is not pixelMap!");
168 return false;
169 }
170 CHECK_AND_RETURN_RET_LOG(detailContext_->inputPixelMap != nullptr, false, "inputPixelMap is nullptr!");
171 if (nVal.argc == NUM_2) { // 2 parameter: pixelmap scaleRatio
172 CHECK_AND_RETURN_RET_LOG(ConfigResolutionBasedOnRatio(env, nVal.argv[NUM_1], detailContext_),
173 false, "ConfigResolutionBasedOnRatio failed");
174 detailContext_->qualityLevel = DETAIL_ENH_LEVEL_LOW; // default as low level
175 }
176 if (nVal.argc == NUM_3) { // 3 parameter: pixelmap scaleRatio level / pixelmap x y
177 double valueToCheck = 0;
178 CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_2], &valueToCheck) == napi_ok,
179 false, "failed to parse");
180 if (valueToCheck >= 0 && valueToCheck <= 3) { // if valueToCheck in [0,3], valueToCheck should be level.
181 CHECK_AND_RETURN_RET_LOG(ConfigResolutionBasedOnRatio(env, nVal.argv[NUM_1], detailContext_), false,
182 "ConfigResolutionBasedOnRatio failed");
183 detailContext_->qualityLevel = static_cast<int>(valueToCheck);
184 } else {
185 CHECK_AND_RETURN_RET_LOG(ConfigResolution(env, nVal.argv[NUM_1], nVal.argv[NUM_2], detailContext_),
186 false, "ConfigResolution failed");
187 detailContext_->qualityLevel = DETAIL_ENH_LEVEL_LOW; // default as low level
188 }
189 }
190 if (nVal.argc == NUM_4) { // 4 parameter: pixelmap x y level
191 CHECK_AND_RETURN_RET_LOG(ConfigResolution(env, nVal.argv[NUM_1], nVal.argv[NUM_2], detailContext_),
192 false, "ConfigResolution failed");
193 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_3],
194 &(detailContext_->qualityLevel)) == napi_ok, false, "Arg 3 type mismatch");
195 }
196 return true;
197 }
198
InitializeEnvironment(napi_env env,napi_callback_info info)199 napi_value VpeNapi::InitializeEnvironment(napi_env env, napi_callback_info info)
200 {
201 napi_value result;
202 napi_get_boolean(env, true, &result);
203 return result;
204 }
205
DeinitializeEnvironment(napi_env env,napi_callback_info info)206 napi_value VpeNapi::DeinitializeEnvironment(napi_env env, napi_callback_info info)
207 {
208 VPETrace vpeTrace("VpeNapi::DetailEnhanceDeinitializeEnvironment");
209 napi_value result;
210 napi_get_boolean(env, true, &result);
211 return result;
212 }
213
SetDstPixelMapInfo(PixelMap & source,void * dstPixels,uint32_t dstPixelsSize,std::unique_ptr<AbsMemory> & memory,PixelMap & dstPixelMap)214 void VpeNapi::SetDstPixelMapInfo(PixelMap& source, void* dstPixels, uint32_t dstPixelsSize,
215 std::unique_ptr<AbsMemory>& memory, PixelMap& dstPixelMap)
216 {
217 AllocatorType sourceType = source.GetAllocatorType();
218 if (sourceType != AllocatorType::DMA_ALLOC) {
219 VPE_LOGW("only support DMA");
220 return;
221 }
222 if (memory == nullptr) {
223 VPE_LOGW("Invalid memory");
224 return;
225 }
226 if (memory->extend.data == nullptr) {
227 VPE_LOGE("memory->extend.data == nullptr");
228 return;
229 }
230 dstPixelMap.SetPixelsAddr(dstPixels, memory->extend.data, memory->data.size, sourceType, nullptr);
231 if (source.GetAllocatorType() == AllocatorType::DMA_ALLOC && source.IsHdr()) {
232 sptr<SurfaceBuffer> sourceSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (source.GetFd()));
233 sptr<SurfaceBuffer> dstSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (dstPixelMap.GetFd()));
234 if (sourceSurfaceBuffer == nullptr) {
235 VPE_LOGE("sourceSurfaceBuffer == nullptr");
236 return;
237 }
238 if (dstSurfaceBuffer == nullptr) {
239 VPE_LOGE("dstSurfaceBuffer == nullptr");
240 return;
241 }
242 VpeUtils::CopySurfaceBufferInfo(sourceSurfaceBuffer, dstSurfaceBuffer);
243 }
244 OHOS::ColorManager::ColorSpace colorspace = source.InnerGetGrColorSpace();
245 dstPixelMap.InnerSetColorSpace(colorspace);
246 }
247
AllocMemory(PixelMap & source,PixelMap & dstPixelMap,const InitializationOptions & opt)248 bool VpeNapi::AllocMemory(PixelMap& source, PixelMap& dstPixelMap, const InitializationOptions& opt)
249 {
250 if (source.GetPixels() == nullptr) {
251 VPE_LOGE("pixels of source are not available");
252 return false;
253 }
254 int32_t bufferSize = source.GetByteCount();
255 if (bufferSize <= 0) {
256 VPE_LOGE("CopyPixelMap parameter bufferSize:[%{public}d] error.", bufferSize);
257 return false;
258 }
259 ImageInfo dstImageInfo;
260 dstPixelMap.GetImageInfo(dstImageInfo);
261 MemoryData memoryData = {nullptr, static_cast<size_t>(bufferSize), "Copy ImageData",
262 dstImageInfo.size, dstImageInfo.pixelFormat};
263 std::unique_ptr<AbsMemory> memory = MemoryManager::CreateMemory(source.GetAllocatorType(), memoryData);
264 if (memory == nullptr) {
265 VPE_LOGE("invalid memory");
266 return false;
267 }
268 void* dstPixels = memory->data.data;
269 if (dstPixels == nullptr) {
270 VPE_LOGE("source crop allocate memory fail allocatetype: %{public}d ", source.GetAllocatorType());
271 return false;
272 }
273 SetDstPixelMapInfo(source, dstPixels, static_cast<size_t>(bufferSize), memory, dstPixelMap);
274 return true;
275 }
276
CreateDstPixelMap(PixelMap & source,const InitializationOptions & opts)277 std::unique_ptr<PixelMap> VpeNapi::CreateDstPixelMap(PixelMap& source, const InitializationOptions& opts)
278 {
279 if (source.GetAllocatorType() != AllocatorType::DMA_ALLOC) {
280 VPE_LOGE("alloc type of source is not dma, create with default method");
281 return source.Create(source, opts);
282 }
283 std::unique_ptr<PixelMap> dstPixelMap = std::make_unique<PixelMap>();
284 if (dstPixelMap == nullptr) {
285 VPE_LOGE("create pixelmap pointer fail");
286 return nullptr;
287 }
288 ImageInfo srcImageInfo;
289 source.GetImageInfo(srcImageInfo);
290 ImageInfo dstImageInfo = {
291 .size = opts.size,
292 .pixelFormat = srcImageInfo.pixelFormat,
293 .alphaType = srcImageInfo.alphaType,
294 };
295 if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
296 return nullptr;
297 }
298 if (!AllocMemory(source, *dstPixelMap.get(), opts)) {
299 VPE_LOGE("alloc memory failed");
300 return nullptr;
301 }
302 return dstPixelMap;
303 }
304
ConvertPixelmapToSurfaceBuffer(const std::shared_ptr<OHOS::Media::PixelMap> & pixelmap,sptr<SurfaceBuffer> & bufferImpl)305 bool VpeNapi::ConvertPixelmapToSurfaceBuffer(const std::shared_ptr<OHOS::Media::PixelMap>& pixelmap,
306 sptr<SurfaceBuffer>& bufferImpl)
307 {
308 BufferRequestConfig bfConfig = {};
309 bfConfig.width = pixelmap->GetWidth();
310 bfConfig.height = pixelmap->GetHeight();
311 bfConfig.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE;
312 bfConfig.strideAlignment = bfConfig.width;
313 bfConfig.format = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888;
314 bfConfig.timeout = 0;
315 bfConfig.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
316 bfConfig.transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
317 CHECK_AND_RETURN_RET_LOG((bufferImpl->Alloc(bfConfig) == GSERROR_OK), false, "invalid OH_PixelmapNative image");
318 return true;
319 }
320
GetSurfaceBufferFromDMAPixelMap(const std::shared_ptr<OHOS::Media::PixelMap> & pixelmap)321 sptr<SurfaceBuffer> VpeNapi::GetSurfaceBufferFromDMAPixelMap(
322 const std::shared_ptr<OHOS::Media::PixelMap>& pixelmap)
323 {
324 CHECK_AND_RETURN_RET_LOG(pixelmap != nullptr, nullptr, "pixelmap == nullptr");
325 if (pixelmap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
326 return reinterpret_cast<SurfaceBuffer*>(pixelmap->GetFd());
327 }
328 auto buffer = SurfaceBuffer::Create();
329 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, nullptr, "get surface buffer failed!");
330 CHECK_AND_RETURN_RET_LOG(ConvertPixelmapToSurfaceBuffer(pixelmap, buffer), nullptr,
331 "get surface buffer failed!");
332 return buffer;
333 }
334
Create(napi_env env,napi_callback_info info)335 napi_value VpeNapi::Create(napi_env env, napi_callback_info info)
336 {
337 napi_value result = nullptr;
338 napi_get_undefined(env, &result);
339 napi_value constructor = nullptr;
340 napi_status status = napi_ok;
341 status = napi_get_reference_value(env, constructor_, &constructor);
342 if (status == napi_ok) {
343 size_t argc = NEW_INSTANCE_ARGC;
344 napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
345 status = napi_new_instance(env, constructor, argc, argv, &result);
346 }
347 if (status != napi_ok) {
348 VPE_LOGE("create instance failed");
349 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "create instance failed");
350 return nullptr;
351 }
352 VPE_LOGI("create done");
353 return result;
354 }
355
PrepareDstPixelMap(napi_env env,DetailEnhanceContext * context)356 std::shared_ptr<PixelMap> VpeNapi::PrepareDstPixelMap(napi_env env, DetailEnhanceContext* context)
357 {
358 CHECK_AND_RETURN_RET_LOG(context->inputPixelMap->GetWidth() >= MIN_RESOLUTION_DETAIL &&
359 context->inputPixelMap->GetHeight() >= MIN_RESOLUTION_DETAIL &&
360 context->inputPixelMap->GetWidth() <= MAX_RESOLUTION_DETAIL &&
361 context->inputPixelMap->GetHeight() <= MAX_RESOLUTION_DETAIL,
362 nullptr, "invalid resolution");
363 InitializationOptions opts {
364 .size = {
365 .width = static_cast<int>(context->xArg),
366 .height = static_cast<int>(context->yArg),
367 },
368 };
369 VPE_LOGD("res:w %{public}d, h %{public}d, -> w %{public}d, h %{public}d",
370 context->inputPixelMap->GetWidth(), context->inputPixelMap->GetHeight(),
371 static_cast<int>(context->xArg), static_cast<int>(context->yArg));
372 std::unique_ptr<PixelMap> outputPtr = context->inputPixelMap->Create(*context->inputPixelMap, opts);
373 if (outputPtr == nullptr) {
374 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_INVALID_VALUE, "create failed");
375 return nullptr;
376 }
377 std::shared_ptr<PixelMap> dstPixelMap{std::move(outputPtr)};
378 return dstPixelMap;
379 }
380
InitDetailAlgo(napi_env env)381 bool VpeNapi::InitDetailAlgo(napi_env env)
382 {
383 VPETrace vpeTrace("VpeNapi::DetailEnhanceInitAlgo");
384 if (g_detailEnh != nullptr) {
385 VPE_LOGW("DetailEnhancerImage handle has created");
386 return true;
387 }
388 g_detailEnh = DetailEnhancerImage::Create();
389 CHECK_AND_RETURN_RET_LOG(g_detailEnh != nullptr, false, "create DetailEnhancerImage failed");
390 return true;
391 }
392
SetDetailAlgoParam(napi_env env,int level)393 bool VpeNapi::SetDetailAlgoParam(napi_env env, int level)
394 {
395 DetailEnhancerParameters param {
396 .uri = "",
397 .level = static_cast<DetailEnhancerLevel>(level),
398 };
399 if (g_detailEnh->SetParameter(param)!= VPE_ALGO_ERR_OK) {
400 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "set parameter failed");
401 return false;
402 }
403 return true;
404 }
405
DetailEnhanceImpl(napi_env env,DetailEnhanceContext * context)406 std::shared_ptr<PixelMap> VpeNapi::DetailEnhanceImpl(napi_env env, DetailEnhanceContext* context)
407 {
408 VPETrace vpeTrace("VpeNapi::DetailEnhanceImpl");
409 if (context == nullptr) {
410 VPE_LOGE("context == nullptr");
411 return nullptr;
412 }
413 if (context->inputPixelMap->GetPixelFormat() == PixelFormat::YCBCR_P010 ||
414 context->inputPixelMap->GetPixelFormat() == PixelFormat::YCRCB_P010) {
415 VPE_LOGI("not support P010");
416 return context->inputPixelMap;
417 }
418 if (!InitDetailAlgo(env)) {
419 VPE_LOGE("init algo failed");
420 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "init algo failed");
421 return nullptr;
422 }
423 if (!SetDetailAlgoParam(env, context->qualityLevel)) {
424 VPE_LOGE("set detail param failed");
425 return nullptr;
426 }
427 if (context->inputPixelMap == nullptr) {
428 VPE_LOGE("*context->inputPixelMap == nullptr");
429 return nullptr;
430 }
431 auto dstPixelMap = PrepareDstPixelMap(env, context);
432 if (dstPixelMap == nullptr) {
433 VPE_LOGE("move failed");
434 return nullptr;
435 }
436 auto output = GetSurfaceBufferFromDMAPixelMap(dstPixelMap);
437 auto input = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
438 CHECK_AND_RETURN_RET_LOG((g_detailEnh != nullptr && g_detailEnh->Process(input, output) == VPE_ALGO_ERR_OK),
439 nullptr, "process failed");
440 return dstPixelMap;
441 }
442
EnhanceDetailWork(napi_env env,void * data)443 void VpeNapi::EnhanceDetailWork(napi_env env, void* data)
444 {
445 DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
446 if (innerAsyncContext == nullptr) {
447 std::string errCodeStr = std::to_string(IMAGE_PROCESSING_ERROR_PROCESS_FAILED);
448 std::string errMsg = "innerAsyncContext is nullptr";
449 napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
450 return;
451 }
452 innerAsyncContext->outputPixelMap = DetailEnhanceImpl(env, innerAsyncContext);
453 };
454
EnhanceDetailCallBackWork(napi_env env,napi_status status,void * data)455 void VpeNapi::EnhanceDetailCallBackWork(napi_env env, napi_status status, void* data)
456 {
457 DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
458 if (innerAsyncContext == nullptr) {
459 std::string errCodeStr = std::to_string(IMAGE_PROCESSING_ERROR_PROCESS_FAILED);
460 std::string errMsg = "innerAsyncContext is nullptr";
461 napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
462 return;
463 }
464 napi_value outputPixelMapNapi = (innerAsyncContext->outputPixelMap == nullptr) ?
465 nullptr : PixelMapNapi::CreatePixelMap(env, innerAsyncContext->outputPixelMap);
466 if (outputPixelMapNapi == nullptr) {
467 return;
468 }
469 if (innerAsyncContext->deferred) {
470 napi_resolve_deferred(env, innerAsyncContext->deferred, outputPixelMapNapi);
471 } else {
472 napi_value callback = nullptr;
473 napi_get_reference_value(env, innerAsyncContext->callbackRef, &callback);
474 napi_call_function(env, nullptr, callback, 1, &(outputPixelMapNapi), nullptr);
475 napi_delete_reference(env, innerAsyncContext->callbackRef);
476 innerAsyncContext->callbackRef = nullptr;
477 }
478 napi_delete_async_work(env, innerAsyncContext->asyncWork);
479 delete innerAsyncContext;
480 };
481
EnhanceDetail(napi_env env,napi_callback_info info)482 napi_value VpeNapi::EnhanceDetail(napi_env env, napi_callback_info info)
483 {
484 VPETrace vpeTrace("VpeNapi::DetailEnhanceProcess");
485 if (detailContext_ == nullptr) {
486 detailContext_ = std::make_shared<DetailEnhanceContext>();
487 }
488 CHECK_AND_RETURN_RET_LOG(detailContext_ != nullptr, nullptr, "context == nullptr");
489 napi_deferred deferred;
490 napi_value promise;
491 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
492 if (!ParseDetailEnhanceParameter(env, info)) {
493 VPE_LOGE("parse parameter failed");
494 return nullptr;
495 }
496 detailContext_->deferred = deferred;
497 napi_value resourceName;
498 napi_create_string_latin1(env, "Asynchronous processing", NAPI_AUTO_LENGTH, &resourceName);
499 napi_status status = napi_create_async_work(env, nullptr, resourceName, EnhanceDetailWork,
500 EnhanceDetailCallBackWork, reinterpret_cast<void*>(detailContext_.get()), &detailContext_->asyncWork);
501 if (status != napi_ok) {
502 VPE_LOGE("create aysnc failed");
503 return nullptr;
504 }
505 napi_queue_async_work(env, detailContext_->asyncWork);
506 return promise;
507 }
508
EnhanceDetailSync(napi_env env,napi_callback_info info)509 napi_value VpeNapi::EnhanceDetailSync(napi_env env, napi_callback_info info)
510 {
511 VPETrace vpeTrace("VpeNapi::DetailEnhanceProcess");
512 if (detailContext_ == nullptr) {
513 detailContext_ = std::make_shared<DetailEnhanceContext>();
514 }
515 CHECK_AND_RETURN_RET_LOG(detailContext_ != nullptr, nullptr, "context == nullptr");
516 CHECK_AND_RETURN_RET_LOG(ParseDetailEnhanceParameter(env, info), nullptr, "parse parameter failed");
517 std::shared_ptr<PixelMap> outputPixelMap = DetailEnhanceImpl(env, detailContext_.get());
518 if (outputPixelMap == nullptr) {
519 VPE_LOGE("DetailEnhanceImpl processed failed");
520 return nullptr;
521 }
522 napi_value outputPixelMapNapi = PixelMapNapi::CreatePixelMap(env, outputPixelMap);
523 return outputPixelMapNapi;
524 }
525
PrepareRect(std::shared_ptr<PixelMap> input,OHOS::Rect & displayArea,float ratio)526 OHOS::Rect VpeNapi::PrepareRect(std::shared_ptr<PixelMap> input, OHOS::Rect& displayArea, float ratio)
527 {
528 OHOS::Rect rect;
529 rect.x = static_cast<int>(displayArea.x * ratio + ROUNDING_OPERATOR);
530 rect.y = static_cast<int>(displayArea.y * ratio + ROUNDING_OPERATOR);
531 rect.w = std::min(input->GetWidth() - 1 - rect.x,
532 static_cast<int>(displayArea.w * ratio + ROUNDING_OPERATOR));
533 rect.h = std::min(input->GetHeight() - 1 - rect.y,
534 static_cast<int>(displayArea.h * ratio + ROUNDING_OPERATOR));
535 return rect;
536 }
537
UpdateMetadataBasedOnHist(ContrastEnhanceContext * context)538 bool VpeNapi::UpdateMetadataBasedOnHist(ContrastEnhanceContext* context)
539 {
540 CHECK_AND_RETURN_RET_LOG(context->inputPixelMap != nullptr && context->oriWidth >= MIN_WIDTH_CONTRAST &&
541 context->oriHeight >= MIN_HEIGHT_CONTRAST && context->oriHeight < MAX_RESOLUTION_CONTRAST &&
542 context->oriWidth < MAX_RESOLUTION_CONTRAST, false, "unsupport resolution");
543 CHECK_AND_RETURN_RET_LOG(context->inputPixelMap->IsHdr(), false, "It's not hdr pixelmap");
544 sptr<SurfaceBuffer> surfaceBuffer = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
545 OHOS::Rect rect = PrepareRect(context->inputPixelMap, context->displayArea, context->fullRatio);
546 VPE_LOGI("area x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d",
547 context->displayArea.x, context->displayArea.y, context->displayArea.w, context->displayArea.h);
548 VPE_LOGI("cur pixelmap:w:%{public}d, h:%{public}d, ori pixelmap:w:%{public}d, h:%{public}d",
549 context->inputPixelMap->GetWidth(), context->inputPixelMap->GetHeight(), context->oriWidth, context->oriHeight);
550 std::tuple<int, int, double, double, double, int> pixelmapInfo =
551 std::make_tuple(context->inputPixelMap->GetUniqueId(), context->contentId,
552 context->curRatio, context->maxRatio, context->defaultRatio, context->animationDuration);
553 return g_contrastEnh->UpdateMetadataBasedOnHist(rect, surfaceBuffer, pixelmapInfo);
554 }
555
UpdateMetadataBasedOnPixel(ContrastEnhanceContext * context)556 bool VpeNapi::UpdateMetadataBasedOnPixel(ContrastEnhanceContext* context)
557 {
558 CHECK_AND_RETURN_RET_LOG(context->inputPixelMap != nullptr &&
559 context->inputPixelMap->GetWidth() >= MIN_WIDTH_CONTRAST &&
560 context->inputPixelMap->GetHeight() >= MIN_HEIGHT_CONTRAST && context->oriHeight < MAX_RESOLUTION_CONTRAST &&
561 context->oriWidth < MAX_RESOLUTION_CONTRAST, false, "unsupport resolution");
562 OHOS::Rect completePixelmapArea = {
563 .x = 0,
564 .y = 0,
565 .w = context->oriWidth,
566 .h = context->oriHeight,
567 };
568 sptr<SurfaceBuffer> surfaceBuffer = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
569 VPE_LOGI("area x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d",
570 context->displayArea.x, context->displayArea.y, context->displayArea.w, context->displayArea.h);
571 return g_contrastEnh->UpdateMetadataBasedOnPixel(context->displayArea, context->curPixelmapArea,
572 completePixelmapArea, surfaceBuffer, context->fullRatio);
573 }
574
SetDetailImage(napi_env env,napi_callback_info info)575 napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
576 {
577 VPETrace vpeTrace("VpeNapi::ContrastProcess");
578 if (contrastContext_ == nullptr) {
579 contrastContext_ = std::make_shared<ContrastEnhanceContext>();
580 VPE_LOGI("create new contrast context");
581 }
582 CHECK_AND_RETURN_RET_LOG(contrastContext_ != nullptr, nullptr, "context == nullptr");
583 NapiValues nVal;
584 CHECK_AND_RETURN_RET_LOG(ParseDetailImageParameter(env, info, nVal), nullptr, "parse parameter failed");
585 CHECK_AND_RETURN_RET_LOG(InitContrastAlgo(env), nullptr, "init contrast algo failed");
586 // 不管是不是区域解码,都先使用直方图的结果进行展示,之后再转变成bitmap的结果
587 CallCallback(env, contrastContext_.get());
588 // 如果在计算完成前坐标位置已经发生了变化,则不需要继续进行计算
589 if (contrastContext_->callbackRef == nullptr) {
590 napi_create_promise(env, &(contrastContext_->deferred), &(nVal.result));
591 }
592 napi_value resourceName;
593 napi_create_string_latin1(env, "Asynchronous processing", NAPI_AUTO_LENGTH, &resourceName);
594 napi_status status = napi_create_async_work(
595 env, nullptr, resourceName,
596 [](napi_env env, void* data) {
597 ContrastEnhanceContext* innerAsyncContext = reinterpret_cast<ContrastEnhanceContext*>(data);
598 if (innerAsyncContext == nullptr) {
599 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_PROCESS_FAILED, "innerAsyncContext == nullptr");
600 return;
601 }
602 UpdateMetadataBasedOnHist(innerAsyncContext);
603 },
604 [](napi_env env, napi_status status, void* data) {
605 ContrastEnhanceContext* innerAsyncContext = reinterpret_cast<ContrastEnhanceContext*>(data);
606 CallCallback(env, innerAsyncContext);
607 if (status != napi_ok) {
608 VPE_LOGE("process failed");
609 }
610 VPE_LOGD("process detail image done");
611 },
612 (void*)(contrastContext_.get()), &contrastContext_->asyncWork);
613 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "create aysnc failed");
614 status = napi_queue_async_work(env, contrastContext_->asyncWork);
615 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "queue aysnc work failed");
616 return nullptr;
617 }
618
GenerateRegionHist(napi_env env,ContrastEnhanceContext * context)619 bool VpeNapi::GenerateRegionHist(napi_env env, ContrastEnhanceContext* context)
620 {
621 CHECK_AND_RETURN_RET_LOG(InitContrastAlgo(env), false, "init contrast algo failed");
622 CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context == nullptr");
623 CHECK_AND_RETURN_RET_LOG(context->lcdPixelMap != nullptr, false, "lcdPixelMap == nullptr");
624 auto input = GetSurfaceBufferFromDMAPixelMap(context->lcdPixelMap);
625 CHECK_AND_RETURN_RET_LOG(input != nullptr, false, "input == nullptr");
626 CHECK_AND_RETURN_RET_LOG(g_contrastEnh != nullptr, false, "g_contrastEnh == nullptr");
627 if (g_contrastEnh->GetRegionHist(input) != 0) { // 9ms
628 VPE_LOGE("processed failed. Clear LUT history");
629 return false;
630 }
631 return true;
632 }
633
InitContrastAlgo(napi_env env)634 bool VpeNapi::InitContrastAlgo(napi_env env)
635 {
636 VPETrace vpeTrace("VpeNapi::DetailEnhanceInitAlgo");
637 if (g_contrastEnh != nullptr) {
638 VPE_LOGD("ContrastEnhancerImage handle has created");
639 return true;
640 }
641 g_contrastEnh = ContrastEnhancerImage::Create();
642 CHECK_AND_RETURN_RET_LOG(g_contrastEnh != nullptr, false, "create ContrastEnhancerImage failed");
643 ContrastEnhancerParameters param {
644 .uri = "",
645 .type = ADAPTIVE_FOV,
646 };
647 if (g_contrastEnh->SetParameter(param)!= VPE_ALGO_ERR_OK) {
648 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "set parameter failed");
649 return false;
650 }
651 return true;
652 }
653
ParseRect(napi_env env,napi_value nVal,OHOS::Rect & rect)654 bool VpeNapi::ParseRect(napi_env env, napi_value nVal, OHOS::Rect& rect)
655 {
656 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(nVal, "x", rect.x), false, "Failed to parse start pos X");
657 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(nVal, "y", rect.y), false, "Failed to parse start pos Y");
658 napi_value tmpValue = nullptr;
659 CHECK_AND_RETURN_RET_LOG(GET_NODE_BY_NAME(nVal, "size", tmpValue), false, "Failed to parse resolution of rect");
660 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(tmpValue, "height", rect.h), false, "Failed to parse height of rect");
661 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(tmpValue, "width", rect.w), false, "Failed to parse width of rect");
662 return true;
663 }
664
ParseSize(napi_env env,napi_value nVal)665 bool VpeNapi::ParseSize(napi_env env, napi_value nVal)
666 {
667 napi_value tmpValue = nullptr;
668 CHECK_AND_RETURN_RET_LOG(GET_NODE_BY_NAME(nVal, "size", tmpValue), false, "Failed to parse resolution of rect");
669 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(nVal, "height", contrastContext_->oriHeight),
670 false, "Failed to parse height of rect");
671 CHECK_AND_RETURN_RET_LOG(GET_INT32_BY_NAME(nVal, "width", contrastContext_->oriWidth),
672 false, "Failed to parse width of rect");
673 return true;
674 }
675
ParseDetailImageParameter(napi_env env,napi_callback_info info,NapiValues & nVal)676 bool VpeNapi::ParseDetailImageParameter(napi_env env, napi_callback_info info, NapiValues& nVal)
677 {
678 VPETrace vpeTrace("VpeNapi::DetailEnhance");
679 std::lock_guard<std::mutex> lock(g_contrastLock);
680 nVal.argc = NUM_9;
681 napi_value argValue[NUM_9] = {0};
682 nVal.argv = argValue;
683 if (!PrepareNapiEnv(env, info, &nVal)) {
684 return false;
685 }
686 if (nVal.argc != NUM_9) {
687 VPE_LOGE("Invalid args count %{public}zu", nVal.argc);
688 return false;
689 } else {
690 CHECK_AND_RETURN_RET_LOG(ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP,
691 false, "Arg 0 type mismatch");
692 contrastContext_->inputPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
693 CHECK_AND_RETURN_RET_LOG(contrastContext_->inputPixelMap != nullptr, false,
694 "contrastContext_->srcPixelMap == nullptr, resuse history");
695 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_1],
696 &(contrastContext_->pixelmapId)) == napi_ok, false, "Arg 1 type mismatch");
697 CHECK_AND_RETURN_RET_LOG(ParseRect(env, argValue[NUM_2], contrastContext_->curPixelmapArea), false,
698 "parse pixelmap area failed");
699 CHECK_AND_RETURN_RET_LOG(ParseRect(env, argValue[NUM_3], contrastContext_->displayArea), false,
700 "parse display area failed");
701 CHECK_AND_RETURN_RET_LOG(ParseSize(env, argValue[NUM_4]), false, "parse resolution of original image failed");
702 CHECK_AND_RETURN_RET_LOG(napi_get_value_bool(env, nVal.argv[NUM_5],
703 &(contrastContext_->genFinalEffect)) == napi_ok, false, "Arg 5 type mismatch");
704 CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_6],
705 &(contrastContext_->maxRatio)) == napi_ok, false, "Arg 6 type mismatch");
706 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_7],
707 &(contrastContext_->animationDuration)) == napi_ok, false, "Arg 7 type mismatch");
708 CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_8],
709 &(contrastContext_->curRatio)) == napi_ok, false, "Arg 8 type mismatch");
710 }
711 contrastContext_->fullRatio = std::min(
712 static_cast<float>(contrastContext_->inputPixelMap->GetWidth()) /
713 static_cast<float>(contrastContext_->curPixelmapArea.w),
714 static_cast<float>(contrastContext_->inputPixelMap->GetHeight()) /
715 static_cast<float>(contrastContext_->curPixelmapArea.h));
716
717 VPE_LOGI("res: %{public}d x %{public}d, curArea: %{public}d x %{public}d, ratio:%{puiblic}f, maxRatio:%{public}f",
718 contrastContext_->inputPixelMap->GetWidth(), contrastContext_->inputPixelMap->GetHeight(),
719 contrastContext_->curPixelmapArea.w, contrastContext_->curPixelmapArea.h,
720 contrastContext_->curRatio, contrastContext_->maxRatio);
721 return true;
722 }
723
ParseLCDParameter(napi_env env,napi_callback_info info,NapiValues & nVal)724 bool VpeNapi::ParseLCDParameter(napi_env env, napi_callback_info info, NapiValues& nVal)
725 {
726 VPETrace vpeTrace("VpeNapi::DetailEnhance");
727 std::lock_guard<std::mutex> lock(g_contrastLock);
728 nVal.argc = NUM_3;
729 napi_value argValue[NUM_3] = {0};
730 nVal.argv = argValue;
731 if (!PrepareNapiEnv(env, info, &nVal)) {
732 return false;
733 }
734 if (nVal.argc != NUM_3) {
735 VPE_LOGE("Invalid args count %{public}zu", nVal.argc);
736 return false;
737 } else {
738 CHECK_AND_RETURN_RET_LOG(ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP,
739 false, "Arg 0 type is not pixelmap");
740 contrastContext_->lcdPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
741 CHECK_AND_RETURN_RET_LOG(contrastContext_->lcdPixelMap != nullptr, false, "pixelmap is nullptr");
742 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_1],
743 &(contrastContext_->contentId)) == napi_ok, false, "Failed to parse lcd param. Arg 1 type mismatch");
744 CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_2],
745 &(contrastContext_->defaultRatio)) == napi_ok, false, "Failed to parse lcd param. Arg 2 type mismatch");
746 CHECK_AND_RETURN_RET_LOG(contrastContext_->lcdPixelMap->GetWidth() > 0 &&
747 contrastContext_->lcdPixelMap->GetHeight() > 0, false, "invalid resolution");
748 contrastContext_->lcdWidth = static_cast<unsigned int>(contrastContext_->lcdPixelMap->GetWidth());
749 contrastContext_->lcdHeight = static_cast<unsigned int>(contrastContext_->lcdPixelMap->GetHeight());
750 }
751 VPE_LOGI("update content info: lcdWidth:%{public}d, lcdHeight:%{public}d",
752 contrastContext_->lcdWidth, contrastContext_->lcdHeight);
753 return true;
754 }
755
SetLcdImage(napi_env env,napi_callback_info info)756 napi_value VpeNapi::SetLcdImage(napi_env env, napi_callback_info info)
757 {
758 VPE_LOGI("set lcd image");
759 VPETrace vpeTrace("VpeNapi::DetailEnhanceProcess");
760 napi_value result = nullptr;
761 if (contrastContext_ == nullptr) {
762 contrastContext_ = std::make_shared<ContrastEnhanceContext>();
763 VPE_LOGI("create new contrast context");
764 }
765 if (contrastContext_ == nullptr) {
766 VPE_LOGE("context == nullptr");
767 return result;
768 }
769 NapiValues nVal;
770 if (!ParseLCDParameter(env, info, nVal)) {
771 VPE_LOGE("parse parameter failed");
772 return result;
773 }
774 napi_value resourceName;
775 napi_create_string_latin1(env, "Asynchronous processing", NAPI_AUTO_LENGTH, &resourceName);
776 napi_status status = napi_create_async_work(
777 env, nullptr, resourceName,
778 [](napi_env env, void* data) {
779 ContrastEnhanceContext* innerAsyncContext = reinterpret_cast<ContrastEnhanceContext*>(data);
780 if (innerAsyncContext == nullptr) {
781 ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_PROCESS_FAILED, "innerAsyncContext == nullptr");
782 return;
783 }
784 GenerateRegionHist(env, innerAsyncContext);
785 },
786 [](napi_env env, napi_status status, void* data) {
787 ContrastEnhanceContext* innerAsyncContext = reinterpret_cast<ContrastEnhanceContext*>(data);
788 CallCallback(env, innerAsyncContext);
789 if (status != napi_ok) {
790 VPE_LOGE("Failed to generate lut baseline for pcicture %{public}d", contrastContext_->contentId);
791 }
792 VPE_LOGI("Generate lut baseline for picture %{public}d successfully. Initial scaling ratio: %{public}f",
793 contrastContext_->contentId, contrastContext_->defaultRatio);
794 },
795 (void*)(contrastContext_.get()), &contrastContext_->asyncWork);
796 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "create aysnc failed");
797 CHECK_AND_RETURN_RET_LOG(napi_queue_async_work(env, contrastContext_->asyncWork) == napi_ok,
798 nullptr, "queue aysnc work failed");
799 return result;
800 }
801
RegisterCallback(napi_env env,napi_callback_info info)802 napi_value VpeNapi::RegisterCallback(napi_env env, napi_callback_info info)
803 {
804 size_t argc = 1;
805 napi_value argv[1];
806 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
807 if (contrastContext_->callbackRef != nullptr) {
808 napi_delete_reference(env, contrastContext_->callbackRef);
809 }
810 napi_create_reference(env, argv[0], 1, &(contrastContext_->callbackRef));
811 return nullptr;
812 }
813
CallCallback(napi_env env,ContrastEnhanceContext * context)814 napi_value VpeNapi::CallCallback(napi_env env, ContrastEnhanceContext* context)
815 {
816 bool noCall = true;
817 if (noCall) {
818 return nullptr;
819 }
820
821 if (context->callbackRef != nullptr) {
822 napi_value global;
823 napi_get_global(env, &global);
824 napi_value callbackFunc;
825 napi_get_reference_value(env, context->callbackRef, &callbackFunc);
826 napi_value result;
827 napi_call_function(env, global, callbackFunc, 0, nullptr, &result);
828 }
829 return nullptr;
830 }
831
Constructor(napi_env env,napi_callback_info info)832 napi_value VpeNapi::Constructor(napi_env env, napi_callback_info info)
833 {
834 napi_value undefineVar = nullptr;
835 napi_get_undefined(env, &undefineVar);
836
837 napi_status status;
838 napi_value thisVar = nullptr;
839 napi_get_undefined(env, &thisVar);
840 size_t argc = NEW_INSTANCE_ARGC;
841 napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
842 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
843 if (status != napi_ok || thisVar == nullptr) {
844 return undefineVar;
845 }
846 VpeNapi* pDetailEnhanceNapi = new VpeNapi();
847 status = napi_wrap_with_size(env, thisVar, reinterpret_cast<void*>(pDetailEnhanceNapi),
848 VpeNapi::Destructor, nullptr, nullptr, static_cast<size_t>(sizeof(VpeNapi)));
849 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefineVar, "Failure wrapping js to native napi");
850 return thisVar;
851 }
852
Destructor(napi_env env,void * nativeObject,void * finalize)853 void VpeNapi::Destructor(napi_env env, void* nativeObject, void* finalize)
854 {
855 if (nativeObject != nullptr) {
856 std::lock_guard<std::mutex> lock(g_imageProcessorMutex);
857 delete reinterpret_cast<VpeNapi*>(nativeObject);
858 nativeObject = nullptr;
859 }
860 }
861
DoInitAfter(napi_env env,napi_value exports,napi_value constructor,size_t property_count,const napi_property_descriptor * properties)862 napi_value VpeNapi::DoInitAfter(napi_env env, napi_value exports, napi_value constructor,
863 size_t property_count, const napi_property_descriptor* properties)
864 {
865 napi_value global = nullptr;
866 CHECK_AND_RETURN_RET_LOG(napi_get_global(env, &global) == napi_ok, nullptr, "Init:get global fail");
867 CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, global, CLASS_NAME.c_str(), constructor) == napi_ok,
868 nullptr, "Init:set global named property fail");
869 CHECK_AND_RETURN_RET_LOG(napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor) == napi_ok,
870 nullptr, "set named property fail");
871 CHECK_AND_RETURN_RET_LOG(napi_define_properties(env, exports, property_count, properties) == napi_ok,
872 nullptr, "define properties fail");
873 return exports;
874 }
875
CreateEnumTypeObject(napi_env env,napi_valuetype type,napi_ref * ref,std::vector<struct QualityLevelEnum> & imageEnumMap)876 napi_value VpeNapi::CreateEnumTypeObject(napi_env env, napi_valuetype type, napi_ref* ref,
877 std::vector<struct QualityLevelEnum>& imageEnumMap)
878 {
879 napi_value result = nullptr;
880 napi_status status;
881 int32_t refCount = 1;
882 std::string propName;
883 status = napi_create_object(env, &result);
884 if (status == napi_ok) {
885 for (auto imgEnum : imageEnumMap) {
886 napi_value enumNapiValue = nullptr;
887 if (type == napi_string) {
888 status = napi_create_string_utf8(env, imgEnum.strVal.c_str(), NAPI_AUTO_LENGTH, &enumNapiValue);
889 } else if (type == napi_number) {
890 status = napi_create_int32(env, imgEnum.numVal, &enumNapiValue);
891 } else {
892 VPE_LOGE("Unsupported type %{public}d!", type);
893 }
894 if (status == napi_ok && enumNapiValue != nullptr) {
895 status = napi_set_named_property(env, result, imgEnum.name.c_str(), enumNapiValue);
896 }
897 if (status != napi_ok) {
898 VPE_LOGE("Failed to add named prop!");
899 break;
900 }
901 }
902 if (status == napi_ok) {
903 status = napi_create_reference(env, result, refCount, ref);
904 if (status == napi_ok) {
905 return result;
906 }
907 }
908 }
909 VPE_LOGE("CreateEnumTypeObject is Failed!");
910 napi_get_undefined(env, &result);
911 return result;
912 }
913
RegisterNapi()914 std::vector<napi_property_descriptor> VpeNapi::RegisterNapi()
915 {
916 std::vector<napi_property_descriptor> props = {
917 DECLARE_NAPI_FUNCTION("enhanceDetail", VpeNapi::EnhanceDetail),
918 DECLARE_NAPI_FUNCTION("enhanceDetailSync", VpeNapi::EnhanceDetailSync),
919 DECLARE_NAPI_FUNCTION("setLcdImage", VpeNapi::SetLcdImage),
920 DECLARE_NAPI_FUNCTION("setDetailImage", VpeNapi::SetDetailImage),
921 DECLARE_NAPI_FUNCTION("registerCallback", VpeNapi::RegisterCallback)
922 };
923 return props;
924 }
925
Init(napi_env env,napi_value exports)926 napi_value VpeNapi::Init(napi_env env, napi_value exports)
927 {
928 std::vector<napi_property_descriptor> props = VpeNapi::RegisterNapi();
929 napi_value constructor = nullptr;
930 CHECK_AND_RETURN_RET_LOG(napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
931 VpeNapi::Constructor, nullptr, props.size(), props.data(), &constructor) == napi_ok,
932 nullptr, "define class fail");
933 CHECK_AND_RETURN_RET_LOG(napi_create_reference(env, constructor, 1, &constructor_) == napi_ok,
934 nullptr, "create reference fail");
935
936 napi_value qualityLevel = CreateEnumTypeObject(env, napi_number, &qualityLevelTypeRef_, g_qualityLevels);
937 CHECK_AND_RETURN_RET_LOG(qualityLevel != nullptr, nullptr, "CreateEnumTypeObject failed");
938 napi_property_descriptor desc[] = {
939 DECLARE_NAPI_PROPERTY("QualityLevel", qualityLevel),
940 DECLARE_NAPI_FUNCTION("create", VpeNapi::Create),
941 DECLARE_NAPI_FUNCTION("initializeEnvironment", VpeNapi::InitializeEnvironment),
942 DECLARE_NAPI_FUNCTION("deinitializeEnvironment", VpeNapi::DeinitializeEnvironment),
943 };
944 auto result = DoInitAfter(env, exports, constructor, sizeof(desc) / sizeof(desc[0]), desc);
945 return result;
946 }
947 }
948 }