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