• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sendable_image_receiver_napi.h"
17 
18 #include <algorithm>
19 #include <uv.h>
20 #include "media_errors.h"
21 #include "image_log.h"
22 #include "image_napi_utils.h"
23 #include "sendable_image_napi.h"
24 #include "image_receiver_context.h"
25 #include "image_receiver_manager.h"
26 
27 #undef LOG_DOMAIN
28 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
29 
30 #undef LOG_TAG
31 #define LOG_TAG "SendableImageReceiverNapi"
32 
33 using std::string;
34 using std::shared_ptr;
35 using std::unique_ptr;
36 using std::vector;
37 using std::make_shared;
38 using std::make_unique;
39 
40 namespace OHOS {
41 namespace Media {
42 static const std::string CLASS_NAME = "ImageReceiver";
43 static const std::string DEVICE_ERRCODE = "001";
44 shared_ptr<ImageReceiver> SendableImageReceiverNapi::staticInstance_ = nullptr;
45 thread_local napi_ref SendableImageReceiverNapi::sConstructor_ = nullptr;
46 using SurfaceListener = SurfaceBufferAvaliableListener;
47 
48 const int ARGS0 = 0;
49 const int ARGS1 = 1;
50 const int ARGS2 = 2;
51 const int ARGS3 = 3;
52 const int ARGS4 = 4;
53 const int PARAM0 = 0;
54 const int PARAM1 = 1;
55 const int PARAM2 = 2;
56 const int PARAM3 = 3;
57 
58 struct ImageEnum {
59     std::string name;
60     int32_t numVal;
61     std::string strVal;
62 };
63 
64 static std::vector<struct ImageEnum> sImageFormatVec = {
65     {"CAMERA_APP_INNER", 4, ""},
66     {"JPEG", 2000, ""},
67 };
68 
SendableImageReceiverNapi()69 SendableImageReceiverNapi::SendableImageReceiverNapi():env_(nullptr)
70 {}
71 
~SendableImageReceiverNapi()72 SendableImageReceiverNapi::~SendableImageReceiverNapi()
73 {
74     release();
75 }
76 
CommonCallbackRoutine(napi_env env,Context & context,const napi_value & valueParam,bool isRelease=true)77 static void CommonCallbackRoutine(napi_env env, Context &context, const napi_value &valueParam, bool isRelease = true)
78 {
79     IMAGE_FUNCTION_IN();
80     napi_value result[2] = {0};
81     napi_value retVal;
82     napi_value callback = nullptr;
83 
84     napi_get_undefined(env, &result[0]);
85     napi_get_undefined(env, &result[1]);
86 
87     if (context == nullptr) {
88         IMAGE_ERR("context is nullptr");
89         return;
90     }
91 
92     if (context->status == SUCCESS) {
93         result[1] = valueParam;
94     }
95 
96     if (context->deferred) {
97         if (context->status == SUCCESS) {
98             napi_resolve_deferred(env, context->deferred, result[1]);
99         } else {
100             napi_reject_deferred(env, context->deferred, result[0]);
101         }
102     } else {
103         napi_create_uint32(env, context->status, &result[0]);
104         napi_get_reference_value(env, context->callbackRef, &callback);
105         napi_call_function(env, nullptr, callback, PARAM2, result, &retVal);
106     }
107 
108     if (isRelease) {
109         if (context->callbackRef != nullptr) {
110             napi_delete_reference(env, context->callbackRef);
111             context->callbackRef = nullptr;
112         }
113 
114         napi_delete_async_work(env, context->work);
115 
116         delete context;
117         context = nullptr;
118     }
119     IMAGE_FUNCTION_OUT();
120 }
121 
NativeRelease()122 void SendableImageReceiverNapi::NativeRelease()
123 {
124     imageReceiver_ = nullptr;
125 }
126 
UnRegisterReceiverListener()127 void SendableImageReceiverNapi::UnRegisterReceiverListener()
128 {
129     if (imageReceiver_ != nullptr) {
130         imageReceiver_->UnRegisterBufferAvaliableListener();
131     }
132 }
133 
GetNative()134 ImageReceiver* SendableImageReceiverNapi::GetNative()
135 {
136     if (imageReceiver_ != nullptr) {
137         return imageReceiver_.get();
138     }
139     return nullptr;
140 }
Init(napi_env env,napi_value exports)141 napi_value SendableImageReceiverNapi::Init(napi_env env, napi_value exports)
142 {
143     IMAGE_FUNCTION_IN();
144     napi_property_descriptor props[] = {
145         DECLARE_NAPI_FUNCTION("getReceivingSurfaceId", JsGetReceivingSurfaceId),
146         DECLARE_NAPI_FUNCTION("readLatestImage", JsReadLatestImage),
147         DECLARE_NAPI_FUNCTION("readNextImage", JsReadNextImage),
148         DECLARE_NAPI_FUNCTION("on", JsOn),
149         DECLARE_NAPI_FUNCTION("release", JsRelease),
150 #ifdef IMAGE_DEBUG_FLAG
151         DECLARE_NAPI_GETTER("test", JsTest),
152         DECLARE_NAPI_GETTER("checkDeviceTest", JsCheckDeviceTest),
153         DECLARE_NAPI_GETTER("testYUV", JsTestYUV),
154 #endif
155         DECLARE_NAPI_GETTER("size", JsGetSize),
156         DECLARE_NAPI_GETTER("capacity", JsGetCapacity),
157         DECLARE_NAPI_GETTER("format", JsGetFormat),
158     };
159     napi_property_descriptor static_prop[] = {
160         DECLARE_NAPI_STATIC_FUNCTION("createImageReceiver", JSCreateImageReceiver),
161     };
162 
163     napi_value constructor = nullptr;
164     size_t props_count = IMG_ARRAY_SIZE(props);
165     size_t static_props_count = IMG_ARRAY_SIZE(static_prop);
166 
167     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
168         napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor,
169         nullptr, props_count, props, &constructor)),
170         nullptr,
171         IMAGE_ERR("define class fail")
172     );
173 
174     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
175         napi_create_reference(env, constructor, 1, &sConstructor_)),
176         nullptr,
177         IMAGE_ERR("create reference fail")
178     );
179 
180     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
181         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
182         nullptr,
183         IMAGE_ERR("set named property fail")
184     );
185     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
186         napi_define_properties(env, exports, static_props_count, static_prop)),
187         nullptr,
188         IMAGE_ERR("define properties fail")
189     );
190 
191     IMAGE_DEBUG("Init success");
192 
193     IMAGE_FUNCTION_OUT();
194     return exports;
195 }
196 
197 struct ImageReceiverInputArgs {
198     napi_value thisVar;
199     size_t argc;
200     napi_value argv[ARGS4];
201     int32_t args[ARGS4];
202 };
203 
parseImageReceiverArgs(napi_env env,napi_callback_info info,ImageReceiverInputArgs & args,std::string & errMsg)204 static bool parseImageReceiverArgs(napi_env env, napi_callback_info info,
205     ImageReceiverInputArgs &args, std::string &errMsg)
206 {
207     napi_status status = napi_get_cb_info(env, info, &(args.argc), args.argv, &(args.thisVar), nullptr);
208     if (status != napi_ok) {
209         IMAGE_ERR("fail to napi_get_cb_info %{public}d", status);
210         errMsg = "Fail to napi_get_cb_info";
211         return false;
212     }
213 
214     if (args.argc != ARGS3 && args.argc != ARGS4) {
215         errMsg = "Invalid arg counts ";
216         errMsg.append(std::to_string(args.argc));
217         return false;
218     }
219 
220     return ImageNapiUtils::ParseImageCreatorReceiverArgs(env, args.argc, args.argv, args.args, errMsg);
221 }
222 
Constructor(napi_env env,napi_callback_info info)223 napi_value SendableImageReceiverNapi::Constructor(napi_env env, napi_callback_info info)
224 {
225     napi_value undefineVar = nullptr;
226     napi_get_undefined(env, &undefineVar);
227 
228     IMAGE_FUNCTION_IN();
229     std::string errMsg;
230     ImageReceiverInputArgs inputArgs;
231     inputArgs.argc = ARGS4;
232     if (!parseImageReceiverArgs(env, info, inputArgs, errMsg) || inputArgs.thisVar == nullptr) {
233         IMAGE_ERR("Failure. %{public}s", errMsg.c_str());
234         return undefineVar;
235     }
236     auto reference = std::make_unique<SendableImageReceiverNapi>();
237     reference->env_ = env;
238     reference->imageReceiver_ = ImageReceiver::CreateImageReceiver((inputArgs.args)[PARAM0],
239         (inputArgs.args)[PARAM1], (inputArgs.args)[PARAM2], (inputArgs.args)[PARAM3]);
240     if (reference->imageReceiver_ == nullptr) {
241         IMAGE_ERR("Create native image receiver failed");
242         return undefineVar;
243     }
244     napi_status status = napi_wrap(env, inputArgs.thisVar, reinterpret_cast<void *>(reference.get()),
245         SendableImageReceiverNapi::Destructor, nullptr, nullptr);
246     if (status == napi_ok) {
247         reference.release();
248         return inputArgs.thisVar;
249     }
250     IMAGE_ERR("Failure wrapping js to native napi");
251     return undefineVar;
252 }
253 
Destructor(napi_env env,void * nativeObject,void * finalize)254 void SendableImageReceiverNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
255 {
256     if (nativeObject != nullptr) {
257         delete reinterpret_cast<SendableImageReceiverNapi*>(nativeObject);
258         nativeObject = nullptr;
259     }
260 }
261 
CheckFormat(int32_t format)262 static bool CheckFormat(int32_t format)
263 {
264     return std::any_of(sImageFormatVec.begin(), sImageFormatVec.end(), [format](const auto& imageEnum) {
265         return imageEnum.numVal == format;
266     });
267 }
268 
CreateImageReceiverJsObject(napi_env env,struct SendableImageReceiverCreateArgs args)269 napi_value SendableImageReceiverNapi::CreateImageReceiverJsObject(napi_env env, struct SendableImageReceiverCreateArgs args)
270 {
271     napi_status status;
272     napi_value constructor = nullptr;
273     napi_value result = nullptr;
274     ImageReceiverInputArgs inputArgs;
275     inputArgs.argc = ARGS4;
276 
277     IMAGE_FUNCTION_IN();
278     if (!CheckFormat(args.format)) {
279         IMAGE_ERR("Invalid type");
280         return nullptr;
281     }
282     napi_create_int32(env, args.width, &(inputArgs.argv[PARAM0]));
283     napi_create_int32(env, args.height, &(inputArgs.argv[PARAM1]));
284     napi_create_int32(env, args.format, &(inputArgs.argv[PARAM2]));
285     napi_create_int32(env, args.capicity, &(inputArgs.argv[PARAM3]));
286     status = napi_get_reference_value(env, sConstructor_, &constructor);
287     if (status != napi_ok || constructor == nullptr) {
288         IMAGE_ERR("Failed to get reference of constructor");
289         return nullptr;
290     }
291 
292     status = napi_new_instance(env, constructor, inputArgs.argc, inputArgs.argv, &result);
293     if (status != napi_ok || result == nullptr) {
294         IMAGE_ERR("New instance could not be obtained");
295         return nullptr;
296     }
297 
298     IMAGE_FUNCTION_OUT();
299     return result;
300 }
301 
JSCreateImageReceiver(napi_env env,napi_callback_info info)302 napi_value SendableImageReceiverNapi::JSCreateImageReceiver(napi_env env, napi_callback_info info)
303 {
304     napi_status status;
305     napi_value constructor = nullptr;
306     napi_value result = nullptr;
307     ImageReceiverInputArgs inputArgs;
308     inputArgs.argc = ARGS4;
309 
310     IMAGE_FUNCTION_IN();
311     napi_get_undefined(env, &result);
312 
313     std::string errMsg;
314     if (!parseImageReceiverArgs(env, info, inputArgs, errMsg)) {
315         return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, errMsg);
316     }
317 
318     if (!CheckFormat(inputArgs.args[PARAM2])) {
319         return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Invalid type");
320     }
321 
322     status = napi_get_reference_value(env, sConstructor_, &constructor);
323     if (IMG_IS_OK(status)) {
324         status = napi_new_instance(env, constructor, inputArgs.argc, inputArgs.argv, &result);
325         if (status == napi_ok) {
326             IMAGE_FUNCTION_OUT();
327             return result;
328         } else {
329             IMAGE_ERR("New instance could not be obtained");
330         }
331     }
332 
333     IMAGE_ERR("Failed to get reference of constructor");
334     return result;
335 }
336 
CheckArgs(const SendableImageReceiverCommonArgs & args)337 static bool CheckArgs(const SendableImageReceiverCommonArgs &args)
338 {
339     if (args.async != CallType::GETTER) {
340         if (args.queryArgs == nullptr) {
341             IMAGE_ERR("No query args function");
342             return false;
343         }
344     }
345 
346     if (args.async != CallType::ASYNC || args.asyncLater) {
347         if (args.nonAsyncBack == nullptr) {
348             IMAGE_ERR("No non async back function");
349             return false;
350         }
351     }
352     return true;
353 }
354 
PrepareOneArg(SendableImageReceiverCommonArgs & args,struct SendableImageReceiverInnerContext & ic)355 static bool PrepareOneArg(SendableImageReceiverCommonArgs &args, struct SendableImageReceiverInnerContext &ic)
356 {
357     if (ic.argc == ARGS1) {
358         auto argType = ImageNapiUtils::getType(args.env, ic.argv[PARAM0]);
359         if (argType == napi_function) {
360             napi_create_reference(args.env, ic.argv[PARAM0], ic.refCount, &(ic.context->callbackRef));
361         } else {
362             IMAGE_ERR("Unsupport arg 0 type: %{public}d", argType);
363             return false;
364         }
365     }
366 
367     if (ic.context->callbackRef == nullptr) {
368         napi_create_promise(args.env, &(ic.context->deferred), &(ic.result));
369     } else {
370         napi_get_undefined(args.env, &ic.result);
371     }
372     return true;
373 }
374 
JSCommonProcessSendEvent(SendableImageReceiverCommonArgs & args,napi_status status,SendableImageReceiverAsyncContext * context,napi_event_priority prio)375 static void JSCommonProcessSendEvent(SendableImageReceiverCommonArgs &args, napi_status status,
376                                      SendableImageReceiverAsyncContext* context, napi_event_priority prio)
377 {
378     auto task = [args, status, context]() {
379         (void)args.callBack(args.env, status, context);
380     };
381     if (napi_status::napi_ok != napi_send_event(args.env, task, prio)) {
382         IMAGE_LOGE("JSCommonProcessSendEvent: failed to SendEvent!");
383     }
384 }
385 
JSCommonProcess(SendableImageReceiverCommonArgs & args)386 napi_value SendableImageReceiverNapi::JSCommonProcess(SendableImageReceiverCommonArgs &args)
387 {
388     IMAGE_FUNCTION_IN();
389     struct SendableImageReceiverInnerContext ic;
390     ic.argc = args.argc;
391     ic.argv.resize(ic.argc);
392     napi_get_undefined(args.env, &ic.result);
393 
394     IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);
395 
396     IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);
397 
398     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, IMAGE_ERR("fail to napi_get_cb_info"));
399 
400     if (args.async != CallType::STATIC) {
401         ic.context = std::make_unique<SendableImageReceiverAsyncContext>();
402         if (ic.context == nullptr) {
403             return ic.result;
404         }
405         ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));
406 
407         IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
408             ic.result, IMAGE_ERR("fail to unwrap context"));
409 
410         if (ic.context->constructor_ == nullptr) {
411             return ic.result;
412         }
413 
414         IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_->imageReceiver_),
415             ic.result, IMAGE_ERR("empty native receiver"));
416     }
417     if (args.async != CallType::GETTER) {
418         if (!args.queryArgs(args, ic)) {
419             return ic.result;
420         }
421     }
422 
423     if (args.async == CallType::ASYNC) {
424         if (args.asyncLater) {
425             args.nonAsyncBack(args, ic);
426         } else {
427             JSCommonProcessSendEvent(args, ic.status, ic.context.get(), napi_eprio_high);
428             ic.context.release();
429         }
430     } else {
431         args.nonAsyncBack(args, ic);
432     }
433 
434     IMAGE_FUNCTION_OUT();
435     return ic.result;
436 }
437 
BuildJsSize(napi_env env,int32_t width,int32_t height)438 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
439 {
440     napi_value result = nullptr;
441     napi_value sizeWith = nullptr;
442     napi_value 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 SendableImageReceiverNapi::JsGetSize(napi_env env, napi_callback_info info)
455 {
456     IMAGE_FUNCTION_IN();
457     SendableImageReceiverCommonArgs args = {
458         .env = env, .info = info,
459         .async = CallType::GETTER,
460     };
461     args.argc = ARGS0;
462 
463     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsGetCapacity(napi_env env, napi_callback_info info)
485 {
486     IMAGE_FUNCTION_IN();
487     SendableImageReceiverCommonArgs args = {
488         .env = env, .info = info,
489         .async = CallType::GETTER,
490     };
491     args.argc = ARGS0;
492 
493     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsGetFormat(napi_env env, napi_callback_info info)
513 {
514     IMAGE_FUNCTION_IN();
515     SendableImageReceiverCommonArgs args = {
516         .env = env, .info = info,
517         .async = CallType::GETTER,
518     };
519     args.argc = ARGS0;
520 
521     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 SendableImageReceiverNapi::JsTest(napi_env env, napi_callback_info info)
610 {
611     IMAGE_FUNCTION_IN();
612     SendableImageReceiverCommonArgs args = {
613         .env = env, .info = info,
614         .async = CallType::GETTER,
615     };
616     args.argc = ARGS0;
617 
618     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
619         ic.context->constructor_->isCallBackTest = true;
620         DoTest(ic.context->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsCheckDeviceTest(napi_env env, napi_callback_info info)
628 {
629     IMAGE_FUNCTION_IN();
630     SendableImageReceiverCommonArgs args = {
631         .env = env, .info = info,
632         .async = CallType::GETTER,
633     };
634     args.argc = ARGS0;
635 
636     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsTestYUV(napi_env env, napi_callback_info info)
652 {
653     IMAGE_FUNCTION_IN();
654     SendableImageReceiverCommonArgs args = {
655         .env = env, .info = info,
656         .async = CallType::GETTER,
657     };
658     args.argc = ARGS0;
659 
660     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
661         ic.context->constructor_->isCallBackTest = true;
662         DoTest(ic.context->constructor_->imageReceiver_, 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 SendableImageReceiverNapi::JsGetReceivingSurfaceId(napi_env env, napi_callback_info info)
671 {
672     IMAGE_FUNCTION_IN();
673     SendableImageReceiverCommonArgs 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->constructor_->imageReceiver_;
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 SendableImageReceiverNapi::JsReadLatestImage(napi_env env, napi_callback_info info)
745 {
746     IMAGE_FUNCTION_IN();
747     SendableImageReceiverCommonArgs 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 = SendableImageNapi::Create(env, image);
779         if (result == nullptr) {
780             IMAGE_ERR("SendableImageNapi 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 SendableImageReceiverNapi::JsReadNextImage(napi_env env, napi_callback_info info)
793 {
794     IMAGE_FUNCTION_IN();
795     SendableImageReceiverCommonArgs 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 = SendableImageNapi::Create(env, image);
827         if (result == nullptr) {
828             IMAGE_ERR("SendableImageNapi 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(SendableImageReceiverCommonArgs & args,SendableImageReceiverInnerContext & ic)870 static bool JsOnQueryArgs(SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &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 = "Invalid 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 
DoCallBackNoUvWork(napi_env env,SendableImageReceiverAsyncContext * context)906 static void DoCallBackNoUvWork(napi_env env, SendableImageReceiverAsyncContext* context)
907 {
908     IMAGE_LINE_IN();
909     if (context == nullptr) {
910         IMAGE_ERR("context is empty");
911     } else {
912         if (context->env != nullptr && context->callbackRef != nullptr) {
913             napi_handle_scope scope = nullptr;
914             napi_open_handle_scope(context->env, &scope);
915             if (scope == nullptr) {
916                 return;
917             }
918             napi_value result[PARAM2] = {0};
919             napi_value retVal;
920             napi_value callback = nullptr;
921             napi_create_uint32(context->env, SUCCESS, &result[0]);
922             napi_get_undefined(context->env, &result[1]);
923             napi_get_reference_value(context->env, context->callbackRef, &callback);
924             if (callback != nullptr) {
925                 napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
926             } else {
927                 IMAGE_ERR("napi_get_reference_value callback is empty");
928             }
929             napi_close_handle_scope(context->env, scope);
930         } else {
931             IMAGE_ERR("env or callbackRef is empty");
932         }
933     }
934     IMAGE_LINE_OUT();
935 }
936 
DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> & context,string name,CompleteCallback callBack)937 void SendableImageReceiverNapi::DoCallBack(shared_ptr<SendableImageReceiverAsyncContext> &context,
938                                            string name, CompleteCallback callBack)
939 {
940     IMAGE_FUNCTION_IN();
941     auto localContext = std::make_unique<shared_ptr<SendableImageReceiverAsyncContext>> (context);
942     if (context == nullptr) {
943         IMAGE_ERR("gContext is empty");
944         localContext.release();
945         return;
946     }
947     if (context->env == nullptr) {
948         IMAGE_ERR("env is empty");
949         localContext.release();
950         return;
951     }
952 
953     auto task = [context]() {
954         (void)DoCallBackNoUvWork(context->env, context.get());
955     };
956     if (napi_status::napi_ok != napi_send_event(context->env, task, napi_eprio_high)) {
957         IMAGE_LOGE("DoCallBackSendEvent: failed to SendEvent!");
958     }
959     localContext.release();
960     IMAGE_FUNCTION_OUT();
961 }
962 
JsOn(napi_env env,napi_callback_info info)963 napi_value SendableImageReceiverNapi::JsOn(napi_env env, napi_callback_info info)
964 {
965     IMAGE_FUNCTION_IN();
966     SendableImageReceiverCommonArgs args = {
967         .env = env, .info = info,
968         .async = CallType::ASYNC,
969         .name = "JsOn",
970     };
971     args.argc = ARGS2;
972     args.asyncLater = true;
973     args.queryArgs = JsOnQueryArgs;
974     args.nonAsyncBack = [](SendableImageReceiverCommonArgs &args, SendableImageReceiverInnerContext &ic) -> bool {
975         IMAGE_LINE_IN();
976         napi_get_undefined(args.env, &(ic.result));
977 
978         auto native = ic.context->constructor_->imageReceiver_;
979         if (native == nullptr) {
980             IMAGE_ERR("Native instance is nullptr");
981             ic.context->status = ERR_IMAGE_INIT_ABNORMAL;
982             return false;
983         }
984         shared_ptr<SendableImageReceiverAvaliableListener> listener =
985             make_shared<SendableImageReceiverAvaliableListener>();
986         listener->context = std::move(ic.context);
987         listener->context->env = args.env;
988         listener->name = args.name;
989 
990         native->RegisterBufferAvaliableListener((std::shared_ptr<SurfaceBufferAvaliableListener> &)listener);
991 
992         IMAGE_LINE_OUT();
993         return true;
994     };
995 
996     return JSCommonProcess(args);
997 }
998 
JsRelease(napi_env env,napi_callback_info info)999 napi_value SendableImageReceiverNapi::JsRelease(napi_env env, napi_callback_info info)
1000 {
1001     IMAGE_FUNCTION_IN();
1002     SendableImageReceiverCommonArgs args = {
1003         .env = env, .info = info,
1004         .async = CallType::ASYNC,
1005         .name = "JsRelease",
1006         .callBack = nullptr,
1007         .argc = ARGS1,
1008         .queryArgs = PrepareOneArg,
1009     };
1010 
1011     args.callBack = [](napi_env env, napi_status status, Context context) {
1012         IMAGE_LINE_IN();
1013         napi_value result = nullptr;
1014         napi_get_undefined(env, &result);
1015 
1016         context->constructor_->UnRegisterReceiverListener();
1017         context->constructor_->NativeRelease();
1018         context->status = SUCCESS;
1019 
1020         IMAGE_LINE_OUT();
1021         CommonCallbackRoutine(env, context, result);
1022     };
1023 
1024     return JSCommonProcess(args);
1025 }
1026 
release()1027 void SendableImageReceiverNapi::release()
1028 {
1029     if (!isRelease) {
1030         NativeRelease();
1031         isRelease = true;
1032     }
1033 }
1034 }  // namespace Media
1035 }  // namespace OHOS
1036