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 "common_napi.h" 25 #include "audio_info.h" 26 #include "task_queue.h" 27 28 namespace OHOS { 29 namespace Media { 30 namespace AVPlayerState { 31 const std::string STATE_IDLE = "idle"; 32 const std::string STATE_INITIALIZED = "initialized"; 33 const std::string STATE_PREPARED = "prepared"; 34 const std::string STATE_PLAYING = "playing"; 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 const std::string STATE_COMPLETED = "completed"; 40 } 41 42 namespace AVPlayerEvent { 43 const std::string EVENT_STATE_CHANGE = "stateChange"; 44 const std::string EVENT_VOLUME_CHANGE = "volumeChange"; 45 const std::string EVENT_END_OF_STREAM = "endOfStream"; 46 const std::string EVENT_SEEK_DONE = "seekDone"; 47 const std::string EVENT_SPEED_DONE = "speedDone"; 48 const std::string EVENT_BITRATE_DONE = "bitrateDone"; 49 const std::string EVENT_TIME_UPDATE = "timeUpdate"; 50 const std::string EVENT_DURATION_UPDATE = "durationUpdate"; 51 const std::string EVENT_BUFFERING_UPDATE = "bufferingUpdate"; 52 const std::string EVENT_START_RENDER_FRAME = "startRenderFrame"; 53 const std::string EVENT_VIDEO_SIZE_CHANGE = "videoSizeChange"; 54 const std::string EVENT_AUDIO_INTERRUPT = "audioInterrupt"; 55 const std::string EVENT_AVAILABLE_BITRATES = "availableBitrates"; 56 const std::string EVENT_ERROR = "error"; 57 } 58 59 using TaskRet = std::pair<int32_t, std::string>; 60 61 class AVPlayerNapi : public AVPlayerNotify { 62 public: 63 __attribute__((visibility("default"))) static napi_value Init(napi_env env, napi_value exports); 64 65 private: 66 static napi_value Constructor(napi_env env, napi_callback_info info); 67 static void Destructor(napi_env env, void *nativeObject, void *finalize); 68 /** 69 * createAVPlayer(callback: AsyncCallback<VideoPlayer>): void 70 * createAVPlayer(): Promise<VideoPlayer> 71 */ 72 static napi_value JsCreateAVPlayer(napi_env env, napi_callback_info info); 73 /** 74 * prepare(callback: AsyncCallback<void>): void 75 * prepare(): Promise<void> 76 */ 77 static napi_value JsPrepare(napi_env env, napi_callback_info info); 78 /** 79 * play(callback: AsyncCallback<void>): void 80 * play(): Promise<void> 81 */ 82 static napi_value JsPlay(napi_env env, napi_callback_info info); 83 /** 84 * pause(callback: AsyncCallback<void>): void 85 * pause(): Promise<void> 86 */ 87 static napi_value JsPause(napi_env env, napi_callback_info info); 88 /** 89 * stop(callback: AsyncCallback<void>): void 90 * stop(): Promise<void> 91 */ 92 static napi_value JsStop(napi_env env, napi_callback_info info); 93 /** 94 * reset(callback: AsyncCallback<void>): void 95 * reset(): Promise<void> 96 */ 97 static napi_value JsReset(napi_env env, napi_callback_info info); 98 /** 99 * release(callback: AsyncCallback<void>): void 100 * release(): Promise<void> 101 */ 102 static napi_value JsRelease(napi_env env, napi_callback_info info); 103 /** 104 * seek(timeMs: number, mode?:SeekMode): void 105 */ 106 static napi_value JsSeek(napi_env env, napi_callback_info info); 107 /** 108 * setSpeed(speed: number): void 109 */ 110 static napi_value JsSetSpeed(napi_env env, napi_callback_info info); 111 /** 112 * setVolume(vol: number): void 113 */ 114 static napi_value JsSetVolume(napi_env env, napi_callback_info info); 115 /** 116 * selectBitrate(bitRate: number): void 117 */ 118 static napi_value JsSelectBitrate(napi_env env, napi_callback_info info); 119 /** 120 * url: string 121 */ 122 static napi_value JsSetUrl(napi_env env, napi_callback_info info); 123 static napi_value JsGetUrl(napi_env env, napi_callback_info info); 124 /** 125 * fdSrc: AVFileDescriptor 126 */ 127 static napi_value JsGetAVFileDescriptor(napi_env env, napi_callback_info info); 128 static napi_value JsSetAVFileDescriptor(napi_env env, napi_callback_info info); 129 /** 130 * surfaceId?: string 131 */ 132 static napi_value JsSetSurfaceID(napi_env env, napi_callback_info info); 133 static napi_value JsGetSurfaceID(napi_env env, napi_callback_info info); 134 /** 135 * loop: boolenan 136 */ 137 static napi_value JsSetLoop(napi_env env, napi_callback_info info); 138 static napi_value JsGetLoop(napi_env env, napi_callback_info info); 139 /** 140 * videoScaleType?: VideoScaleType 141 */ 142 static napi_value JsSetVideoScaleType(napi_env env, napi_callback_info info); 143 static napi_value JsGetVideoScaleType(napi_env env, napi_callback_info info); 144 /** 145 * audioInterruptMode?: audio.AudioInterruptMode 146 */ 147 static napi_value JsGetAudioInterruptMode(napi_env env, napi_callback_info info); 148 static napi_value JsSetAudioInterruptMode(napi_env env, napi_callback_info info); 149 /** 150 * readonly currentTime: number 151 */ 152 static napi_value JsGetCurrentTime(napi_env env, napi_callback_info info); 153 /** 154 * readonly duration: number 155 */ 156 static napi_value JsGetDuration(napi_env env, napi_callback_info info); 157 /** 158 * readonly state: AVPlayState 159 */ 160 static napi_value JsGetState(napi_env env, napi_callback_info info); 161 /** 162 * readonly width: number 163 */ 164 static napi_value JsGetWidth(napi_env env, napi_callback_info info); 165 /** 166 * readonly height: number 167 */ 168 static napi_value JsGetHeight(napi_env env, napi_callback_info info); 169 /** 170 * getTrackDescription(callback:AsyncCallback<Array<MediaDescription>>): void 171 * getTrackDescription(): Promise<Array<MediaDescription>> 172 */ 173 static napi_value JsGetTrackDescription(napi_env env, napi_callback_info info); 174 /** 175 * on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void; 176 * off(type: 'stateChange'): void; 177 * on(type: 'volumeChange', callback: Callback<number>): void; 178 * off(type: 'volumeChange'): void; 179 * on(type: 'endOfStream', callback: Callback<void>): void; 180 * off(type: 'endOfStream'): void; 181 * on(type: 'seekDone', callback: Callback<number>): void; 182 * off(type: 'seekDone'): void; 183 * on(type: 'speedDone', callback: Callback<number>): void; 184 * off(type: 'speedDone'): void; 185 * on(type: 'bitrateDone', callback: Callback<number>): void; 186 * off(type: 'bitrateDone'): void; 187 * on(type: 'timeUpdate', callback: Callback<number>): void; 188 * off(type: 'timeUpdate'): void; 189 * on(type: 'durationUpdate', callback: Callback<number>): void; 190 * off(type: 'durationUpdate'): void; 191 * on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void; 192 * off(type: 'bufferingUpdate'): void; 193 * on(type: 'startRenderFrame', callback: Callback<void>): void; 194 * off(type: 'startRenderFrame'): void; 195 * on(type: 'videoSizeChange', callback: (width: number, height: number) => void): void; 196 * off(type: 'videoSizeChange'): void; 197 * on(type: 'audioInterrupt', callback: (info: audio.InterruptEvent) => void): void; 198 * off(type: 'audioInterrupt'): void; 199 * on(type: 'availableBitrates', callback: (bitrates: Array<number>) => void): void; 200 * off(type: 'availableBitrates'): void; 201 * on(type: 'error', callback: ErrorCallback): void; 202 * off(type: 'error'): void; 203 */ 204 static napi_value JsSetOnCallback(napi_env env, napi_callback_info info); 205 static napi_value JsClearOnCallback(napi_env env, napi_callback_info info); 206 207 static AVPlayerNapi* GetJsInstance(napi_env env, napi_callback_info info); 208 static AVPlayerNapi* GetJsInstanceWithParameter(napi_env env, napi_callback_info info, 209 size_t &argc, napi_value *argv); 210 AVPlayerNapi(); 211 ~AVPlayerNapi() override; 212 void SaveCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref); 213 void ClearCallbackReference(); 214 void ClearCallbackReference(const std::string &callbackName); 215 void StartListenCurrentResource(); 216 void PauseListenCurrentResource(); 217 void OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg); 218 void SetSource(std::string url); 219 void SetSurface(const std::string &surfaceStr); 220 void ResetUserParameters(); 221 222 std::shared_ptr<TaskHandler<TaskRet>> PrepareTask(); 223 std::shared_ptr<TaskHandler<TaskRet>> PlayTask(); 224 std::shared_ptr<TaskHandler<TaskRet>> PauseTask(); 225 std::shared_ptr<TaskHandler<TaskRet>> StopTask(); 226 std::shared_ptr<TaskHandler<TaskRet>> ResetTask(); 227 std::shared_ptr<TaskHandler<TaskRet>> ReleaseTask(); 228 std::string GetCurrentState(); 229 bool IsControllable(); 230 231 void NotifyDuration(int32_t duration) override; 232 void NotifyPosition(int32_t position) override; 233 void NotifyState(PlayerStates state) override; 234 void NotifyVideoSize(int32_t width, int32_t height) override; 235 236 struct AVPlayerContext : public MediaAsyncContext { AVPlayerContextAVPlayerContext237 explicit AVPlayerContext(napi_env env) : MediaAsyncContext(env) {} 238 ~AVPlayerContext() = default; CheckTaskResultAVPlayerContext239 void CheckTaskResult() 240 { 241 if (asyncTask != nullptr) { 242 auto result = asyncTask->GetResult(); 243 if (result.HasResult() && result.Value().first != MSERR_EXT_API9_OK) { 244 SignError(result.Value().first, result.Value().second); 245 } 246 } 247 } 248 std::shared_ptr<TaskHandler<TaskRet>> asyncTask = nullptr; 249 AVPlayerNapi *napi = nullptr; 250 }; 251 static thread_local napi_ref constructor_; 252 napi_env env_ = nullptr; 253 std::shared_ptr<Player> player_ = nullptr; 254 std::shared_ptr<AVPlayerCallback> playerCb_ = nullptr; 255 std::atomic<bool> isReleased_ = false; 256 std::string url_ = ""; 257 struct AVFileDescriptor fileDescriptor_; 258 std::string surface_ = ""; 259 bool loop_ = false; 260 int32_t videoScaleType_ = 0; 261 std::vector<Format> trackInfoVec_; 262 OHOS::AudioStandard::InterruptMode interruptMode_ = AudioStandard::InterruptMode::SHARE_MODE; 263 std::unique_ptr<TaskQueue> taskQue_; 264 std::mutex mutex_; 265 std::mutex taskMutex_; 266 std::map<std::string, std::shared_ptr<AutoRef>> refMap_; 267 PlayerStates state_ = PLAYER_IDLE; 268 std::condition_variable preparingCond_; 269 std::condition_variable stateChangeCond_; 270 std::condition_variable resettingCond_; 271 int32_t width_ = 0; 272 int32_t height_ = 0; 273 int32_t position_ = -1; 274 int32_t duration_ = -1; 275 }; 276 } // namespace Media 277 } // namespace OHOS 278 #endif // AV_PLAYER_NAPI_H