1 /*
2 * Copyright (c) 2025 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 "PlayerNative.h"
17 #include "dfx/error/av_codec_sample_error.h"
18
19 #undef LOG_DOMAIN
20 #undef LOG_TAG
21 #define LOG_DOMAIN 0xFF00
22 #define LOG_TAG "player"
23
24 struct CallbackContext {
25 napi_env env = nullptr;
26 napi_ref callbackRef = nullptr;
27 };
28
Callback(void * asyncContext)29 void Callback(void *asyncContext)
30 {
31 uv_loop_s *loop = nullptr;
32 CallbackContext *context = (CallbackContext *)asyncContext;
33 napi_get_uv_event_loop(context->env, &loop);
34 uv_work_t *work = new uv_work_t;
35 work->data = context;
36 uv_queue_work(
37 loop, work, [](uv_work_t *work) {},
38 [](uv_work_t *work, int status) {
39 CallbackContext *context = (CallbackContext *)work->data;
40 napi_handle_scope scope = nullptr;
41 // 管理 napi_value 的生命周期,防止内存泄露
42 napi_open_handle_scope(context->env, &scope);
43 napi_value callback = nullptr;
44 napi_get_reference_value(context->env, context->callbackRef, &callback);
45 // 回调至UI侧
46 napi_call_function(context->env, nullptr, callback, 0, nullptr, nullptr);
47 napi_close_handle_scope(context->env, scope);
48 delete context;
49 delete work;
50 });
51 }
52
SetPlaybackSpeed(napi_env env,napi_callback_info info)53 napi_value PlayerNative::SetPlaybackSpeed(napi_env env, napi_callback_info info)
54 {
55 double speed;
56 size_t argc = 1;
57 napi_value args[1] = {nullptr};
58 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
59
60 napi_get_value_double(env, args[0], &speed);
61 Player::GetInstance().SetSpeed(static_cast<float>(speed));
62 return nullptr;
63 }
64
Play(napi_env env,napi_callback_info info)65 napi_value PlayerNative::Play(napi_env env, napi_callback_info info)
66 {
67 SampleInfo sampleInfo;
68 size_t argc = 6; // 参数个数,这里ArkTS往native测传递了四个参数,故此处赋值为4
69 napi_value args[6] = {nullptr}; // napi_value类型数组,用于存储接收的ArkTS侧参数
70 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); // 从info中获取参数信息到参数数组args[]
71
72 int index = 0;
73 napi_get_value_int32(env, args[index++], &sampleInfo.inputFd);
74 napi_get_value_int64(env, args[index++], &sampleInfo.inputFileOffset);
75 napi_get_value_int64(env, args[index++], &sampleInfo.inputFileSize);
76 napi_get_value_int32(env, args[index++], &sampleInfo.codecType);
77 napi_get_value_int32(env, args[index++], &sampleInfo.codecRunMode);
78
79 auto asyncContext = new CallbackContext();
80 asyncContext->env = env;
81 napi_create_reference(env, args[index], 1, &asyncContext->callbackRef);
82
83 sampleInfo.playDoneCallback = &Callback;
84 sampleInfo.playDoneCallbackData = asyncContext;
85 int32_t ret = Player::GetInstance().Init(sampleInfo);
86 if (ret == AVCODEC_SAMPLE_ERR_OK) {
87 Player::GetInstance().Start();
88 }
89 return nullptr;
90 }
91
92 EXTERN_C_START
Init(napi_env env,napi_value exports)93 static napi_value Init(napi_env env, napi_value exports)
94 {
95 napi_property_descriptor classProp[] = {
96 {"playNative", nullptr, PlayerNative::Play, nullptr, nullptr, nullptr, napi_default, nullptr},
97 {"setPlaybackSpeed", nullptr, PlayerNative::SetPlaybackSpeed, nullptr, nullptr, nullptr, napi_default, nullptr},
98 };
99
100 NativeXComponentSample::PluginManager::GetInstance()->Export(env, exports);
101 napi_define_properties(env, exports, sizeof(classProp) / sizeof(classProp[0]), classProp);
102 return exports;
103 }
104 EXTERN_C_END
105
106 static napi_module PlayerModule = {
107 .nm_version = 1,
108 .nm_flags = 0,
109 .nm_filename = nullptr,
110 .nm_register_func = Init,
111 .nm_modname = "player",
112 .nm_priv = ((void *)0),
113 .reserved = { 0 },
114 };
115
RegisterPlayerModule(void)116 extern "C" __attribute__((constructor)) void RegisterPlayerModule(void)
117 {
118 napi_module_register(&PlayerModule);
119 }