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
JSCommonProcess(SendableImageReceiverCommonArgs & args)375 napi_value SendableImageReceiverNapi::JSCommonProcess(SendableImageReceiverCommonArgs &args)
376 {
377 IMAGE_FUNCTION_IN();
378 struct SendableImageReceiverInnerContext ic;
379 ic.argc = args.argc;
380 ic.argv.resize(ic.argc);
381 napi_get_undefined(args.env, &ic.result);
382
383 IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);
384
385 IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);
386
387 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, IMAGE_ERR("fail to napi_get_cb_info"));
388
389 if (args.async != CallType::STATIC) {
390 ic.context = std::make_unique<SendableImageReceiverAsyncContext>();
391 if (ic.context == nullptr) {
392 return ic.result;
393 }
394 ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));
395
396 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
397 ic.result, IMAGE_ERR("fail to unwrap context"));
398
399 if (ic.context->constructor_ == nullptr) {
400 return ic.result;
401 }
402
403 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_->imageReceiver_),
404 ic.result, IMAGE_ERR("empty native receiver"));
405 }
406 if (args.async != CallType::GETTER) {
407 if (!args.queryArgs(args, ic)) {
408 return ic.result;
409 }
410 }
411
412 if (args.async == CallType::ASYNC) {
413 if (args.asyncLater) {
414 args.nonAsyncBack(args, ic);
415 } else {
416 napi_value _resource = nullptr;
417 napi_create_string_utf8((args.env), (args.name.c_str()), NAPI_AUTO_LENGTH, &_resource);
418 (ic.status) = napi_create_async_work(args.env, nullptr, _resource,
419 ([](napi_env env, void *data) {}),
420 (reinterpret_cast<napi_async_complete_callback>(args.callBack)),
421 static_cast<void *>((ic.context).get()), &(ic.context->work));
422 napi_queue_async_work((args.env), (ic.context->work));
423 ic.context.release();
424 }
425 } else {
426 args.nonAsyncBack(args, ic);
427 }
428
429 IMAGE_FUNCTION_OUT();
430 return ic.result;
431 }
432
BuildJsSize(napi_env env,int32_t width,int32_t height)433 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
434 {
435 napi_value result = nullptr;
436 napi_value sizeWith = nullptr;
437 napi_value sizeHeight = nullptr;
438
439 napi_create_object(env, &result);
440
441 napi_create_int32(env, width, &sizeWith);
442 napi_set_named_property(env, result, "width", sizeWith);
443
444 napi_create_int32(env, height, &sizeHeight);
445 napi_set_named_property(env, result, "height", sizeHeight);
446 return result;
447 }
448
JsGetSize(napi_env env,napi_callback_info info)449 napi_value SendableImageReceiverNapi::JsGetSize(napi_env env, napi_callback_info info)
450 {
451 IMAGE_FUNCTION_IN();
452 SendableImageReceiverCommonArgs args = {
453 .env = env, .info = info,
454 .async = CallType::GETTER,
455 };
456 args.argc = ARGS0;
457
458 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
459 napi_get_undefined(args.env, &(ic.result));
460 auto native = ic.context->constructor_->imageReceiver_;
461 if (native == nullptr) {
462 IMAGE_ERR("Native instance is nullptr");
463 return false;
464 }
465
466 if (native->iraContext_ == nullptr) {
467 IMAGE_ERR("Image receiver context is nullptr");
468 return false;
469 }
470 ic.result = BuildJsSize(args.env,
471 native->iraContext_->GetWidth(),
472 native->iraContext_->GetHeight());
473 return true;
474 };
475
476 return JSCommonProcess(args);
477 }
478
JsGetCapacity(napi_env env,napi_callback_info info)479 napi_value SendableImageReceiverNapi::JsGetCapacity(napi_env env, napi_callback_info info)
480 {
481 IMAGE_FUNCTION_IN();
482 SendableImageReceiverCommonArgs args = {
483 .env = env, .info = info,
484 .async = CallType::GETTER,
485 };
486 args.argc = ARGS0;
487
488 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
489 napi_get_undefined(args.env, &(ic.result));
490 auto native = ic.context->constructor_->imageReceiver_;
491 if (native == nullptr) {
492 IMAGE_ERR("Native instance is nullptr");
493 return false;
494 }
495
496 if (native->iraContext_ == nullptr) {
497 IMAGE_ERR("Image receiver context is nullptr");
498 return false;
499 }
500 napi_create_int32(args.env, native->iraContext_->GetCapicity(), &(ic.result));
501 return true;
502 };
503
504 return JSCommonProcess(args);
505 }
506
JsGetFormat(napi_env env,napi_callback_info info)507 napi_value SendableImageReceiverNapi::JsGetFormat(napi_env env, napi_callback_info info)
508 {
509 IMAGE_FUNCTION_IN();
510 SendableImageReceiverCommonArgs args = {
511 .env = env, .info = info,
512 .async = CallType::GETTER,
513 };
514 args.argc = ARGS0;
515
516 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
517 napi_get_undefined(args.env, &(ic.result));
518 auto native = ic.context->constructor_->imageReceiver_;
519 if (native == nullptr) {
520 IMAGE_ERR("Native instance is nullptr");
521 return false;
522 }
523
524 if (native->iraContext_ == nullptr) {
525 IMAGE_ERR("Image receiver context is nullptr");
526 return false;
527 }
528 napi_create_int32(args.env, native->iraContext_->GetFormat(), &(ic.result));
529 return true;
530 };
531
532 return JSCommonProcess(args);
533 }
534
535 #ifdef IMAGE_DEBUG_FLAG
TestRequestBuffer(OHOS::sptr<OHOS::Surface> & receiverSurface,OHOS::BufferRequestConfig requestConfig,OHOS::BufferFlushConfig flushConfig)536 static void TestRequestBuffer(OHOS::sptr<OHOS::Surface> &receiverSurface,
537 OHOS::BufferRequestConfig requestConfig,
538 OHOS::BufferFlushConfig flushConfig)
539 {
540 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
541 int32_t releaseFence;
542 if (receiverSurface == nullptr) {
543 IMAGE_ERR("Image receiver receiverSurface is nullptr");
544 return;
545 }
546 requestConfig.width = receiverSurface->GetDefaultWidth();
547 requestConfig.height = receiverSurface->GetDefaultHeight();
548 receiverSurface->RequestBuffer(buffer, releaseFence, requestConfig);
549 if (buffer == nullptr) {
550 IMAGE_ERR("Image receiver buffer is nullptr");
551 return;
552 }
553 IMAGE_ERR("RequestBuffer");
554 int32_t *p = reinterpret_cast<int32_t *>(buffer->GetVirAddr());
555 int32_t size = static_cast<int32_t>(buffer->GetSize() / 4);
556 if (p != nullptr) {
557 for (int32_t i = 0; i < size; i++) {
558 p[i] = i;
559 }
560 }
561 receiverSurface->FlushBuffer(buffer, -1, flushConfig);
562 IMAGE_ERR("FlushBuffer");
563 }
564
DoTest(std::shared_ptr<ImageReceiver> imageReceiver,int pixelFormat)565 static void DoTest(std::shared_ptr<ImageReceiver> imageReceiver, int pixelFormat)
566 {
567 OHOS::BufferRequestConfig requestConfig = {
568 .width = 0x100,
569 .height = 0x100,
570 .strideAlignment = 0x8,
571 .format = pixelFormat,
572 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
573 .timeout = 0,
574 };
575
576 OHOS::BufferFlushConfig flushConfig = {
577 .damage = {
578 .w = 0x100,
579 .h = 0x100,
580 },
581 };
582
583 if (imageReceiver == nullptr || imageReceiver->iraContext_ == nullptr) {
584 IMAGE_ERR("Image receiver DoTest imageReceiver is nullptr");
585 return;
586 }
587 std::string receiveKey = imageReceiver->iraContext_->GetReceiverKey();
588 IMAGE_ERR("ReceiverKey = %{public}s", receiveKey.c_str());
589 OHOS::sptr<OHOS::Surface> receiverSurface = ImageReceiver::getSurfaceById(receiveKey);
590 if (receiverSurface == nullptr) {
591 IMAGE_ERR("Image receiver DoTest receiverSurface is nullptr");
592 return;
593 }
594 IMAGE_ERR("getDefaultWidth = %{public}d", receiverSurface->GetDefaultWidth());
595 IMAGE_ERR("getDefaultHeight = %{public}d", receiverSurface->GetDefaultHeight());
596 IMAGE_ERR("TestRequestBuffer 1 ...");
597 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
598 IMAGE_ERR("TestRequestBuffer 2 ...");
599 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
600 IMAGE_ERR("TestRequestBuffer 3 ...");
601 TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
602 }
603
JsTest(napi_env env,napi_callback_info info)604 napi_value SendableImageReceiverNapi::JsTest(napi_env env, napi_callback_info info)
605 {
606 IMAGE_FUNCTION_IN();
607 SendableImageReceiverCommonArgs args = {
608 .env = env, .info = info,
609 .async = CallType::GETTER,
610 };
611 args.argc = ARGS0;
612
613 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
614 ic.context->constructor_->isCallBackTest = true;
615 DoTest(ic.context->constructor_->imageReceiver_, PIXEL_FMT_RGBA_8888);
616 return true;
617 };
618
619 return JSCommonProcess(args);
620 }
621
JsCheckDeviceTest(napi_env env,napi_callback_info info)622 napi_value SendableImageReceiverNapi::JsCheckDeviceTest(napi_env env, napi_callback_info info)
623 {
624 IMAGE_FUNCTION_IN();
625 SendableImageReceiverCommonArgs args = {
626 .env = env, .info = info,
627 .async = CallType::GETTER,
628 };
629 args.argc = ARGS0;
630
631 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
632 napi_get_undefined(args.env, &(ic.result));
633 napi_value mess = nullptr;
634 ic.context->constructor_->isCallBackTest = true;
635 napi_create_string_utf8(args.env, DEVICE_ERRCODE.c_str(), NAPI_AUTO_LENGTH, &mess);
636 ic.result = mess;
637 if (args.async != CallType::GETTER) {
638 DoTest(ic.context->constructor_->imageReceiver_, PIXEL_FMT_RGBA_8888);
639 }
640 return true;
641 };
642
643 return JSCommonProcess(args);
644 }
645
JsTestYUV(napi_env env,napi_callback_info info)646 napi_value SendableImageReceiverNapi::JsTestYUV(napi_env env, napi_callback_info info)
647 {
648 IMAGE_FUNCTION_IN();
649 SendableImageReceiverCommonArgs args = {
650 .env = env, .info = info,
651 .async = CallType::GETTER,
652 };
653 args.argc = ARGS0;
654
655 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
656 ic.context->constructor_->isCallBackTest = true;
657 DoTest(ic.context->constructor_->imageReceiver_, PIXEL_FMT_YCBCR_422_SP);
658 return true;
659 };
660
661 return JSCommonProcess(args);
662 }
663 #endif
664
JsGetReceivingSurfaceId(napi_env env,napi_callback_info info)665 napi_value SendableImageReceiverNapi::JsGetReceivingSurfaceId(napi_env env, napi_callback_info info)
666 {
667 IMAGE_FUNCTION_IN();
668 SendableImageReceiverCommonArgs args = {
669 .env = env, .info = info,
670 .async = CallType::ASYNC,
671 .name = "JsGetReceivingSurfaceId",
672 .callBack = nullptr,
673 .argc = ARGS1,
674 .queryArgs = PrepareOneArg,
675 };
676
677 args.callBack = [](napi_env env, napi_status status, Context context) {
678 IMAGE_LINE_IN();
679 napi_value result = nullptr;
680 napi_get_undefined(env, &result);
681
682 auto native = context->constructor_->imageReceiver_;
683 if (native == nullptr) {
684 IMAGE_ERR("Native instance is nullptr");
685 context->status = ERR_IMAGE_INIT_ABNORMAL;
686 } else if (native->iraContext_ == nullptr) {
687 IMAGE_ERR("Image receiver context is nullptr");
688 context->status = ERR_IMAGE_INIT_ABNORMAL;
689 } else {
690 napi_create_string_utf8(env, native->iraContext_->GetReceiverKey().c_str(),
691 NAPI_AUTO_LENGTH, &result);
692 context->status = SUCCESS;
693 }
694
695 IMAGE_LINE_OUT();
696 CommonCallbackRoutine(env, context, result);
697 };
698
699 return JSCommonProcess(args);
700 }
701
702 #ifdef IMAGE_SAVE_BUFFER_TO_PIC
DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)703 static void DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)
704 {
705 if (surfaceBuffer1 == nullptr) {
706 IMAGE_ERR("surfaceBuffer1 is null");
707 return;
708 }
709
710 ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance();
711 shared_ptr<ImageReceiver> imageReceiver1 = imageReceiverManager.getImageReceiverByKeyId("1");
712 if (imageReceiver1 == nullptr || imageReceiver1->iraContext_ == nullptr) {
713 return;
714 }
715 IMAGE_ERR("DoCallBackTest format %{public}d", imageReceiver1->iraContext_->GetFormat());
716
717 InitializationOptions opts;
718 opts.size.width = surfaceBuffer1->GetWidth();
719 opts.size.height = surfaceBuffer1->GetHeight();
720 opts.pixelFormat = OHOS::Media::PixelFormat::BGRA_8888;
721 opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
722 opts.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
723 opts.editable = true;
724 IMAGE_ERR("DoCallBackTest Width %{public}d", opts.size.width);
725 IMAGE_ERR("DoCallBackTest Height %{public}d", opts.size.height);
726 int fd = open("/data/receiver/test.jpg", O_RDWR | O_CREAT);
727 imageReceiver1->SaveBufferAsImage(fd, surfaceBuffer1, opts);
728 }
729 #endif
FailedCallbackRoutine(napi_env env,Context & context,uint32_t errCode)730 static void FailedCallbackRoutine(napi_env env, Context &context, uint32_t errCode)
731 {
732 napi_value result = nullptr;
733 napi_get_undefined(env, &result);
734 if (context != nullptr) {
735 context->status = ERR_IMAGE_INIT_ABNORMAL;
736 }
737 CommonCallbackRoutine(env, context, result);
738 }
JsReadLatestImage(napi_env env,napi_callback_info info)739 napi_value SendableImageReceiverNapi::JsReadLatestImage(napi_env env, napi_callback_info info)
740 {
741 IMAGE_FUNCTION_IN();
742 SendableImageReceiverCommonArgs args = {
743 .env = env, .info = info,
744 .async = CallType::ASYNC,
745 .name = "JsReadLatestImage",
746 .callBack = nullptr,
747 .argc = ARGS1,
748 .queryArgs = PrepareOneArg,
749 };
750
751 args.callBack = [](napi_env env, napi_status status, Context context) {
752 IMAGE_LINE_IN();
753 auto native = context->constructor_->imageReceiver_;
754 if (native == nullptr) {
755 IMAGE_ERR("Native instance is nullptr");
756 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
757 return;
758 }
759 auto image = native->LastNativeImage();
760 if (image == nullptr) {
761 IMAGE_ERR("LastNativeImage is nullptr");
762 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
763 return;
764 }
765 #ifdef IMAGE_DEBUG_FLAG
766 if (context->constructor_->isCallBackTest) {
767 context->constructor_->isCallBackTest = false;
768 #ifdef IMAGE_SAVE_BUFFER_TO_PIC
769 DoCallBackTest(image->GetBuffer());
770 #endif
771 }
772 #endif
773 napi_value result = SendableImageNapi::Create(env, image);
774 if (result == nullptr) {
775 IMAGE_ERR("SendableImageNapi Create is nullptr");
776 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
777 return;
778 }
779 context->status = SUCCESS;
780 IMAGE_LINE_OUT();
781 CommonCallbackRoutine(env, context, result);
782 };
783
784 return JSCommonProcess(args);
785 }
786
JsReadNextImage(napi_env env,napi_callback_info info)787 napi_value SendableImageReceiverNapi::JsReadNextImage(napi_env env, napi_callback_info info)
788 {
789 IMAGE_FUNCTION_IN();
790 SendableImageReceiverCommonArgs args = {
791 .env = env, .info = info,
792 .async = CallType::ASYNC,
793 .name = "JsReadNextImage",
794 .callBack = nullptr,
795 .argc = ARGS1,
796 .queryArgs = PrepareOneArg,
797 };
798
799 args.callBack = [](napi_env env, napi_status status, Context context) {
800 IMAGE_LINE_IN();
801 auto native = context->constructor_->imageReceiver_;
802 if (native == nullptr) {
803 IMAGE_ERR("Native instance is nullptr");
804 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
805 return;
806 }
807 auto image = native->NextNativeImage();
808 if (image == nullptr) {
809 IMAGE_ERR("NextNativeImage is nullptr");
810 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
811 return;
812 }
813 #ifdef IMAGE_DEBUG_FLAG
814 if (context->constructor_->isCallBackTest) {
815 context->constructor_->isCallBackTest = false;
816 #ifdef IMAGE_SAVE_BUFFER_TO_PIC
817 DoCallBackTest(image->GetBuffer());
818 #endif
819 }
820 #endif
821 napi_value result = SendableImageNapi::Create(env, image);
822 if (result == nullptr) {
823 IMAGE_ERR("SendableImageNapi Create is nullptr");
824 FailedCallbackRoutine(env, context, ERR_IMAGE_INIT_ABNORMAL);
825 return;
826 }
827 context->status = SUCCESS;
828 IMAGE_LINE_OUT();
829 CommonCallbackRoutine(env, context, result);
830 };
831
832 return JSCommonProcess(args);
833 }
834
CheckOnParam0(napi_env env,napi_value value,const std::string & refStr)835 static bool CheckOnParam0(napi_env env, napi_value value, const std::string& refStr)
836 {
837 bool ret = true;
838 size_t bufLength = 0;
839 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
840 if (status != napi_ok || bufLength > PATH_MAX) {
841 return false;
842 }
843
844 char *buffer = static_cast<char *>(malloc((bufLength + 1) * sizeof(char)));
845 if (buffer == nullptr) {
846 return false;
847 }
848
849 status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
850 if (status != napi_ok) {
851 ret = false;
852 } else {
853 std::string strValue = buffer;
854 if (strValue.compare(refStr) != 0) {
855 IMAGE_ERR("strValue is %{public}s", strValue.c_str());
856 ret = false;
857 }
858 }
859
860 free(buffer);
861 buffer = nullptr;
862 return ret;
863 }
864
JsOnQueryArgs(SendableImageReceiverCommonArgs & args,SendableImageReceiverInnerContext & ic)865 static bool JsOnQueryArgs(SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic)
866 {
867 if (ic.argc == ARGS2) {
868 auto argType0 = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
869 auto argType1 = ImageNapiUtils::getType(args.env, ic.argv[PARAM1]);
870 if (argType0 == napi_string && argType1 == napi_function) {
871 if (!ImageNapiUtils::GetUtf8String(args.env, ic.argv[PARAM0], ic.onType)) {
872 ImageNapiUtils::ThrowExceptionError(args.env, static_cast<int32_t>(napi_invalid_arg),
873 "Could not get On type string");
874 return false;
875 }
876
877 if (!CheckOnParam0(args.env, ic.argv[PARAM0], "imageArrival")) {
878 ImageNapiUtils::ThrowExceptionError(args.env, static_cast<int32_t>(napi_invalid_arg),
879 "Unsupport PARAM0");
880 return false;
881 }
882
883 napi_create_reference(args.env, ic.argv[PARAM1], ic.refCount, &(ic.context->callbackRef));
884 } else {
885 std::string errMsg = "Unsupport args type: ";
886 ImageNapiUtils::ThrowExceptionError(args.env, static_cast<int32_t>(napi_invalid_arg),
887 errMsg.append(std::to_string(argType0)).append(std::to_string(argType1)));
888 return false;
889 }
890 } else {
891 std::string errMsg = "Invalid argc: ";
892 ImageNapiUtils::ThrowExceptionError(args.env, static_cast<int32_t>(napi_invalid_arg),
893 errMsg.append(std::to_string(ic.argc)));
894 return false;
895 }
896
897 napi_get_undefined(args.env, &ic.result);
898 return true;
899 }
900
Callback(uv_work_t * work,int status)901 static void Callback(uv_work_t *work, int status)
902 {
903 IMAGE_LINE_IN();
904 Context context = reinterpret_cast<Context>(work->data);
905 if (context == nullptr) {
906 IMAGE_ERR("context is empty");
907 } else {
908 if (context->env != nullptr && context->callbackRef != nullptr) {
909 napi_handle_scope scope = nullptr;
910 napi_open_handle_scope(context->env, &scope);
911 if (scope == nullptr) {
912 delete work;
913 return;
914 }
915 napi_value result[PARAM2] = {0};
916 napi_value retVal;
917 napi_value callback = nullptr;
918 napi_create_uint32(context->env, SUCCESS, &result[0]);
919 napi_get_undefined(context->env, &result[1]);
920 napi_get_reference_value(context->env, context->callbackRef, &callback);
921 if (callback != nullptr) {
922 napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
923 } else {
924 IMAGE_ERR("napi_get_reference_value callback is empty");
925 }
926 napi_close_handle_scope(context->env, scope);
927 } else {
928 IMAGE_ERR("env or callbackRef is empty");
929 }
930 }
931 delete work;
932 IMAGE_LINE_OUT();
933 }
934
DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> & context,string name,CompleteCallback callBack)935 void SendableImageReceiverNapi::DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> &context,
936 string name, CompleteCallback callBack)
937 {
938 IMAGE_FUNCTION_IN();
939 auto localContext = std::make_unique<shared_ptr<SendableImageReceiverAsyncContext>> (context);
940 if (context == nullptr) {
941 IMAGE_ERR("gContext is empty");
942 localContext.release();
943 return;
944 }
945 if (context->env == nullptr) {
946 IMAGE_ERR("env is empty");
947 localContext.release();
948 return;
949 }
950
951 uv_loop_s *loop = nullptr;
952 napi_get_uv_event_loop(context->env, &loop);
953 if (loop == nullptr) {
954 IMAGE_ERR("napi_get_uv_event_loop failed");
955 localContext.release();
956 return;
957 }
958
959 unique_ptr<uv_work_t> work = make_unique<uv_work_t>();
960 if (work == nullptr) {
961 IMAGE_ERR("DoCallBack: No memory");
962 localContext.release();
963 return;
964 }
965 work->data = reinterpret_cast<void *>(context.get());
966 int ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
967 Callback(work, status);
968 });
969 if (ret != 0) {
970 IMAGE_ERR("Failed to execute DoCallBack work queue");
971 } else {
972 work.release();
973 }
974 localContext.release();
975 IMAGE_FUNCTION_OUT();
976 }
977
JsOn(napi_env env,napi_callback_info info)978 napi_value SendableImageReceiverNapi::JsOn(napi_env env, napi_callback_info info)
979 {
980 IMAGE_FUNCTION_IN();
981 SendableImageReceiverCommonArgs args = {
982 .env = env, .info = info,
983 .async = CallType::ASYNC,
984 .name = "JsOn",
985 };
986 args.argc = ARGS2;
987 args.asyncLater = true;
988 args.queryArgs = JsOnQueryArgs;
989 args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
990 IMAGE_LINE_IN();
991 napi_get_undefined(args.env, &(ic.result));
992
993 auto native = ic.context->constructor_->imageReceiver_;
994 if (native == nullptr) {
995 IMAGE_ERR("Native instance is nullptr");
996 ic.context->status = ERR_IMAGE_INIT_ABNORMAL;
997 return false;
998 }
999 shared_ptr<SendableImageReceiverAvaliableListener> listener =
1000 make_shared<SendableImageReceiverAvaliableListener>();
1001 listener->context = std::move(ic.context);
1002 listener->context->env = args.env;
1003 listener->name = args.name;
1004
1005 native->RegisterBufferAvaliableListener((std::shared_ptr<SurfaceBufferAvaliableListener> &)listener);
1006
1007 IMAGE_LINE_OUT();
1008 return true;
1009 };
1010
1011 return JSCommonProcess(args);
1012 }
1013
JsRelease(napi_env env,napi_callback_info info)1014 napi_value SendableImageReceiverNapi::JsRelease(napi_env env, napi_callback_info info)
1015 {
1016 IMAGE_FUNCTION_IN();
1017 SendableImageReceiverCommonArgs args = {
1018 .env = env, .info = info,
1019 .async = CallType::ASYNC,
1020 .name = "JsRelease",
1021 .callBack = nullptr,
1022 .argc = ARGS1,
1023 .queryArgs = PrepareOneArg,
1024 };
1025
1026 args.callBack = [](napi_env env, napi_status status, Context context) {
1027 IMAGE_LINE_IN();
1028 napi_value result = nullptr;
1029 napi_get_undefined(env, &result);
1030
1031 context->constructor_->UnRegisterReceiverListener();
1032 context->constructor_->NativeRelease();
1033 context->status = SUCCESS;
1034
1035 IMAGE_LINE_OUT();
1036 CommonCallbackRoutine(env, context, result);
1037 };
1038
1039 return JSCommonProcess(args);
1040 }
1041
release()1042 void SendableImageReceiverNapi::release()
1043 {
1044 if (!isRelease) {
1045 NativeRelease();
1046 isRelease = true;
1047 }
1048 }
1049 } // namespace Media
1050 } // namespace OHOS
1051