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