1 /*
2 * Copyright (C) 2022 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_napi.h"
17
18 #include "napi/native_node_api.h"
19 #include "hilog/log.h"
20 #include "media_errors.h"
21 #include "image_format.h"
22 #include "image_napi_utils.h"
23
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ImageNapi"};
26 constexpr int NUM0 = 0;
27 constexpr int NUM1 = 1;
28 constexpr int NUM2 = 2;
29 const std::string MY_NAME = "ImageNapi";
30 }
31
32 namespace OHOS {
33 namespace Media {
34 using OHOS::HiviewDFX::HiLog;
35 struct ImageAsyncContext {
36 napi_env env = nullptr;
37 napi_async_work work = nullptr;
38 napi_deferred deferred = nullptr;
39 napi_ref callbackRef = nullptr;
40 napi_ref thisRef = nullptr;
41 ImageNapi *napi = nullptr;
42 uint32_t status;
43 int32_t componentType;
44 NativeImage* image = nullptr;
45 NativeComponent* component = nullptr;
46 bool isTestContext = false;
47 };
48 ImageHolderManager<NativeImage> ImageNapi::sNativeImageHolder_;
49 thread_local napi_ref ImageNapi::sConstructor_ = nullptr;
50
ImageNapi()51 ImageNapi::ImageNapi()
52 {}
53
~ImageNapi()54 ImageNapi::~ImageNapi()
55 {
56 NativeRelease();
57 }
58
NativeRelease()59 void ImageNapi::NativeRelease()
60 {
61 if (native_ != nullptr) {
62 native_->release();
63 native_ = nullptr;
64 }
65 }
66
Init(napi_env env,napi_value exports)67 napi_value ImageNapi::Init(napi_env env, napi_value exports)
68 {
69 IMAGE_FUNCTION_IN();
70 napi_property_descriptor props[] = {
71 DECLARE_NAPI_GETTER("clipRect", JSGetClipRect),
72 DECLARE_NAPI_GETTER("size", JsGetSize),
73 DECLARE_NAPI_GETTER("format", JsGetFormat),
74 DECLARE_NAPI_FUNCTION("getComponent", JsGetComponent),
75 DECLARE_NAPI_FUNCTION("release", JsRelease),
76 };
77 size_t size = IMG_ARRAY_SIZE(props);
78 napi_value thisVar = nullptr;
79 auto name = MY_NAME.c_str();
80 if (napi_define_class(env, name, SIZE_MAX, Constructor, nullptr, size, props, &thisVar) != napi_ok) {
81 IMAGE_ERR("Define class failed");
82 return exports;
83 }
84
85 if (sConstructor_ != nullptr) {
86 napi_delete_reference(env, sConstructor_);
87 sConstructor_ = nullptr;
88 }
89
90 if (napi_create_reference(env, thisVar, NUM1, &sConstructor_) != napi_ok) {
91 IMAGE_ERR("Create reference failed");
92 return exports;
93 }
94
95 if (napi_set_named_property(env, exports, name, thisVar) != napi_ok) {
96 IMAGE_ERR("Define class failed");
97 return exports;
98 }
99
100 IMAGE_DEBUG("Init success");
101 return exports;
102 }
103
104
GetNativeImage(napi_env env,napi_value image)105 std::shared_ptr<NativeImage> ImageNapi::GetNativeImage(napi_env env, napi_value image)
106 {
107 ImageNapi* napi = nullptr;
108
109 napi_status status = napi_unwrap(env, image, reinterpret_cast<void**>(&napi));
110 if (!IMG_IS_OK(status) || napi == nullptr) {
111 IMAGE_ERR("GetImage napi unwrap failed");
112 return nullptr;
113 }
114 return napi->native_;
115 }
116
Constructor(napi_env env,napi_callback_info info)117 napi_value ImageNapi::Constructor(napi_env env, napi_callback_info info)
118 {
119 napi_status status;
120 napi_value thisVar = nullptr;
121 napi_value undefineVar;
122 size_t argc = NUM1;
123 napi_value argv[NUM1];
124
125 IMAGE_FUNCTION_IN();
126 napi_get_undefined(env, &undefineVar);
127 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
128 if (status != napi_ok || thisVar == nullptr || argc != NUM1) {
129 IMAGE_ERR("Constructor Failed to napi_get_cb_info");
130 return undefineVar;
131 }
132 std::string id;
133 if (!ImageNapiUtils::GetUtf8String(env, argv[NUM0], id) || (id.size() == NUM0)) {
134 IMAGE_ERR("Failed to parse native image id");
135 return undefineVar;
136 }
137 std::unique_ptr<ImageNapi> napi = std::make_unique<ImageNapi>();
138 napi->native_ = sNativeImageHolder_.get(id);
139 napi->isTestImage_ = false;
140 if (napi->native_ == nullptr) {
141 if (MY_NAME.compare(id.c_str()) == 0) {
142 napi->isTestImage_ = true;
143 } else {
144 IMAGE_ERR("Failed to get native image");
145 return undefineVar;
146 }
147 }
148 status = napi_wrap(env, thisVar,
149 reinterpret_cast<void *>(napi.get()), ImageNapi::Destructor, nullptr, nullptr);
150 if (status != napi_ok) {
151 IMAGE_ERR("Failure wrapping js to native napi");
152 return undefineVar;
153 }
154
155 napi.release();
156 IMAGE_FUNCTION_OUT();
157 return thisVar;
158 }
159
Destructor(napi_env env,void * nativeObject,void * finalize)160 void ImageNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
161 {
162 if (nativeObject != nullptr) {
163 delete reinterpret_cast<ImageNapi *>(nativeObject);
164 }
165 }
166
Create(napi_env env)167 napi_value ImageNapi::Create(napi_env env)
168 {
169 napi_value constructor = nullptr;
170 napi_value result = nullptr;
171 napi_value argv[NUM1];
172
173 IMAGE_FUNCTION_IN();
174 if (env == nullptr) {
175 IMAGE_ERR("Input args is invalid");
176 return nullptr;
177 }
178 if (napi_get_reference_value(env, sConstructor_, &constructor) == napi_ok && constructor != nullptr) {
179 if (napi_create_string_utf8(env, MY_NAME.c_str(), NAPI_AUTO_LENGTH, &(argv[NUM0])) != napi_ok) {
180 IMAGE_ERR("Create native image id Failed");
181 }
182 if (napi_new_instance(env, constructor, NUM1, argv, &result) != napi_ok) {
183 IMAGE_ERR("New instance could not be obtained");
184 }
185 }
186 IMAGE_FUNCTION_OUT();
187 return result;
188 }
Create(napi_env env,std::shared_ptr<NativeImage> nativeImage)189 napi_value ImageNapi::Create(napi_env env, std::shared_ptr<NativeImage> nativeImage)
190 {
191 napi_value constructor = nullptr;
192 napi_value result = nullptr;
193 napi_value argv[NUM1];
194
195 IMAGE_FUNCTION_IN();
196 if (env == nullptr || nativeImage == nullptr) {
197 IMAGE_ERR("Input args is invalid %{public}p vs %{public}p", env, nativeImage.get());
198 return nullptr;
199 }
200 if (napi_get_reference_value(env, sConstructor_, &constructor) == napi_ok && constructor != nullptr) {
201 auto id = sNativeImageHolder_.save(nativeImage);
202 if (napi_create_string_utf8(env, id.c_str(), NAPI_AUTO_LENGTH, &(argv[NUM0])) != napi_ok) {
203 IMAGE_ERR("Create native image id Failed");
204 }
205 if (napi_new_instance(env, constructor, NUM1, argv, &result) != napi_ok) {
206 IMAGE_ERR("New instance could not be obtained");
207 }
208 }
209 IMAGE_FUNCTION_OUT();
210 return result;
211 }
JsCheckObjectType(napi_env env,napi_value value,napi_valuetype type)212 static inline bool JsCheckObjectType(napi_env env, napi_value value, napi_valuetype type)
213 {
214 return (ImageNapiUtils::getType(env, value) == type);
215 }
216
JsGetCallbackFunc(napi_env env,napi_value value,napi_ref * result)217 static inline bool JsGetCallbackFunc(napi_env env, napi_value value, napi_ref *result)
218 {
219 if (JsCheckObjectType(env, value, napi_function)) {
220 napi_create_reference(env, value, NUM1, result);
221 return true;
222 }
223 return false;
224 }
225
JsGetInt32Args(napi_env env,napi_value value,int * result)226 static inline bool JsGetInt32Args(napi_env env, napi_value value, int *result)
227 {
228 if (JsCheckObjectType(env, value, napi_number)) {
229 napi_get_value_int32(env, value, result);
230 return true;
231 }
232 return false;
233 }
234 using AsyncExecCallback = void (*)(napi_env env, ImageAsyncContext* ctx);
235 using AsyncCompleteCallback = void (*)(napi_env env, napi_status status, ImageAsyncContext* ctx);
JsCreateWork(napi_env env,const char * name,AsyncExecCallback exec,AsyncCompleteCallback complete,ImageAsyncContext * ctx)236 static bool JsCreateWork(napi_env env, const char* name, AsyncExecCallback exec,
237 AsyncCompleteCallback complete, ImageAsyncContext* ctx)
238 {
239 napi_value resource = nullptr;
240 napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &resource);
241 napi_status status = napi_create_async_work(
242 env, nullptr, resource, reinterpret_cast<napi_async_execute_callback>(exec),
243 reinterpret_cast<napi_async_complete_callback>(complete), static_cast<void *>(ctx), &(ctx->work));
244 if (status != napi_ok) {
245 IMAGE_ERR("fail to create async work %{public}d", status);
246 return false;
247 }
248
249 if (napi_queue_async_work(env, ctx->work) != napi_ok) {
250 IMAGE_ERR("fail to queue async work");
251 return false;
252 }
253 return true;
254 }
255
GetNative()256 NativeImage* ImageNapi::GetNative()
257 {
258 if (native_ != nullptr) {
259 return native_.get();
260 }
261 return nullptr;
262 }
263
UnwrapContext(napi_env env,napi_callback_info info,size_t * argc=nullptr,napi_value * argv=nullptr)264 static std::unique_ptr<ImageAsyncContext> UnwrapContext(napi_env env, napi_callback_info info,
265 size_t* argc = nullptr, napi_value* argv = nullptr)
266 {
267 napi_value thisVar = nullptr;
268 size_t tmp = NUM0;
269
270 IMAGE_FUNCTION_IN();
271
272 if (napi_get_cb_info(env, info, (argc == nullptr)?&tmp:argc, argv, &thisVar, nullptr) != napi_ok) {
273 IMAGE_ERR("Fail to napi_get_cb_info");
274 return nullptr;
275 }
276
277 std::unique_ptr<ImageAsyncContext> ctx = std::make_unique<ImageAsyncContext>();
278 if (napi_unwrap(env, thisVar, reinterpret_cast<void**>(&ctx->napi)) != napi_ok || ctx->napi == nullptr) {
279 IMAGE_ERR("fail to unwrap constructor_");
280 return nullptr;
281 }
282 ctx->image = ctx->napi->GetNative();
283 napi_create_reference(env, thisVar, NUM1, &(ctx->thisRef));
284 return ctx;
285 }
286
ProcessPromise(napi_env env,napi_deferred deferred,napi_value * result,bool resolved)287 static inline void ProcessPromise(napi_env env, napi_deferred deferred, napi_value* result, bool resolved)
288 {
289 if (resolved) {
290 napi_resolve_deferred(env, deferred, result[NUM1]);
291 } else {
292 napi_reject_deferred(env, deferred, result[NUM0]);
293 }
294 }
ProcessCallback(napi_env env,napi_ref ref,napi_value * result)295 static inline void ProcessCallback(napi_env env, napi_ref ref, napi_value* result)
296 {
297 napi_value retVal;
298 napi_value callback;
299 napi_get_reference_value(env, ref, &callback);
300 napi_call_function(env, nullptr, callback, NUM2, result, &retVal);
301 napi_delete_reference(env, ref);
302 }
CommonCallbackRoutine(napi_env env,ImageAsyncContext * & context,const napi_value & valueParam)303 static void CommonCallbackRoutine(napi_env env, ImageAsyncContext* &context, const napi_value &valueParam)
304 {
305 IMAGE_FUNCTION_IN();
306 napi_value result[2] = {0};
307
308 if (context == nullptr) {
309 IMAGE_ERR("context is nullptr");
310 return;
311 }
312
313 if (context->status == SUCCESS) {
314 napi_create_uint32(env, context->status, &result[0]);
315 result[1] = valueParam;
316 } else {
317 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
318 "There is generic napi failure!");
319 napi_get_undefined(env, &result[1]);
320 }
321
322 if (context->deferred) {
323 ProcessPromise(env, context->deferred, result, context->status == SUCCESS);
324 } else {
325 ProcessCallback(env, context->callbackRef, result);
326 }
327
328 napi_delete_async_work(env, context->work);
329
330 delete context;
331 context = nullptr;
332 IMAGE_FUNCTION_OUT();
333 }
334
BuildIntProperty(napi_env env,const std::string & name,int32_t val,napi_value result)335 static void BuildIntProperty(napi_env env, const std::string &name,
336 int32_t val, napi_value result)
337 {
338 napi_value nVal;
339 napi_create_int32(env, val, &nVal);
340 napi_set_named_property(env, result, name.c_str(), nVal);
341 }
342
BuildJsSize(napi_env env,int32_t width,int32_t height)343 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
344 {
345 napi_value result = nullptr;
346
347 napi_create_object(env, &result);
348
349 BuildIntProperty(env, "width", width, result);
350 BuildIntProperty(env, "height", height, result);
351 return result;
352 }
353
BuildJsRegion(napi_env env,int32_t width,int32_t height,int32_t x,int32_t y)354 static napi_value BuildJsRegion(napi_env env, int32_t width,
355 int32_t height, int32_t x, int32_t y)
356 {
357 napi_value result = nullptr;
358
359 napi_create_object(env, &result);
360
361 napi_set_named_property(env, result, "size", BuildJsSize(env, width, height));
362
363 BuildIntProperty(env, "x", x, result);
364 BuildIntProperty(env, "y", y, result);
365 return result;
366 }
367
JSGetClipRect(napi_env env,napi_callback_info info)368 napi_value ImageNapi::JSGetClipRect(napi_env env, napi_callback_info info)
369 {
370 napi_value result = nullptr;
371
372 IMAGE_FUNCTION_IN();
373 napi_get_undefined(env, &result);
374 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
375 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
376 const int32_t WIDTH = 8192;
377 const int32_t HEIGHT = 8;
378 return BuildJsRegion(env, WIDTH, HEIGHT, NUM0, NUM0);
379 }
380 if (context == nullptr || context->image == nullptr) {
381 IMAGE_ERR("Image surface buffer is nullptr");
382 return result;
383 }
384
385 int32_t width = NUM0;
386 int32_t height = NUM0;
387 if (context->image->GetSize(width, height) != SUCCESS) {
388 IMAGE_ERR("Image native get size failed");
389 return result;
390 }
391 return BuildJsRegion(env, width, height, NUM0, NUM0);
392 }
393
JsGetSize(napi_env env,napi_callback_info info)394 napi_value ImageNapi::JsGetSize(napi_env env, napi_callback_info info)
395 {
396 napi_value result = nullptr;
397
398 IMAGE_FUNCTION_IN();
399 napi_get_undefined(env, &result);
400 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
401 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
402 const int32_t WIDTH = 8192;
403 const int32_t HEIGHT = 8;
404 return BuildJsSize(env, WIDTH, HEIGHT);
405 }
406 if (context == nullptr || context->image == nullptr) {
407 IMAGE_ERR("Image surface buffer is nullptr");
408 return result;
409 }
410
411 int32_t width = NUM0;
412 int32_t height = NUM0;
413 if (context->image->GetSize(width, height) != SUCCESS) {
414 IMAGE_ERR("Image native get size failed");
415 return result;
416 }
417 return BuildJsSize(env, width, height);
418 }
419
JsGetFormat(napi_env env,napi_callback_info info)420 napi_value ImageNapi::JsGetFormat(napi_env env, napi_callback_info info)
421 {
422 napi_value result = nullptr;
423
424 IMAGE_FUNCTION_IN();
425 napi_get_undefined(env, &result);
426 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
427 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
428 const int32_t FORMAT = 12;
429 napi_create_int32(env, FORMAT, &result);
430 return result;
431 }
432 if (context == nullptr || context->image == nullptr) {
433 IMAGE_ERR("Image surface buffer is nullptr");
434 return result;
435 }
436
437 int32_t format = NUM0;
438 if (context->image->GetFormat(format) != SUCCESS) {
439 IMAGE_ERR("Image native get format failed");
440 return result;
441 }
442
443 napi_create_int32(env, format, &result);
444 return result;
445 }
446
JSReleaseCallBack(napi_env env,napi_status status,ImageAsyncContext * context)447 static void JSReleaseCallBack(napi_env env, napi_status status,
448 ImageAsyncContext* context)
449 {
450 IMAGE_FUNCTION_IN();
451 napi_value result = nullptr;
452 napi_get_undefined(env, &result);
453
454 if (context == nullptr) {
455 IMAGE_ERR("context is nullptr");
456 return;
457 }
458
459 if (context->thisRef != nullptr) {
460 napi_value thisVar;
461 napi_get_reference_value(env, context->thisRef, &thisVar);
462 napi_delete_reference(env, context->thisRef);
463 if (thisVar != nullptr) {
464 ImageNapi *tmp = nullptr;
465 auto status_ = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&tmp));
466 if (status_ != napi_ok) {
467 IMAGE_ERR("NAPI remove wrap failed status %{public}d", status_);
468 }
469 }
470 }
471
472 context->status = SUCCESS;
473 IMAGE_FUNCTION_OUT();
474 CommonCallbackRoutine(env, context, result);
475 }
476
JsRelease(napi_env env,napi_callback_info info)477 napi_value ImageNapi::JsRelease(napi_env env, napi_callback_info info)
478 {
479 IMAGE_FUNCTION_IN();
480 napi_value result = nullptr;
481 size_t argc = NUM1;
482 napi_value argv[NUM1] = {0};
483
484 napi_get_undefined(env, &result);
485 auto context = UnwrapContext(env, info, &argc, argv);
486 if (context == nullptr) {
487 IMAGE_ERR("fail to unwrap constructor_");
488 return result;
489 }
490 if (argc == NUM1) {
491 if (!JsGetCallbackFunc(env, argv[NUM0], &(context->callbackRef))) {
492 IMAGE_ERR("Unsupport arg 0 type");
493 return result;
494 }
495 } else {
496 napi_create_promise(env, &(context->deferred), &result);
497 }
498
499 if (JsCreateWork(env, "JsRelease", [](napi_env env, ImageAsyncContext* data) {},
500 JSReleaseCallBack, context.get())) {
501 context.release();
502 }
503 IMAGE_FUNCTION_OUT();
504 return result;
505 }
506
CreateArrayBuffer(napi_env env,uint8_t * src,size_t srcLen,napi_value * res)507 static bool CreateArrayBuffer(napi_env env, uint8_t* src, size_t srcLen, napi_value *res)
508 {
509 if (src == nullptr || srcLen == 0) {
510 return false;
511 }
512 auto status = napi_create_external_arraybuffer(env, src, srcLen,
513 [](napi_env env, void* data, void* hint) { }, nullptr, res);
514 if (status != napi_ok) {
515 return false;
516 }
517 return true;
518 }
519
IsEqual(const int32_t & check,ImageFormat format)520 static inline bool IsEqual(const int32_t& check, ImageFormat format)
521 {
522 return (check == int32_t(format));
523 }
IsEqual(const int32_t & check,ComponentType type)524 static inline bool IsEqual(const int32_t& check, ComponentType type)
525 {
526 return (check == int32_t(type));
527 }
IsYUVComponent(const int32_t & type)528 static inline bool IsYUVComponent(const int32_t& type)
529 {
530 return (IsEqual(type, ComponentType::YUV_Y) ||
531 IsEqual(type, ComponentType::YUV_U) ||
532 IsEqual(type, ComponentType::YUV_V));
533 }
IsYUV422SPImage(int32_t format)534 static inline bool IsYUV422SPImage(int32_t format)
535 {
536 return (IsEqual(format, ImageFormat::YCBCR_422_SP) ||
537 (format == int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP)));
538 }
CheckComponentType(const int32_t & type,int32_t format)539 static inline bool CheckComponentType(const int32_t& type, int32_t format)
540 {
541 return ((IsYUV422SPImage(format) && IsYUVComponent(type)) ||
542 (!IsYUV422SPImage(format) && IsEqual(type, ComponentType::JPEG)));
543 }
544
BuildJsComponentObject(napi_env env,int32_t type,uint8_t * buffer,NativeComponent * component,napi_value * result)545 static bool BuildJsComponentObject(napi_env env, int32_t type, uint8_t* buffer,
546 NativeComponent* component, napi_value* result)
547 {
548 napi_value array;
549 if (!CreateArrayBuffer(env, buffer, component->size, &array)) {
550 return false;
551 }
552 napi_create_object(env, result);
553 napi_set_named_property(env, *result, "byteBuffer", array);
554 BuildIntProperty(env, "componentType", type, *result);
555 BuildIntProperty(env, "rowStride", component->rowStride, *result);
556 BuildIntProperty(env, "pixelStride", component->pixelStride, *result);
557 return true;
558 }
TestGetComponentCallBack(napi_env env,napi_status status,ImageAsyncContext * context)559 static void TestGetComponentCallBack(napi_env env, napi_status status, ImageAsyncContext* context)
560 {
561 if (context == nullptr) {
562 HiLog::Error(LABEL, "Invalid input context");
563 return;
564 }
565 napi_value result;
566 napi_value array;
567 void *nativePtr = nullptr;
568 if (napi_create_arraybuffer(env, NUM1, &nativePtr, &array) != napi_ok || nativePtr == nullptr) {
569 return;
570 }
571 napi_create_object(env, &result);
572 napi_set_named_property(env, result, "byteBuffer", array);
573 BuildIntProperty(env, "componentType", context->componentType, result);
574 BuildIntProperty(env, "rowStride", NUM0, result);
575 BuildIntProperty(env, "pixelStride", NUM0, result);
576 context->status = SUCCESS;
577 CommonCallbackRoutine(env, context, result);
578 }
579
JsGetComponentCallBack(napi_env env,napi_status status,ImageAsyncContext * context)580 static void JsGetComponentCallBack(napi_env env, napi_status status, ImageAsyncContext* context)
581 {
582 IMAGE_FUNCTION_IN();
583 napi_value result;
584 napi_get_undefined(env, &result);
585
586 if (context != nullptr && context->napi != nullptr && context->isTestContext) {
587 TestGetComponentCallBack(env, status, context);
588 return;
589 }
590
591 if (context == nullptr) {
592 HiLog::Error(LABEL, "Invalid input context");
593 return;
594 }
595 context->status = ERROR;
596 NativeComponent* component = context->component;
597 if (component == nullptr) {
598 HiLog::Error(LABEL, "Invalid component");
599 CommonCallbackRoutine(env, context, result);
600 return;
601 }
602
603 uint8_t *buffer = nullptr;
604 if (component->virAddr != nullptr) {
605 buffer = component->virAddr;
606 } else {
607 buffer = component->raw.data();
608 }
609
610 if (buffer == nullptr || component->size == NUM0) {
611 HiLog::Error(LABEL, "Invalid buffer");
612 CommonCallbackRoutine(env, context, result);
613 return;
614 }
615
616 if (BuildJsComponentObject(env, context->componentType, buffer, component, &result)) {
617 context->status = SUCCESS;
618 } else {
619 HiLog::Error(LABEL, "napi_create_arraybuffer failed!");
620 }
621
622 IMAGE_FUNCTION_OUT();
623 CommonCallbackRoutine(env, context, result);
624 }
JsGetComponentExec(napi_env env,ImageAsyncContext * context)625 static void JsGetComponentExec(napi_env env, ImageAsyncContext* context)
626 {
627 if (context == nullptr || context->napi == nullptr) {
628 HiLog::Error(LABEL, "Invalid input context");
629 return;
630 }
631
632 auto native = context->napi->GetNative();
633 if (native == nullptr) {
634 HiLog::Error(LABEL, "Empty native");
635 return;
636 }
637 context->component = native->GetComponent(context->componentType);
638 }
639
JsGetComponentArgs(napi_env env,size_t argc,napi_value * argv,ImageAsyncContext * context)640 static bool JsGetComponentArgs(napi_env env, size_t argc, napi_value* argv, ImageAsyncContext* context)
641 {
642 if (argv == nullptr || context == nullptr || argc < NUM1 || context->napi == nullptr) {
643 IMAGE_ERR("argv is nullptr");
644 return false;
645 }
646
647 if (!JsGetInt32Args(env, argv[NUM0], &(context->componentType))) {
648 IMAGE_ERR("Unsupport arg 0 type");
649 return false;
650 }
651
652 auto native = context->napi->GetNative();
653 if (native == nullptr && !context->isTestContext) {
654 IMAGE_ERR("native is nullptr");
655 return false;
656 }
657
658 int32_t format = NUM0;
659 if (context->isTestContext) {
660 const int32_t TEST_FORMAT = 12;
661 format = TEST_FORMAT;
662 } else {
663 native->GetFormat(format);
664 }
665
666 if (!CheckComponentType(context->componentType, format)) {
667 IMAGE_ERR("Unsupport component type 0 value: %{public}d", context->componentType);
668 return false;
669 }
670
671 if (argc == NUM2 && !JsGetCallbackFunc(env, argv[NUM1], &(context->callbackRef))) {
672 IMAGE_ERR("Unsupport arg 1 type");
673 return false;
674 }
675 return true;
676 }
677
JsGetComponent(napi_env env,napi_callback_info info)678 napi_value ImageNapi::JsGetComponent(napi_env env, napi_callback_info info)
679 {
680 IMAGE_FUNCTION_IN();
681 napi_value result = nullptr;
682 size_t argc = NUM2;
683 napi_value argv[NUM2] = {0};
684
685 napi_get_undefined(env, &result);
686 auto context = UnwrapContext(env, info, &argc, argv);
687 if (context == nullptr) {
688 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
689 "fail to unwrap constructor_ ");
690 }
691 context->isTestContext = context->napi->isTestImage_;
692 if (!JsGetComponentArgs(env, argc, argv, context.get())) {
693 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
694 "Unsupport arg type!");
695 }
696
697 if (context->callbackRef == nullptr) {
698 napi_create_promise(env, &(context->deferred), &result);
699 }
700
701 if (JsCreateWork(env, "JsGetComponent", JsGetComponentExec, JsGetComponentCallBack, context.get())) {
702 context.release();
703 }
704
705 IMAGE_FUNCTION_OUT();
706 return result;
707 }
708 } // namespace Media
709 } // namespace OHOS
710