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