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 "media_errors.h"
21 #include "image_log.h"
22 #include "image_napi_utils.h"
23 #include "sendable_image_napi.h"
24 #include "image_receiver_context.h"
25 #include "image_receiver_manager.h"
26
27 #undef LOG_DOMAIN
28 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
29
30 #undef LOG_TAG
31 #define LOG_TAG "SendableImageReceiverNapi"
32
33 using std::string;
34 using std::shared_ptr;
35 using std::unique_ptr;
36 using std::vector;
37 using std::make_shared;
38 using std::make_unique;
39
40 namespace OHOS {
41 namespace Media {
42 static const std::string CLASS_NAME = "ImageReceiver";
43 static const std::string DEVICE_ERRCODE = "001";
44 shared_ptr<ImageReceiver> SendableImageReceiverNapi::staticInstance_ = nullptr;
45 thread_local napi_ref SendableImageReceiverNapi::sConstructor_ = nullptr;
46 using SurfaceListener = SurfaceBufferAvaliableListener;
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> sImageFormatVec = {
65 {"CAMERA_APP_INNER", 4, ""},
66 {"JPEG", 2000, ""},
67 };
68
SendableImageReceiverNapi()69 SendableImageReceiverNapi::SendableImageReceiverNapi():env_(nullptr)
70 {}
71
~SendableImageReceiverNapi()72 SendableImageReceiverNapi::~SendableImageReceiverNapi()
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 SendableImageReceiverNapi::NativeRelease()
123 {
124 imageReceiver_ = nullptr;
125 }
126
UnRegisterReceiverListener()127 void SendableImageReceiverNapi::UnRegisterReceiverListener()
128 {
129 if (imageReceiver_ != nullptr) {
130 imageReceiver_->UnRegisterBufferAvaliableListener();
131 }
132 }
133
GetNative()134 ImageReceiver* SendableImageReceiverNapi::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 SendableImageReceiverNapi::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("release", JsRelease),
150 #ifdef IMAGE_DEBUG_FLAG
151 DECLARE_NAPI_GETTER("test", JsTest),
152 DECLARE_NAPI_GETTER("checkDeviceTest", JsCheckDeviceTest),
153 DECLARE_NAPI_GETTER("testYUV", JsTestYUV),
154 #endif
155 DECLARE_NAPI_GETTER("size", JsGetSize),
156 DECLARE_NAPI_GETTER("capacity", JsGetCapacity),
157 DECLARE_NAPI_GETTER("format", JsGetFormat),
158 };
159 napi_property_descriptor static_prop[] = {
160 DECLARE_NAPI_STATIC_FUNCTION("createImageReceiver", JSCreateImageReceiver),
161 };
162
163 napi_value constructor = nullptr;
164 size_t props_count = IMG_ARRAY_SIZE(props);
165 size_t static_props_count = IMG_ARRAY_SIZE(static_prop);
166
167 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
168 napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor,
169 nullptr, props_count, props, &constructor)),
170 nullptr,
171 IMAGE_ERR("define class fail")
172 );
173
174 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
175 napi_create_reference(env, constructor, 1, &sConstructor_)),
176 nullptr,
177 IMAGE_ERR("create reference fail")
178 );
179
180 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
181 napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
182 nullptr,
183 IMAGE_ERR("set named property fail")
184 );
185 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
186 napi_define_properties(env, exports, static_props_count, static_prop)),
187 nullptr,
188 IMAGE_ERR("define properties fail")
189 );
190
191 IMAGE_DEBUG("Init success");
192
193 IMAGE_FUNCTION_OUT();
194 return exports;
195 }
196
197 struct ImageReceiverInputArgs {
198 napi_value thisVar;
199 size_t argc;
200 napi_value argv[ARGS4];
201 int32_t args[ARGS4];
202 };
203
parseImageReceiverArgs(napi_env env,napi_callback_info info,ImageReceiverInputArgs & args,std::string & errMsg)204 static bool parseImageReceiverArgs(napi_env env, napi_callback_info info,
205 ImageReceiverInputArgs &args, std::string &errMsg)
206 {
207 napi_status status = napi_get_cb_info(env, info, &(args.argc), args.argv, &(args.thisVar), nullptr);
208 if (status != napi_ok) {
209 IMAGE_ERR("fail to napi_get_cb_info %{public}d", status);
210 errMsg = "Fail to napi_get_cb_info";
211 return false;
212 }
213
214 if (args.argc != ARGS3 && args.argc != ARGS4) {
215 errMsg = "Invalid arg counts ";
216 errMsg.append(std::to_string(args.argc));
217 return false;
218 }
219
220 return ImageNapiUtils::ParseImageCreatorReceiverArgs(env, args.argc, args.argv, args.args, errMsg);
221 }
222
Constructor(napi_env env,napi_callback_info info)223 napi_value SendableImageReceiverNapi::Constructor(napi_env env, napi_callback_info info)
224 {
225 napi_value undefineVar = nullptr;
226 napi_get_undefined(env, &undefineVar);
227
228 IMAGE_FUNCTION_IN();
229 std::string errMsg;
230 ImageReceiverInputArgs inputArgs;
231 inputArgs.argc = ARGS4;
232 if (!parseImageReceiverArgs(env, info, inputArgs, errMsg) || inputArgs.thisVar == nullptr) {
233 IMAGE_ERR("Failure. %{public}s", errMsg.c_str());
234 return undefineVar;
235 }
236 auto reference = std::make_unique<SendableImageReceiverNapi>();
237 reference->env_ = env;
238 reference->imageReceiver_ = ImageReceiver::CreateImageReceiver((inputArgs.args)[PARAM0],
239 (inputArgs.args)[PARAM1], (inputArgs.args)[PARAM2], (inputArgs.args)[PARAM3]);
240 if (reference->imageReceiver_ == nullptr) {
241 IMAGE_ERR("Create native image receiver failed");
242 return undefineVar;
243 }
244 napi_status status = napi_wrap(env, inputArgs.thisVar, reinterpret_cast<void *>(reference.get()),
245 SendableImageReceiverNapi::Destructor, nullptr, nullptr);
246 if (status == napi_ok) {
247 reference.release();
248 return inputArgs.thisVar;
249 }
250 IMAGE_ERR("Failure wrapping js to native napi");
251 return undefineVar;
252 }
253
Destructor(napi_env env,void * nativeObject,void * finalize)254 void SendableImageReceiverNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
255 {
256 if (nativeObject != nullptr) {
257 delete reinterpret_cast<SendableImageReceiverNapi*>(nativeObject);
258 nativeObject = nullptr;
259 }
260 }
261
CheckFormat(int32_t format)262 static bool CheckFormat(int32_t format)
263 {
264 return std::any_of(sImageFormatVec.begin(), sImageFormatVec.end(), [format](const auto& imageEnum) {
265 return imageEnum.numVal == format;
266 });
267 }
268
CreateImageReceiverJsObject(napi_env env,struct SendableImageReceiverCreateArgs args)269 napi_value SendableImageReceiverNapi::CreateImageReceiverJsObject(napi_env env, struct SendableImageReceiverCreateArgs args)
270 {
271 napi_status status;
272 napi_value constructor = nullptr;
273 napi_value result = nullptr;
274 ImageReceiverInputArgs inputArgs;
275 inputArgs.argc = ARGS4;
276
277 IMAGE_FUNCTION_IN();
278 if (!CheckFormat(args.format)) {
279 IMAGE_ERR("Invalid type");
280 return nullptr;
281 }
282 napi_create_int32(env, args.width, &(inputArgs.argv[PARAM0]));
283 napi_create_int32(env, args.height, &(inputArgs.argv[PARAM1]));
284 napi_create_int32(env, args.format, &(inputArgs.argv[PARAM2]));
285 napi_create_int32(env, args.capicity, &(inputArgs.argv[PARAM3]));
286 status = napi_get_reference_value(env, sConstructor_, &constructor);
287 if (status != napi_ok || constructor == nullptr) {
288 IMAGE_ERR("Failed to get reference of constructor");
289 return nullptr;
290 }
291
292 status = napi_new_instance(env, constructor, inputArgs.argc, inputArgs.argv, &result);
293 if (status != napi_ok || result == nullptr) {
294 IMAGE_ERR("New instance could not be obtained");
295 return nullptr;
296 }
297
298 IMAGE_FUNCTION_OUT();
299 return result;
300 }
301
JSCreateImageReceiver(napi_env env,napi_callback_info info)302 napi_value SendableImageReceiverNapi::JSCreateImageReceiver(napi_env env, napi_callback_info info)
303 {
304 napi_status status;
305 napi_value constructor = nullptr;
306 napi_value result = nullptr;
307 ImageReceiverInputArgs inputArgs;
308 inputArgs.argc = ARGS4;
309
310 IMAGE_FUNCTION_IN();
311 napi_get_undefined(env, &result);
312
313 std::string errMsg;
314 if (!parseImageReceiverArgs(env, info, inputArgs, errMsg)) {
315 return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, errMsg);
316 }
317
318 if (!CheckFormat(inputArgs.args[PARAM2])) {
319 return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Invalid type");
320 }
321
322 status = napi_get_reference_value(env, sConstructor_, &constructor);
323 if (IMG_IS_OK(status)) {
324 status = napi_new_instance(env, constructor, inputArgs.argc, inputArgs.argv, &result);
325 if (status == napi_ok) {
326 IMAGE_FUNCTION_OUT();
327 return result;
328 } else {
329 IMAGE_ERR("New instance could not be obtained");
330 }
331 }
332
333 IMAGE_ERR("Failed to get reference of constructor");
334 return result;
335 }
336
CheckArgs(const SendableImageReceiverCommonArgs & args)337 static bool CheckArgs(const SendableImageReceiverCommonArgs &args)
338 {
339 if (args.async != CallType::GETTER) {
340 if (args.queryArgs == nullptr) {
341 IMAGE_ERR("No query args function");
342 return false;
343 }
344 }
345
346 if (args.async != CallType::ASYNC || args.asyncLater) {
347 if (args.nonAsyncBack == nullptr) {
348 IMAGE_ERR("No non async back function");
349 return false;
350 }
351 }
352 return true;
353 }
354
PrepareOneArg(SendableImageReceiverCommonArgs & args,struct SendableImageReceiverInnerContext & ic)355 static bool PrepareOneArg(SendableImageReceiverCommonArgs &args, struct SendableImageReceiverInnerContext &ic)
356 {
357 if (ic.argc == ARGS1) {
358 auto argType = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
359 if (argType == napi_function) {
360 napi_create_reference(args.env, ic.argv[PARAM0], ic.refCount, &(ic.context->callbackRef));
361 } else {
362 IMAGE_ERR("Unsupport arg 0 type: %{public}d", argType);
363 return false;
364 }
365 }
366
367 if (ic.context->callbackRef == nullptr) {
368 napi_create_promise(args.env, &(ic.context->deferred), &(ic.result));
369 } else {
370 napi_get_undefined(args.env, &ic.result);
371 }
372 return true;
373 }
374
JSCommonProcessSendEvent(SendableImageReceiverCommonArgs & args,napi_status status,SendableImageReceiverAsyncContext * context,napi_event_priority prio)375 static void JSCommonProcessSendEvent(SendableImageReceiverCommonArgs &args, napi_status status,
376 SendableImageReceiverAsyncContext* context, napi_event_priority prio)
377 {
378 auto task = [args, status, context]() {
379 (void)args.callBack(args.env, status, context);
380 };
381 if (napi_status::napi_ok != napi_send_event(args.env, task, prio)) {
382 IMAGE_LOGE("JSCommonProcessSendEvent: failed to SendEvent!");
383 }
384 }
385
JSCommonProcess(SendableImageReceiverCommonArgs & args)386 napi_value SendableImageReceiverNapi::JSCommonProcess(SendableImageReceiverCommonArgs &args)
387 {
388 IMAGE_FUNCTION_IN();
389 struct SendableImageReceiverInnerContext ic;
390 ic.argc = args.argc;
391 ic.argv.resize(ic.argc);
392 napi_get_undefined(args.env, &ic.result);
393
394 IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);
395
396 IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);
397
398 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, IMAGE_ERR("fail to napi_get_cb_info"));
399
400 if (args.async != CallType::STATIC) {
401 ic.context = std::make_unique<SendableImageReceiverAsyncContext>();
402 if (ic.context == nullptr) {
403 return ic.result;
404 }
405 ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));
406
407 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
408 ic.result, IMAGE_ERR("fail to unwrap context"));
409
410 if (ic.context->constructor_ == nullptr) {
411 return ic.result;
412 }
413
414 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_->imageReceiver_),
415 ic.result, IMAGE_ERR("empty native receiver"));
416 }
417 if (args.async != CallType::GETTER) {
418 if (!args.queryArgs(args, ic)) {
419 return ic.result;
420 }
421 }
422
423 if (args.async == CallType::ASYNC) {
424 if (args.asyncLater) {
425 args.nonAsyncBack(args, ic);
426 } else {
427 JSCommonProcessSendEvent(args, ic.status, ic.context.get(), napi_eprio_high);
428 ic.context.release();
429 }
430 } else {
431 args.nonAsyncBack(args, ic);
432 }
433
434 IMAGE_FUNCTION_OUT();
435 return ic.result;
436 }
437
BuildJsSize(napi_env env,int32_t width,int32_t height)438 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
439 {
440 napi_value result = nullptr;
441 napi_value sizeWith = nullptr;
442 napi_value 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 SendableImageReceiverNapi::JsGetSize(napi_env env, napi_callback_info info)
455 {
456 IMAGE_FUNCTION_IN();
457 SendableImageReceiverCommonArgs args = {
458 .env = env, .info = info,
459 .async = CallType::GETTER,
460 };
461 args.argc = ARGS0;
462
463 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsGetCapacity(napi_env env, napi_callback_info info)
485 {
486 IMAGE_FUNCTION_IN();
487 SendableImageReceiverCommonArgs args = {
488 .env = env, .info = info,
489 .async = CallType::GETTER,
490 };
491 args.argc = ARGS0;
492
493 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsGetFormat(napi_env env, napi_callback_info info)
513 {
514 IMAGE_FUNCTION_IN();
515 SendableImageReceiverCommonArgs args = {
516 .env = env, .info = info,
517 .async = CallType::GETTER,
518 };
519 args.argc = ARGS0;
520
521 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsTest(napi_env env, napi_callback_info info)
610 {
611 IMAGE_FUNCTION_IN();
612 SendableImageReceiverCommonArgs args = {
613 .env = env, .info = info,
614 .async = CallType::GETTER,
615 };
616 args.argc = ARGS0;
617
618 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
619 ic.context->constructor_->isCallBackTest = true;
620 DoTest(ic.context->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsCheckDeviceTest(napi_env env, napi_callback_info info)
628 {
629 IMAGE_FUNCTION_IN();
630 SendableImageReceiverCommonArgs args = {
631 .env = env, .info = info,
632 .async = CallType::GETTER,
633 };
634 args.argc = ARGS0;
635
636 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsTestYUV(napi_env env, napi_callback_info info)
652 {
653 IMAGE_FUNCTION_IN();
654 SendableImageReceiverCommonArgs args = {
655 .env = env, .info = info,
656 .async = CallType::GETTER,
657 };
658 args.argc = ARGS0;
659
660 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
661 ic.context->constructor_->isCallBackTest = true;
662 DoTest(ic.context->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsGetReceivingSurfaceId(napi_env env, napi_callback_info info)
671 {
672 IMAGE_FUNCTION_IN();
673 SendableImageReceiverCommonArgs 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->constructor_->imageReceiver_;
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 SendableImageReceiverNapi::JsReadLatestImage(napi_env env, napi_callback_info info)
745 {
746 IMAGE_FUNCTION_IN();
747 SendableImageReceiverCommonArgs 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 = SendableImageNapi::Create(env, image);
779 if (result == nullptr) {
780 IMAGE_ERR("SendableImageNapi 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 SendableImageReceiverNapi::JsReadNextImage(napi_env env, napi_callback_info info)
793 {
794 IMAGE_FUNCTION_IN();
795 SendableImageReceiverCommonArgs 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 = SendableImageNapi::Create(env, image);
827 if (result == nullptr) {
828 IMAGE_ERR("SendableImageNapi 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(SendableImageReceiverCommonArgs & args,SendableImageReceiverInnerContext & ic)870 static bool JsOnQueryArgs(SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 = "Invalid 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
DoCallBackNoUvWork(napi_env env,SendableImageReceiverAsyncContext * context)906 static void DoCallBackNoUvWork(napi_env env, SendableImageReceiverAsyncContext* context)
907 {
908 IMAGE_LINE_IN();
909 if (context == nullptr) {
910 IMAGE_ERR("context is empty");
911 } else {
912 if (context->env != nullptr && context->callbackRef != nullptr) {
913 napi_handle_scope scope = nullptr;
914 napi_open_handle_scope(context->env, &scope);
915 if (scope == nullptr) {
916 return;
917 }
918 napi_value result[PARAM2] = {0};
919 napi_value retVal;
920 napi_value callback = nullptr;
921 napi_create_uint32(context->env, SUCCESS, &result[0]);
922 napi_get_undefined(context->env, &result[1]);
923 napi_get_reference_value(context->env, context->callbackRef, &callback);
924 if (callback != nullptr) {
925 napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
926 } else {
927 IMAGE_ERR("napi_get_reference_value callback is empty");
928 }
929 napi_close_handle_scope(context->env, scope);
930 } else {
931 IMAGE_ERR("env or callbackRef is empty");
932 }
933 }
934 IMAGE_LINE_OUT();
935 }
936
DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> & context,string name,CompleteCallback callBack)937 void SendableImageReceiverNapi::DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> &context,
938 string name, CompleteCallback callBack)
939 {
940 IMAGE_FUNCTION_IN();
941 auto localContext = std::make_unique<shared_ptr<SendableImageReceiverAsyncContext>> (context);
942 if (context == nullptr) {
943 IMAGE_ERR("gContext is empty");
944 localContext.release();
945 return;
946 }
947 if (context->env == nullptr) {
948 IMAGE_ERR("env is empty");
949 localContext.release();
950 return;
951 }
952
953 auto task = [context]() {
954 (void)DoCallBackNoUvWork(context->env, context.get());
955 };
956 if (napi_status::napi_ok != napi_send_event(context->env, task, napi_eprio_high)) {
957 IMAGE_LOGE("DoCallBackSendEvent: failed to SendEvent!");
958 }
959 localContext.release();
960 IMAGE_FUNCTION_OUT();
961 }
962
JsOn(napi_env env,napi_callback_info info)963 napi_value SendableImageReceiverNapi::JsOn(napi_env env, napi_callback_info info)
964 {
965 IMAGE_FUNCTION_IN();
966 SendableImageReceiverCommonArgs args = {
967 .env = env, .info = info,
968 .async = CallType::ASYNC,
969 .name = "JsOn",
970 };
971 args.argc = ARGS2;
972 args.asyncLater = true;
973 args.queryArgs = JsOnQueryArgs;
974 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
975 IMAGE_LINE_IN();
976 napi_get_undefined(args.env, &(ic.result));
977
978 auto native = ic.context->constructor_->imageReceiver_;
979 if (native == nullptr) {
980 IMAGE_ERR("Native instance is nullptr");
981 ic.context->status = ERR_IMAGE_INIT_ABNORMAL;
982 return false;
983 }
984 shared_ptr<SendableImageReceiverAvaliableListener> listener =
985 make_shared<SendableImageReceiverAvaliableListener>();
986 listener->context = std::move(ic.context);
987 listener->context->env = args.env;
988 listener->name = args.name;
989
990 native->RegisterBufferAvaliableListener((std::shared_ptr<SurfaceBufferAvaliableListener> &)listener);
991
992 IMAGE_LINE_OUT();
993 return true;
994 };
995
996 return JSCommonProcess(args);
997 }
998
JsRelease(napi_env env,napi_callback_info info)999 napi_value SendableImageReceiverNapi::JsRelease(napi_env env, napi_callback_info info)
1000 {
1001 IMAGE_FUNCTION_IN();
1002 SendableImageReceiverCommonArgs args = {
1003 .env = env, .info = info,
1004 .async = CallType::ASYNC,
1005 .name = "JsRelease",
1006 .callBack = nullptr,
1007 .argc = ARGS1,
1008 .queryArgs = PrepareOneArg,
1009 };
1010
1011 args.callBack = [](napi_env env, napi_status status, Context context) {
1012 IMAGE_LINE_IN();
1013 napi_value result = nullptr;
1014 napi_get_undefined(env, &result);
1015
1016 context->constructor_->UnRegisterReceiverListener();
1017 context->constructor_->NativeRelease();
1018 context->status = SUCCESS;
1019
1020 IMAGE_LINE_OUT();
1021 CommonCallbackRoutine(env, context, result);
1022 };
1023
1024 return JSCommonProcess(args);
1025 }
1026
release()1027 void SendableImageReceiverNapi::release()
1028 {
1029 if (!isRelease) {
1030 NativeRelease();
1031 isRelease = true;
1032 }
1033 }
1034 } // namespace Media
1035 } // namespace OHOS
1036