no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,474 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2016-2022 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "VideoPlayer.h"
using namespace cc;
#if CC_PLATFORM == CC_PLATFORM_IOS
//-------------------------------------------------------------------------------------
#import <AVKit/AVPlayerViewController.h>
#import <CoreMedia/CMTime.h>
#include "platform/FileUtils.h"
#include "platform/ios/WarpCocosContent.h"
@interface UIVideoViewWrapperIos : NSObject
typedef NS_ENUM(NSInteger, PlayerbackState) {
PlayerbackStateUnknown = 0,
PlayerbackStatePaused,
PlayerbackStopped,
PlayerbackStatePlaying,
PlayerbackStateCompleted
};
@property (assign, nonatomic) AVPlayerViewController *playerController;
- (void)setFrame:(int)left
:(int)top
:(int)width
:(int)height;
- (void)setURL:(int)videoSource :(ccstd::string &)videoUrl;
- (void)play;
- (void)pause;
- (void)resume;
- (void)stop;
- (BOOL)isPlaying;
- (void)seekTo:(float)sec;
- (float)currentTime;
- (float)duration;
- (void)setVisible:(BOOL)visible;
- (void)setKeepRatioEnabled:(BOOL)enabled;
- (void)setPlaybackRate:(float)value;
- (void)setMute:(BOOL)enabled;
- (void)setLoop:(BOOL)enabled;
- (void)setFullScreenEnabled:(BOOL)enabled;
- (void)showPlaybackControls:(BOOL)value;
- (BOOL)isFullScreenEnabled;
- (void)cleanup;
- (id)init:(void *)videoPlayer;
- (void)videoFinished:(NSNotification *)notification;
@end
@implementation UIVideoViewWrapperIos {
int _left;
int _top;
int _width;
int _height;
bool _keepRatioEnabled;
bool _keepLoopEnabled;
bool _fullscreen;
CGRect _restoreRect;
PlayerbackState _state;
VideoPlayer *_videoPlayer;
}
- (id)init:(void *)videoPlayer {
if (self = [super init]) {
_keepRatioEnabled = FALSE;
_keepLoopEnabled = FALSE;
_left = _top = _width = _height = 0;
[self initPlayerController];
_videoPlayer = (VideoPlayer *)videoPlayer;
}
return self;
}
- (void)initPlayerController {
self.playerController = [AVPlayerViewController new];
[self setFrame:_left:_top:_width:_height];
[self showPlaybackControls:TRUE];
[self setKeepRatioEnabled:_keepRatioEnabled];
_state = PlayerbackStateUnknown;
}
- (void)dealloc {
[self cleanup];
[super dealloc];
}
- (void)setFrame:(int)left
:(int)top
:(int)width
:(int)height {
if (_left == left && _width == width && _top == top && _height == height)
return;
_left = left;
_width = width;
_top = top;
_height = height;
[self.playerController.view setFrame:CGRectMake(left, top, width, height)];
}
- (void)setFullScreenEnabled:(BOOL)enabled {
// AVPlayerViewController doesn't provide API to enable fullscreen. But you can toggle
// fullsreen by the playback controllers.
}
- (BOOL)isFullScreenEnabled {
return false;
}
- (BOOL)isPlaying {
return (self.playerController.player && self.playerController.player.rate != 0);
}
- (void)setURL:(int)videoSource :(ccstd::string &)videoUrl {
[self cleanup];
[self initPlayerController];
if (videoSource == 1)
self.playerController.player = [[[AVPlayer alloc] initWithURL:[NSURL URLWithString:@(videoUrl.c_str())]] autorelease];
else
self.playerController.player = [[[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:@(videoUrl.c_str())]] autorelease];
[self registerPlayerEventListener];
}
- (void)seekTo:(float)sec {
if (self.playerController.player)
[self.playerController.player seekToTime:CMTimeMake(sec * 600, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
- (float)currentTime {
if (self.playerController.player)
return CMTimeGetSeconds([self.playerController.player currentTime]);
return -1;
}
- (float)duration {
if (self.playerController.player)
return CMTimeGetSeconds(self.playerController.player.currentItem.asset.duration);
return -1;
;
}
- (void)setVisible:(BOOL)visible {
[self.playerController.view setHidden:!visible];
if (!visible)
[self pause];
}
- (void)setKeepRatioEnabled:(BOOL)enabled {
_keepRatioEnabled = enabled;
if (_keepRatioEnabled)
self.playerController.videoGravity = AVLayerVideoGravityResizeAspectFill;
else
self.playerController.videoGravity = AVLayerVideoGravityResize;
}
- (void)setMute:(BOOL)enabled {
[self.playerController.player setMuted:enabled];
}
- (void)setLoop:(BOOL)enabled {
_keepLoopEnabled = enabled;
if (_keepLoopEnabled) {
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(runLoopTheVideo:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerController.player.currentItem];
}
}
- (void)setPlaybackRate:(float)value {
if (self.playerController.player) {
[self.playerController.player playImmediatelyAtRate:value];
}
}
- (void)play {
if (self.playerController.player && ![self isPlaying]) {
[self.playerController.player play];
_state = PlayerbackStatePlaying;
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::PLAYING);
}
}
- (void)runLoopTheVideo:(NSNotification *)notification {
if (_keepLoopEnabled) {
AVPlayerItem *playerItem = notification.object;
[self seekTo:0];
[self.playerController.player play];
}
}
- (void)pause {
if ([self isPlaying]) {
[self.playerController.player pause];
_state = PlayerbackStatePaused;
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::PAUSED);
}
}
- (void)resume {
if (self.playerController.player && _state == PlayerbackStatePaused)
[self play];
}
- (void)stop {
// AVPlayer doesn't have `stop` method, so just pause it, and seek time to 0.
if (self.playerController.player && _state != PlayerbackStopped) {
[self seekTo:0];
[self.playerController.player pause];
_state = PlayerbackStopped;
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::STOPPED);
}
}
// Private functions
- (void)cleanup {
[self stop];
[self removePlayerEventListener];
[self.playerController.view removeFromSuperview];
[self.playerController release];
}
- (void)removePlayerEventListener {
if (self.playerController.player) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.playerController.player.currentItem];
[self.playerController.player removeObserver:self forKeyPath:@"status"];
}
}
- (void)registerPlayerEventListener {
if (self.playerController.player) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(videoFinished:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.playerController.player.currentItem];
[self.playerController.player addObserver:self forKeyPath:@"status" options:0 context:nil];
}
}
- (void)showPlaybackControls:(BOOL)value {
self.playerController.showsPlaybackControls = value;
}
- (void)videoFinished:(NSNotification *)notification {
if (_videoPlayer != nullptr) {
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::COMPLETED);
_state = PlayerbackStateCompleted;
// Seek to 0 to make it playable again.
[self seekTo:0];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
auto player = self.playerController.player;
if (object == player && [keyPath isEqualToString:@"status"]) {
if (player.status == AVPlayerStatusReadyToPlay) {
[self addPlayerControllerSubView];
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::META_LOADED);
if (![self isPlaying]) { //User may start playing after getting the META_LOADED message
_videoPlayer->onPlayEvent((int)VideoPlayer::EventType::READY_TO_PLAY);
}
} else if (player.status == AVPlayerStatusFailed) {
// something went wrong. player.error should contain some information
NSLog(@"Failed to load video");
}
}
}
- (void)addPlayerControllerSubView {
//auto rootView = UIApplication.sharedApplication.delegate.window.rootViewController.view;
auto rootView = WarpCocosContent.shareInstance.renderView;
[rootView addSubview:self.playerController.view];
}
@end
//------------------------------------------------------------------------------------------------------------
VideoPlayer::VideoPlayer()
: _videoPlayerIndex(-1),
_fullScreenEnabled(false),
_fullScreenDirty(false),
_keepAspectRatioEnabled(false) {
_videoView = [[UIVideoViewWrapperIos alloc] init:this];
#if CC_VIDEOPLAYER_DEBUG_DRAW
_debugDrawNode = DrawNode::create();
addChild(_debugDrawNode);
#endif
}
VideoPlayer::~VideoPlayer() {
destroy();
}
void VideoPlayer::destroy() {
if (_videoView != nil) {
[((UIVideoViewWrapperIos *)_videoView) release];
_videoView = nil;
}
}
void VideoPlayer::setURL(const ccstd::string &videoUrl) {
if (videoUrl.find("://") == ccstd::string::npos) {
_videoURL = FileUtils::getInstance()->fullPathForFilename(videoUrl);
_videoSource = VideoPlayer::Source::FILENAME;
} else {
_videoURL = videoUrl;
_videoSource = VideoPlayer::Source::URL;
}
[((UIVideoViewWrapperIos *)_videoView) setURL:(int) _videoSource:_videoURL];
}
void VideoPlayer::setFullScreenEnabled(bool enabled) {
[((UIVideoViewWrapperIos *)_videoView) setFullScreenEnabled:enabled];
}
void VideoPlayer::setKeepAspectRatioEnabled(bool enable) {
if (_keepAspectRatioEnabled != enable) {
_keepAspectRatioEnabled = enable;
[((UIVideoViewWrapperIos *)_videoView) setKeepRatioEnabled:enable];
}
}
void VideoPlayer::setMute(bool enable) {
if (!_videoURL.empty()) {
if (enable) {
[((UIVideoViewWrapperIos *)_videoView) setMute:YES];
} else {
[((UIVideoViewWrapperIos *)_videoView) setMute:NO];
}
}
}
void VideoPlayer::setLoop(bool enable) {
if (!_videoURL.empty()) {
if (enable) {
[((UIVideoViewWrapperIos *)_videoView) setLoop:YES];
}
else {
[((UIVideoViewWrapperIos *)_videoView) setLoop:NO];
}
}
}
void VideoPlayer::setPlaybackRate(float value) {
if (!_videoURL.empty()) {
[((UIVideoViewWrapperIos *)_videoView) setPlaybackRate:value];
}
}
void VideoPlayer::play() {
if (!_videoURL.empty() && _isVisible) {
[((UIVideoViewWrapperIos *)_videoView) play];
}
}
void VideoPlayer::pause() {
if (!_videoURL.empty()) {
[((UIVideoViewWrapperIos *)_videoView) pause];
}
}
void VideoPlayer::stop() {
if (!_videoURL.empty()) {
[((UIVideoViewWrapperIos *)_videoView) stop];
}
}
void VideoPlayer::seekTo(float sec) {
if (!_videoURL.empty()) {
[((UIVideoViewWrapperIos *)_videoView) seekTo:sec];
}
}
float VideoPlayer::currentTime() const {
return [((UIVideoViewWrapperIos *)_videoView) currentTime];
}
float VideoPlayer::duration() const {
return [((UIVideoViewWrapperIos *)_videoView) duration];
}
void VideoPlayer::setVisible(bool visible) {
_isVisible = visible;
if (!visible) {
[((UIVideoViewWrapperIos *)_videoView) setVisible:NO];
} else {
[((UIVideoViewWrapperIos *)_videoView) setVisible:YES];
}
}
void VideoPlayer::addEventListener(const ccstd::string &name, const VideoPlayer::ccVideoPlayerCallback &callback) {
_eventCallback[name] = callback;
}
void VideoPlayer::onPlayEvent(int event) {
switch ((EventType)event) {
case EventType::PLAYING:
_eventCallback["play"]();
break;
case EventType::PAUSED:
_eventCallback["pause"]();
break;
case EventType::STOPPED:
_eventCallback["stoped"]();
break;
case EventType::COMPLETED:
_eventCallback["ended"]();
break;
case EventType::META_LOADED:
_eventCallback["loadedmetadata"]();
break;
case EventType::CLICKED:
_eventCallback["click"]();
break;
case EventType::READY_TO_PLAY:
_eventCallback["suspend"]();
break;
default:
break;
}
}
void VideoPlayer::setFrame(float x, float y, float width, float height) {
auto scaleFactor = [[UIScreen mainScreen] nativeScale];
[((UIVideoViewWrapperIos *)_videoView) setFrame:x / scaleFactor:y / scaleFactor:width / scaleFactor:height / scaleFactor];
}
#endif

View File

@@ -0,0 +1,227 @@
/****************************************************************************
Copyright (c) 2014-2017 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "VideoPlayer.h"
#if (CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS)
#include <jni.h>
#include <cstdlib>
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#include "platform/FileUtils.h"
#include "platform/java/jni/JniHelper.h"
//-----------------------------------------------------------------------------------------------------------
static const ccstd::string VIDEO_HELPER_CLASS_NAME = "com/cocos/lib/CocosVideoHelper";
using namespace cc; //NOLINT
static void executeVideoCallback(int index, int event);
#define QUIT_FULLSCREEN 1000
extern "C" {
JNIEXPORT
//NOLINTNEXTLINE
void Java_com_cocos_lib_CocosVideoHelper_nativeExecuteVideoCallback(JNIEnv *env, jobject obj, jint index, jint event) {
executeVideoCallback(index, event);
}
}
int createVideoWidgetJNI() {
JniMethodInfo t;
int ret = -1;
if (JniHelper::getStaticMethodInfo(t, VIDEO_HELPER_CLASS_NAME.c_str(), "createVideoWidget", "()I")) {
ret = t.env->CallStaticIntMethod(t.classID, t.methodID);
ccDeleteLocalRef(t.env, t.classID);
}
return ret;
}
//-----------------------------------------------------------------------------------------------------------
static ccstd::unordered_map<int, VideoPlayer *> sAllVideoPlayers;
VideoPlayer::VideoPlayer()
: _videoPlayerIndex(-1),
_fullScreenEnabled(false),
_fullScreenDirty(false),
_keepAspectRatioEnabled(false) {
_videoPlayerIndex = createVideoWidgetJNI();
sAllVideoPlayers[_videoPlayerIndex] = this;
#if CC_VIDEOPLAYER_DEBUG_DRAW
_debugDrawNode = DrawNode::create();
addChild(_debugDrawNode);
#endif
}
VideoPlayer::~VideoPlayer() {
destroy();
}
void VideoPlayer::destroy() {
if (_videoPlayerIndex != -1) {
auto iter = sAllVideoPlayers.find(_videoPlayerIndex);
if (iter != sAllVideoPlayers.end()) {
sAllVideoPlayers.erase(iter);
}
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "removeVideoWidget",
_videoPlayerIndex);
_videoPlayerIndex = -1;
}
}
void VideoPlayer::setURL(const ccstd::string &videoUrl) {
if (videoUrl.find("://") == ccstd::string::npos) {
_videoURL = FileUtils::getInstance()->fullPathForFilename(videoUrl);
_videoSource = VideoPlayer::Source::FILENAME;
} else {
_videoURL = videoUrl;
_videoSource = VideoPlayer::Source::URL;
}
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setVideoUrl", _videoPlayerIndex,
static_cast<int>(_videoSource), _videoURL);
}
void VideoPlayer::setFrame(float x, float y, float width, float height) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setVideoRect", _videoPlayerIndex,
static_cast<int>(x), static_cast<int>(y), static_cast<int>(width), static_cast<int>(height));
}
void VideoPlayer::setPlaybackRate(float value) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setPlaybackRate", _videoPlayerIndex, value);
}
void VideoPlayer::setMute(bool enable) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setMute", _videoPlayerIndex, enable);
}
void VideoPlayer::setLoop(bool enable) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setLoop", _videoPlayerIndex, enable);
}
void VideoPlayer::setFullScreenEnabled(bool fullscreen) {
if (_fullScreenEnabled != fullscreen) {
_fullScreenEnabled = fullscreen;
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setFullScreenEnabled", _videoPlayerIndex, fullscreen);
}
}
void VideoPlayer::setKeepAspectRatioEnabled(bool enable) {
if (_keepAspectRatioEnabled != enable) {
_keepAspectRatioEnabled = enable;
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setVideoKeepRatioEnabled", _videoPlayerIndex, enable);
}
}
void VideoPlayer::play() {
if (!_videoURL.empty()) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "startVideo", _videoPlayerIndex);
}
}
void VideoPlayer::pause() {
if (!_videoURL.empty()) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "pauseVideo", _videoPlayerIndex);
}
}
void VideoPlayer::stop() {
if (!_videoURL.empty()) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "stopVideo", _videoPlayerIndex);
}
}
void VideoPlayer::seekTo(float sec) {
if (!_videoURL.empty()) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "seekVideoTo", _videoPlayerIndex, int(sec * 1000));
}
}
void VideoPlayer::setVisible(bool visible) {
JniHelper::callStaticVoidMethod(VIDEO_HELPER_CLASS_NAME, "setVideoVisible", _videoPlayerIndex, visible);
}
void VideoPlayer::addEventListener(const ccstd::string &name, const VideoPlayer::ccVideoPlayerCallback &callback) {
_eventCallback[name] = callback;
}
void VideoPlayer::onPlayEvent(int event) {
if (event == QUIT_FULLSCREEN) {
_fullScreenEnabled = false;
} else {
auto videoEvent = static_cast<VideoPlayer::EventType>(event);
switch (videoEvent) {
case EventType::PLAYING:
_eventCallback["play"]();
break;
case EventType::PAUSED:
_eventCallback["pause"]();
break;
case EventType::STOPPED:
_eventCallback["stoped"]();
break;
case EventType::COMPLETED:
_eventCallback["ended"]();
break;
case EventType::META_LOADED:
_eventCallback["loadedmetadata"]();
break;
case EventType::CLICKED:
_eventCallback["click"]();
break;
case EventType::READY_TO_PLAY:
_eventCallback["suspend"]();
break;
default:
break;
}
}
}
void executeVideoCallback(int index, int event) {
auto it = sAllVideoPlayers.find(index);
if (it != sAllVideoPlayers.end()) {
sAllVideoPlayers[index]->onPlayEvent(event);
}
}
float VideoPlayer::currentTime() const {
return JniHelper::callStaticFloatMethod(VIDEO_HELPER_CLASS_NAME, "getCurrentTime", _videoPlayerIndex);
}
float VideoPlayer::duration() const {
return JniHelper::callStaticFloatMethod(VIDEO_HELPER_CLASS_NAME, "getDuration", _videoPlayerIndex);
}
#endif

View File

@@ -0,0 +1,194 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2016-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <functional>
#include "base/Macros.h"
#include "base/RefCounted.h"
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#ifndef OBJC_CLASS
#ifdef __OBJC__
#define OBJC_CLASS(name) @class name
#else
#define OBJC_CLASS(name) class name
#endif
#endif // OBJC_CLASS
namespace cc {
/**
* @class VideoPlayer
* @brief Displays a video file.
*
* @note VideoPlayer displays a video file base on system widget.
* It's mean VideoPlayer displays a video file above all graphical elements of cocos2d-x.
* @js NA
*/
class VideoPlayer final {
public:
/**
* Videoplayer play event type.
*/
enum class EventType {
PLAYING = 0,
PAUSED,
STOPPED,
COMPLETED,
META_LOADED,
CLICKED,
READY_TO_PLAY,
UPDATE,
};
VideoPlayer();
~VideoPlayer();
/**
* Destroy VideoPlayer, remove it from parent
*/
void destroy();
/**
* A callback which will be called after specific VideoPlayer event happens.
*/
using ccVideoPlayerCallback = std::function<void()>;
/**
* Sets a URL as a video source for VideoPlayer.
*/
virtual void setURL(const ccstd::string &videoURL);
/**
* Starts playback.
*/
virtual void play();
/**
* Pauses playback.
*/
virtual void pause();
/**
* Stops playback.
*/
virtual void stop();
/**
* Seeks to specified time position.
*
* @param sec The offset in seconds from the start to seek to.
*/
virtual void seekTo(float sec);
/**
* Get the current play time, measure in seconds.
*/
float currentTime() const;
float duration() const;
/**
* Causes the video player to keep aspect ratio or no when displaying the video.
*
* @param enable Specify true to keep aspect ratio or false to scale the video until
* both dimensions fit the visible bounds of the view exactly.
*/
virtual void setKeepAspectRatioEnabled(bool enable);
/**
* Indicates whether the video player keep aspect ratio when displaying the video.
*/
virtual bool isKeepAspectRatioEnabled() const { return _keepAspectRatioEnabled; }
/**
* Causes the video player to enter or exit full-screen mode.
*
* @param fullscreen Specify true to enter full-screen mode or false to exit full-screen mode.
*/
virtual void setFullScreenEnabled(bool fullscreen);
/**
* Register a callback to be invoked when the video state is updated.
*
* @param callback The callback that will be run.
*/
virtual void addEventListener(const ccstd::string &name, const VideoPlayer::ccVideoPlayerCallback &callback);
/**
* @brief A function which will be called when video is playing.
*
* @param event @see VideoPlayer::EventType.
*/
virtual void onPlayEvent(int event);
/**
* Toggle visibility of VideoPlayer.
*/
virtual void setVisible(bool visible);
/**
* Set the rect of VideoPlayer.
*/
virtual void setFrame(float x, float y, float width, float height);
/**
* Set playback rate of VideoPlayer.
*/
virtual void setPlaybackRate(float value);
/**
* Set mute of VideoPlayer.
*/
virtual void setMute(bool enable);
/**
* Set loop of VideoPlayer.
*/
virtual void setLoop(bool enable);
protected:
enum class Source {
FILENAME = 0,
URL
};
bool _isVisible;
bool _fullScreenDirty;
bool _fullScreenEnabled;
bool _keepAspectRatioEnabled;
ccstd::string _videoURL;
Source _videoSource;
int _videoPlayerIndex;
ccstd::unordered_map<ccstd::string, ccVideoPlayerCallback> _eventCallback;
void *_videoView;
};
} // namespace cc