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