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