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