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