• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_RECORDER_NAPI_H
17 #define AV_RECORDER_NAPI_H
18 
19 #include "recorder.h"
20 #include "av_common.h"
21 #include "media_errors.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 #include "common_napi.h"
25 #include "task_queue.h"
26 #include "recorder_profiles.h"
27 
28 namespace OHOS {
29 namespace Media {
30 /* type AVRecorderState = 'idle' | 'prepared' | 'started' | 'paused' | 'stopped' | 'released' | 'error'; */
31 namespace AVRecorderState {
32 const std::string STATE_IDLE = "idle";
33 const std::string STATE_PREPARED = "prepared";
34 const std::string STATE_STARTED = "started";
35 const std::string STATE_PAUSED = "paused";
36 const std::string STATE_STOPPED = "stopped";
37 const std::string STATE_RELEASED = "released";
38 const std::string STATE_ERROR = "error";
39 }
40 
41 namespace AVRecordergOpt {
42 const std::string PREPARE = "Prepare";
43 const std::string GETINPUTSURFACE = "GetInputSurface";
44 const std::string START = "Start";
45 const std::string PAUSE = "Pause";
46 const std::string RESUME = "Resume";
47 const std::string STOP = "Stop";
48 const std::string RESET = "Reset";
49 const std::string RELEASE = "Release";
50 const std::string GET_AV_RECORDER_PROFILE = "GetAVRecorderProfile";
51 const std::string SET_AV_RECORDER_CONFIG = "SetAVRecorderConfig";
52 }
53 
54 constexpr int32_t AVRECORDER_DEFAULT_AUDIO_BIT_RATE = 48000;
55 constexpr int32_t AVRECORDER_DEFAULT_AUDIO_CHANNELS = 2;
56 constexpr int32_t AVRECORDER_DEFAULT_AUDIO_SAMPLE_RATE = 48000;
57 constexpr int32_t AVRECORDER_DEFAULT_VIDEO_BIT_RATE = 48000;
58 constexpr int32_t AVRECORDER_DEFAULT_FRAME_HEIGHT = -1;
59 constexpr int32_t AVRECORDER_DEFAULT_FRAME_WIDTH = -1;
60 constexpr int32_t AVRECORDER_DEFAULT_FRAME_RATE = 30;
61 
62 const std::map<std::string, std::vector<std::string>> stateCtrlList = {
63     {AVRecorderState::STATE_IDLE, {
64         AVRecordergOpt::PREPARE,
65         AVRecordergOpt::RESET,
66         AVRecordergOpt::RELEASE,
67         AVRecordergOpt::GET_AV_RECORDER_PROFILE,
68         AVRecordergOpt::SET_AV_RECORDER_CONFIG,
69     }},
70     {AVRecorderState::STATE_PREPARED, {
71         AVRecordergOpt::GETINPUTSURFACE,
72         AVRecordergOpt::START,
73         AVRecordergOpt::RESET,
74         AVRecordergOpt::RELEASE
75     }},
76     {AVRecorderState::STATE_STARTED, {
77         AVRecordergOpt::START,
78         AVRecordergOpt::RESUME,
79         AVRecordergOpt::PAUSE,
80         AVRecordergOpt::STOP,
81         AVRecordergOpt::RESET,
82         AVRecordergOpt::RELEASE
83     }},
84     {AVRecorderState::STATE_PAUSED, {
85         AVRecordergOpt::PAUSE,
86         AVRecordergOpt::RESUME,
87         AVRecordergOpt::STOP,
88         AVRecordergOpt::RESET,
89         AVRecordergOpt::RELEASE
90     }},
91     {AVRecorderState::STATE_STOPPED, {
92         AVRecordergOpt::STOP,
93         AVRecordergOpt::PREPARE,
94         AVRecordergOpt::RESET,
95         AVRecordergOpt::RELEASE
96     }},
97     {AVRecorderState::STATE_RELEASED, {
98         AVRecordergOpt::RELEASE
99     }},
100     {AVRecorderState::STATE_ERROR, {
101         AVRecordergOpt::RESET,
102         AVRecordergOpt::RELEASE
103     }},
104 };
105 
106 /**
107  * on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void
108  * on(type: 'error', callback: ErrorCallback): void
109  */
110 namespace AVRecorderEvent {
111 const std::string EVENT_STATE_CHANGE = "stateChange";
112 const std::string EVENT_ERROR = "error";
113 }
114 
115 struct AVRecorderAsyncContext;
116 struct AVRecorderProfile {
117     int32_t audioBitrate = AVRECORDER_DEFAULT_AUDIO_BIT_RATE;
118     int32_t audioChannels = AVRECORDER_DEFAULT_AUDIO_CHANNELS;
119     int32_t auidoSampleRate = AVRECORDER_DEFAULT_AUDIO_SAMPLE_RATE;
120     AudioCodecFormat audioCodecFormat = AudioCodecFormat::AUDIO_DEFAULT;
121 
122     int32_t videoBitrate = AVRECORDER_DEFAULT_VIDEO_BIT_RATE;
123     int32_t videoFrameWidth = AVRECORDER_DEFAULT_FRAME_HEIGHT;
124     int32_t videoFrameHeight = AVRECORDER_DEFAULT_FRAME_WIDTH;
125     int32_t videoFrameRate = AVRECORDER_DEFAULT_FRAME_RATE;
126     VideoCodecFormat videoCodecFormat = VideoCodecFormat::VIDEO_DEFAULT;
127 
128     OutputFormatType fileFormat = OutputFormatType::FORMAT_DEFAULT;
129 };
130 
131 struct AVRecorderConfig {
132     AudioSourceType audioSourceType; // source type;
133     VideoSourceType videoSourceType;
134     AVRecorderProfile profile;
135     std::string url;
136     int32_t rotation = 0; // Optional
137     Location location; // Optional
138     bool withVideo = false;
139     bool withAudio = false;
140 };
141 
142 using RetInfo = std::pair<int32_t, std::string>;
143 
144 class AVRecorderNapi {
145 public:
146     __attribute__((visibility("default"))) static napi_value Init(napi_env env, napi_value exports);
147 
148     using AvRecorderTaskqFunc = RetInfo (AVRecorderNapi::*)();
149 
150 private:
151     static napi_value Constructor(napi_env env, napi_callback_info info);
152     static void Destructor(napi_env env, void *nativeObject, void *finalize);
153     /**
154      * createAVRecorder(callback: AsyncCallback<VideoPlayer>): void
155      * createAVRecorder(): Promise<VideoPlayer>
156      */
157     static napi_value JsCreateAVRecorder(napi_env env, napi_callback_info info);
158     /**
159      * prepare(config: AVRecorderConfig, callback: AsyncCallback<void>): void;
160      * prepare(config: AVRecorderConfig): Promise<void>;
161      */
162     static napi_value JsPrepare(napi_env env, napi_callback_info info);
163     /**
164      * getInputSurface(callback: AsyncCallback<string>): void
165      * getInputSurface(): Promise<string>
166      */
167     static napi_value JsGetInputSurface(napi_env env, napi_callback_info info);
168     /**
169      * start(callback: AsyncCallback<void>): void;
170      * start(): Promise<void>;
171      */
172     static napi_value JsStart(napi_env env, napi_callback_info info);
173     /**
174      * pause(callback: AsyncCallback<void>): void;
175      * pause(): Promise<void>;
176      */
177     static napi_value JsPause(napi_env env, napi_callback_info info);
178     /**
179      * resume(callback: AsyncCallback<void>): void;
180      * resume(): Promise<void>;
181      */
182     static napi_value JsResume(napi_env env, napi_callback_info info);
183     /**
184      * stop(callback: AsyncCallback<void>): void;
185      * stop(): Promise<void>;
186      */
187     static napi_value JsStop(napi_env env, napi_callback_info info);
188     /**
189      * reset(callback: AsyncCallback<void>): void
190      * reset(): Promise<void>
191      */
192     static napi_value JsReset(napi_env env, napi_callback_info info);
193     /**
194      * release(callback: AsyncCallback<void>): void
195      * release(): Promise<void>
196      */
197     static napi_value JsRelease(napi_env env, napi_callback_info info);
198     /**
199      * on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void
200      * on(type: 'error', callback: ErrorCallback): void
201      */
202     static napi_value JsSetEventCallback(napi_env env, napi_callback_info info);
203     /**
204      * off(type: 'stateChange'): void;
205      * off(type: 'error'): void;
206      */
207     static napi_value JsCancelEventCallback(napi_env env, napi_callback_info info);
208     /**
209      * readonly state: AVRecorderState;
210      */
211     static napi_value JsGetState(napi_env env, napi_callback_info info);
212     /**
213      * getVideoRecorderProfile(sourceId: number, qualityLevel: VideoRecorderQualityLevel,
214      *     callback: AsyncCallback<AVRecorderProfile>);
215      * getVideoRecorderProfile(sourceId: number, qualityLevel: VideoRecorderQualityLevel): Promise<AVRecorderProfile>;
216     */
217     static napi_value JsGetAVRecorderProfile(napi_env env, napi_callback_info info);
218     /**
219      * setAVRecorderConfig(config: AVRecorderConfig, callback: AsyncCallback<void>): void;
220      * setAVRecorderConfig(config: AVRecorderConfig): Promise<void>;
221     */
222     static napi_value JsSetAVRecorderConfig(napi_env env, napi_callback_info info);
223 
224     static AVRecorderNapi* GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
225         size_t &argCount, napi_value *args);
226     static std::shared_ptr<TaskHandler<RetInfo>> GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx);
227     static std::shared_ptr<TaskHandler<RetInfo>> GetPromiseTask(AVRecorderNapi *avnapi, const std::string &opt);
228     static std::shared_ptr<TaskHandler<RetInfo>> GetAVRecorderProfileTask(
229         const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx);
230     static std::shared_ptr<TaskHandler<RetInfo>> SetAVRecorderConfigTask(
231         std::unique_ptr<AVRecorderAsyncContext> &asyncCtx);
232     static napi_value ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt);
233 
234     static int32_t GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat);
235     static int32_t GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat);
236     static int32_t GetOutputFormat(const std::string &extension, OutputFormatType &type);
237 
238     static int32_t GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result,
239         bool &getValue);
240 
241     static int32_t GetAVRecorderProfile(std::shared_ptr<AVRecorderProfile> &profile,
242         const int32_t sourceId, const int32_t qualityLevel);
243 
244     AVRecorderNapi();
245     ~AVRecorderNapi();
246 
247     RetInfo GetInputSurface();
248     RetInfo Start();
249     RetInfo Pause();
250     RetInfo Resume();
251     RetInfo Stop();
252     RetInfo Reset();
253     RetInfo Release();
254     RetInfo GetVideoRecorderProfile();
255 
256     void ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add = "");
257     void StateCallback(const std::string &state);
258     void SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref);
259     void CancelCallbackReference(const std::string &callbackName);
260     void CancelCallback();
261     void RemoveSurface();
262 
263     int32_t CheckStateMachine(const std::string &opt);
264     int32_t CheckRepeatOperation(const std::string &opt);
265     int32_t GetSourceType(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args);
266     int32_t GetProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args);
267     int32_t GetConfig(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args);
268     int32_t GetSourceIdAndQuality(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env,
269         napi_value sourceIdArgs, napi_value qualityArgs, const std::string &opt);
270     RetInfo SetProfile(std::shared_ptr<AVRecorderConfig> config);
271     RetInfo Configure(std::shared_ptr<AVRecorderConfig> config);
272 
273     static thread_local napi_ref constructor_;
274     napi_env env_ = nullptr;
275     std::shared_ptr<Recorder> recorder_ = nullptr;
276     std::shared_ptr<RecorderCallback> recorderCb_ = nullptr;
277     std::map<std::string, std::shared_ptr<AutoRef>> eventCbMap_;
278     std::unique_ptr<TaskQueue> taskQue_;
279     static std::map<std::string, AvRecorderTaskqFunc> taskQFuncs_;
280     sptr<Surface> surface_ = nullptr;
281     int32_t videoSourceID_ = -1;
282     int32_t audioSourceID_ = -1;
283     bool withVideo_ = false;
284     bool getVideoInputSurface_ = false;
285     int32_t sourceId_ = -1;
286     int32_t qualityLevel_ = -1;
287     bool hasConfiged_ = false;
288 };
289 
290 struct AVRecorderAsyncContext : public MediaAsyncContext {
AVRecorderAsyncContextAVRecorderAsyncContext291     explicit AVRecorderAsyncContext(napi_env env) : MediaAsyncContext(env) {}
292     ~AVRecorderAsyncContext() = default;
293 
294     void AVRecorderSignError(int32_t errCode, const std::string &operate,
295         const std::string &param, const std::string &add = "");
296 
297     AVRecorderNapi *napi = nullptr;
298     std::shared_ptr<AVRecorderConfig> config_ = nullptr;
299     std::string opt_ = "";
300     std::shared_ptr<TaskHandler<RetInfo>> task_ = nullptr;
301     std::shared_ptr<AVRecorderProfile> profile_ = nullptr;
302 };
303 
304 class MediaJsAVRecorderProfile : public MediaJsResult {
305 public:
MediaJsAVRecorderProfile(std::shared_ptr<AVRecorderProfile> value)306     explicit MediaJsAVRecorderProfile(std::shared_ptr<AVRecorderProfile> value)
307         : value_(value)
308     {
309     }
310     ~MediaJsAVRecorderProfile() = default;
311     napi_status GetJsResult(napi_env env, napi_value &result) override;
312     int32_t SetAudioCodecFormat(AudioCodecFormat &codecFormat, std::string &mime);
313     int32_t SetVideoCodecFormat(VideoCodecFormat &codecFormat, std::string &mime);
314     int32_t SetFileFormat(OutputFormatType &type, std::string &extension);
315 
316 private:
317     std::shared_ptr<AVRecorderProfile> value_ = nullptr;
318 };
319 } // namespace Media
320 } // namespace OHOS
321 #endif // AV_RECORDER_NAPI_H