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