no message
This commit is contained in:
474
cocos/ui/videoplayer/VideoPlayer-ios.mm
Normal file
474
cocos/ui/videoplayer/VideoPlayer-ios.mm
Normal 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
|
||||
227
cocos/ui/videoplayer/VideoPlayer-java.cpp
Normal file
227
cocos/ui/videoplayer/VideoPlayer-java.cpp
Normal 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
|
||||
194
cocos/ui/videoplayer/VideoPlayer.h
Normal file
194
cocos/ui/videoplayer/VideoPlayer.h
Normal 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
|
||||
Reference in New Issue
Block a user