1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "image_packer_napi.h"
17 #include "hilog/log.h"
18 #include "media_errors.h"
19 #include "image_napi_utils.h"
20 #include "image_packer.h"
21 #include "image_source.h"
22 #include "image_source_napi.h"
23 #include "pixel_map_napi.h"
24 #include "image_trace.h"
25 #include "hitrace_meter.h"
26
27 using OHOS::HiviewDFX::HiLog;
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ImagePackerNapi"};
30 constexpr uint32_t NUM_0 = 0;
31 constexpr uint32_t NUM_1 = 1;
32 constexpr uint32_t NUM_2 = 2;
33 }
34
35 namespace OHOS {
36 namespace Media {
37 static const std::string CLASS_NAME_IMAGEPACKER = "ImagePacker";
38 std::shared_ptr<ImagePacker> ImagePackerNapi::sImgPck_ = nullptr;
39 std::shared_ptr<ImageSource> ImagePackerNapi::sImgSource_ = nullptr;
40 thread_local napi_ref ImagePackerNapi::sConstructor_ = nullptr;
41
42 const int ARGS_THREE = 3;
43 const int PARAM0 = 0;
44 const int PARAM1 = 1;
45 const int PARAM2 = 2;
46 const int PARAM3 = 3;
47 const uint8_t BYTE_FULL = 0xFF;
48 const int32_t SIZE = 100;
49 const int32_t TYPE_IMAGE_SOURCE = 1;
50 const int32_t TYPE_PIXEL_MAP = 2;
51 const int64_t DEFAULT_BUFFER_SIZE = 25 * 1024 * 1024; // 25M is the maximum default packedSize
52
53 struct ImagePackerAsyncContext {
54 napi_env env;
55 napi_async_work work;
56 napi_deferred deferred;
57 napi_ref callbackRef = nullptr;
58 napi_ref errorMsg = nullptr;
59 ImagePackerNapi *constructor_;
60 bool status = false;
61 std::shared_ptr<ImageSource> rImageSource;
62 PackOption packOption;
63 std::shared_ptr<ImagePacker> rImagePacker;
64 std::shared_ptr<PixelMap> rPixelMap;
65 std::unique_ptr<uint8_t[]> resultBuffer;
66 int32_t packType = TYPE_IMAGE_SOURCE;
67 int64_t resultBufferSize = 0;
68 int64_t packedSize = 0;
69 };
70
71 struct PackingOption {
72 std::string format;
73 uint8_t quality = 100;
74 };
75
ImagePackerNapi()76 ImagePackerNapi::ImagePackerNapi():env_(nullptr)
77 {}
78
~ImagePackerNapi()79 ImagePackerNapi::~ImagePackerNapi()
80 {
81 release();
82 }
83
CommonCallbackRoutine(napi_env env,ImagePackerAsyncContext * & connect,const napi_value & valueParam)84 static void CommonCallbackRoutine(napi_env env, ImagePackerAsyncContext* &connect, const napi_value &valueParam)
85 {
86 napi_value result[NUM_2] = {0};
87 napi_value retVal;
88 napi_value callback = nullptr;
89
90 napi_get_undefined(env, &result[NUM_0]);
91 napi_get_undefined(env, &result[NUM_1]);
92
93 if (connect->status == SUCCESS) {
94 result[NUM_1] = valueParam;
95 } else if (connect->errorMsg != nullptr) {
96 napi_get_reference_value(env, connect->errorMsg, &result[NUM_0]);
97 napi_delete_reference(env, connect->errorMsg);
98 } else {
99 napi_create_string_utf8(env, "Internal error", NAPI_AUTO_LENGTH, &(result[NUM_0]));
100 }
101
102 if (connect->deferred) {
103 if (connect->status == SUCCESS) {
104 napi_resolve_deferred(env, connect->deferred, result[NUM_1]);
105 } else {
106 napi_reject_deferred(env, connect->deferred, result[NUM_0]);
107 }
108 } else {
109 napi_get_reference_value(env, connect->callbackRef, &callback);
110 napi_call_function(env, nullptr, callback, PARAM2, result, &retVal);
111 napi_delete_reference(env, connect->callbackRef);
112 }
113
114 napi_delete_async_work(env, connect->work);
115
116 delete connect;
117 connect = nullptr;
118 }
119
BuildMsgOnError(napi_env env,ImagePackerAsyncContext * context,bool assertion,const std::string msg)120 static void BuildMsgOnError(napi_env env,
121 ImagePackerAsyncContext* context, bool assertion, const std::string msg)
122 {
123 napi_value tmpError;
124 napi_status status;
125 if (!assertion) {
126 HiLog::Error(LABEL, "%{public}s", msg.c_str());
127 status = napi_create_string_utf8(env, msg.c_str(), NAPI_AUTO_LENGTH, &tmpError);
128 if (status != napi_ok) {
129 HiLog::Error(LABEL, "Create error msg error");
130 return;
131 }
132 napi_create_reference(env, tmpError, NUM_1, &(context->errorMsg));
133 }
134 }
135
STATIC_EXEC_FUNC(Packing)136 STATIC_EXEC_FUNC(Packing)
137 {
138 int64_t packedSize = 0;
139 auto context = static_cast<ImagePackerAsyncContext*>(data);
140 HiLog::Debug(LABEL, "image packer get supported format");
141 std::set<std::string> formats;
142 uint32_t ret = context->rImagePacker->GetSupportedFormats(formats);
143 if (ret != SUCCESS) {
144 HiLog::Error(LABEL, "image packer get supported format failed, ret=%{public}u.", ret);
145 }
146 HiLog::Info(LABEL, "ImagePacker BufferSize %{public}" PRId64, context->resultBufferSize);
147 context->resultBuffer = std::make_unique<uint8_t[]>(
148 (context->resultBufferSize <= 0)?DEFAULT_BUFFER_SIZE:context->resultBufferSize);
149 if (context->resultBuffer == nullptr) {
150 BuildMsgOnError(env, context, context->resultBuffer == nullptr, "ImagePacker buffer alloc error");
151 return;
152 }
153 context->rImagePacker->StartPacking(context->resultBuffer.get(),
154 context->resultBufferSize, context->packOption);
155 if (context->packType == TYPE_IMAGE_SOURCE) {
156 HiLog::Info(LABEL, "ImagePacker set image source");
157 if (context->rImageSource == nullptr) {
158 BuildMsgOnError(env, context, context->rImageSource == nullptr, "ImageSource is nullptr");
159 return;
160 }
161 context->rImagePacker->AddImage(*(context->rImageSource));
162 } else {
163 HiLog::Info(LABEL, "ImagePacker set pixelmap");
164 if (context->rPixelMap == nullptr) {
165 BuildMsgOnError(env, context, context->rImageSource == nullptr, "Pixelmap is nullptr");
166 return;
167 }
168 context->rImagePacker->AddImage(*(context->rPixelMap));
169 }
170 context->rImagePacker->FinalizePacking(packedSize);
171 HiLog::Debug(LABEL, "packedSize=%{public}" PRId64, packedSize);
172 if (packedSize > 0 && (packedSize < context->resultBufferSize)) {
173 context->packedSize = packedSize;
174 context->status = SUCCESS;
175 } else {
176 context->status = ERROR;
177 HiLog::Error(LABEL, "Packing failed, packedSize outside size.");
178 }
179 }
180
STATIC_COMPLETE_FUNC(PackingError)181 STATIC_COMPLETE_FUNC(PackingError)
182 {
183 napi_value result = nullptr;
184 napi_get_undefined(env, &result);
185 auto context = static_cast<ImagePackerAsyncContext*>(data);
186 context->status = ERROR;
187 CommonCallbackRoutine(env, context, result);
188 }
189
STATIC_COMPLETE_FUNC(Packing)190 STATIC_COMPLETE_FUNC(Packing)
191 {
192 napi_value result = nullptr;
193 napi_get_undefined(env, &result);
194 auto context = static_cast<ImagePackerAsyncContext*>(data);
195
196 if (!ImageNapiUtils::CreateArrayBuffer(env, context->resultBuffer.get(),
197 context->packedSize, &result)) {
198 context->status = ERROR;
199 HiLog::Error(LABEL, "napi_create_arraybuffer failed!");
200 napi_get_undefined(env, &result);
201 } else {
202 context->status = SUCCESS;
203 }
204 context->resultBuffer = nullptr;
205 context->resultBufferSize = 0;
206 CommonCallbackRoutine(env, context, result);
207 }
208
Init(napi_env env,napi_value exports)209 napi_value ImagePackerNapi::Init(napi_env env, napi_value exports)
210 {
211 napi_property_descriptor props[] = {
212 DECLARE_NAPI_FUNCTION("packing", Packing),
213 DECLARE_NAPI_FUNCTION("packingFromPixelMap", Packing),
214 DECLARE_NAPI_FUNCTION("release", Release),
215 DECLARE_NAPI_GETTER("supportedFormats", GetSupportedFormats),
216 };
217 napi_property_descriptor static_prop[] = {
218 DECLARE_NAPI_STATIC_FUNCTION("createImagePacker", CreateImagePacker),
219 };
220
221 napi_value constructor = nullptr;
222
223 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
224 napi_define_class(env, CLASS_NAME_IMAGEPACKER.c_str(), NAPI_AUTO_LENGTH, Constructor,
225 nullptr, IMG_ARRAY_SIZE(props), props, &constructor)), nullptr,
226 HiLog::Error(LABEL, "define class fail")
227 );
228
229 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
230 napi_create_reference(env, constructor, 1, &sConstructor_)),
231 nullptr,
232 HiLog::Error(LABEL, "create reference fail")
233 );
234
235 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
236 napi_set_named_property(env, exports, CLASS_NAME_IMAGEPACKER.c_str(), constructor)),
237 nullptr,
238 HiLog::Error(LABEL, "set named property fail")
239 );
240 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
241 napi_define_properties(env, exports, IMG_ARRAY_SIZE(static_prop), static_prop)),
242 nullptr,
243 HiLog::Error(LABEL, "define properties fail")
244 );
245
246 HiLog::Debug(LABEL, "Init success");
247 return exports;
248 }
249
Constructor(napi_env env,napi_callback_info info)250 napi_value ImagePackerNapi::Constructor(napi_env env, napi_callback_info info)
251 {
252 napi_value undefineVar = nullptr;
253 napi_get_undefined(env, &undefineVar);
254
255 napi_status status;
256 napi_value thisVar = nullptr;
257
258 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
259 if (status == napi_ok && thisVar != nullptr) {
260 std::unique_ptr<ImagePackerNapi> pImgPackerNapi = std::make_unique<ImagePackerNapi>();
261 if (pImgPackerNapi != nullptr) {
262 pImgPackerNapi->env_ = env;
263 pImgPackerNapi->nativeImgPck = sImgPck_;
264 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(pImgPackerNapi.get()),
265 ImagePackerNapi::Destructor, nullptr, nullptr);
266 if (status == napi_ok) {
267 pImgPackerNapi.release();
268 return thisVar;
269 } else {
270 HiLog::Error(LABEL, "Failure wrapping js to native napi");
271 }
272 }
273 }
274
275 return undefineVar;
276 }
277
CreateImagePacker(napi_env env,napi_callback_info info)278 napi_value ImagePackerNapi::CreateImagePacker(napi_env env, napi_callback_info info)
279 {
280 StartTrace(HITRACE_TAG_ZIMAGE, "CreateImagePacker");
281 napi_value constructor = nullptr;
282 napi_value result = nullptr;
283 napi_status status;
284
285 std::shared_ptr<ImagePacker> imagePacker = std::make_shared<ImagePacker>();
286 status = napi_get_reference_value(env, sConstructor_, &constructor);
287 if (IMG_IS_OK(status)) {
288 sImgPck_ = imagePacker;
289 status = napi_new_instance(env, constructor, 0, nullptr, &result);
290 if (status == napi_ok) {
291 return result;
292 } else {
293 HiLog::Error(LABEL, "New instance could not be obtained");
294 }
295 }
296 FinishTrace(HITRACE_TAG_ZIMAGE);
297 return result;
298 }
299
Destructor(napi_env env,void * nativeObject,void * finalize)300 void ImagePackerNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
301 {
302 }
303
parseBufferSize(napi_env env,napi_value root)304 static int64_t parseBufferSize(napi_env env, napi_value root)
305 {
306 napi_value tempValue = nullptr;
307 int64_t tmpNumber = DEFAULT_BUFFER_SIZE;
308 if (napi_get_named_property(env, root, "bufferSize", &tempValue) != napi_ok) {
309 HiLog::Info(LABEL, "No bufferSize, Using default");
310 return tmpNumber;
311 }
312 napi_get_value_int64(env, tempValue, &tmpNumber);
313 HiLog::Info(LABEL, "BufferSize is %{public}" PRId64, tmpNumber);
314 if (tmpNumber < 0) {
315 return DEFAULT_BUFFER_SIZE;
316 }
317 return tmpNumber;
318 }
319
parsePackOptions(napi_env env,napi_value root,PackOption * opts)320 static bool parsePackOptions(napi_env env, napi_value root, PackOption* opts)
321 {
322 napi_value tmpValue = nullptr;
323 uint32_t tmpNumber = 0;
324
325 if (!GET_NODE_BY_NAME(root, "format", tmpValue)) {
326 HiLog::Error(LABEL, "No format in pack option");
327 return false;
328 }
329
330 bool isFormatArray = false;
331 napi_is_array(env, tmpValue, &isFormatArray);
332 auto formatType = ImageNapiUtils::getType(env, tmpValue);
333
334 HiLog::Debug(LABEL, "parsePackOptions format type %{public}d, is array %{public}d",
335 formatType, isFormatArray);
336
337 char buffer[SIZE] = {0};
338 size_t res = 0;
339 if (napi_string == formatType) {
340 if (napi_get_value_string_utf8(env, tmpValue, buffer, SIZE, &res) != napi_ok) {
341 HiLog::Error(LABEL, "Parse pack option format failed");
342 return false;
343 }
344 opts->format = std::string(buffer);
345 } else if (isFormatArray) {
346 uint32_t len = 0;
347 if (napi_get_array_length(env, tmpValue, &len) != napi_ok) {
348 HiLog::Error(LABEL, "Parse pack napi_get_array_length failed");
349 return false;
350 }
351 HiLog::Debug(LABEL, "Parse pack array_length=%{public}u", len);
352 for (size_t i = 0; i < len; i++) {
353 napi_value item;
354 napi_get_element(env, tmpValue, i, &item);
355 if (napi_get_value_string_utf8(env, item, buffer, SIZE, &res) != napi_ok) {
356 HiLog::Error(LABEL, "Parse format in item failed %{public}zu", i);
357 continue;
358 }
359 opts->format = std::string(buffer);
360 HiLog::Debug(LABEL, "format is %{public}s.", opts->format.c_str());
361 }
362 } else {
363 HiLog::Error(LABEL, "Invalid pack option format type");
364 return false;
365 }
366 HiLog::Debug(LABEL, "parsePackOptions format:[%{public}s]", opts->format.c_str());
367
368 if (!GET_UINT32_BY_NAME(root, "quality", tmpNumber)) {
369 HiLog::Error(LABEL, "No quality in pack option");
370 return false;
371 }
372 if (tmpNumber > SIZE) {
373 HiLog::Error(LABEL, "Invalid quality");
374 opts->quality = BYTE_FULL;
375 } else {
376 opts->quality = static_cast<uint8_t>(tmpNumber & 0xff);
377 }
378 return true;
379 }
380
ParserPackingArgumentType(napi_env env,napi_value argv)381 static int32_t ParserPackingArgumentType(napi_env env, napi_value argv)
382 {
383 napi_value constructor = nullptr;
384 napi_value global = nullptr;
385 bool isInstance = false;
386 napi_status ret = napi_invalid_arg;
387
388 napi_get_global(env, &global);
389
390 ret = napi_get_named_property(env, global, "ImageSource", &constructor);
391 if (ret != napi_ok) {
392 HiLog::Error(LABEL, "Get ImageSourceNapi property failed!");
393 }
394
395 ret = napi_instanceof(env, argv, constructor, &isInstance);
396 if (ret == napi_ok && isInstance) {
397 HiLog::Debug(LABEL, "This is ImageSourceNapi type!");
398 return TYPE_IMAGE_SOURCE;
399 }
400
401 ret = napi_get_named_property(env, global, "PixelMap", &constructor);
402 if (ret != napi_ok) {
403 HiLog::Error(LABEL, "Get PixelMapNapi property failed!");
404 }
405
406 ret = napi_instanceof(env, argv, constructor, &isInstance);
407 if (ret == napi_ok && isInstance) {
408 HiLog::Debug(LABEL, "This is PixelMapNapi type!");
409 return TYPE_PIXEL_MAP;
410 }
411
412 HiLog::Error(LABEL, "Inalued type!");
413 return TYPE_IMAGE_SOURCE;
414 }
415
GetImageSourceFromNapi(napi_env env,napi_value value)416 static std::shared_ptr<ImageSource> GetImageSourceFromNapi(napi_env env, napi_value value)
417 {
418 if (env == nullptr || value == nullptr) {
419 HiLog::Error(LABEL, "GetImageSourceFromNapi input is null");
420 }
421 std::unique_ptr<ImageSourceNapi> imageSourceNapi = std::make_unique<ImageSourceNapi>();
422 napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&imageSourceNapi));
423 if (!IMG_IS_OK(status)) {
424 HiLog::Error(LABEL, "GetImageSourceFromNapi napi unwrap failed");
425 return nullptr;
426 }
427 if (imageSourceNapi == nullptr) {
428 HiLog::Error(LABEL, "GetImageSourceFromNapi imageSourceNapi is nullptr");
429 return nullptr;
430 }
431 return imageSourceNapi.release()->nativeImgSrc;
432 }
433
ParserPackingArguments(napi_env env,napi_value * argv,size_t argc,ImagePackerAsyncContext * context)434 static void ParserPackingArguments(napi_env env,
435 napi_value* argv, size_t argc, ImagePackerAsyncContext* context)
436 {
437 int32_t refCount = 1;
438 if (argc < PARAM1 || argc > PARAM3) {
439 BuildMsgOnError(env, context, (argc < PARAM1 || argc > PARAM3), "Arguments Count error");
440 }
441 context->packType = ParserPackingArgumentType(env, argv[PARAM0]);
442 if (context->packType == TYPE_IMAGE_SOURCE) {
443 context->rImageSource = GetImageSourceFromNapi(env, argv[PARAM0]);
444 BuildMsgOnError(env, context, context->rImageSource != nullptr, "ImageSource mismatch");
445 } else {
446 context->rPixelMap = PixelMapNapi::GetPixelMap(env, argv[PARAM0]);
447 BuildMsgOnError(env, context, context->rPixelMap != nullptr, "PixelMap mismatch");
448 }
449 if (argc > PARAM1 && ImageNapiUtils::getType(env, argv[PARAM1]) == napi_object) {
450 BuildMsgOnError(env, context,
451 parsePackOptions(env, argv[PARAM1], &(context->packOption)), "PackOptions mismatch");
452 context->resultBufferSize = parseBufferSize(env, argv[PARAM1]);
453 }
454 if (argc > PARAM2 && ImageNapiUtils::getType(env, argv[PARAM2]) == napi_function) {
455 napi_create_reference(env, argv[PARAM2], refCount, &(context->callbackRef));
456 }
457 }
458
Packing(napi_env env,napi_callback_info info)459 napi_value ImagePackerNapi::Packing(napi_env env, napi_callback_info info)
460 {
461 StartTrace(HITRACE_TAG_ZIMAGE, "Packing");
462 napi_status status;
463 napi_value result = nullptr;
464 size_t argc = ARGS_THREE;
465 napi_value argv[ARGS_THREE] = {0};
466 napi_value thisVar = nullptr;
467
468 napi_get_undefined(env, &result);
469
470 IMG_JS_ARGS(env, info, status, argc, argv, thisVar);
471 NAPI_ASSERT(env, IMG_IS_OK(status), "fail to napi_get_cb_info");
472
473 std::unique_ptr<ImagePackerAsyncContext> asyncContext = std::make_unique<ImagePackerAsyncContext>();
474 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
475 NAPI_ASSERT(env, IMG_IS_READY(status, asyncContext->constructor_), "fail to unwrap constructor_");
476
477 asyncContext->rImagePacker = std::move(asyncContext->constructor_->nativeImgPck);
478 ParserPackingArguments(env, argv, argc, asyncContext.get());
479 if (asyncContext->callbackRef == nullptr) {
480 napi_create_promise(env, &(asyncContext->deferred), &result);
481 }
482
483 ImageNapiUtils::HicheckerReport();
484
485 if (asyncContext->errorMsg != nullptr) {
486 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "PackingError",
487 [](napi_env env, void *data) {}, PackingErrorComplete, asyncContext, asyncContext->work);
488 } else {
489 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Packing",
490 PackingExec, PackingComplete, asyncContext, asyncContext->work);
491 }
492
493 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
494 nullptr, HiLog::Error(LABEL, "fail to create async work"));
495 FinishTrace(HITRACE_TAG_ZIMAGE);
496 return result;
497 }
498
GetSupportedFormats(napi_env env,napi_callback_info info)499 napi_value ImagePackerNapi::GetSupportedFormats(napi_env env, napi_callback_info info)
500 {
501 napi_value result = nullptr;
502 napi_get_undefined(env, &result);
503
504 napi_status status;
505 napi_value thisVar = nullptr;
506 size_t argCount = 0;
507
508 IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
509
510 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
511
512 std::unique_ptr<ImagePackerAsyncContext> context = std::make_unique<ImagePackerAsyncContext>();
513 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
514
515 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
516 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
517 std::set<std::string> formats;
518 uint32_t ret = context->constructor_->nativeImgPck->GetSupportedFormats(formats);
519
520 IMG_NAPI_CHECK_RET_D((ret == SUCCESS),
521 nullptr, HiLog::Error(LABEL, "fail to get supported formats"));
522
523 napi_create_array(env, &result);
524 size_t i = 0;
525 for (const std::string& formatStr: formats) {
526 napi_value format = nullptr;
527 napi_create_string_latin1(env, formatStr.c_str(), formatStr.length(), &format);
528 napi_set_element(env, result, i, format);
529 i++;
530 }
531 return result;
532 }
533
ReleaseComplete(napi_env env,napi_status status,void * data)534 static void ReleaseComplete(napi_env env, napi_status status, void *data)
535 {
536 napi_value result = nullptr;
537 napi_get_undefined(env, &result);
538
539 auto context = static_cast<ImagePackerAsyncContext*>(data);
540 if (context != nullptr && context->constructor_ != nullptr) {
541 delete context->constructor_;
542 context->constructor_ = nullptr;
543 }
544 CommonCallbackRoutine(env, context, result);
545 }
546
Release(napi_env env,napi_callback_info info)547 napi_value ImagePackerNapi::Release(napi_env env, napi_callback_info info)
548 {
549 StartTrace(HITRACE_TAG_ZIMAGE, "Release");
550 napi_value result = nullptr;
551 napi_get_undefined(env, &result);
552
553 int32_t refCount = 1;
554 napi_status status;
555 napi_value thisVar = nullptr;
556 napi_value argValue[NUM_1] = {0};
557 size_t argCount = 1;
558
559 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
560 HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
561 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
562
563 std::unique_ptr<ImagePackerAsyncContext> context = std::make_unique<ImagePackerAsyncContext>();
564 status = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
565
566 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_), result,
567 HiLog::Error(LABEL, "fail to unwrap context"));
568 HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
569 if (argCount == 1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
570 napi_create_reference(env, argValue[NUM_0], refCount, &context->callbackRef);
571 }
572
573 if (context->callbackRef == nullptr) {
574 napi_create_promise(env, &(context->deferred), &result);
575 }
576
577 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Release",
578 [](napi_env env, void *data) {}, ReleaseComplete, context, context->work);
579 FinishTrace(HITRACE_TAG_ZIMAGE);
580 return result;
581 }
release()582 void ImagePackerNapi::release()
583 {
584 if (!isRelease) {
585 nativeImgPck = nullptr;
586 isRelease = true;
587 }
588 }
589 } // namespace Media
590 } // namespace OHOS
591