• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "napi/native_api.h"
16 #include <cstdint>
17 #include <map>
18 #include <js_native_api.h>
19 #include "multimedia/player_framework/avtranscoder.h"
20 #include "multimedia/player_framework/avtranscoder_base.h"
21 #include <fstream>
22 #include <hilog/log.h>
23 #include <thread>
24 #include <vector>
25 #include <string>
26 #include <future>
27 #define FAIL (-1)
28 #define SUCCESS 0
29 #define PARAM_0 0
30 #define PARAM_1 1
31 #define PARAM_2 2
32 #define PARAM_3 3
33 #define PARAM_4 4
34 #define LOG_MSG_TAG "AVTransCoderNdk"
35 #define LOG(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
36 #define LOGE(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
37 #define LOGD(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
38 const std::string CREATEAVTRANSCODER_EVENT = "create";
39 const std::string PREPAREAVTRANSCODER_EVENT = "prepare";
40 const std::string STARTAVTRANSCODER_EVENT = "setVideoType";
41 const std::string PAUSEAVTRANSCODER_EVENT = "pause";
42 const std::string RESUMEAVTRANSCODER_EVENT = "resume";
43 const std::string CANCELAVTRANSCODER_EVENT = "cancel";
44 const std::string RELEASEAVTRANSCODER_EVENT = "release";
45 const std::string ERROR_EVENT = "error";
46 const std::string END_EVENT = "end";
47 const std::int32_t AUDIO_BITRATE = 200000;
48 const std::int32_t VIDEO_BITRATE = 3000000;
49 
50 typedef enum {
51     /* prepared states */
52     TRANSCODER_PREPARED = 1,
53     /* started states */
54     TRANSCODER_STARTED = 2,
55     /* paused states */
56     TRANSCODER_PAUSED = 3,
57     /* stopped states */
58     TRANSCODER_CANCELLED = 4,
59     /* completed states */
60     TRANSCODER_COMPLETED = 5,
61 } AVTranscoderState;
62 
63 typedef struct NdkAVTransCoderUser {
64     using StateChangeFunc = std::function<void()>;
65     NdkAVTransCoderUser();
66     NdkAVTransCoderUser(const NdkAVTransCoderUser &other) = delete;
67     NdkAVTransCoderUser &operator=(const NdkAVTransCoderUser &other) = delete;
68     ~NdkAVTransCoderUser();
69 
70     void OnStateChangeCb(OH_AVTranscoder *transcoder, OH_AVTranscoder_State state);
71     void OnErrorCb(OH_AVTranscoder *transcoder, int32_t errorCode, const char *errorMsg);
72     void OnProgressUpdateCb(OH_AVTranscoder *transcoder, int progress);
73     std::map<uint32_t, StateChangeFunc> stateChangeFuncs_;
74 
75     OH_AVTranscoder *transcoder = nullptr;
76     int32_t errorCode = AV_ERR_OK;
77     int32_t transCoderState = -1;
78     int avTranscoderProgress = 0;
79     int inStartStateCount = 0;
80 } NdkAVTransCoderUser;
NdkAVTransCoderUser()81 NdkAVTransCoderUser::NdkAVTransCoderUser() {}
~NdkAVTransCoderUser()82 NdkAVTransCoderUser::~NdkAVTransCoderUser() {}
83 
84 typedef struct NdkAVTransCoderContext {
85     NdkAVTransCoderUser *transcoderUser = nullptr;
86     OH_AVTranscoder *transcoder = nullptr;
87     OH_AVTranscoder_Config *config = nullptr;
88 } NdkAVTransCoderContext;
89 static NdkAVTransCoderContext g_ctx;
90 
OnProgressUpdateCb(OH_AVTranscoder * transcoder,int progress)91 void NdkAVTransCoderUser::OnProgressUpdateCb(OH_AVTranscoder *transcoder, int progress)
92 {
93     LOG("NdkAVTransCoderUser OnProgressUpdateCb progress: %{public}d", progress);
94     this->avTranscoderProgress = progress;
95 }
96 
AvTranscoderRelease(OH_AVTranscoder * transcoder)97 static void AvTranscoderRelease(OH_AVTranscoder *transcoder)
98 {
99     if (transcoder != nullptr) {
100         OH_AVErrCode errCode = OH_AVTranscoder_Release(transcoder);
101         LOG("OH_AVTranscoder_Release errCode:%{public}d", errCode);
102     }
103     if (g_ctx.transcoder != nullptr) {
104         g_ctx.transcoder = nullptr;
105     }
106     if (g_ctx.config != nullptr) {
107         OH_AVErrCode errCode = OH_AVTranscoderConfig_Release(g_ctx.config);
108         g_ctx.config = nullptr;
109         LOG("OH_AVTranscoderConfig_Release errCode:%{public}d", errCode);
110     }
111 }
112 
OnErrorCb(OH_AVTranscoder * transcoder,int32_t errorCode,const char * errorMsg)113 void NdkAVTransCoderUser::OnErrorCb(OH_AVTranscoder *transcoder, int32_t errorCode, const char *errorMsg)
114 {
115     LOG("NdkAVTransCoderUser OnErrorCb errorCode: %{public}d ,errorMsg: %{public}s", errorCode,
116         errorMsg == nullptr ? "unknown" : errorMsg);
117     this->errorCode = errorCode;
118     AvTranscoderRelease(transcoder);
119 }
120 
OnStateChangeCb(OH_AVTranscoder * transcoder,OH_AVTranscoder_State state)121 void NdkAVTransCoderUser::OnStateChangeCb(OH_AVTranscoder *transcoder, OH_AVTranscoder_State state)
122 {
123     if (transcoder == nullptr) {
124         return;
125     }
126     int32_t ret = -1;
127     switch (state) {
128         case AVTRANSCODER_PREPARED: {
129             this->transCoderState = TRANSCODER_PREPARED;
130             if (this->stateChangeFuncs_.count(TRANSCODER_PREPARED) > 0) {
131                 this->stateChangeFuncs_[TRANSCODER_PREPARED]();
132             }
133             break;
134         }
135         case AVTRANSCODER_STARTED: {
136             this->transCoderState = TRANSCODER_STARTED;
137             if (this->stateChangeFuncs_.count(TRANSCODER_STARTED) > 0) {
138                 this->stateChangeFuncs_[TRANSCODER_STARTED]();
139             }
140             break;
141         }
142         case AVTRANSCODER_PAUSED: {
143             this->transCoderState = TRANSCODER_PAUSED;
144             if (this->stateChangeFuncs_.count(TRANSCODER_PAUSED) > 0) {
145                 this->stateChangeFuncs_[TRANSCODER_PAUSED]();
146             }
147             break;
148         }
149         case AVTRANSCODER_CANCELLED: {
150             this->transCoderState = TRANSCODER_CANCELLED;
151             if (this->stateChangeFuncs_.count(TRANSCODER_CANCELLED) > 0) {
152                 this->stateChangeFuncs_[TRANSCODER_CANCELLED]();
153             }
154             break;
155         }
156         case AVTRANSCODER_COMPLETED: {
157             this->transCoderState = TRANSCODER_COMPLETED;
158             if (this->stateChangeFuncs_.count(TRANSCODER_COMPLETED) > 0) {
159                 this->stateChangeFuncs_[TRANSCODER_COMPLETED]();
160             }
161             break;
162         }
163         default:
164             break;
165     }
166 }
167 
AvTranscoderStateChangeCbImpl(OH_AVTranscoder * transcoder,OH_AVTranscoder_State state,void * userData)168 static void AvTranscoderStateChangeCbImpl(OH_AVTranscoder *transcoder, OH_AVTranscoder_State state, void *userData)
169 {
170     LOG("AvTranscoderStateChangeCbImpl state: %{public}d", state);
171     NdkAVTransCoderUser *ndkAVTransCoderUser = reinterpret_cast<NdkAVTransCoderUser *>(userData);
172     if (ndkAVTransCoderUser == nullptr || transcoder == nullptr) {
173         LOGE("AvTranscoderStateChangeCbImpl ndkAVTransCoderUser or transcoder is nullptr");
174         return;
175     }
176     ndkAVTransCoderUser->OnStateChangeCb(transcoder, state);
177 }
178 
AvTranscoderErrorCbImpl(OH_AVTranscoder * transcoder,int32_t errorCode,const char * errorMsg,void * userData)179 static void AvTranscoderErrorCbImpl(OH_AVTranscoder *transcoder, int32_t errorCode, const char *errorMsg,
180                                     void *userData)
181 {
182     LOG("AvTranscoderErrorCbImpl errorCode: %{public}d, errorMsg: %{public}s", errorCode,
183         errorMsg == nullptr ? "unknown" : errorMsg);
184     NdkAVTransCoderUser *ndkAVTransCoderUser = reinterpret_cast<NdkAVTransCoderUser *>(userData);
185     if (ndkAVTransCoderUser == nullptr || transcoder == nullptr) {
186         LOGE("AvTranscoderErrorCbImpl ndkAVTransCoderUser or transcoder is nullptr");
187         return;
188     }
189     ndkAVTransCoderUser->OnErrorCb(transcoder, errorCode, errorMsg);
190 }
191 
AvTranscoderProgressUpdateCbImpl(OH_AVTranscoder * transcoder,int progress,void * userData)192 static void AvTranscoderProgressUpdateCbImpl(OH_AVTranscoder *transcoder, int progress, void *userData)
193 {
194     LOG("AvTranscoderProgressUpdateCbImpl progress: %{public}d", progress);
195     NdkAVTransCoderUser *ndkAVTransCoderUser = reinterpret_cast<NdkAVTransCoderUser *>(userData);
196     if (ndkAVTransCoderUser == nullptr || transcoder == nullptr) {
197         LOGE("AvTranscoderProgressUpdateCbImpl ndkAVTransCoderUser or transcoder is nullptr");
198         return;
199     }
200     ndkAVTransCoderUser->OnProgressUpdateCb(transcoder, progress);
201 }
202 
AvTranscoderStateChangeFuncs(NdkAVTransCoderUser * transcoderUser)203 static void AvTranscoderStateChangeFuncs(NdkAVTransCoderUser *transcoderUser)
204 {
205     transcoderUser->stateChangeFuncs_ = {
206         {TRANSCODER_PREPARED, [transcoderUser]() {
207             // 状态为AVTRANSCODER_PREPARED时开始转码
208             OH_AVErrCode errCode = OH_AVTranscoder_Start(transcoderUser->transcoder);
209             transcoderUser->errorCode = errCode;
210             LOG("OH_AVTranscoder_Start errCode:%{public}d", errCode);
211         }},
212         {TRANSCODER_STARTED, []() { LOG("AvTranscoderStateChange: TRANSCODER_STARTED"); }},
213         {TRANSCODER_PAUSED, []() { LOG("AvTranscoderStateChange: TRANSCODER_PAUSED"); }},
214         {TRANSCODER_CANCELLED, []() { LOG("AvTranscoderStateChange: TRANSCODER_CANCELLED"); }},
215         {TRANSCODER_COMPLETED, [transcoderUser]() {
216             // AVTRANSCODER_COMPLETED时释放资源
217             AvTranscoderRelease(transcoderUser->transcoder);
218         }}};
219 }
220 
createDefaultTransCoderConfig(int32_t dstFd)221 static OH_AVTranscoder_Config *createDefaultTransCoderConfig(int32_t dstFd)
222 {
223     OH_AVTranscoder_Config *config = OH_AVTranscoderConfig_Create();
224     OH_AVTranscoderConfig_SetDstFD(config, dstFd);                                  // 设置转码的目标文件属dstFd。
225     OH_AVTranscoderConfig_SetDstFileType(config, AV_OUTPUT_FORMAT_MPEG_4);          // 封装格式。
226     OH_AVTranscoderConfig_SetDstVideoType(config, "video/avc");                     // 视频编码格式,可选。
227     OH_AVTranscoderConfig_SetDstAudioType(config, "audio/mp4a-latm");               // 音频编码格式,可选。
228     OH_AVTranscoderConfig_SetDstAudioBitrate(config, AUDIO_BITRATE);                // 音频比特率,可选。
229     OH_AVTranscoderConfig_SetDstVideoBitrate(config, VIDEO_BITRATE);                // 视频比特率,可选。
230     return config;
231 }
OHAvTranscoderNdkPlay(napi_env env,napi_callback_info info)232 static napi_value OHAvTranscoderNdkPlay(napi_env env, napi_callback_info info)
233 {
234     napi_value result = nullptr;
235     int backParam = FAIL;
236     size_t argc = PARAM_4;
237     napi_value args[PARAM_4] = {nullptr};
238     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
239     int32_t srcFd = PARAM_0;
240     napi_get_value_int32(env, args[PARAM_0], &srcFd);
241     int64_t srcOffset = PARAM_0;
242     napi_get_value_int64(env, args[PARAM_1], &srcOffset);
243     int64_t length = PARAM_0;
244     napi_get_value_int64(env, args[PARAM_2], &length);
245     int32_t dstFd = PARAM_0;
246     napi_get_value_int32(env, args[PARAM_3], &dstFd);
247 
248     OH_AVTranscoder *transcoder = OH_AVTranscoder_Create();
249     NdkAVTransCoderUser *transcoderUser = nullptr;
250     transcoderUser = new NdkAVTransCoderUser();
251     transcoderUser->transcoder = transcoder;
252     g_ctx.transcoder = transcoder;
253     g_ctx.config = createDefaultTransCoderConfig(dstFd);
254 
255     OH_AVErrCode errCode = OH_AVTranscoderConfig_SetSrcFD(g_ctx.config, srcFd, srcOffset, length); // 设置转码源视频FD
256     OH_AVTranscoder_SetStateCallback(transcoder, AvTranscoderStateChangeCbImpl, transcoderUser); // 设置状态回调
257     OH_AVTranscoder_SetErrorCallback(transcoder, AvTranscoderErrorCbImpl, transcoderUser); // 设置错误码回调
258     OH_AVTranscoder_SetProgressUpdateCallback(transcoder, AvTranscoderProgressUpdateCbImpl, transcoderUser); // 设置进度值回调
259     g_ctx.transcoderUser = transcoderUser;
260     AvTranscoderStateChangeFuncs(transcoderUser);
261     if (errCode != AV_ERR_OK) {
262         backParam = errCode;
263         LOG("Transcoder setSrcFD failed, ret %{public}d", backParam);
264     }
265     errCode = OH_AVTranscoder_Prepare(transcoder, g_ctx.config);
266     if (errCode != AV_ERR_OK) {
267         backParam = errCode;
268         LOG("Transcoder prepare failed, ret %{public}d", backParam);
269     }
270     napi_create_int32(env, backParam, &result);
271     return result;
272 }
273 
OHAvTranscoderNdkPause(napi_env env,napi_callback_info info)274 static napi_value OHAvTranscoderNdkPause(napi_env env, napi_callback_info info)
275 {
276     int ret = 100;
277     ret = OH_AVTranscoder_Pause(g_ctx.transcoder); // 暂停转码
278     LOG("OH_AVTranscoder_Pause ret:%{public}d", ret);
279     napi_value value;
280     napi_create_int32(env, ret, &value);
281     return value;
282 }
283 
OHAvTranscoderNdkResume(napi_env env,napi_callback_info info)284 static napi_value OHAvTranscoderNdkResume(napi_env env, napi_callback_info info)
285 {
286     int ret = 100;
287     ret = OH_AVTranscoder_Resume(g_ctx.transcoder); // 恢复转码
288     LOG("OH_AVTranscoder_Resume ret:%{public}d", ret);
289     napi_value value;
290     napi_create_int32(env, ret, &value);
291     return value;
292 }
293 
OHAvTranscoderNdkCancel(napi_env env,napi_callback_info info)294 static napi_value OHAvTranscoderNdkCancel(napi_env env, napi_callback_info info)
295 {
296     int ret = 100;
297     ret = OH_AVTranscoder_Cancel(g_ctx.transcoder); // 取消转码
298     LOG("OH_AVTranscoder_Cancel ret:%{public}d", ret);
299     napi_value value;
300     napi_create_int32(env, ret, &value);
301     return value;
302 }
303 
OHAvTranscoderNdkRelease(napi_env env,napi_callback_info info)304 static napi_value OHAvTranscoderNdkRelease(napi_env env, napi_callback_info info)
305 {
306     int ret = 100;
307     LOG("OH_AVTranscoder_Release ret:%{public}d", ret);
308     if (g_ctx.transcoder != nullptr) {
309         ret = OH_AVTranscoder_Release(g_ctx.transcoder); // 释放转码实例
310         LOG("OH_AVTranscoder_Release ret:%{public}d", ret);
311         g_ctx.transcoder = nullptr;
312     }
313     if (g_ctx.config != nullptr) {
314         ret = OH_AVTranscoderConfig_Release(g_ctx.config); // 释放转码配置实例
315         LOG("OH_AVTranscoderConfig_Release ret:%{public}d", ret);
316         g_ctx.config = nullptr;
317     }
318     napi_value value;
319     napi_create_int32(env, ret, &value);
320     return value;
321 }
322 
323 EXTERN_C_START
Init(napi_env env,napi_value exports)324 static napi_value Init(napi_env env, napi_value exports)
325 {
326     napi_property_descriptor desc[] = {
327         {"AvTranscoderNdkPlay", nullptr, OHAvTranscoderNdkPlay, nullptr, nullptr, nullptr, napi_default, nullptr},
328         {"AvTranscoderNdkPause", nullptr, OHAvTranscoderNdkPause, nullptr, nullptr, nullptr, napi_default, nullptr},
329         {"AvTranscoderNdkResume", nullptr, OHAvTranscoderNdkResume, nullptr, nullptr, nullptr, napi_default, nullptr},
330         {"AvTranscoderNdkCancel", nullptr, OHAvTranscoderNdkCancel, nullptr, nullptr, nullptr, napi_default, nullptr},
331         {"AvTranscoderNdkRelease", nullptr, OHAvTranscoderNdkRelease, nullptr, nullptr, nullptr, napi_default,
332          nullptr}};
333     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
334     return exports;
335 }
336 EXTERN_C_END
337 
338 static napi_module demoModule = {
339     .nm_version = 1,
340     .nm_flags = 0,
341     .nm_filename = nullptr,
342     .nm_register_func = Init,
343     .nm_modname = "entry",
344     .nm_priv = ((void *)0),
345     .reserved = {0},
346 };
347 
RegisterEntryModule(void)348 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
349