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_PLAYER_NAPI_H 17 #define AV_PLAYER_NAPI_H 18 19 #include "player.h" 20 #include "media_errors.h" 21 #include "napi/native_api.h" 22 #include "napi/native_node_api.h" 23 #include "avplayer_callback.h" 24 #include "media_data_source_callback.h" 25 #include "common_napi.h" 26 #include "audio_info.h" 27 #include "audio_effect.h" 28 #include "task_queue.h" 29 30 namespace OHOS { 31 namespace Media { 32 namespace AVPlayerState { 33 const std::string STATE_IDLE = "idle"; 34 const std::string STATE_INITIALIZED = "initialized"; 35 const std::string STATE_PREPARED = "prepared"; 36 const std::string STATE_PLAYING = "playing"; 37 const std::string STATE_PAUSED = "paused"; 38 const std::string STATE_STOPPED = "stopped"; 39 const std::string STATE_RELEASED = "released"; 40 const std::string STATE_ERROR = "error"; 41 const std::string STATE_COMPLETED = "completed"; 42 } 43 44 namespace AVPlayerEvent { 45 const std::string EVENT_STATE_CHANGE = "stateChange"; 46 const std::string EVENT_VOLUME_CHANGE = "volumeChange"; 47 const std::string EVENT_END_OF_STREAM = "endOfStream"; 48 const std::string EVENT_SEEK_DONE = "seekDone"; 49 const std::string EVENT_SPEED_DONE = "speedDone"; 50 const std::string EVENT_BITRATE_DONE = "bitrateDone"; 51 const std::string EVENT_TIME_UPDATE = "timeUpdate"; 52 const std::string EVENT_DURATION_UPDATE = "durationUpdate"; 53 const std::string EVENT_SUBTITLE_TEXT_UPDATE = "subtitleTextUpdate"; 54 const std::string EVENT_BUFFERING_UPDATE = "bufferingUpdate"; 55 const std::string EVENT_START_RENDER_FRAME = "startRenderFrame"; 56 const std::string EVENT_VIDEO_SIZE_CHANGE = "videoSizeChange"; 57 const std::string EVENT_AUDIO_INTERRUPT = "audioInterrupt"; 58 const std::string EVENT_AVAILABLE_BITRATES = "availableBitrates"; 59 const std::string EVENT_TRACKCHANGE = "trackChange"; 60 const std::string EVENT_TRACK_INFO_UPDATE = "trackInfoUpdate"; 61 const std::string EVENT_ERROR = "error"; 62 } 63 64 using TaskRet = std::pair<int32_t, std::string>; 65 66 class AVPlayerNapi : public AVPlayerNotify { 67 public: 68 __attribute__((visibility("default"))) static napi_value Init(napi_env env, napi_value exports); 69 70 private: 71 static napi_value Constructor(napi_env env, napi_callback_info info); 72 static void Destructor(napi_env env, void *nativeObject, void *finalize); 73 /** 74 * createAVPlayer(callback: AsyncCallback<VideoPlayer>): void 75 * createAVPlayer(): Promise<VideoPlayer> 76 */ 77 static napi_value JsCreateAVPlayer(napi_env env, napi_callback_info info); 78 /** 79 * prepare(callback: AsyncCallback<void>): void 80 * prepare(): Promise<void> 81 */ 82 static napi_value JsPrepare(napi_env env, napi_callback_info info); 83 /** 84 * play(callback: AsyncCallback<void>): void 85 * play(): Promise<void> 86 */ 87 static napi_value JsPlay(napi_env env, napi_callback_info info); 88 /** 89 * pause(callback: AsyncCallback<void>): void 90 * pause(): Promise<void> 91 */ 92 static napi_value JsPause(napi_env env, napi_callback_info info); 93 /** 94 * stop(callback: AsyncCallback<void>): void 95 * stop(): Promise<void> 96 */ 97 static napi_value JsStop(napi_env env, napi_callback_info info); 98 /** 99 * reset(callback: AsyncCallback<void>): void 100 * reset(): Promise<void> 101 */ 102 static napi_value JsReset(napi_env env, napi_callback_info info); 103 /** 104 * release(callback: AsyncCallback<void>): void 105 * release(): Promise<void> 106 */ 107 static napi_value JsRelease(napi_env env, napi_callback_info info); 108 /** 109 * seek(timeMs: number, mode?:SeekMode): void 110 */ 111 static napi_value JsSeek(napi_env env, napi_callback_info info); 112 /** 113 * setSpeed(speed: number): void 114 */ 115 static napi_value JsSetSpeed(napi_env env, napi_callback_info info); 116 /** 117 * setVolume(vol: number): void 118 */ 119 static napi_value JsSetVolume(napi_env env, napi_callback_info info); 120 /** 121 * selectBitrate(bitRate: number): void 122 */ 123 static napi_value JsSelectBitrate(napi_env env, napi_callback_info info); 124 /** 125 * addSubtitleUrl: string 126 */ 127 static napi_value JsAddSubtitleUrl(napi_env env, napi_callback_info info); 128 /** 129 * addSubtitleFdSrc: AVFileDescriptor 130 */ 131 static napi_value JsAddSubtitleAVFileDescriptor(napi_env env, napi_callback_info info); 132 /** 133 * url: string 134 */ 135 static napi_value JsSetUrl(napi_env env, napi_callback_info info); 136 static napi_value JsGetUrl(napi_env env, napi_callback_info info); 137 /** 138 * fdSrc: AVFileDescriptor 139 */ 140 static napi_value JsGetAVFileDescriptor(napi_env env, napi_callback_info info); 141 static napi_value JsSetAVFileDescriptor(napi_env env, napi_callback_info info); 142 /** 143 * dataSrc: DataSrcDescriptor 144 */ 145 static napi_value JsSetDataSrc(napi_env env, napi_callback_info info); 146 static napi_value JsGetDataSrc(napi_env env, napi_callback_info info); 147 /** 148 * surfaceId?: string 149 */ 150 static napi_value JsSetSurfaceID(napi_env env, napi_callback_info info); 151 static napi_value JsGetSurfaceID(napi_env env, napi_callback_info info); 152 /** 153 * loop: boolenan 154 */ 155 static napi_value JsSetLoop(napi_env env, napi_callback_info info); 156 static napi_value JsGetLoop(napi_env env, napi_callback_info info); 157 /** 158 * videoScaleType?: VideoScaleType 159 */ 160 static napi_value JsSetVideoScaleType(napi_env env, napi_callback_info info); 161 static napi_value JsGetVideoScaleType(napi_env env, napi_callback_info info); 162 /** 163 * audioInterruptMode?: audio.AudioInterruptMode 164 */ 165 static napi_value JsGetAudioInterruptMode(napi_env env, napi_callback_info info); 166 static napi_value JsSetAudioInterruptMode(napi_env env, napi_callback_info info); 167 168 /** 169 * audioRendererInfo?: audio.AudioRendererInfo 170 */ 171 static napi_value JsGetAudioRendererInfo(napi_env env, napi_callback_info info); 172 static napi_value JsSetAudioRendererInfo(napi_env env, napi_callback_info info); 173 174 /** 175 * audioEffectMode ?: audio.AudioEffectMode; 176 */ 177 static napi_value JsGetAudioEffectMode(napi_env env, napi_callback_info info); 178 static napi_value JsSetAudioEffectMode(napi_env env, napi_callback_info info); 179 /** 180 * readonly currentTime: number 181 */ 182 static napi_value JsGetCurrentTime(napi_env env, napi_callback_info info); 183 /** 184 * readonly duration: number 185 */ 186 static napi_value JsGetDuration(napi_env env, napi_callback_info info); 187 /** 188 * readonly state: AVPlayState 189 */ 190 static napi_value JsGetState(napi_env env, napi_callback_info info); 191 /** 192 * readonly width: number 193 */ 194 static napi_value JsGetWidth(napi_env env, napi_callback_info info); 195 /** 196 * readonly height: number 197 */ 198 static napi_value JsGetHeight(napi_env env, napi_callback_info info); 199 /** 200 * getTrackDescription(callback:AsyncCallback<Array<MediaDescription>>): void 201 * getTrackDescription(): Promise<Array<MediaDescription>> 202 */ 203 static napi_value JsGetTrackDescription(napi_env env, napi_callback_info info); 204 /** 205 * selectTrack(index: number): void; 206 */ 207 static napi_value JsSelectTrack(napi_env env, napi_callback_info info); 208 /** 209 * deselectTrack(index: number): void; 210 */ 211 static napi_value JsDeselectTrack(napi_env env, napi_callback_info info); 212 /** 213 * GetCurrentTrack(trackType: MediaType, callback: AsyncCallback<number>): void; 214 * GetCurrentTrack(trackType: MediaType): Promise<number>; 215 */ 216 static napi_value JsGetCurrentTrack(napi_env env, napi_callback_info info); 217 /** 218 * on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void; 219 * off(type: 'stateChange'): void; 220 * on(type: 'volumeChange', callback: Callback<number>): void; 221 * off(type: 'volumeChange'): void; 222 * on(type: 'endOfStream', callback: Callback<void>): void; 223 * off(type: 'endOfStream'): void; 224 * on(type: 'seekDone', callback: Callback<number>): void; 225 * off(type: 'seekDone'): void; 226 * on(type: 'speedDone', callback: Callback<number>): void; 227 * off(type: 'speedDone'): void; 228 * on(type: 'bitrateDone', callback: Callback<number>): void; 229 * off(type: 'bitrateDone'): void; 230 * on(type: 'timeUpdate', callback: Callback<number>): void; 231 * off(type: 'timeUpdate'): void; 232 * on(type: 'durationUpdate', callback: Callback<number>): void; 233 * off(type: 'durationUpdate'): void; 234 * on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void; 235 * off(type: 'bufferingUpdate'): void; 236 * on(type: 'startRenderFrame', callback: Callback<void>): void; 237 * off(type: 'startRenderFrame'): void; 238 * on(type: 'videoSizeChange', callback: (width: number, height: number) => void): void; 239 * off(type: 'videoSizeChange'): void; 240 * on(type: 'audioInterrupt', callback: (info: audio.InterruptEvent) => void): void; 241 * off(type: 'audioInterrupt'): void; 242 * on(type: 'availableBitrates', callback: (bitrates: Array<number>) => void): void; 243 * off(type: 'availableBitrates'): void; 244 * on(type: 'error', callback: ErrorCallback): void; 245 * off(type: 'error'): void; 246 */ 247 static napi_value JsSetOnCallback(napi_env env, napi_callback_info info); 248 static napi_value JsClearOnCallback(napi_env env, napi_callback_info info); 249 250 static AVPlayerNapi* GetJsInstance(napi_env env, napi_callback_info info); 251 static AVPlayerNapi* GetJsInstanceWithParameter(napi_env env, napi_callback_info info, 252 size_t &argc, napi_value *argv); 253 static bool JsHandleParameter(napi_env env, napi_value args, AVPlayerNapi *jsPlayer); 254 AVPlayerNapi(); 255 ~AVPlayerNapi() override; 256 void SaveCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref); 257 void ClearCallbackReference(); 258 void ClearCallbackReference(const std::string &callbackName); 259 void StartListenCurrentResource(); 260 void PauseListenCurrentResource(); 261 void OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg); 262 void SetSource(std::string url); 263 void AddSubSource(std::string url); 264 void SetSurface(const std::string &surfaceStr); 265 void ResetUserParameters(); 266 267 std::shared_ptr<TaskHandler<TaskRet>> PrepareTask(); 268 std::shared_ptr<TaskHandler<TaskRet>> PlayTask(); 269 std::shared_ptr<TaskHandler<TaskRet>> PauseTask(); 270 std::shared_ptr<TaskHandler<TaskRet>> StopTask(); 271 std::shared_ptr<TaskHandler<TaskRet>> ResetTask(); 272 std::shared_ptr<TaskHandler<TaskRet>> ReleaseTask(); 273 std::string GetCurrentState(); 274 bool IsControllable(); 275 bool IsLiveSource() const; 276 277 void NotifyDuration(int32_t duration) override; 278 void NotifyPosition(int32_t position) override; 279 void NotifyState(PlayerStates state) override; 280 void NotifyVideoSize(int32_t width, int32_t height) override; 281 void NotifyIsLiveStream() override; 282 void StopTaskQue(); 283 void WaitTaskQueStop(); 284 285 std::condition_variable stopTaskQueCond_; 286 bool taskQueStoped_ = false; 287 288 struct AVPlayerContext : public MediaAsyncContext { AVPlayerContextAVPlayerContext289 explicit AVPlayerContext(napi_env env) : MediaAsyncContext(env) {} 290 ~AVPlayerContext() = default; CheckTaskResultAVPlayerContext291 void CheckTaskResult() 292 { 293 if (asyncTask != nullptr) { 294 auto result = asyncTask->GetResult(); 295 if (result.HasResult() && result.Value().first != MSERR_EXT_API9_OK) { 296 SignError(result.Value().first, result.Value().second); 297 } 298 } 299 } 300 std::shared_ptr<TaskHandler<TaskRet>> asyncTask = nullptr; 301 AVPlayerNapi *napi = nullptr; 302 }; 303 void GetCurrentTrackTask(std::unique_ptr<AVPlayerContext> &promiseCtx, napi_env env, napi_value args); 304 static thread_local napi_ref constructor_; 305 napi_env env_ = nullptr; 306 std::shared_ptr<Player> player_ = nullptr; 307 std::shared_ptr<AVPlayerCallback> playerCb_ = nullptr; 308 std::shared_ptr<MediaDataSourceCallback> dataSrcCb_ = nullptr; 309 std::atomic<bool> isReleased_ = false; 310 std::string url_ = ""; 311 struct AVFileDescriptor fileDescriptor_; 312 struct AVDataSrcDescriptor dataSrcDescriptor_; 313 std::string surface_ = ""; 314 bool loop_ = false; 315 int32_t videoScaleType_ = 0; 316 std::vector<Format> trackInfoVec_; 317 OHOS::AudioStandard::InterruptMode interruptMode_ = AudioStandard::InterruptMode::SHARE_MODE; 318 OHOS::AudioStandard::AudioRendererInfo audioRendererInfo_ = OHOS::AudioStandard::AudioRendererInfo { 319 OHOS::AudioStandard::ContentType::CONTENT_TYPE_MUSIC, 320 OHOS::AudioStandard::StreamUsage::STREAM_USAGE_MEDIA, 321 0 322 }; 323 int32_t audioEffectMode_ = OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT; 324 std::unique_ptr<TaskQueue> taskQue_; 325 std::mutex mutex_; 326 std::mutex taskMutex_; 327 std::map<std::string, std::shared_ptr<AutoRef>> refMap_; 328 PlayerStates state_ = PLAYER_IDLE; 329 std::condition_variable stateChangeCond_; 330 std::atomic<bool> stopWait_; 331 int32_t width_ = 0; 332 int32_t height_ = 0; 333 int32_t position_ = -1; 334 int32_t duration_ = -1; 335 bool isLiveStream_ = false; 336 }; 337 } // namespace Media 338 } // namespace OHOS 339 #endif // AV_PLAYER_NAPI_H