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