• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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