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