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