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 ¶m, 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