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