• 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 <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