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_receiver_napi.h"
17 #include <uv.h>
18 #include "media_errors.h"
19 #include "hilog/log.h"
20 #include "image_napi_utils.h"
21 #include "image_receiver_context.h"
22 #include "image_napi.h"
23 #include "image_receiver_manager.h"
24
25 using OHOS::HiviewDFX::HiLog;
26 using std::string;
27 using std::shared_ptr;
28 using std::unique_ptr;
29 using std::vector;
30 using std::make_shared;
31 using std::make_unique;
32
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ImageReceiverNapi"};
35 }
36
37 namespace OHOS {
38 namespace Media {
39 static const std::string CLASS_NAME = "ImageReceiver";
40 shared_ptr<ImageReceiver> ImageReceiverNapi::staticInstance_ = nullptr;
41 thread_local napi_ref ImageReceiverNapi::sConstructor_ = nullptr;
42 using SurfaceListener = SurfaceBufferAvaliableListener;
43
44 const int ARGS0 = 0;
45 const int ARGS1 = 1;
46 const int ARGS2 = 2;
47 const int ARGS4 = 4;
48 const int PARAM0 = 0;
49 const int PARAM1 = 1;
50 const int PARAM2 = 2;
51 const int PARAM3 = 3;
52
ImageReceiverNapi()53 ImageReceiverNapi::ImageReceiverNapi()
54 :env_(nullptr), wrapper_(nullptr)
55 {}
56
~ImageReceiverNapi()57 ImageReceiverNapi::~ImageReceiverNapi()
58 {
59 NativeRelease();
60 if (wrapper_ != nullptr) {
61 napi_delete_reference(env_, wrapper_);
62 }
63 }
64
CommonCallbackRoutine(napi_env env,Context & context,const napi_value & valueParam,bool isRelease=true)65 static void CommonCallbackRoutine(napi_env env, Context &context, const napi_value &valueParam, bool isRelease = true)
66 {
67 IMAGE_FUNCTION_IN();
68 napi_value result[2] = {0};
69 napi_value retVal;
70 napi_value callback = nullptr;
71
72 napi_get_undefined(env, &result[0]);
73 napi_get_undefined(env, &result[1]);
74
75 if (context->status == SUCCESS) {
76 result[1] = valueParam;
77 }
78
79 if (context->deferred) {
80 if (context->status == SUCCESS) {
81 napi_resolve_deferred(env, context->deferred, result[1]);
82 } else {
83 napi_reject_deferred(env, context->deferred, result[0]);
84 }
85 } else {
86 napi_create_uint32(env, context->status, &result[0]);
87 napi_get_reference_value(env, context->callbackRef, &callback);
88 napi_call_function(env, nullptr, callback, PARAM2, result, &retVal);
89 }
90
91 if (isRelease) {
92 if (context->callbackRef != nullptr) {
93 napi_delete_reference(env, context->callbackRef);
94 context->callbackRef = nullptr;
95 }
96
97 napi_delete_async_work(env, context->work);
98
99 delete context;
100 context = nullptr;
101 }
102 IMAGE_FUNCTION_OUT();
103 }
104
NativeRelease()105 void ImageReceiverNapi::NativeRelease()
106 {
107 if (imageReceiver_ != nullptr) {
108 imageReceiver_->~ImageReceiver();
109 imageReceiver_ = nullptr;
110 }
111 }
112
Init(napi_env env,napi_value exports)113 napi_value ImageReceiverNapi::Init(napi_env env, napi_value exports)
114 {
115 IMAGE_FUNCTION_IN();
116 napi_property_descriptor props[] = {
117 DECLARE_NAPI_FUNCTION("getReceivingSurfaceId", JsGetReceivingSurfaceId),
118 DECLARE_NAPI_FUNCTION("readLatestImage", JsReadLatestImage),
119 DECLARE_NAPI_FUNCTION("readNextImage", JsReadNextImage),
120 DECLARE_NAPI_FUNCTION("on", JsOn),
121 DECLARE_NAPI_FUNCTION("release", JsRelease),
122 #ifdef IMAGE_DEBUG_FLAG
123 DECLARE_NAPI_GETTER("test", JsTest),
124 #endif
125 DECLARE_NAPI_GETTER("size", JsGetSize),
126 DECLARE_NAPI_GETTER("capacity", JsGetCapacity),
127 DECLARE_NAPI_GETTER("format", JsGetFormat),
128 };
129 napi_property_descriptor static_prop[] = {
130 DECLARE_NAPI_STATIC_FUNCTION("createImageReceiver", JSCreateImageReceiver),
131 };
132
133 napi_value constructor = nullptr;
134 size_t props_count = IMG_ARRAY_SIZE(props);
135 size_t static_props_count = IMG_ARRAY_SIZE(static_prop);
136
137 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
138 napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor,
139 nullptr, props_count, props, &constructor)),
140 nullptr,
141 IMAGE_ERR("define class fail")
142 );
143
144 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
145 napi_create_reference(env, constructor, 1, &sConstructor_)),
146 nullptr,
147 IMAGE_ERR("create reference fail")
148 );
149
150 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
151 napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
152 nullptr,
153 IMAGE_ERR("set named property fail")
154 );
155 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
156 napi_define_properties(env, exports, static_props_count, static_prop)),
157 nullptr,
158 IMAGE_ERR("define properties fail")
159 );
160
161 IMAGE_DEBUG("Init success");
162
163 IMAGE_FUNCTION_OUT();
164 return exports;
165 }
166
Constructor(napi_env env,napi_callback_info info)167 napi_value ImageReceiverNapi::Constructor(napi_env env, napi_callback_info info)
168 {
169 napi_value undefineVar = nullptr;
170 napi_get_undefined(env, &undefineVar);
171
172 napi_status status;
173 napi_value thisVar = nullptr;
174
175 IMAGE_FUNCTION_IN();
176 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
177 if (status == napi_ok && thisVar != nullptr) {
178 std::unique_ptr<ImageReceiverNapi> reference = std::make_unique<ImageReceiverNapi>();
179 if (reference != nullptr) {
180 reference->env_ = env;
181 reference->imageReceiver_ = staticInstance_;
182 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(reference.get()),
183 ImageReceiverNapi::Destructor, nullptr, &(reference->wrapper_));
184 if (status == napi_ok) {
185 IMAGE_FUNCTION_OUT();
186 reference.release();
187 return thisVar;
188 } else {
189 IMAGE_ERR("Failure wrapping js to native napi");
190 }
191 }
192 }
193
194 return undefineVar;
195 }
196
Destructor(napi_env env,void * nativeObject,void * finalize)197 void ImageReceiverNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
198 {
199 ImageReceiverNapi *pImageReceiverNapi = reinterpret_cast<ImageReceiverNapi*>(nativeObject);
200
201 if (IMG_NOT_NULL(pImageReceiverNapi)) {
202 pImageReceiverNapi->~ImageReceiverNapi();
203 }
204 }
205
JSCreateImageReceiver(napi_env env,napi_callback_info info)206 napi_value ImageReceiverNapi::JSCreateImageReceiver(napi_env env, napi_callback_info info)
207 {
208 napi_status status;
209 napi_value constructor = nullptr, result = nullptr, thisVar = nullptr;
210 size_t argc = ARGS4;
211 napi_value argv[ARGS4] = {0};
212 int32_t args[ARGS4] = {0};
213
214 IMAGE_FUNCTION_IN();
215 napi_get_undefined(env, &result);
216
217 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
218 if (status != napi_ok) {
219 IMAGE_ERR("fail to napi_get_cb_info %{public}d", status);
220 return result;
221 }
222
223 if (argc != ARGS4) {
224 IMAGE_ERR("Invailed arg counts %{public}zu", argc);
225 return result;
226 }
227
228 for (size_t i = PARAM0; i < argc; i++) {
229 napi_valuetype argvType = ImageNapiUtils::getType(env, argv[i]);
230 if (argvType != napi_number) {
231 IMAGE_ERR("Invailed arg %{public}zu type %{public}d", i, argvType);
232 return result;
233 }
234
235 status = napi_get_value_int32(env, argv[i], &(args[i]));
236 if (status != napi_ok) {
237 IMAGE_ERR("fail to get arg %{public}zu : %{public}d", i, status);
238 return result;
239 }
240 }
241
242 status = napi_get_reference_value(env, sConstructor_, &constructor);
243 if (IMG_IS_OK(status)) {
244 staticInstance_ = ImageReceiver::CreateImageReceiver(args[PARAM0], args[PARAM1], args[PARAM2], args[PARAM3]);
245 status = napi_new_instance(env, constructor, 0, nullptr, &result);
246 if (status == napi_ok) {
247 IMAGE_FUNCTION_OUT();
248 return result;
249 } else {
250 IMAGE_ERR("New instance could not be obtained");
251 }
252 }
253
254 IMAGE_ERR("Failed to get reference of constructor");
255 return result;
256 }
257
CheckArgs(ImageReceiverCommonArgs & args)258 static bool CheckArgs(ImageReceiverCommonArgs &args)
259 {
260 if (args.async != CallType::GETTER) {
261 if (args.queryArgs == nullptr) {
262 IMAGE_ERR("No query args function");
263 return false;
264 }
265 }
266
267 if (args.async != CallType::ASYNC || args.asyncLater) {
268 if (args.nonAsyncBack == nullptr) {
269 IMAGE_ERR("No non async back function");
270 return false;
271 }
272 }
273 return true;
274 }
275
PrepareOneArg(ImageReceiverCommonArgs & args,struct ImageReceiverInnerContext & ic)276 static bool PrepareOneArg(ImageReceiverCommonArgs &args, struct ImageReceiverInnerContext &ic)
277 {
278 if (ic.argc == ARGS1) {
279 auto argType = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
280 if (argType == napi_function) {
281 napi_create_reference(args.env, ic.argv[PARAM0], ic.refCount, &(ic.context->callbackRef));
282 } else {
283 IMAGE_ERR("Unsupport arg 0 type: %{public}d", argType);
284 return false;
285 }
286 }
287
288 if (ic.context->callbackRef == nullptr) {
289 napi_create_promise(args.env, &(ic.context->deferred), &(ic.result));
290 } else {
291 napi_get_undefined(args.env, &ic.result);
292 }
293 return true;
294 }
295
JSCommonProcess(ImageReceiverCommonArgs & args)296 napi_value ImageReceiverNapi::JSCommonProcess(ImageReceiverCommonArgs &args)
297 {
298 IMAGE_FUNCTION_IN();
299 struct ImageReceiverInnerContext ic;
300 ic.argc = args.argc;
301 ic.argv.resize(ic.argc);
302 napi_get_undefined(args.env, &ic.result);
303
304 IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);
305
306 IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);
307
308 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, IMAGE_ERR("fail to napi_get_cb_info"));
309
310 if (args.async != CallType::STATIC) {
311 ic.context = std::make_unique<ImageReceiverAsyncContext>();
312 ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));
313
314 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
315 ic.result, IMAGE_ERR("fail to unwrap context"));
316
317 ic.context->receiver_ = ic.context->constructor_->imageReceiver_;
318
319 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->receiver_),
320 ic.result, IMAGE_ERR("empty native receiver"));
321 }
322 if (args.async != CallType::GETTER) {
323 if (!args.queryArgs(args, ic)) {
324 return ic.result;
325 }
326 }
327
328 if (args.async == CallType::ASYNC) {
329 if (args.asyncLater) {
330 args.nonAsyncBack(args, ic);
331 } else {
332 napi_value _resource = nullptr;
333 napi_create_string_utf8((args.env), (args.name.c_str()), NAPI_AUTO_LENGTH, &_resource);
334 (ic.status) = napi_create_async_work(args.env, nullptr, _resource,
335 ([](napi_env env, void *data) {}),
336 (reinterpret_cast<napi_async_complete_callback>(args.callBack)),
337 static_cast<void *>((ic.context).get()), &(ic.context->work));
338 napi_queue_async_work((args.env), (ic.context->work));
339 ic.context.release();
340 }
341 } else {
342 args.nonAsyncBack(args, ic);
343 }
344
345 IMAGE_FUNCTION_OUT();
346 return ic.result;
347 }
348
BuildJsSize(napi_env env,int32_t width,int32_t height)349 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
350 {
351 napi_value result = nullptr, sizeWith = nullptr, sizeHeight = nullptr;
352
353 napi_create_object(env, &result);
354
355 napi_create_int32(env, width, &sizeWith);
356 napi_set_named_property(env, result, "width", sizeWith);
357
358 napi_create_int32(env, height, &sizeHeight);
359 napi_set_named_property(env, result, "height", sizeHeight);
360 return result;
361 }
362
JsGetSize(napi_env env,napi_callback_info info)363 napi_value ImageReceiverNapi::JsGetSize(napi_env env, napi_callback_info info)
364 {
365 IMAGE_FUNCTION_IN();
366 ImageReceiverCommonArgs args = {
367 .env = env, .info = info,
368 .async = CallType::GETTER,
369 };
370 args.argc = ARGS0;
371
372 args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
373 napi_get_undefined(args.env, &(ic.result));
374 auto native = ic.context->constructor_->imageReceiver_;
375 if (native == nullptr) {
376 IMAGE_ERR("Native instance is nullptr");
377 return false;
378 }
379
380 if (native->iraContext_ == nullptr) {
381 IMAGE_ERR("Image receiver context is nullptr");
382 return false;
383 }
384 ic.result = BuildJsSize(args.env,
385 native->iraContext_->GetWidth(),
386 native->iraContext_->GetHeight());
387 return true;
388 };
389
390 return JSCommonProcess(args);
391 }
392
JsGetCapacity(napi_env env,napi_callback_info info)393 napi_value ImageReceiverNapi::JsGetCapacity(napi_env env, napi_callback_info info)
394 {
395 IMAGE_FUNCTION_IN();
396 ImageReceiverCommonArgs args = {
397 .env = env, .info = info,
398 .async = CallType::GETTER,
399 };
400 args.argc = ARGS0;
401
402 args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
403 napi_get_undefined(args.env, &(ic.result));
404 auto native = ic.context->constructor_->imageReceiver_;
405 if (native == nullptr) {
406 IMAGE_ERR("Native instance is nullptr");
407 return false;
408 }
409
410 if (native->iraContext_ == nullptr) {
411 IMAGE_ERR("Image receiver context is nullptr");
412 return false;
413 }
414 napi_create_int32(args.env, native->iraContext_->GetCapicity(), &(ic.result));
415 return true;
416 };
417
418 return JSCommonProcess(args);
419 }
420
JsGetFormat(napi_env env,napi_callback_info info)421 napi_value ImageReceiverNapi::JsGetFormat(napi_env env, napi_callback_info info)
422 {
423 IMAGE_FUNCTION_IN();
424 ImageReceiverCommonArgs args = {
425 .env = env, .info = info,
426 .async = CallType::GETTER,
427 };
428 args.argc = ARGS0;
429
430 args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
431 napi_get_undefined(args.env, &(ic.result));
432 auto native = ic.context->constructor_->imageReceiver_;
433 if (native == nullptr) {
434 IMAGE_ERR("Native instance is nullptr");
435 return false;
436 }
437
438 if (native->iraContext_ == nullptr) {
439 IMAGE_ERR("Image receiver context is nullptr");
440 return false;
441 }
442 napi_create_int32(args.env, native->iraContext_->GetFormat(), &(ic.result));
443 return true;
444 };
445
446 return JSCommonProcess(args);
447 }
448
449 #ifdef IMAGE_DEBUG_FLAG
TestRequestBuffer(OHOS::sptr<OHOS::Surface> & receiverSurface,OHOS::BufferRequestConfig requestConfig,OHOS::BufferFlushConfig flushConfig)450 static void TestRequestBuffer(OHOS::sptr<OHOS::Surface> &receiverSurface,
451 OHOS::BufferRequestConfig requestConfig,
452 OHOS::BufferFlushConfig flushConfig)
453 {
454 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
455 int32_t releaseFence;
456 requestConfig.width = receiverSurface->GetDefaultWidth();
457 requestConfig.height = receiverSurface->GetDefaultHeight();
458 receiverSurface->RequestBuffer(buffer, releaseFence, requestConfig);
459 IMAGE_ERR("RequestBuffer");
460 int32_t *p = (int32_t *)buffer->GetVirAddr();
461 IMAGE_ERR("RequestBuffer %{public}p", p);
462 if (p != nullptr) {
463 for (int32_t i = 0; i < requestConfig.width * requestConfig.height; i++) {
464 p[i] = i;
465 }
466 }
467 receiverSurface->FlushBuffer(buffer, -1, flushConfig);
468 IMAGE_ERR("FlushBuffer");
469 }
470
DoTest(std::shared_ptr<ImageReceiver> imageReceiver)471 static void DoTest(std::shared_ptr<ImageReceiver> imageReceiver)
472 {
473 OHOS::BufferRequestConfig requestConfig = {
474 .width = 0x100,
475 .height = 0x100,
476 .strideAlignment = 0x8,
477 .format = PIXEL_FMT_RGBA_8888,
478 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
479 .timeout = 0,
480 };
481
482 OHOS::BufferFlushConfig flushConfig = {
483 .damage = {
484 .w = 0x100,
485 .h = 0x100,
486 },
487 };
488
489 std::string receiveKey = imageReceiver->iraContext_->GetReceiverKey();
490 IMAGE_ERR("ReceiverKey = %{public}s", receiveKey.c_str());
491 OHOS::sptr<OHOS::Surface> receiverSurface = ImageReceiver::getSurfaceById(receiveKey);
492 IMAGE_ERR("getDefaultWidth = %{public}d", receiverSurface->GetDefaultWidth());
493 IMAGE_ERR("getDefaultHeight = %{public}d", receiverSurface->GetDefaultHeight());
494 IMAGE_ERR("TestRequestBuffer 1 ...");
495 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
496 IMAGE_ERR("TestRequestBuffer 2 ...");
497 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
498 IMAGE_ERR("TestRequestBuffer 3 ...");
499 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
500 }
501
JsTest(napi_env env,napi_callback_info info)502 napi_value ImageReceiverNapi::JsTest(napi_env env, napi_callback_info info)
503 {
504 IMAGE_FUNCTION_IN();
505 ImageReceiverCommonArgs args = {
506 .env = env, .info = info,
507 .async = CallType::GETTER,
508 };
509 args.argc = ARGS0;
510
511 args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
512 ic.context->constructor_->isCallBackTest = true;
513 DoTest(ic.context->receiver_);
514 return true;
515 };
516
517 return JSCommonProcess(args);
518 }
519 #endif
520
JsGetReceivingSurfaceId(napi_env env,napi_callback_info info)521 napi_value ImageReceiverNapi::JsGetReceivingSurfaceId(napi_env env, napi_callback_info info)
522 {
523 IMAGE_FUNCTION_IN();
524 ImageReceiverCommonArgs args = {
525 .env = env, .info = info,
526 .async = CallType::ASYNC,
527 .name = "JsGetReceivingSurfaceId",
528 .callBack = nullptr,
529 .argc = ARGS1,
530 .queryArgs = PrepareOneArg,
531 };
532
533 args.callBack = [](napi_env env, napi_status status, Context context) {
534 IMAGE_LINE_IN();
535 napi_value result = nullptr;
536 napi_get_undefined(env, &result);
537
538 auto native = context->receiver_;
539 if (native == nullptr) {
540 IMAGE_ERR("Native instance is nullptr");
541 context->status = ERR_IMAGE_INIT_ABNORMAL;
542 } else if (native->iraContext_ == nullptr) {
543 IMAGE_ERR("Image receiver context is nullptr");
544 context->status = ERR_IMAGE_INIT_ABNORMAL;
545 } else {
546 napi_create_string_utf8(env, native->iraContext_->GetReceiverKey().c_str(),
547 NAPI_AUTO_LENGTH, &result);
548 context->status = SUCCESS;
549 }
550
551 IMAGE_LINE_OUT();
552 CommonCallbackRoutine(env, context, result);
553 };
554
555 return JSCommonProcess(args);
556 }
557
558 #ifdef IMAGE_DEBUG_FLAG
DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)559 static void DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)
560 {
561 if (surfaceBuffer1 == nullptr) {
562 IMAGE_ERR("surfaceBuffer1 is null");
563 return;
564 }
565
566 ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance();
567 shared_ptr<ImageReceiver> imageReceiver1 = imageReceiverManager.getImageReceiverByKeyId("1");
568 IMAGE_ERR("DoCallBackTest format %{public}d", imageReceiver1->iraContext_->GetFormat());
569
570 InitializationOptions opts;
571 opts.size.width = surfaceBuffer1->GetWidth();
572 opts.size.height = surfaceBuffer1->GetHeight();
573 opts.pixelFormat = OHOS::Media::PixelFormat::BGRA_8888;
574 opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
575 opts.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
576 opts.editable = true;
577 IMAGE_ERR("DoCallBackTest Width %{public}d", opts.size.width);
578 IMAGE_ERR("DoCallBackTest Height %{public}d", opts.size.height);
579 #ifdef SAVE_IMAGE_FLAG
580 int fd = open("/data/receiver/test.jpg", O_RDWR | O_CREAT);
581 imageReceiver1->SaveBufferAsImage(fd, surfaceBuffer1, opts);
582 #endif
583 }
584 #endif
JsReadLatestImage(napi_env env,napi_callback_info info)585 napi_value ImageReceiverNapi::JsReadLatestImage(napi_env env, napi_callback_info info)
586 {
587 IMAGE_FUNCTION_IN();
588 ImageReceiverCommonArgs args = {
589 .env = env, .info = info,
590 .async = CallType::ASYNC,
591 .name = "JsReadLatestImage",
592 .callBack = nullptr,
593 .argc = ARGS1,
594 .queryArgs = PrepareOneArg,
595 };
596
597 args.callBack = [](napi_env env, napi_status status, Context context) {
598 IMAGE_LINE_IN();
599 napi_value result = nullptr;
600 napi_get_undefined(env, &result);
601
602 auto native = context->constructor_->imageReceiver_;
603 if (native == nullptr) {
604 IMAGE_ERR("Native instance is nullptr");
605 context->status = ERR_IMAGE_INIT_ABNORMAL;
606 } else {
607 auto surfacebuffer = native->ReadLastImage();
608 #ifdef IMAGE_DEBUG_FLAG
609 if (context->constructor_->isCallBackTest) {
610 context->constructor_->isCallBackTest = false;
611 DoCallBackTest(surfacebuffer);
612 }
613 #endif
614 result = ImageNapi::Create(env, surfacebuffer, native);
615 if (result == nullptr) {
616 IMAGE_ERR("ImageNapi Create failed");
617 context->status = ERR_IMAGE_INIT_ABNORMAL;
618 napi_get_undefined(env, &result);
619 } else {
620 context->status = SUCCESS;
621 }
622 }
623
624 IMAGE_LINE_OUT();
625 CommonCallbackRoutine(env, context, result);
626 };
627
628 return JSCommonProcess(args);
629 }
630
JsReadNextImage(napi_env env,napi_callback_info info)631 napi_value ImageReceiverNapi::JsReadNextImage(napi_env env, napi_callback_info info)
632 {
633 IMAGE_FUNCTION_IN();
634 ImageReceiverCommonArgs args = {
635 .env = env, .info = info,
636 .async = CallType::ASYNC,
637 .name = "JsReadNextImage",
638 .callBack = nullptr,
639 .argc = ARGS1,
640 .queryArgs = PrepareOneArg,
641 };
642
643 args.callBack = [](napi_env env, napi_status status, Context context) {
644 IMAGE_LINE_IN();
645 napi_value result = nullptr;
646 napi_get_undefined(env, &result);
647
648 auto native = context->constructor_->imageReceiver_;
649 if (native == nullptr) {
650 IMAGE_ERR("Native instance is nullptr");
651 context->status = ERR_IMAGE_INIT_ABNORMAL;
652 } else {
653 auto surfacebuffer = native->ReadNextImage();
654 #ifdef IMAGE_DEBUG_FLAG
655 if (context->constructor_->isCallBackTest) {
656 context->constructor_->isCallBackTest = false;
657 DoCallBackTest(surfacebuffer);
658 }
659 #endif
660 result = ImageNapi::Create(env, surfacebuffer, native);
661 if (result == nullptr) {
662 IMAGE_ERR("ImageNapi Create failed");
663 context->status = ERR_IMAGE_INIT_ABNORMAL;
664 napi_get_undefined(env, &result);
665 } else {
666 context->status = SUCCESS;
667 }
668 }
669
670 IMAGE_LINE_OUT();
671 CommonCallbackRoutine(env, context, result);
672 };
673
674 return JSCommonProcess(args);
675 }
676
JsOnQueryArgs(ImageReceiverCommonArgs & args,ImageReceiverInnerContext & ic)677 static bool JsOnQueryArgs(ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic)
678 {
679 if (ic.argc == ARGS2) {
680 auto argType0 = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
681 auto argType1 = ImageNapiUtils::getType(args.env, ic.argv[PARAM1]);
682 if (argType0 == napi_string && argType1 == napi_function) {
683 if (!ImageNapiUtils::GetUtf8String(args.env, ic.argv[PARAM0], ic.onType)) {
684 IMAGE_ERR("Could not get On type string");
685 return false;
686 }
687 napi_create_reference(args.env, ic.argv[PARAM1], ic.refCount, &(ic.context->callbackRef));
688 } else {
689 IMAGE_ERR("Unsupport args type: %{public}d %{public}d", argType0, argType1);
690 return false;
691 }
692 } else {
693 IMAGE_ERR("Invailed argc: %{public}zu", ic.argc);
694 return false;
695 }
696
697 napi_get_undefined(args.env, &ic.result);
698 return true;
699 }
700
DoCallBack(shared_ptr<ImageReceiverAsyncContext> context,string name,CompleteCallback callBack)701 void ImageReceiverNapi::DoCallBack(shared_ptr<ImageReceiverAsyncContext> context,
702 string name, CompleteCallback callBack)
703 {
704 IMAGE_FUNCTION_IN();
705 if (context == nullptr) {
706 IMAGE_ERR("gContext is empty");
707 return;
708 }
709
710 if (context->env == nullptr) {
711 IMAGE_ERR("env is empty");
712 return;
713 }
714
715 uv_loop_s *loop = nullptr;
716 napi_get_uv_event_loop(context->env, &loop);
717 if (loop == nullptr) {
718 IMAGE_ERR("napi_get_uv_event_loop failed");
719 return;
720 }
721
722 unique_ptr<uv_work_t> work = make_unique<uv_work_t>();
723 if (work == nullptr) {
724 IMAGE_ERR("DoCallBack: No memory");
725 return;
726 }
727
728 work->data = reinterpret_cast<void *>(context.get());
729 int ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
730 IMAGE_LINE_IN();
731 Context context = reinterpret_cast<Context>(work->data);
732 if (context == nullptr) {
733 IMAGE_ERR("contex is empty");
734 } else {
735 napi_value result[PARAM2] = {0};
736 napi_value retVal;
737 napi_value callback = nullptr;
738 if (context->env != nullptr && context->callbackRef != nullptr) {
739 napi_create_uint32(context->env, SUCCESS, &result[0]);
740 napi_get_undefined(context->env, &result[1]);
741 napi_get_reference_value(context->env, context->callbackRef, &callback);
742 if (callback != nullptr) {
743 napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
744 } else {
745 IMAGE_ERR("napi_get_reference_value callback is empty");
746 }
747 } else {
748 IMAGE_ERR("env or callbackRef is empty");
749 }
750 }
751 if (work != nullptr) {
752 delete work;
753 }
754 IMAGE_LINE_OUT();
755 });
756
757 if (ret != 0) {
758 IMAGE_ERR("Failed to execute DoCallBack work queue");
759 } else {
760 work.release();
761 }
762 IMAGE_FUNCTION_OUT();
763 }
764
JsOn(napi_env env,napi_callback_info info)765 napi_value ImageReceiverNapi::JsOn(napi_env env, napi_callback_info info)
766 {
767 IMAGE_FUNCTION_IN();
768 ImageReceiverCommonArgs args = {
769 .env = env, .info = info,
770 .async = CallType::ASYNC,
771 .name = "JsOn",
772 };
773 args.argc = ARGS2;
774 args.asyncLater = true;
775 args.queryArgs = JsOnQueryArgs;
776 args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
777 IMAGE_LINE_IN();
778 napi_get_undefined(args.env, &(ic.result));
779
780 auto native = ic.context->constructor_->imageReceiver_;
781 if (native == nullptr) {
782 IMAGE_ERR("Native instance is nullptr");
783 ic.context->status = ERR_IMAGE_INIT_ABNORMAL;
784 return false;
785 }
786 shared_ptr<ImageReceiverAvaliableListener> listener = make_shared<ImageReceiverAvaliableListener>();
787 listener->context = std::move(ic.context);
788 listener->context->env = args.env;
789 listener->name = args.name;
790
791 IMAGE_ERR("listener is %{public}p", listener.get());
792
793 native->RegisterBufferAvaliableListener((std::shared_ptr<SurfaceBufferAvaliableListener> &)listener);
794
795 IMAGE_LINE_OUT();
796 return true;
797 };
798
799 return JSCommonProcess(args);
800 }
801
JsRelease(napi_env env,napi_callback_info info)802 napi_value ImageReceiverNapi::JsRelease(napi_env env, napi_callback_info info)
803 {
804 IMAGE_FUNCTION_IN();
805 ImageReceiverCommonArgs args = {
806 .env = env, .info = info,
807 .async = CallType::ASYNC,
808 .name = "JsRelease",
809 .callBack = nullptr,
810 .argc = ARGS1,
811 .queryArgs = PrepareOneArg,
812 };
813
814 args.callBack = [](napi_env env, napi_status status, Context context) {
815 IMAGE_LINE_IN();
816 napi_value result = nullptr;
817 napi_get_undefined(env, &result);
818
819 context->constructor_->NativeRelease();
820 context->status = SUCCESS;
821
822 IMAGE_LINE_OUT();
823 CommonCallbackRoutine(env, context, result);
824 };
825
826 return JSCommonProcess(args);
827 }
828 } // namespace Media
829 } // namespace OHOS
830