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