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_RATE_DONE = "playbackRateDone"; 52 const std::string EVENT_BITRATE_DONE = "bitrateDone"; 53 const std::string EVENT_TIME_UPDATE = "timeUpdate"; 54 const std::string EVENT_DURATION_UPDATE = "durationUpdate"; 55 const std::string EVENT_SUBTITLE_TEXT_UPDATE = "subtitleTextUpdate"; 56 const std::string EVENT_BUFFERING_UPDATE = "bufferingUpdate"; 57 const std::string EVENT_START_RENDER_FRAME = "startRenderFrame"; 58 const std::string EVENT_VIDEO_SIZE_CHANGE = "videoSizeChange"; 59 const std::string EVENT_AUDIO_INTERRUPT = "audioInterrupt"; 60 const std::string EVENT_AVAILABLE_BITRATES = "availableBitrates"; 61 const std::string EVENT_TRACKCHANGE = "trackChange"; 62 const std::string EVENT_TRACK_INFO_UPDATE = "trackInfoUpdate"; 63 const std::string EVENT_DRM_INFO_UPDATE = "mediaKeySystemInfoUpdate"; 64 const std::string EVENT_SET_DECRYPT_CONFIG_DONE = "setDecryptConfigDone"; 65 const std::string EVENT_AUDIO_DEVICE_CHANGE = "audioOutputDeviceChangeWithInfo"; 66 const std::string EVENT_SUBTITLE_UPDATE = "subtitleUpdate"; 67 const std::string EVENT_ERROR = "error"; 68 const std::string EVENT_AMPLITUDE_UPDATE = "amplitudeUpdate"; 69 const std::string EVENT_SEI_MESSAGE_INFO = "seiMessageReceived"; 70 const std::string EVENT_SUPER_RESOLUTION_CHANGED = "superResolutionChanged"; 71 } 72 73 using TaskRet = std::pair<int32_t, std::string>; 74 75 class AVPlayerNapi : public AVPlayerNotify { 76 public: 77 __attribute__((visibility("default"))) static napi_value Init(napi_env env, napi_value exports); 78 79 private: 80 static napi_value Constructor(napi_env env, napi_callback_info info); 81 static void Destructor(napi_env env, void *nativeObject, void *finalize); 82 /** 83 * createAVPlayer(callback: AsyncCallback<VideoPlayer>): void 84 * createAVPlayer(): Promise<VideoPlayer> 85 */ 86 static napi_value JsCreateAVPlayer(napi_env env, napi_callback_info info); 87 /** 88 * prepare(callback: AsyncCallback<void>): void 89 * prepare(): Promise<void> 90 */ 91 static napi_value JsPrepare(napi_env env, napi_callback_info info); 92 /** 93 * play(callback: AsyncCallback<void>): void 94 * play(): Promise<void> 95 */ 96 static napi_value JsPlay(napi_env env, napi_callback_info info); 97 /** 98 * pause(callback: AsyncCallback<void>): void 99 * pause(): Promise<void> 100 */ 101 static napi_value JsPause(napi_env env, napi_callback_info info); 102 /** 103 * stop(callback: AsyncCallback<void>): void 104 * stop(): Promise<void> 105 */ 106 static napi_value JsStop(napi_env env, napi_callback_info info); 107 /** 108 * reset(callback: AsyncCallback<void>): void 109 * reset(): Promise<void> 110 */ 111 static napi_value JsReset(napi_env env, napi_callback_info info); 112 /** 113 * release(callback: AsyncCallback<void>): void 114 * release(): Promise<void> 115 */ 116 static napi_value JsRelease(napi_env env, napi_callback_info info); 117 /** 118 * seek(timeMs: number, mode?:SeekMode): void 119 */ 120 static napi_value JsSeek(napi_env env, napi_callback_info info); 121 /** 122 * setPlayRange(startTimeMs: number, endTimeMs: number, mode?: SeekMode): void 123 */ 124 static napi_value JsSetPlaybackRange(napi_env env, napi_callback_info info); 125 /** 126 * setSpeed(speed: number): void 127 */ 128 static napi_value JsSetSpeed(napi_env env, napi_callback_info info); 129 /** 130 * setPlaybackRate(rate: float): void 131 */ 132 static napi_value JsSetPlaybackRate(napi_env env, napi_callback_info info); 133 /** 134 * setVolume(vol: number): void 135 */ 136 static napi_value JsSetVolume(napi_env env, napi_callback_info info); 137 /** 138 * selectBitrate(bitRate: number): void 139 */ 140 static napi_value JsSelectBitrate(napi_env env, napi_callback_info info); 141 /** 142 * addSubtitleUrl: string 143 */ 144 static napi_value JsAddSubtitleUrl(napi_env env, napi_callback_info info); 145 /** 146 * addSubtitleFdSrc: AVFileDescriptor 147 */ 148 static napi_value JsAddSubtitleAVFileDescriptor(napi_env env, napi_callback_info info); 149 /** 150 * url: string 151 */ 152 static napi_value JsSetUrl(napi_env env, napi_callback_info info); 153 static napi_value JsGetUrl(napi_env env, napi_callback_info info); 154 /** 155 * fdSrc: AVFileDescriptor 156 */ 157 static napi_value JsGetAVFileDescriptor(napi_env env, napi_callback_info info); 158 static napi_value JsSetAVFileDescriptor(napi_env env, napi_callback_info info); 159 /** 160 * dataSrc: DataSrcDescriptor 161 */ 162 static napi_value JsSetDataSrc(napi_env env, napi_callback_info info); 163 static napi_value JsGetDataSrc(napi_env env, napi_callback_info info); 164 /** 165 * surfaceId?: string 166 */ 167 static napi_value JsSetSurfaceID(napi_env env, napi_callback_info info); 168 static napi_value JsGetSurfaceID(napi_env env, napi_callback_info info); 169 /** 170 * loop: boolenan 171 */ 172 static napi_value JsSetLoop(napi_env env, napi_callback_info info); 173 static napi_value JsGetLoop(napi_env env, napi_callback_info info); 174 /** 175 * videoScaleType?: VideoScaleType 176 */ 177 static napi_value JsSetVideoScaleType(napi_env env, napi_callback_info info); 178 static napi_value JsGetVideoScaleType(napi_env env, napi_callback_info info); 179 /** 180 * audioInterruptMode?: audio.AudioInterruptMode 181 */ 182 static napi_value JsGetAudioInterruptMode(napi_env env, napi_callback_info info); 183 static napi_value JsSetAudioInterruptMode(napi_env env, napi_callback_info info); 184 185 /** 186 * audioRendererInfo?: audio.AudioRendererInfo 187 */ 188 static napi_value JsGetAudioRendererInfo(napi_env env, napi_callback_info info); 189 static napi_value JsSetAudioRendererInfo(napi_env env, napi_callback_info info); 190 191 /** 192 * audioEffectMode ?: audio.AudioEffectMode; 193 */ 194 static napi_value JsGetAudioEffectMode(napi_env env, napi_callback_info info); 195 static napi_value JsSetAudioEffectMode(napi_env env, napi_callback_info info); 196 /** 197 * readonly currentTime: number 198 */ 199 static napi_value JsGetCurrentTime(napi_env env, napi_callback_info info); 200 /** 201 * readonly currentPlaybackPosition: number 202 */ 203 static napi_value JsGetPlaybackPosition(napi_env env, napi_callback_info info); 204 /** 205 * readonly forceLoadVideo: boolean 206 */ 207 static napi_value JsForceLoadVideo(napi_env env, napi_callback_info info); 208 /** 209 * readonly duration: number 210 */ 211 static napi_value JsGetDuration(napi_env env, napi_callback_info info); 212 /** 213 * readonly state: AVPlayState 214 */ 215 static napi_value JsGetState(napi_env env, napi_callback_info info); 216 /** 217 * readonly width: number 218 */ 219 static napi_value JsGetWidth(napi_env env, napi_callback_info info); 220 /** 221 * readonly height: number 222 */ 223 static napi_value JsGetHeight(napi_env env, napi_callback_info info); 224 /** 225 * getTrackDescription(callback:AsyncCallback<Array<MediaDescription>>): void 226 * getTrackDescription(): Promise<Array<MediaDescription>> 227 */ 228 static napi_value JsGetTrackDescription(napi_env env, napi_callback_info info); 229 /** 230 * JsGetSelectedTracks(callback:AsyncCallback<Array<number>>): void 231 * JsGetSelectedTracks(): Promise<Array<number>> 232 */ 233 static napi_value JsGetSelectedTracks(napi_env env, napi_callback_info info); 234 /** 235 * selectTrack(index: number, mode?: SwitchMode): void; 236 */ 237 static napi_value JsSelectTrack(napi_env env, napi_callback_info info); 238 /** 239 * deselectTrack(index: number): void; 240 */ 241 static napi_value JsDeselectTrack(napi_env env, napi_callback_info info); 242 /** 243 * GetCurrentTrack(trackType: MediaType, callback: AsyncCallback<number>): void; 244 * GetCurrentTrack(trackType: MediaType): Promise<number>; 245 */ 246 static napi_value JsGetCurrentTrack(napi_env env, napi_callback_info info); 247 /** 248 * setDecryptionConfig(mediaKeySession: drm.MediaKeySession, secureVideoPath: boolean): void; 249 */ 250 static napi_value JsSetDecryptConfig(napi_env env, napi_callback_info info); 251 252 static napi_value JsSetMediaSource(napi_env env, napi_callback_info info); 253 /** 254 * getMediaKeySystemInfos(): Array<MediaKeySystemInfo>; 255 */ 256 static napi_value JsGetMediaKeySystemInfos(napi_env env, napi_callback_info info); 257 258 static napi_value JsSetPlaybackStrategy(napi_env env, napi_callback_info info); 259 260 static napi_value JsSetMediaMuted(napi_env env, napi_callback_info info); 261 262 static napi_value JsSetSuperResolution(napi_env env, napi_callback_info info); 263 264 static napi_value JsSetVideoWindowSize(napi_env env, napi_callback_info info); 265 266 static napi_value JsSetStartFrameRateOptEnabled(napi_env env, napi_callback_info info); 267 268 static napi_value JsEnableCameraPostprocessing(napi_env env, napi_callback_info info); 269 270 /** 271 * getPlaybackInfo(): playbackInfo; 272 */ 273 static napi_value JsGetPlaybackInfo(napi_env env, napi_callback_info info); 274 275 static napi_value JsIsSeekContinuousSupported(napi_env env, napi_callback_info info); 276 277 /** 278 * on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void; 279 * off(type: 'stateChange'): void; 280 * on(type: 'volumeChange', callback: Callback<number>): void; 281 * off(type: 'volumeChange'): void; 282 * on(type: 'endOfStream', callback: Callback<void>): void; 283 * off(type: 'endOfStream'): void; 284 * on(type: 'seekDone', callback: Callback<number>): void; 285 * off(type: 'seekDone'): void; 286 * on(type: 'speedDone', callback: Callback<number>): void; 287 * off(type: 'speedDone'): void; 288 * on(type: 'bitrateDone', callback: Callback<number>): void; 289 * off(type: 'bitrateDone'): void; 290 * on(type: 'timeUpdate', callback: Callback<number>): void; 291 * off(type: 'timeUpdate'): void; 292 * on(type: 'durationUpdate', callback: Callback<number>): void; 293 * off(type: 'durationUpdate'): void; 294 * on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void; 295 * off(type: 'bufferingUpdate'): void; 296 * on(type: 'startRenderFrame', callback: Callback<void>): void; 297 * off(type: 'startRenderFrame'): void; 298 * on(type: 'videoSizeChange', callback: (width: number, height: number) => void): void; 299 * off(type: 'videoSizeChange'): void; 300 * on(type: 'audioInterrupt', callback: (info: audio.InterruptEvent) => void): void; 301 * off(type: 'audioInterrupt'): void; 302 * on(type: 'availableBitrates', callback: (bitrates: Array<number>) => void): void; 303 * off(type: 'availableBitrates'): void; 304 * on(type: 'error', callback: ErrorCallback): void; 305 * off(type: 'error'): void; 306 * on(type: 'mediaKeySystemInfoUpdate', callback: (mediaKeySystemInfo: Array<MediaKeySystemInfo>) => void): void; 307 * off(type: 'mediaKeySystemInfoUpdate'): void; 308 */ 309 static napi_value JsSetOnCallback(napi_env env, napi_callback_info info); 310 static napi_value JsClearOnCallback(napi_env env, napi_callback_info info); 311 312 static AVPlayerNapi* GetJsInstance(napi_env env, napi_callback_info info); 313 static AVPlayerNapi* GetJsInstanceWithParameter(napi_env env, napi_callback_info info, 314 size_t &argc, napi_value *argv); 315 static bool JsHandleParameter(napi_env env, napi_value args, AVPlayerNapi *jsPlayer); 316 static void SeekEnqueueTask(AVPlayerNapi *jsPlayer, int32_t time, int32_t mode); 317 static bool VerifyExpectedType(const NapiTypeCheckUnit &unit, AVPlayerNapi *jsPlayer, const std::string &msg); 318 static std::shared_ptr<AVMediaSource> GetAVMediaSource(napi_env env, napi_value value, 319 std::shared_ptr<AVMediaSourceTmp> &srcTmp); 320 static bool IsSystemApp(); 321 AVPlayerNapi(); 322 ~AVPlayerNapi() override; 323 void SaveCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref); 324 void ClearCallbackReference(); 325 void ClearCallbackReference(const std::string &callbackName); 326 void StartListenCurrentResource(); 327 void PauseListenCurrentResource(); 328 void QueueOnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg); 329 void OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg); 330 void SetSource(std::string url); 331 void AddSubSource(std::string url); 332 void SetSurface(const std::string &surfaceStr); 333 void ResetUserParameters(); 334 void SetDataSource(AVPlayerNapi *jsPlayer); 335 336 std::shared_ptr<TaskHandler<TaskRet>> PrepareTask(); 337 std::shared_ptr<TaskHandler<TaskRet>> PlayTask(); 338 std::shared_ptr<TaskHandler<TaskRet>> PauseTask(); 339 std::shared_ptr<TaskHandler<TaskRet>> StopTask(); 340 std::shared_ptr<TaskHandler<TaskRet>> ResetTask(); 341 std::shared_ptr<TaskHandler<TaskRet>> ReleaseTask(); 342 std::shared_ptr<TaskHandler<TaskRet>> SetPlaybackStrategyTask(AVPlayStrategy playStrategy); 343 std::shared_ptr<TaskHandler<TaskRet>> SetMediaMutedTask(MediaType type, bool isMuted); 344 std::shared_ptr<TaskHandler<TaskRet>> SetSuperResolutionTask(bool enabled); 345 std::shared_ptr<TaskHandler<TaskRet>> SetVideoWindowSizeTask(int32_t width, int32_t height); 346 std::shared_ptr<TaskHandler<TaskRet>> EnableCameraPostprocessingTask(); 347 std::shared_ptr<TaskHandler<TaskRet>> EqueueSetPlayRangeTask(int32_t start, int32_t end, int32_t mode); 348 std::shared_ptr<TaskHandler<TaskRet>> ForceLoadVideoTask(bool status); 349 350 std::string GetCurrentState(); 351 bool IsControllable(); 352 bool CanSetPlayRange(); 353 bool CanSetSuperResolution(); 354 bool IsVideoWindowSizeValid(int32_t width, int32_t height); 355 bool CanCameraPostprocessing(); 356 bool IsLiveSource() const; 357 void EnqueueNetworkTask(const std::string url); 358 void EnqueueFdTask(const int32_t fd); 359 360 PlayerSeekMode TransferSeekMode(int32_t mode); 361 PlayerSwitchMode TransferSwitchMode(int32_t mode); 362 363 void NotifyDuration(int32_t duration) override; 364 void NotifyPosition(int32_t position) override; 365 void NotifyState(PlayerStates state) override; 366 void NotifyVideoSize(int32_t width, int32_t height) override; 367 void NotifyIsLiveStream() override; 368 void NotifyDrmInfoUpdated(const std::multimap<std::string, std::vector<uint8_t>> &infos) override; 369 void StopTaskQue(); 370 void WaitTaskQueStop(); 371 void HandleListenerStateChange(std::string callbackName, bool state); 372 void DeviceChangeCallbackOn(AVPlayerNapi *jsPlayer, std::string callbackName); 373 void DeviceChangeCallbackOff(AVPlayerNapi *jsPlayer, std::string callbackName); 374 void SeiMessageCallbackOn( 375 AVPlayerNapi *jsPlayer, std::string callbackName, const std::vector<int32_t> &payloadTypes); 376 void SeiMessageCallbackOff( 377 AVPlayerNapi *jsPlayer, std::string &callbackName, const std::vector<int32_t> &payloadTypes); 378 int32_t GetJsApiVersion() override; 379 void GetAVPlayStrategyFromStrategyTmp(AVPlayStrategy &strategy, const AVPlayStrategyTmp &strategyTmp); 380 bool IsPalyingDurationValid(const AVPlayStrategyTmp &strategyTmp); 381 void EnqueueMediaSourceTask(AVPlayerNapi *jsPlayer, const std::shared_ptr<AVMediaSource> &mediaSource, 382 const struct AVPlayStrategy &strategy); 383 void AddMediaStreamToAVMediaSource( 384 const std::shared_ptr<AVMediaSourceTmp> &srcTmp, std::shared_ptr<AVMediaSource> &mediaSource); 385 bool IsLivingMaxDelayTimeValid(const AVPlayStrategyTmp &strategyTmp); 386 bool IsRateValid(float rate); 387 388 std::condition_variable stopTaskQueCond_; 389 bool taskQueStoped_ = false; 390 bool deviceChangeCallbackflag_ = false; 391 bool seiMessageCallbackflag_ = false; 392 bool reportMediaProgressCallbackflag_ = false; 393 394 struct AVPlayerContext : public MediaAsyncContext { AVPlayerContextAVPlayerContext395 explicit AVPlayerContext(napi_env env) : MediaAsyncContext(env) {} 396 ~AVPlayerContext() = default; 397 void CheckTaskResult(bool isTimeLimited = false, uint32_t milliseconds = 0) 398 { 399 if (asyncTask != nullptr) { 400 auto result = isTimeLimited ? asyncTask->GetResultWithTimeLimit(milliseconds) : asyncTask->GetResult(); 401 if (result.HasResult() && result.Value().first != MSERR_EXT_API9_OK) { 402 SignError(result.Value().first, result.Value().second); 403 } 404 } 405 } 406 std::shared_ptr<TaskHandler<TaskRet>> asyncTask = nullptr; 407 AVPlayerNapi *napi = nullptr; 408 std::vector<Format> trackInfoVec_; 409 }; 410 std::shared_ptr<TaskHandler<TaskRet>> GetTrackDescriptionTask(const std::unique_ptr<AVPlayerContext> &promiseCtx); 411 void GetCurrentTrackTask(std::unique_ptr<AVPlayerContext> &promiseCtx, napi_env env, napi_value args); 412 void HandleSelectTrack(std::unique_ptr<AVPlayerContext> &promiseCtx, napi_env env, napi_value args[], 413 size_t argCount); 414 static thread_local napi_ref constructor_; 415 napi_env env_ = nullptr; 416 std::shared_ptr<Player> player_ = nullptr; 417 std::shared_ptr<AVPlayerCallback> playerCb_ = nullptr; 418 std::shared_ptr<MediaDataSourceCallback> dataSrcCb_ = nullptr; 419 std::atomic<bool> isReleased_ = false; 420 std::atomic<bool> isInterrupted_ = false; 421 std::string url_ = ""; 422 bool enabled_ = false; 423 struct AVFileDescriptor fileDescriptor_; 424 struct AVDataSrcDescriptor dataSrcDescriptor_; 425 std::string surface_ = ""; 426 bool loop_ = false; 427 int32_t videoScaleType_ = 0; 428 std::vector<Format> trackInfoVec_; 429 OHOS::AudioStandard::InterruptMode interruptMode_ = AudioStandard::InterruptMode::SHARE_MODE; 430 OHOS::AudioStandard::AudioRendererInfo audioRendererInfo_ = OHOS::AudioStandard::AudioRendererInfo { 431 OHOS::AudioStandard::ContentType::CONTENT_TYPE_MUSIC, 432 OHOS::AudioStandard::StreamUsage::STREAM_USAGE_MEDIA, 433 0 434 }; 435 int32_t audioEffectMode_ = OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT; 436 std::unique_ptr<TaskQueue> taskQue_; 437 std::mutex mutex_; 438 std::mutex taskMutex_; 439 std::map<std::string, std::shared_ptr<AutoRef>> refMap_; 440 PlayerStates state_ = PLAYER_IDLE; 441 std::condition_variable stateChangeCond_; 442 std::atomic<bool> stopWait_; 443 bool avplayerExit_ = false; 444 int32_t width_ = 0; 445 int32_t height_ = 0; 446 int32_t position_ = -1; 447 int32_t duration_ = -1; 448 bool isLiveStream_ = false; 449 std::shared_mutex drmMutex_{}; 450 std::multimap<std::string, std::vector<uint8_t>> localDrmInfos_; 451 Format playbackInfo_; 452 int32_t index_ = -1; 453 int32_t mode_ = SWITCH_SMOOTH; 454 std::mutex syncMutex_; 455 bool getApiVersionFlag_ = true; 456 457 std::atomic<bool> isReadyReleased_ = false; 458 bool isForceLoadVideo_ = false; 459 bool hasSetStateChangeCb_ = false; 460 int32_t mutedMediaType_ = OHOS::Media::MediaType::MEDIA_TYPE_MAX_COUNT; 461 }; 462 } // namespace Media 463 } // namespace OHOS 464 #endif // AV_PLAYER_NAPI_H