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 #ifndef AV_TRANSCODER_NAPI_H
17 #define AV_TRANSCODER_NAPI_H
18 
19 #include "av_common.h"
20 #include "media_errors.h"
21 #include "napi/native_api.h"
22 #include "napi/native_node_api.h"
23 #include "common_napi.h"
24 #include "task_queue.h"
25 #include "transcoder.h"
26 
27 namespace OHOS {
28 namespace Media {
29 namespace AVTransCoderState {
30 const std::string STATE_IDLE = "idle";
31 const std::string STATE_PREPARED = "prepared";
32 const std::string STATE_STARTED = "started";
33 const std::string STATE_PAUSED = "paused";
34 const std::string STATE_CANCELLED = "cancelled";
35 const std::string STATE_COMPLETED = "completed";
36 const std::string STATE_RELEASED = "released";
37 const std::string STATE_ERROR = "error";
38 }
39 
40 namespace AVTransCoderOpt {
41 const std::string PREPARE = "Prepare";
42 const std::string START = "Start";
43 const std::string PAUSE = "Pause";
44 const std::string RESUME = "Resume";
45 const std::string CANCEL = "Cancel";
46 const std::string RELEASE = "Release";
47 const std::string SET_AV_TRANSCODER_CONFIG = "SetAVTransCoderConfig";
48 }
49 
50 constexpr int32_t AVTRANSCODER_DEFAULT_AUDIO_BIT_RATE = 48000;
51 constexpr int32_t AVTRANSCODER_DEFAULT_VIDEO_BIT_RATE = -1;
52 constexpr int32_t AVTRANSCODER_DEFAULT_FRAME_HEIGHT = -1;
53 constexpr int32_t AVTRANSCODER_DEFAULT_FRAME_WIDTH = -1;
54 
55 const std::map<std::string, std::vector<std::string>> STATE_LIST = {
56     {AVTransCoderState::STATE_IDLE, {
57         AVTransCoderOpt::PREPARE,
58         AVTransCoderOpt::RELEASE
59     }},
60     {AVTransCoderState::STATE_PREPARED, {
61         AVTransCoderOpt::START,
62         AVTransCoderOpt::RELEASE
63     }},
64     {AVTransCoderState::STATE_STARTED, {
65         AVTransCoderOpt::START,
66         AVTransCoderOpt::PAUSE,
67         AVTransCoderOpt::RESUME,
68         AVTransCoderOpt::CANCEL,
69         AVTransCoderOpt::RELEASE
70     }},
71     {AVTransCoderState::STATE_PAUSED, {
72         AVTransCoderOpt::START,
73         AVTransCoderOpt::PAUSE,
74         AVTransCoderOpt::RESUME,
75         AVTransCoderOpt::CANCEL,
76         AVTransCoderOpt::RELEASE
77     }},
78     {AVTransCoderState::STATE_CANCELLED, {
79         AVTransCoderOpt::RELEASE
80     }},
81     {AVTransCoderState::STATE_COMPLETED, {
82         AVTransCoderOpt::RELEASE
83     }},
84     {AVTransCoderState::STATE_RELEASED, {
85         AVTransCoderOpt::RELEASE
86     }},
87     {AVTransCoderState::STATE_ERROR, {
88         AVTransCoderOpt::RELEASE
89     }},
90 };
91 
92 /**
93  * on(type: 'complete', callback: Callback<void>): void
94  * on(type: 'error', callback: ErrorCallback): void
95  * on(type: 'progressUpdate', callback: Callback<number>): void
96  */
97 namespace AVTransCoderEvent {
98 const std::string EVENT_COMPLETE = "complete";
99 const std::string EVENT_ERROR = "error";
100 const std::string EVENT_PROGRESS_UPDATE = "progressUpdate";
101 }
102 
103 struct AVTransCoderAsyncContext;
104 
105 struct AVTransCoderConfig {
106     AudioCodecFormat audioCodecFormat = AudioCodecFormat::AUDIO_DEFAULT;
107     int32_t audioBitrate = AVTRANSCODER_DEFAULT_AUDIO_BIT_RATE;
108     OutputFormatType fileFormat = OutputFormatType::FORMAT_DEFAULT;
109     VideoCodecFormat videoCodecFormat = VideoCodecFormat::VIDEO_DEFAULT;
110     int32_t videoBitrate = AVTRANSCODER_DEFAULT_VIDEO_BIT_RATE;
111     int32_t videoFrameWidth = AVTRANSCODER_DEFAULT_FRAME_HEIGHT;
112     int32_t videoFrameHeight = AVTRANSCODER_DEFAULT_FRAME_WIDTH;
113 };
114 
115 using RetInfo = std::pair<int32_t, std::string>;
116 
117 class AVTransCoderNapi {
118 public:
119     __attribute__((visibility("default"))) static napi_value Init(napi_env env, napi_value exports);
120 
121     using AvTransCoderTaskqFunc = RetInfo (AVTransCoderNapi::*)();
122 
123 private:
124     static napi_value Constructor(napi_env env, napi_callback_info info);
125     static void Destructor(napi_env env, void *nativeObject, void *finalize);
126     /**
127      * createAVTransCoder(): Promise<VideoPlayer>
128      */
129     static napi_value JsCreateAVTransCoder(napi_env env, napi_callback_info info);
130     /**
131      * prepare(config: AVTransCoderConfig): Promise<void>;
132      */
133     static napi_value JsPrepare(napi_env env, napi_callback_info info);
134     /**
135      * start(): Promise<void>;
136      */
137     static napi_value JsStart(napi_env env, napi_callback_info info);
138     /**
139      * pause(): Promise<void>;
140      */
141     static napi_value JsPause(napi_env env, napi_callback_info info);
142     /**
143      * resume(): Promise<void>;
144      */
145     static napi_value JsResume(napi_env env, napi_callback_info info);
146     /**
147      * cancel(): Promise<void>;
148      */
149     static napi_value JsCancel(napi_env env, napi_callback_info info);
150     /**
151      * release(): Promise<void>
152      */
153     static napi_value JsRelease(napi_env env, napi_callback_info info);
154     /**
155      * on(type: 'complete', callback: Callback<void>): void
156      * on(type: 'error', callback: ErrorCallback): void
157      * on(type: 'progressUpdate', callback: Callback<number>): void
158      */
159     static napi_value JsSetEventCallback(napi_env env, napi_callback_info info);
160     /**
161      * off(type: 'complete'): void;
162      * off(type: 'error'): void;
163      * off(type: 'progressUpdate'): void
164      */
165     static napi_value JsCancelEventCallback(napi_env env, napi_callback_info info);
166 
167     /**
168      * srcUrl: string
169      */
170     static napi_value JsGetSrcUrl(napi_env env, napi_callback_info info);
171 
172     static napi_value JsSetSrcFd(napi_env env, napi_callback_info info);
173     static napi_value JsGetSrcFd(napi_env env, napi_callback_info info);
174 
175     static napi_value JsSetDstFd(napi_env env, napi_callback_info info);
176     static napi_value JsGetDstFd(napi_env env, napi_callback_info info);
177 
178     static AVTransCoderNapi* GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
179         size_t &argCount, napi_value *args);
180     static napi_value ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt);
181     static std::shared_ptr<TaskHandler<RetInfo>> GetPrepareTask(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx);
182     static std::shared_ptr<TaskHandler<RetInfo>> GetPromiseTask(AVTransCoderNapi *avnapi, const std::string &opt);
183 
184     static int32_t GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat);
185     static int32_t GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat);
186     static int32_t GetOutputFormat(const std::string &extension, OutputFormatType &type);
187 
188     AVTransCoderNapi();
189     ~AVTransCoderNapi();
190 
191     RetInfo Start();
192     RetInfo Pause();
193     RetInfo Resume();
194     RetInfo Cancel();
195     RetInfo Release();
196 
197     RetInfo SetInputFile(int32_t fd, int64_t offset, int64_t size);
198     RetInfo SetOutputFile(int32_t fd);
199 
200     int32_t CheckStateMachine(const std::string &opt);
201     int32_t CheckRepeatOperation(const std::string &opt);
202 
203     void ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add = "");
204     void StateCallback(const std::string &state);
205     void SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref);
206     void CancelCallbackReference(const std::string &callbackName);
207     void CancelCallback();
208 
209     RetInfo Configure(std::shared_ptr<AVTransCoderConfig> config);
210     int32_t GetAudioConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx, napi_env env, napi_value args);
211     int32_t GetVideoConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx, napi_env env, napi_value args);
212     int32_t GetConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx, napi_env env, napi_value args);
213 
214     static thread_local napi_ref constructor_;
215     napi_env env_ = nullptr;
216     std::shared_ptr<TransCoder> transCoder_ = nullptr;
217     std::shared_ptr<TransCoderCallback> transCoderCb_ = nullptr;
218     std::map<std::string, std::shared_ptr<AutoRef>> eventCbMap_;
219     std::unique_ptr<TaskQueue> taskQue_;
220     static std::map<std::string, AvTransCoderTaskqFunc> taskQFuncs_;
221     bool hasConfiged_ = false;
222 
223     std::string srcUrl_ = "";
224     struct AVFileDescriptor srcFd_;
225     int32_t dstFd_ = -1;
226 };
227 
228 struct AVTransCoderAsyncContext : public MediaAsyncContext {
AVTransCoderAsyncContextAVTransCoderAsyncContext229     explicit AVTransCoderAsyncContext(napi_env env) : MediaAsyncContext(env) {}
230     ~AVTransCoderAsyncContext() = default;
231 
232     void AVTransCoderSignError(int32_t errCode, const std::string &operate,
233         const std::string &param, const std::string &add = "");
234 
235     AVTransCoderNapi *napi = nullptr;
236     std::shared_ptr<AVTransCoderConfig> config_ = nullptr;
237     std::string opt_ = "";
238     std::shared_ptr<TaskHandler<RetInfo>> task_ = nullptr;
239 };
240 
241 class MediaJsAVTransCoderConfig : public MediaJsResult {
242 public:
MediaJsAVTransCoderConfig(std::shared_ptr<AVTransCoderConfig> value)243     explicit MediaJsAVTransCoderConfig(std::shared_ptr<AVTransCoderConfig> value)
244         : value_(value)
245     {
246     }
247     ~MediaJsAVTransCoderConfig() = default;
248 
249 private:
250     std::shared_ptr<AVTransCoderConfig> value_ = nullptr;
251 };
252 
253 } // namespace Media
254 } // namespace OHOS
255 #endif // AV_RECORDER_NAPI_H