• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "avimagegenerator_napi.h"
17 #include "media_log.h"
18 #include "media_errors.h"
19 #include "common_napi.h"
20 #include "pixel_map_napi.h"
21 #include "string_ex.h"
22 #include "player_xcollie.h"
23 #include "media_dfx.h"
24 #ifdef SUPPORT_JSSTACK
25 #include "xpower_event_js.h"
26 #endif
27 #include "av_common.h"
28 #if !defined(CROSS_PLATFORM)
29 #include "ipc_skeleton.h"
30 #include "tokenid_kit.h"
31 #endif
32 
33 using namespace OHOS::AudioStandard;
34 
35 namespace {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVImageGeneratorNapi" };
37 constexpr uint8_t ARG_ZERO = 0;
38 constexpr uint8_t ARG_ONE = 1;
39 constexpr uint8_t ARG_TWO = 2;
40 constexpr uint8_t ARG_THREE = 3;
41 constexpr uint8_t ARG_FOUR = 4;
42 }
43 
44 namespace OHOS {
45 namespace Media {
46 thread_local napi_ref AVImageGeneratorNapi::constructor_ = nullptr;
47 const std::string CLASS_NAME = "AVImageGenerator";
48 
AVImageGeneratorNapi()49 AVImageGeneratorNapi::AVImageGeneratorNapi()
50 {
51     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
52 }
53 
~AVImageGeneratorNapi()54 AVImageGeneratorNapi::~AVImageGeneratorNapi()
55 {
56     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
57 }
58 
Init(napi_env env,napi_value exports)59 napi_value AVImageGeneratorNapi::Init(napi_env env, napi_value exports)
60 {
61     napi_property_descriptor staticProperty[] = {
62         DECLARE_NAPI_STATIC_FUNCTION("createAVImageGenerator", JsCreateAVImageGenerator),
63     };
64 
65     napi_property_descriptor properties[] = {
66         DECLARE_NAPI_FUNCTION("fetchFrameByTime", JsFetchFrameAtTime),
67         DECLARE_NAPI_FUNCTION("fetchScaledFrameByTime", JsFetchScaledFrameAtTime),
68         DECLARE_NAPI_FUNCTION("release", JsRelease),
69 
70         DECLARE_NAPI_GETTER_SETTER("fdSrc", JsGetAVFileDescriptor, JsSetAVFileDescriptor),
71     };
72 
73     napi_value constructor = nullptr;
74     CHECK_AND_RETURN_RET_LOG(sizeof(properties[0]) != 0, nullptr, "Failed to define calss");
75 
76     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
77         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
78     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVImageGenerator class");
79 
80     status = napi_create_reference(env, constructor, 1, &constructor_);
81     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
82 
83     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
84     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
85 
86     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
87     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
88 
89     MEDIA_LOGD("AVImageGeneratorNapi Init success");
90     return exports;
91 }
92 
Constructor(napi_env env,napi_callback_info info)93 napi_value AVImageGeneratorNapi::Constructor(napi_env env, napi_callback_info info)
94 {
95     napi_value result = nullptr;
96     napi_get_undefined(env, &result);
97 
98     size_t argCount = 0;
99     napi_value jsThis = nullptr;
100     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
101     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
102 
103     AVImageGeneratorNapi *generator = new(std::nothrow) AVImageGeneratorNapi();
104     CHECK_AND_RETURN_RET_LOG(generator != nullptr, result, "failed to new AVImageGeneratorNapi");
105 
106     generator->env_ = env;
107     generator->helper_ = AVMetadataHelperFactory::CreateAVMetadataHelper();
108     if (generator->helper_ == nullptr) {
109         delete generator;
110         MEDIA_LOGE("failed to CreateMetadataHelper");
111         return result;
112     }
113 
114     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(generator),
115         AVImageGeneratorNapi::Destructor, nullptr, nullptr);
116     if (status != napi_ok) {
117         delete generator;
118         MEDIA_LOGE("Failed to wrap native instance");
119         return result;
120     }
121 
122     MEDIA_LOGI("Constructor success");
123     return jsThis;
124 }
125 
Destructor(napi_env env,void * nativeObject,void * finalize)126 void AVImageGeneratorNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
127 {
128     MEDIA_LOGI("0x%{public}06" PRIXPTR " Destructor", FAKE_POINTER(nativeObject));
129     (void)finalize;
130     CHECK_AND_RETURN(nativeObject != nullptr);
131     AVImageGeneratorNapi *napi = reinterpret_cast<AVImageGeneratorNapi *>(nativeObject);
132     std::thread([napi]() -> void {
133         MEDIA_LOGD("Destructor Release enter");
134         if (napi != nullptr && napi->helper_ != nullptr) {
135             napi->helper_->Release();
136         }
137         delete napi;
138     }).detach();
139     MEDIA_LOGD("Destructor success");
140 }
141 
JsCreateAVImageGenerator(napi_env env,napi_callback_info info)142 napi_value AVImageGeneratorNapi::JsCreateAVImageGenerator(napi_env env, napi_callback_info info)
143 {
144     MediaTrace trace("AVImageGeneratorNapi::JsCreateAVImageGenerator");
145     napi_value result = nullptr;
146     napi_get_undefined(env, &result);
147     MEDIA_LOGI("JsCreateAVImageGenerator In");
148 
149     std::unique_ptr<MediaAsyncContext> asyncContext = std::make_unique<MediaAsyncContext>(env);
150 
151     // get args
152     napi_value jsThis = nullptr;
153     napi_value args[1] = { nullptr };
154     size_t argCount = 1;
155     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
156     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
157 
158     asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
159     asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
160     asyncContext->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
161     asyncContext->ctorFlag = true;
162 
163     auto ret = MediaAsyncContext::SendCompleteEvent(env, asyncContext.get(), napi_eprio_high);
164     if (ret != napi_status::napi_ok) {
165         MEDIA_LOGE("failed to SendEvent, ret = %{public}d", ret);
166     } else {
167         asyncContext.release();
168     }
169     MEDIA_LOGI("JsCreateAVImageGenerator Out");
170     return result;
171 }
172 
GetFetchFrameArgs(std::unique_ptr<AVImageGeneratorAsyncContext> & asyncCtx,napi_env env,napi_value timeUs,napi_value option,napi_value params)173 int32_t AVImageGeneratorNapi::GetFetchFrameArgs(std::unique_ptr<AVImageGeneratorAsyncContext> &asyncCtx, napi_env env,
174     napi_value timeUs, napi_value option, napi_value params)
175 {
176     napi_status ret = napi_get_value_int64(env, timeUs, &asyncCtx->timeUs_);
177     if (ret != napi_ok) {
178         asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get timeUs");
179         return MSERR_INVALID_VAL;
180     }
181     ret = napi_get_value_int32(env, option, &asyncCtx->option_);
182     if (ret != napi_ok) {
183         asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get option");
184         return MSERR_INVALID_VAL;
185     }
186 
187     int32_t width = -1;
188     if (!CommonNapi::GetPropertyInt32(env, params, "width", width)) {
189         MEDIA_LOGW("failed to get width");
190     }
191 
192     int32_t height = -1;
193     if (!CommonNapi::GetPropertyInt32(env, params, "height", height)) {
194         MEDIA_LOGW("failed to get height");
195     }
196 
197     PixelFormat colorFormat = PixelFormat::RGBA_8888;
198     int32_t formatVal = 3;
199     CommonNapi::GetPropertyInt32(env, params, "colorFormat", formatVal);
200     colorFormat = static_cast<PixelFormat>(formatVal);
201     if (colorFormat != PixelFormat::RGB_565 && colorFormat != PixelFormat::RGB_888 &&
202         colorFormat != PixelFormat::RGBA_8888) {
203         asyncCtx->SignError(MSERR_INVALID_VAL, "formatVal is invalid");
204         return MSERR_INVALID_VAL;
205     }
206 
207     asyncCtx->param_.dstWidth = width;
208     asyncCtx->param_.dstHeight = height;
209     asyncCtx->param_.colorFormat = colorFormat;
210     return MSERR_OK;
211 }
212 
JsFetchFrameAtTime(napi_env env,napi_callback_info info)213 napi_value AVImageGeneratorNapi::JsFetchFrameAtTime(napi_env env, napi_callback_info info)
214 {
215     MediaTrace trace("AVImageGeneratorNapi::JsFetchFrameAtTime");
216     MEDIA_LOGI("JsFetchFrameAtTime  in");
217     const int32_t maxArgs = ARG_FOUR;  // args + callback
218     const int32_t argCallback = ARG_THREE;  // index three, the 4th param if exist
219     const int32_t argPixelParam = ARG_TWO;  // index 2, the 3rd param
220     size_t argCount = maxArgs;
221     napi_value args[maxArgs] = { nullptr };
222     napi_value result = nullptr;
223     napi_get_undefined(env, &result);
224 
225     AVImageGeneratorNapi *napi = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args);
226     CHECK_AND_RETURN_RET_LOG(napi != nullptr, result, "failed to GetJsInstance");
227 
228     auto asyncCtx = std::make_unique<AVImageGeneratorAsyncContext>(env);
229     asyncCtx->innerHelper_ = napi->helper_;
230     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[argCallback]);
231     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
232     napi_valuetype valueType = napi_undefined;
233     bool notParamValid = argCount < argCallback || napi_typeof(env, args[argPixelParam], &valueType) != napi_ok ||
234         valueType != napi_object ||
235         napi->GetFetchFrameArgs(asyncCtx, env, args[ARG_ZERO], args[ARG_ONE], args[ARG_TWO]) != MSERR_OK;
236     if (notParamValid) {
237         asyncCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "JsFetchFrameAtTime");
238     }
239 
240     if (napi->state_ != HelperState::HELPER_STATE_RUNNABLE && !asyncCtx->errFlag) {
241         asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "Current state is not runnable, can't fetchFrame.");
242     }
243 
244     napi_value resource = nullptr;
245     napi_create_string_utf8(env, "JsFetchFrameAtTime", NAPI_AUTO_LENGTH, &resource);
246     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
247         auto asyncCtx = reinterpret_cast<AVImageGeneratorAsyncContext *>(data);
248         CHECK_AND_RETURN_LOG(asyncCtx && !asyncCtx->errFlag && asyncCtx->innerHelper_, "Invalid context.");
249         auto pixelMap = asyncCtx->innerHelper_->
250             FetchFrameYuv(asyncCtx->timeUs_, asyncCtx->option_, asyncCtx->param_);
251         asyncCtx->pixel_ = pixelMap;
252         CHECK_AND_RETURN(asyncCtx->pixel_ == nullptr);
253         asyncCtx->SignError(MSERR_EXT_API9_UNSUPPORT_FORMAT, "FetchFrameByTime failed.");
254     }, CreatePixelMapComplete, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
255     NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
256     asyncCtx.release();
257     MEDIA_LOGI("JsFetchFrameAtTime Out");
258     return result;
259 }
260 
GetFetchScaledFrameArgs(std::unique_ptr<AVImageGeneratorAsyncContext> & asyncCtx,napi_env env,napi_value timeUs,napi_value option,napi_value outputSize)261 int32_t AVImageGeneratorNapi::GetFetchScaledFrameArgs(std::unique_ptr<AVImageGeneratorAsyncContext> &asyncCtx,
262                                                       napi_env env, napi_value timeUs, napi_value option,
263                                                       napi_value outputSize)
264 {
265     napi_status ret = napi_get_value_int64(env, timeUs, &asyncCtx->timeUs_);
266     if (ret != napi_ok) {
267         asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get timeUs");
268         return MSERR_INVALID_VAL;
269     }
270     ret = napi_get_value_int32(env, option, &asyncCtx->option_);
271     if (ret != napi_ok) {
272         asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get option");
273         return MSERR_INVALID_VAL;
274     }
275 
276     int32_t width = 0;
277     int32_t height = 0;
278     if (outputSize == nullptr) {
279         MEDIA_LOGI("User has not set outputSize");
280     } else {
281         if (!CommonNapi::GetPropertyInt32(env, outputSize, "width", width)) {
282             MEDIA_LOGW("User has not set width");
283         }
284         if (!CommonNapi::GetPropertyInt32(env, outputSize, "height", height)) {
285             MEDIA_LOGW("User has not set height");
286         }
287     }
288 
289     asyncCtx->param_.dstWidth = width;
290     asyncCtx->param_.dstHeight = height;
291     asyncCtx->param_.colorFormat = PixelFormat::UNKNOWN;
292     MEDIA_LOGI("searchMode=%{public}d width=%{public}d height=%{public}d GetFetchScaledFrameArgs",
293         asyncCtx->option_, width, height);
294     return MSERR_OK;
295 }
296 
VerifyTheParameters(napi_env env,napi_callback_info info,std::unique_ptr<AVImageGeneratorAsyncContext> & promiseCtx)297 napi_value AVImageGeneratorNapi::VerifyTheParameters(napi_env env, napi_callback_info info,
298                                                      std::unique_ptr<AVImageGeneratorAsyncContext> &promiseCtx)
299 {
300     size_t argCount = ARG_THREE;
301     const int32_t maxArgs = ARG_THREE;  // timeUs: number, options: AVImageQueryOptions, param: PixelMapParams
302     const int32_t argOutputSizeIndex = ARG_TWO;
303     napi_value args[maxArgs] = { nullptr };
304     napi_value result = nullptr;
305     CHECK_AND_RETURN_RET_LOG(env != nullptr, nullptr, "env is null");
306     napi_get_undefined(env, &result);
307 
308     AVImageGeneratorNapi *napi = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args);
309     CHECK_AND_RETURN_RET_LOG(napi != nullptr, nullptr, "failed to GetJsInstance");
310 
311     promiseCtx = std::make_unique<AVImageGeneratorAsyncContext>(env);
312     CHECK_AND_RETURN_RET_LOG(promiseCtx != nullptr, nullptr, "promiseCtx is null");
313     promiseCtx->napi = napi;
314     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
315 
316     napi_valuetype valueType = napi_undefined;
317     bool notParamValid = argCount < argOutputSizeIndex;
318     if (notParamValid) {
319         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "JsFetchScaledFrameAtTime");
320         return nullptr;
321     }
322     if (argCount == maxArgs) {
323         notParamValid = napi_typeof(env, args[argOutputSizeIndex], &valueType) != napi_ok ||
324             valueType != napi_object || promiseCtx->napi->GetFetchScaledFrameArgs(promiseCtx, env, args[ARG_ZERO],
325             args[ARG_ONE], args[ARG_TWO]) != MSERR_OK;
326     } else {
327         notParamValid = promiseCtx->napi->GetFetchScaledFrameArgs(
328             promiseCtx, env, args[ARG_ZERO], args[ARG_ONE], nullptr) != MSERR_OK;
329     }
330     if (notParamValid) {
331         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "JsFetchScaledFrameAtTime");
332         return nullptr;
333     }
334 
335     if (napi->state_ != HelperState::HELPER_STATE_RUNNABLE) {
336         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
337             "Current state is not runnable, can't fetchScaledFrame.");
338         return nullptr;
339     }
340 
341     return result;
342 }
343 
JsFetchScaledFrameAtTime(napi_env env,napi_callback_info info)344 napi_value AVImageGeneratorNapi::JsFetchScaledFrameAtTime(napi_env env, napi_callback_info info)
345 {
346     MediaTrace trace("AVImageGeneratorNapi::JsFetchScaledFrameAtTime");
347     MEDIA_LOGI("JsFetchScaledFrameAtTime in");
348     std::unique_ptr<AVImageGeneratorAsyncContext> promiseCtx = nullptr;
349     napi_value result = VerifyTheParameters(env, info, promiseCtx);
350     CHECK_AND_RETURN_RET_LOG(result != nullptr, result, "failed to VerifyTheParameters");
351 
352     napi_value resource = nullptr;
353     napi_create_string_utf8(env, "JsFetchScaledFrameAtTime", NAPI_AUTO_LENGTH, &resource);
354     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
355         auto asyncCtx = reinterpret_cast<AVImageGeneratorAsyncContext *>(data);
356         CHECK_AND_RETURN_LOG(asyncCtx && asyncCtx->napi && !asyncCtx->errFlag,
357             "Invalid AVImageGeneratorAsyncContext.");
358         CHECK_AND_RETURN_LOG(asyncCtx->napi->helper_ != nullptr, "Invalid AVImageGeneratorNapi.");
359         auto pixelMap = asyncCtx->napi->helper_->
360             FetchScaledFrameYuv(asyncCtx->timeUs_, asyncCtx->option_, asyncCtx->param_);
361         asyncCtx->pixel_ = pixelMap;
362         if (asyncCtx->pixel_ == nullptr) {
363             asyncCtx->SignError(MSERR_EXT_API9_UNSUPPORT_FORMAT, "JsFetchScaledFrameAtTime failed.");
364         }
365     }, CreatePixelMapComplete, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
366     NAPI_CALL(env, napi_queue_async_work(env, promiseCtx->work));
367     promiseCtx.release();
368     return result;
369 }
370 
CreatePixelMapComplete(napi_env env,napi_status status,void * data)371 void AVImageGeneratorNapi::CreatePixelMapComplete(napi_env env, napi_status status, void *data)
372 {
373     napi_value result = nullptr;
374 
375     MEDIA_LOGI("CreatePixelMapComplete In");
376     auto context = static_cast<AVImageGeneratorAsyncContext*>(data);
377 
378     if (status == napi_ok && context->errCode == napi_ok) {
379         MEDIA_LOGI("set pixel map success");
380         context->status = MSERR_OK;
381         result = Media::PixelMapNapi::CreatePixelMap(env, context->pixel_);
382     } else {
383         context->status = context->errCode == napi_ok ? MSERR_INVALID_VAL : context->errCode;
384         MEDIA_LOGW("set pixel map failed");
385         napi_get_undefined(env, &result);
386     }
387 
388     CommonCallbackRoutine(env, context, result);
389 }
390 
CommonCallbackRoutine(napi_env env,AVImageGeneratorAsyncContext * & asyncContext,const napi_value & valueParam)391 void AVImageGeneratorNapi::CommonCallbackRoutine(napi_env env, AVImageGeneratorAsyncContext* &asyncContext,
392     const napi_value &valueParam)
393 {
394     napi_value result[2] = {0};
395     napi_value retVal;
396     napi_value callback = nullptr;
397 
398     napi_get_undefined(env, &result[0]);
399     napi_get_undefined(env, &result[1]);
400 
401     napi_handle_scope scope = nullptr;
402     napi_open_handle_scope(env, &scope);
403     CHECK_AND_RETURN(scope != nullptr && asyncContext != nullptr);
404     if (asyncContext->status == ERR_OK) {
405         result[1] = valueParam;
406     }
407     napi_create_uint32(env, asyncContext->status, &result[0]);
408 
409     if (asyncContext->errFlag) {
410         (void)CommonNapi::CreateError(env, asyncContext->errCode, asyncContext->errMessage, callback);
411         result[0] = callback;
412     }
413     if (asyncContext->deferred && asyncContext->status == ERR_OK) {
414         napi_resolve_deferred(env, asyncContext->deferred, result[1]);
415     } else if (asyncContext->deferred) {
416         napi_reject_deferred(env, asyncContext->deferred, result[0]);
417     } else {
418         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
419         napi_call_function(env, nullptr, callback, ARG_TWO, result, &retVal);
420         napi_delete_reference(env, asyncContext->callbackRef);
421     }
422 
423     napi_delete_async_work(env, asyncContext->work);
424     napi_close_handle_scope(env, scope);
425 
426     delete asyncContext;
427     asyncContext = nullptr;
428 }
429 
JsRelease(napi_env env,napi_callback_info info)430 napi_value AVImageGeneratorNapi::JsRelease(napi_env env, napi_callback_info info)
431 {
432     MediaTrace trace("AVImageGeneratorNapi::release");
433     napi_value result = nullptr;
434     napi_get_undefined(env, &result);
435     MEDIA_LOGI("JsRelease In");
436 
437     auto promiseCtx = std::make_unique<AVImageGeneratorAsyncContext>(env);
438     napi_value args[1] = { nullptr };
439     size_t argCount = 1;
440     AVImageGeneratorNapi *generator = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args);
441     CHECK_AND_RETURN_RET_LOG(generator != nullptr, result, "failed to GetJsInstance");
442     promiseCtx->innerHelper_ = generator->helper_;
443     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
444     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
445 
446     if (generator->state_ == HelperState::HELPER_STATE_RELEASED) {
447         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "Has released once, can't release again.");
448     }
449 
450     napi_value resource = nullptr;
451     napi_create_string_utf8(env, "JsRelease", NAPI_AUTO_LENGTH, &resource);
452     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
453         auto promiseCtx = reinterpret_cast<AVImageGeneratorAsyncContext *>(data);
454         CHECK_AND_RETURN_LOG(promiseCtx && promiseCtx->innerHelper_, "Invalid promiseCtx.");
455         promiseCtx->innerHelper_->Release();
456     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
457     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
458     promiseCtx.release();
459     MEDIA_LOGI("JsRelease Out");
460     return result;
461 }
462 
JsSetAVFileDescriptor(napi_env env,napi_callback_info info)463 napi_value AVImageGeneratorNapi::JsSetAVFileDescriptor(napi_env env, napi_callback_info info)
464 {
465     MediaTrace trace("AVImageGeneratorNapi::set fd");
466     napi_value result = nullptr;
467     napi_get_undefined(env, &result);
468     MEDIA_LOGI("JsSetAVFileDescriptor In");
469 
470     napi_value args[1] = { nullptr };
471     size_t argCount = 1; // url: string
472     AVImageGeneratorNapi *generator = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args);
473     CHECK_AND_RETURN_RET_LOG(generator != nullptr, result, "failed to GetJsInstanceWithParameter");
474 
475     CHECK_AND_RETURN_RET_LOG(
476         generator->state_ == HelperState::HELPER_STATE_IDLE, result, "Has set source once, unsupport set again");
477 
478     napi_valuetype valueType = napi_undefined;
479     bool notValidParam = argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object ||
480         !CommonNapi::GetFdArgument(env, args[0], generator->fileDescriptor_);
481     CHECK_AND_RETURN_RET_LOG(!notValidParam, result, "Invalid file descriptor, return");
482     CHECK_AND_RETURN_RET_LOG(generator->helper_, result, "Invalid AVImageGeneratorNapi.");
483 
484     auto fileDescriptor = generator->fileDescriptor_;
485     auto res = generator->helper_->SetSource(fileDescriptor.fd, fileDescriptor.offset, fileDescriptor.length);
486     generator->state_ = res == MSERR_OK ? HelperState::HELPER_STATE_RUNNABLE : HelperState::HELPER_ERROR;
487     return result;
488 }
489 
JsGetAVFileDescriptor(napi_env env,napi_callback_info info)490 napi_value AVImageGeneratorNapi::JsGetAVFileDescriptor(napi_env env, napi_callback_info info)
491 {
492     MediaTrace trace("AVImageGeneratorNapi::get fd");
493     napi_value result = nullptr;
494     napi_get_undefined(env, &result);
495     MEDIA_LOGI("JsGetAVFileDescriptor In");
496 
497     AVImageGeneratorNapi *generator = AVImageGeneratorNapi::GetJsInstance(env, info);
498     CHECK_AND_RETURN_RET_LOG(generator != nullptr, result, "failed to GetJsInstance");
499 
500     napi_value value = nullptr;
501     (void)napi_create_object(env, &value);
502     (void)CommonNapi::AddNumberPropInt32(env, value, "fd", generator->fileDescriptor_.fd);
503     (void)CommonNapi::AddNumberPropInt64(env, value, "offset", generator->fileDescriptor_.offset);
504     (void)CommonNapi::AddNumberPropInt64(env, value, "length", generator->fileDescriptor_.length);
505 
506     MEDIA_LOGI("JsGetAVFileDescriptor Out");
507     return value;
508 }
509 
GetJsInstance(napi_env env,napi_callback_info info)510 AVImageGeneratorNapi* AVImageGeneratorNapi::GetJsInstance(napi_env env, napi_callback_info info)
511 {
512     size_t argCount = 0;
513     napi_value jsThis = nullptr;
514     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
515     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
516 
517     AVImageGeneratorNapi *generator = nullptr;
518     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&generator));
519     CHECK_AND_RETURN_RET_LOG(status == napi_ok && generator != nullptr, nullptr, "failed to napi_unwrap");
520 
521     return generator;
522 }
523 
GetJsInstanceWithParameter(napi_env env,napi_callback_info info,size_t & argc,napi_value * argv)524 AVImageGeneratorNapi* AVImageGeneratorNapi::GetJsInstanceWithParameter(napi_env env, napi_callback_info info,
525     size_t &argc, napi_value *argv)
526 {
527     napi_value jsThis = nullptr;
528     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
529     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
530 
531     AVImageGeneratorNapi *generator = nullptr;
532     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&generator));
533     CHECK_AND_RETURN_RET_LOG(status == napi_ok && generator != nullptr, nullptr, "failed to napi_unwrap");
534 
535     return generator;
536 }
537 } // namespace Media
538 } // namespace OHOS