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