• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 shared_ptr<ImageReceiver> ImageReceiverNapi::staticInstance_ = nullptr;
41 thread_local napi_ref ImageReceiverNapi::sConstructor_ = nullptr;
42 using SurfaceListener = SurfaceBufferAvaliableListener;
43 
44 const int ARGS0 = 0;
45 const int ARGS1 = 1;
46 const int ARGS2 = 2;
47 const int ARGS4 = 4;
48 const int PARAM0 = 0;
49 const int PARAM1 = 1;
50 const int PARAM2 = 2;
51 const int PARAM3 = 3;
52 
ImageReceiverNapi()53 ImageReceiverNapi::ImageReceiverNapi()
54     :env_(nullptr), wrapper_(nullptr)
55 {}
56 
~ImageReceiverNapi()57 ImageReceiverNapi::~ImageReceiverNapi()
58 {
59     NativeRelease();
60     if (wrapper_ != nullptr) {
61         napi_delete_reference(env_, wrapper_);
62     }
63 }
64 
CommonCallbackRoutine(napi_env env,Context & context,const napi_value & valueParam,bool isRelease=true)65 static void CommonCallbackRoutine(napi_env env, Context &context, const napi_value &valueParam, bool isRelease = true)
66 {
67     IMAGE_FUNCTION_IN();
68     napi_value result[2] = {0};
69     napi_value retVal;
70     napi_value callback = nullptr;
71 
72     napi_get_undefined(env, &result[0]);
73     napi_get_undefined(env, &result[1]);
74 
75     if (context->status == SUCCESS) {
76         result[1] = valueParam;
77     }
78 
79     if (context->deferred) {
80         if (context->status == SUCCESS) {
81             napi_resolve_deferred(env, context->deferred, result[1]);
82         } else {
83             napi_reject_deferred(env, context->deferred, result[0]);
84         }
85     } else {
86         napi_create_uint32(env, context->status, &result[0]);
87         napi_get_reference_value(env, context->callbackRef, &callback);
88         napi_call_function(env, nullptr, callback, PARAM2, result, &retVal);
89     }
90 
91     if (isRelease) {
92         if (context->callbackRef != nullptr) {
93             napi_delete_reference(env, context->callbackRef);
94             context->callbackRef = nullptr;
95         }
96 
97         napi_delete_async_work(env, context->work);
98 
99         delete context;
100         context = nullptr;
101     }
102     IMAGE_FUNCTION_OUT();
103 }
104 
NativeRelease()105 void ImageReceiverNapi::NativeRelease()
106 {
107     if (imageReceiver_ != nullptr) {
108         imageReceiver_->~ImageReceiver();
109         imageReceiver_ = nullptr;
110     }
111 }
112 
Init(napi_env env,napi_value exports)113 napi_value ImageReceiverNapi::Init(napi_env env, napi_value exports)
114 {
115     IMAGE_FUNCTION_IN();
116     napi_property_descriptor props[] = {
117         DECLARE_NAPI_FUNCTION("getReceivingSurfaceId", JsGetReceivingSurfaceId),
118         DECLARE_NAPI_FUNCTION("readLatestImage", JsReadLatestImage),
119         DECLARE_NAPI_FUNCTION("readNextImage", JsReadNextImage),
120         DECLARE_NAPI_FUNCTION("on", JsOn),
121         DECLARE_NAPI_FUNCTION("release", JsRelease),
122 #ifdef IMAGE_DEBUG_FLAG
123         DECLARE_NAPI_GETTER("test", JsTest),
124 #endif
125         DECLARE_NAPI_GETTER("size", JsGetSize),
126         DECLARE_NAPI_GETTER("capacity", JsGetCapacity),
127         DECLARE_NAPI_GETTER("format", JsGetFormat),
128     };
129     napi_property_descriptor static_prop[] = {
130         DECLARE_NAPI_STATIC_FUNCTION("createImageReceiver", JSCreateImageReceiver),
131     };
132 
133     napi_value constructor = nullptr;
134     size_t props_count = IMG_ARRAY_SIZE(props);
135     size_t static_props_count = IMG_ARRAY_SIZE(static_prop);
136 
137     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
138         napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor,
139         nullptr, props_count, props, &constructor)),
140         nullptr,
141         IMAGE_ERR("define class fail")
142     );
143 
144     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
145         napi_create_reference(env, constructor, 1, &sConstructor_)),
146         nullptr,
147         IMAGE_ERR("create reference fail")
148     );
149 
150     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
151         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
152         nullptr,
153         IMAGE_ERR("set named property fail")
154     );
155     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
156         napi_define_properties(env, exports, static_props_count, static_prop)),
157         nullptr,
158         IMAGE_ERR("define properties fail")
159     );
160 
161     IMAGE_DEBUG("Init success");
162 
163     IMAGE_FUNCTION_OUT();
164     return exports;
165 }
166 
Constructor(napi_env env,napi_callback_info info)167 napi_value ImageReceiverNapi::Constructor(napi_env env, napi_callback_info info)
168 {
169     napi_value undefineVar = nullptr;
170     napi_get_undefined(env, &undefineVar);
171 
172     napi_status status;
173     napi_value thisVar = nullptr;
174 
175     IMAGE_FUNCTION_IN();
176     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
177     if (status == napi_ok && thisVar != nullptr) {
178         std::unique_ptr<ImageReceiverNapi> reference = std::make_unique<ImageReceiverNapi>();
179         if (reference != nullptr) {
180             reference->env_ = env;
181             reference->imageReceiver_ = staticInstance_;
182             status = napi_wrap(env, thisVar, reinterpret_cast<void *>(reference.get()),
183                                ImageReceiverNapi::Destructor, nullptr, &(reference->wrapper_));
184             if (status == napi_ok) {
185                 IMAGE_FUNCTION_OUT();
186                 reference.release();
187                 return thisVar;
188             } else {
189                 IMAGE_ERR("Failure wrapping js to native napi");
190             }
191         }
192     }
193 
194     return undefineVar;
195 }
196 
Destructor(napi_env env,void * nativeObject,void * finalize)197 void ImageReceiverNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
198 {
199     ImageReceiverNapi *pImageReceiverNapi = reinterpret_cast<ImageReceiverNapi*>(nativeObject);
200 
201     if (IMG_NOT_NULL(pImageReceiverNapi)) {
202         pImageReceiverNapi->~ImageReceiverNapi();
203     }
204 }
205 
JSCreateImageReceiver(napi_env env,napi_callback_info info)206 napi_value ImageReceiverNapi::JSCreateImageReceiver(napi_env env, napi_callback_info info)
207 {
208     napi_status status;
209     napi_value constructor = nullptr, result = nullptr, thisVar = nullptr;
210     size_t argc = ARGS4;
211     napi_value argv[ARGS4] = {0};
212     int32_t args[ARGS4] = {0};
213 
214     IMAGE_FUNCTION_IN();
215     napi_get_undefined(env, &result);
216 
217     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
218     if (status != napi_ok) {
219         IMAGE_ERR("fail to napi_get_cb_info %{public}d", status);
220         return result;
221     }
222 
223     if (argc != ARGS4) {
224         IMAGE_ERR("Invailed arg counts %{public}zu", argc);
225         return result;
226     }
227 
228     for (size_t i = PARAM0; i < argc; i++) {
229         napi_valuetype argvType = ImageNapiUtils::getType(env, argv[i]);
230         if (argvType != napi_number) {
231             IMAGE_ERR("Invailed arg %{public}zu type %{public}d", i, argvType);
232             return result;
233         }
234 
235         status = napi_get_value_int32(env, argv[i], &(args[i]));
236         if (status != napi_ok) {
237             IMAGE_ERR("fail to get arg %{public}zu : %{public}d", i, status);
238             return result;
239         }
240     }
241 
242     status = napi_get_reference_value(env, sConstructor_, &constructor);
243     if (IMG_IS_OK(status)) {
244         staticInstance_ = ImageReceiver::CreateImageReceiver(args[PARAM0], args[PARAM1], args[PARAM2], args[PARAM3]);
245         status = napi_new_instance(env, constructor, 0, nullptr, &result);
246         if (status == napi_ok) {
247             IMAGE_FUNCTION_OUT();
248             return result;
249         } else {
250             IMAGE_ERR("New instance could not be obtained");
251         }
252     }
253 
254     IMAGE_ERR("Failed to get reference of constructor");
255     return result;
256 }
257 
CheckArgs(ImageReceiverCommonArgs & args)258 static bool CheckArgs(ImageReceiverCommonArgs &args)
259 {
260     if (args.async != CallType::GETTER) {
261         if (args.queryArgs == nullptr) {
262             IMAGE_ERR("No query args function");
263             return false;
264         }
265     }
266 
267     if (args.async != CallType::ASYNC || args.asyncLater) {
268         if (args.nonAsyncBack == nullptr) {
269             IMAGE_ERR("No non async back function");
270             return false;
271         }
272     }
273     return true;
274 }
275 
PrepareOneArg(ImageReceiverCommonArgs & args,struct ImageReceiverInnerContext & ic)276 static bool PrepareOneArg(ImageReceiverCommonArgs &args, struct ImageReceiverInnerContext &ic)
277 {
278     if (ic.argc == ARGS1) {
279         auto argType = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
280         if (argType == napi_function) {
281             napi_create_reference(args.env, ic.argv[PARAM0], ic.refCount, &(ic.context->callbackRef));
282         } else {
283             IMAGE_ERR("Unsupport arg 0 type: %{public}d", argType);
284             return false;
285         }
286     }
287 
288     if (ic.context->callbackRef == nullptr) {
289         napi_create_promise(args.env, &(ic.context->deferred), &(ic.result));
290     } else {
291         napi_get_undefined(args.env, &ic.result);
292     }
293     return true;
294 }
295 
JSCommonProcess(ImageReceiverCommonArgs & args)296 napi_value ImageReceiverNapi::JSCommonProcess(ImageReceiverCommonArgs &args)
297 {
298     IMAGE_FUNCTION_IN();
299     struct ImageReceiverInnerContext ic;
300     ic.argc = args.argc;
301     ic.argv.resize(ic.argc);
302     napi_get_undefined(args.env, &ic.result);
303 
304     IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);
305 
306     IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);
307 
308     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, IMAGE_ERR("fail to napi_get_cb_info"));
309 
310     if (args.async != CallType::STATIC) {
311         ic.context = std::make_unique<ImageReceiverAsyncContext>();
312         ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));
313 
314         IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
315             ic.result, IMAGE_ERR("fail to unwrap context"));
316 
317         ic.context->receiver_ = ic.context->constructor_->imageReceiver_;
318 
319         IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->receiver_),
320             ic.result, IMAGE_ERR("empty native receiver"));
321     }
322     if (args.async != CallType::GETTER) {
323         if (!args.queryArgs(args, ic)) {
324             return ic.result;
325         }
326     }
327 
328     if (args.async == CallType::ASYNC) {
329         if (args.asyncLater) {
330             args.nonAsyncBack(args, ic);
331         } else {
332             napi_value _resource = nullptr;
333             napi_create_string_utf8((args.env), (args.name.c_str()), NAPI_AUTO_LENGTH, &_resource);
334             (ic.status) = napi_create_async_work(args.env, nullptr, _resource,
335                                                  ([](napi_env env, void *data) {}),
336                                                  (reinterpret_cast<napi_async_complete_callback>(args.callBack)),
337                                                  static_cast<void *>((ic.context).get()), &(ic.context->work));
338             napi_queue_async_work((args.env), (ic.context->work));
339             ic.context.release();
340         }
341     } else {
342         args.nonAsyncBack(args, ic);
343     }
344 
345     IMAGE_FUNCTION_OUT();
346     return ic.result;
347 }
348 
BuildJsSize(napi_env env,int32_t width,int32_t height)349 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
350 {
351     napi_value result = nullptr, sizeWith = nullptr, sizeHeight = nullptr;
352 
353     napi_create_object(env, &result);
354 
355     napi_create_int32(env, width, &sizeWith);
356     napi_set_named_property(env, result, "width", sizeWith);
357 
358     napi_create_int32(env, height, &sizeHeight);
359     napi_set_named_property(env, result, "height", sizeHeight);
360     return result;
361 }
362 
JsGetSize(napi_env env,napi_callback_info info)363 napi_value ImageReceiverNapi::JsGetSize(napi_env env, napi_callback_info info)
364 {
365     IMAGE_FUNCTION_IN();
366     ImageReceiverCommonArgs args = {
367         .env = env, .info = info,
368         .async = CallType::GETTER,
369     };
370     args.argc = ARGS0;
371 
372     args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
373         napi_get_undefined(args.env, &(ic.result));
374         auto native = ic.context->constructor_->imageReceiver_;
375         if (native == nullptr) {
376             IMAGE_ERR("Native instance is nullptr");
377             return false;
378         }
379 
380         if (native->iraContext_ == nullptr) {
381             IMAGE_ERR("Image receiver context is nullptr");
382             return false;
383         }
384         ic.result = BuildJsSize(args.env,
385                                 native->iraContext_->GetWidth(),
386                                 native->iraContext_->GetHeight());
387         return true;
388     };
389 
390     return JSCommonProcess(args);
391 }
392 
JsGetCapacity(napi_env env,napi_callback_info info)393 napi_value ImageReceiverNapi::JsGetCapacity(napi_env env, napi_callback_info info)
394 {
395     IMAGE_FUNCTION_IN();
396     ImageReceiverCommonArgs args = {
397         .env = env, .info = info,
398         .async = CallType::GETTER,
399     };
400     args.argc = ARGS0;
401 
402     args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
403         napi_get_undefined(args.env, &(ic.result));
404         auto native = ic.context->constructor_->imageReceiver_;
405         if (native == nullptr) {
406             IMAGE_ERR("Native instance is nullptr");
407             return false;
408         }
409 
410         if (native->iraContext_ == nullptr) {
411             IMAGE_ERR("Image receiver context is nullptr");
412             return false;
413         }
414         napi_create_int32(args.env, native->iraContext_->GetCapicity(), &(ic.result));
415         return true;
416     };
417 
418     return JSCommonProcess(args);
419 }
420 
JsGetFormat(napi_env env,napi_callback_info info)421 napi_value ImageReceiverNapi::JsGetFormat(napi_env env, napi_callback_info info)
422 {
423     IMAGE_FUNCTION_IN();
424     ImageReceiverCommonArgs args = {
425         .env = env, .info = info,
426         .async = CallType::GETTER,
427     };
428     args.argc = ARGS0;
429 
430     args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
431         napi_get_undefined(args.env, &(ic.result));
432         auto native = ic.context->constructor_->imageReceiver_;
433         if (native == nullptr) {
434             IMAGE_ERR("Native instance is nullptr");
435             return false;
436         }
437 
438         if (native->iraContext_ == nullptr) {
439             IMAGE_ERR("Image receiver context is nullptr");
440             return false;
441         }
442         napi_create_int32(args.env, native->iraContext_->GetFormat(), &(ic.result));
443         return true;
444     };
445 
446     return JSCommonProcess(args);
447 }
448 
449 #ifdef IMAGE_DEBUG_FLAG
TestRequestBuffer(OHOS::sptr<OHOS::Surface> & receiverSurface,OHOS::BufferRequestConfig requestConfig,OHOS::BufferFlushConfig flushConfig)450 static void TestRequestBuffer(OHOS::sptr<OHOS::Surface> &receiverSurface,
451                               OHOS::BufferRequestConfig requestConfig,
452                               OHOS::BufferFlushConfig flushConfig)
453 {
454     OHOS::sptr<OHOS::SurfaceBuffer> buffer;
455     int32_t releaseFence;
456     requestConfig.width = receiverSurface->GetDefaultWidth();
457     requestConfig.height = receiverSurface->GetDefaultHeight();
458     receiverSurface->RequestBuffer(buffer, releaseFence, requestConfig);
459     IMAGE_ERR("RequestBuffer");
460     int32_t *p = (int32_t *)buffer->GetVirAddr();
461     IMAGE_ERR("RequestBuffer %{public}p", p);
462     if (p != nullptr) {
463         for (int32_t i = 0; i < requestConfig.width * requestConfig.height; i++) {
464             p[i] = i;
465         }
466     }
467     receiverSurface->FlushBuffer(buffer, -1, flushConfig);
468     IMAGE_ERR("FlushBuffer");
469 }
470 
DoTest(std::shared_ptr<ImageReceiver> imageReceiver)471 static void DoTest(std::shared_ptr<ImageReceiver> imageReceiver)
472 {
473     OHOS::BufferRequestConfig requestConfig = {
474         .width = 0x100,
475         .height = 0x100,
476         .strideAlignment = 0x8,
477         .format = PIXEL_FMT_RGBA_8888,
478         .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
479         .timeout = 0,
480     };
481 
482     OHOS::BufferFlushConfig flushConfig = {
483         .damage = {
484             .w = 0x100,
485             .h = 0x100,
486         },
487     };
488 
489     std::string receiveKey = imageReceiver->iraContext_->GetReceiverKey();
490     IMAGE_ERR("ReceiverKey = %{public}s", receiveKey.c_str());
491     OHOS::sptr<OHOS::Surface> receiverSurface = ImageReceiver::getSurfaceById(receiveKey);
492     IMAGE_ERR("getDefaultWidth = %{public}d", receiverSurface->GetDefaultWidth());
493     IMAGE_ERR("getDefaultHeight = %{public}d", receiverSurface->GetDefaultHeight());
494     IMAGE_ERR("TestRequestBuffer 1 ...");
495     TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
496     IMAGE_ERR("TestRequestBuffer 2 ...");
497     TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
498     IMAGE_ERR("TestRequestBuffer 3 ...");
499     TestRequestBuffer(receiverSurface, requestConfig, flushConfig);
500 }
501 
JsTest(napi_env env,napi_callback_info info)502 napi_value ImageReceiverNapi::JsTest(napi_env env, napi_callback_info info)
503 {
504     IMAGE_FUNCTION_IN();
505     ImageReceiverCommonArgs args = {
506         .env = env, .info = info,
507         .async = CallType::GETTER,
508     };
509     args.argc = ARGS0;
510 
511     args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
512         ic.context->constructor_->isCallBackTest = true;
513         DoTest(ic.context->receiver_);
514         return true;
515     };
516 
517     return JSCommonProcess(args);
518 }
519 #endif
520 
JsGetReceivingSurfaceId(napi_env env,napi_callback_info info)521 napi_value ImageReceiverNapi::JsGetReceivingSurfaceId(napi_env env, napi_callback_info info)
522 {
523     IMAGE_FUNCTION_IN();
524     ImageReceiverCommonArgs args = {
525         .env = env, .info = info,
526         .async = CallType::ASYNC,
527         .name = "JsGetReceivingSurfaceId",
528         .callBack = nullptr,
529         .argc = ARGS1,
530         .queryArgs = PrepareOneArg,
531     };
532 
533     args.callBack = [](napi_env env, napi_status status, Context context) {
534         IMAGE_LINE_IN();
535         napi_value result = nullptr;
536         napi_get_undefined(env, &result);
537 
538         auto native = context->receiver_;
539         if (native == nullptr) {
540             IMAGE_ERR("Native instance is nullptr");
541             context->status = ERR_IMAGE_INIT_ABNORMAL;
542         } else if (native->iraContext_ == nullptr) {
543             IMAGE_ERR("Image receiver context is nullptr");
544             context->status = ERR_IMAGE_INIT_ABNORMAL;
545         } else {
546             napi_create_string_utf8(env, native->iraContext_->GetReceiverKey().c_str(),
547                                     NAPI_AUTO_LENGTH, &result);
548             context->status = SUCCESS;
549         }
550 
551         IMAGE_LINE_OUT();
552         CommonCallbackRoutine(env, context, result);
553     };
554 
555     return JSCommonProcess(args);
556 }
557 
558 #ifdef IMAGE_DEBUG_FLAG
DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)559 static void DoCallBackTest(OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer1)
560 {
561     if (surfaceBuffer1 == nullptr) {
562         IMAGE_ERR("surfaceBuffer1 is null");
563         return;
564     }
565 
566     ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance();
567     shared_ptr<ImageReceiver> imageReceiver1 = imageReceiverManager.getImageReceiverByKeyId("1");
568     IMAGE_ERR("DoCallBackTest format %{public}d", imageReceiver1->iraContext_->GetFormat());
569 
570     InitializationOptions opts;
571     opts.size.width = surfaceBuffer1->GetWidth();
572     opts.size.height = surfaceBuffer1->GetHeight();
573     opts.pixelFormat = OHOS::Media::PixelFormat::BGRA_8888;
574     opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
575     opts.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
576     opts.editable = true;
577     IMAGE_ERR("DoCallBackTest Width %{public}d", opts.size.width);
578     IMAGE_ERR("DoCallBackTest Height %{public}d", opts.size.height);
579 #ifdef SAVE_IMAGE_FLAG
580     int fd = open("/data/receiver/test.jpg", O_RDWR | O_CREAT);
581     imageReceiver1->SaveBufferAsImage(fd, surfaceBuffer1, opts);
582 #endif
583 }
584 #endif
JsReadLatestImage(napi_env env,napi_callback_info info)585 napi_value ImageReceiverNapi::JsReadLatestImage(napi_env env, napi_callback_info info)
586 {
587     IMAGE_FUNCTION_IN();
588     ImageReceiverCommonArgs args = {
589         .env = env, .info = info,
590         .async = CallType::ASYNC,
591         .name = "JsReadLatestImage",
592         .callBack = nullptr,
593         .argc = ARGS1,
594         .queryArgs = PrepareOneArg,
595     };
596 
597     args.callBack = [](napi_env env, napi_status status, Context context) {
598         IMAGE_LINE_IN();
599         napi_value result = nullptr;
600         napi_get_undefined(env, &result);
601 
602         auto native = context->constructor_->imageReceiver_;
603         if (native == nullptr) {
604             IMAGE_ERR("Native instance is nullptr");
605             context->status = ERR_IMAGE_INIT_ABNORMAL;
606         } else {
607             auto surfacebuffer = native->ReadLastImage();
608 #ifdef IMAGE_DEBUG_FLAG
609             if (context->constructor_->isCallBackTest) {
610                 context->constructor_->isCallBackTest = false;
611                 DoCallBackTest(surfacebuffer);
612             }
613 #endif
614             result = ImageNapi::Create(env, surfacebuffer, native);
615             if (result == nullptr) {
616                 IMAGE_ERR("ImageNapi Create failed");
617                 context->status = ERR_IMAGE_INIT_ABNORMAL;
618                 napi_get_undefined(env, &result);
619             } else {
620                 context->status = SUCCESS;
621             }
622         }
623 
624         IMAGE_LINE_OUT();
625         CommonCallbackRoutine(env, context, result);
626     };
627 
628     return JSCommonProcess(args);
629 }
630 
JsReadNextImage(napi_env env,napi_callback_info info)631 napi_value ImageReceiverNapi::JsReadNextImage(napi_env env, napi_callback_info info)
632 {
633     IMAGE_FUNCTION_IN();
634     ImageReceiverCommonArgs args = {
635         .env = env, .info = info,
636         .async = CallType::ASYNC,
637         .name = "JsReadNextImage",
638         .callBack = nullptr,
639         .argc = ARGS1,
640         .queryArgs = PrepareOneArg,
641     };
642 
643     args.callBack = [](napi_env env, napi_status status, Context context) {
644         IMAGE_LINE_IN();
645         napi_value result = nullptr;
646         napi_get_undefined(env, &result);
647 
648         auto native = context->constructor_->imageReceiver_;
649         if (native == nullptr) {
650             IMAGE_ERR("Native instance is nullptr");
651             context->status = ERR_IMAGE_INIT_ABNORMAL;
652         } else {
653             auto surfacebuffer = native->ReadNextImage();
654 #ifdef IMAGE_DEBUG_FLAG
655             if (context->constructor_->isCallBackTest) {
656                 context->constructor_->isCallBackTest = false;
657                 DoCallBackTest(surfacebuffer);
658             }
659 #endif
660             result = ImageNapi::Create(env, surfacebuffer, native);
661             if (result == nullptr) {
662                 IMAGE_ERR("ImageNapi Create failed");
663                 context->status = ERR_IMAGE_INIT_ABNORMAL;
664                 napi_get_undefined(env, &result);
665             } else {
666                 context->status = SUCCESS;
667             }
668         }
669 
670         IMAGE_LINE_OUT();
671         CommonCallbackRoutine(env, context, result);
672     };
673 
674     return JSCommonProcess(args);
675 }
676 
JsOnQueryArgs(ImageReceiverCommonArgs & args,ImageReceiverInnerContext & ic)677 static bool JsOnQueryArgs(ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic)
678 {
679     if (ic.argc == ARGS2) {
680         auto argType0 = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
681         auto argType1 = ImageNapiUtils::getType(args.env, ic.argv[PARAM1]);
682         if (argType0 == napi_string && argType1 == napi_function) {
683             if (!ImageNapiUtils::GetUtf8String(args.env, ic.argv[PARAM0], ic.onType)) {
684                 IMAGE_ERR("Could not get On type string");
685                 return false;
686             }
687             napi_create_reference(args.env, ic.argv[PARAM1], ic.refCount, &(ic.context->callbackRef));
688         } else {
689             IMAGE_ERR("Unsupport args type: %{public}d %{public}d", argType0, argType1);
690             return false;
691         }
692     } else {
693         IMAGE_ERR("Invailed argc: %{public}zu", ic.argc);
694         return false;
695     }
696 
697     napi_get_undefined(args.env, &ic.result);
698     return true;
699 }
700 
DoCallBack(shared_ptr<ImageReceiverAsyncContext> context,string name,CompleteCallback callBack)701 void ImageReceiverNapi::DoCallBack(shared_ptr<ImageReceiverAsyncContext> context,
702                                    string name, CompleteCallback callBack)
703 {
704     IMAGE_FUNCTION_IN();
705     if (context == nullptr) {
706         IMAGE_ERR("gContext is empty");
707         return;
708     }
709 
710     if (context->env == nullptr) {
711         IMAGE_ERR("env is empty");
712         return;
713     }
714 
715     uv_loop_s *loop = nullptr;
716     napi_get_uv_event_loop(context->env, &loop);
717     if (loop == nullptr) {
718         IMAGE_ERR("napi_get_uv_event_loop failed");
719         return;
720     }
721 
722     unique_ptr<uv_work_t> work = make_unique<uv_work_t>();
723     if (work == nullptr) {
724         IMAGE_ERR("DoCallBack: No memory");
725         return;
726     }
727 
728     work->data = reinterpret_cast<void *>(context.get());
729     int ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
730         IMAGE_LINE_IN();
731         Context context = reinterpret_cast<Context>(work->data);
732         if (context == nullptr) {
733             IMAGE_ERR("contex is empty");
734         } else {
735             napi_value result[PARAM2] = {0};
736             napi_value retVal;
737             napi_value callback = nullptr;
738             if (context->env != nullptr && context->callbackRef != nullptr) {
739                 napi_create_uint32(context->env, SUCCESS, &result[0]);
740                 napi_get_undefined(context->env, &result[1]);
741                 napi_get_reference_value(context->env, context->callbackRef, &callback);
742                 if (callback != nullptr) {
743                     napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
744                 } else {
745                     IMAGE_ERR("napi_get_reference_value callback is empty");
746                 }
747             } else {
748                 IMAGE_ERR("env or callbackRef is empty");
749             }
750         }
751         if (work != nullptr) {
752             delete work;
753         }
754         IMAGE_LINE_OUT();
755     });
756 
757     if (ret != 0) {
758         IMAGE_ERR("Failed to execute DoCallBack work queue");
759     } else {
760         work.release();
761     }
762     IMAGE_FUNCTION_OUT();
763 }
764 
JsOn(napi_env env,napi_callback_info info)765 napi_value ImageReceiverNapi::JsOn(napi_env env, napi_callback_info info)
766 {
767     IMAGE_FUNCTION_IN();
768     ImageReceiverCommonArgs args = {
769         .env = env, .info = info,
770         .async = CallType::ASYNC,
771         .name = "JsOn",
772     };
773     args.argc = ARGS2;
774     args.asyncLater = true;
775     args.queryArgs = JsOnQueryArgs;
776     args.nonAsyncBack = [](ImageReceiverCommonArgs &args, ImageReceiverInnerContext &ic) -> bool {
777         IMAGE_LINE_IN();
778         napi_get_undefined(args.env, &(ic.result));
779 
780         auto native = ic.context->constructor_->imageReceiver_;
781         if (native == nullptr) {
782             IMAGE_ERR("Native instance is nullptr");
783             ic.context->status = ERR_IMAGE_INIT_ABNORMAL;
784             return false;
785         }
786         shared_ptr<ImageReceiverAvaliableListener> listener = make_shared<ImageReceiverAvaliableListener>();
787         listener->context = std::move(ic.context);
788         listener->context->env = args.env;
789         listener->name = args.name;
790 
791         IMAGE_ERR("listener is %{public}p", listener.get());
792 
793         native->RegisterBufferAvaliableListener((std::shared_ptr<SurfaceBufferAvaliableListener> &)listener);
794 
795         IMAGE_LINE_OUT();
796         return true;
797     };
798 
799     return JSCommonProcess(args);
800 }
801 
JsRelease(napi_env env,napi_callback_info info)802 napi_value ImageReceiverNapi::JsRelease(napi_env env, napi_callback_info info)
803 {
804     IMAGE_FUNCTION_IN();
805     ImageReceiverCommonArgs args = {
806         .env = env, .info = info,
807         .async = CallType::ASYNC,
808         .name = "JsRelease",
809         .callBack = nullptr,
810         .argc = ARGS1,
811         .queryArgs = PrepareOneArg,
812     };
813 
814     args.callBack = [](napi_env env, napi_status status, Context context) {
815         IMAGE_LINE_IN();
816         napi_value result = nullptr;
817         napi_get_undefined(env, &result);
818 
819         context->constructor_->NativeRelease();
820         context->status = SUCCESS;
821 
822         IMAGE_LINE_OUT();
823         CommonCallbackRoutine(env, context, result);
824     };
825 
826     return JSCommonProcess(args);
827 }
828 }  // namespace Media
829 }  // namespace OHOS
830