• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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