您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx 3.3 视频播放的实现-VideoPlayer的使用

2015-03-18 11:05 573 查看
最近因为项目需求需要使用到视频播放功能。

在3.x版本之前如果需要用到视频播放功能就要使用原生的视频播放实现技术,好在3.x之后官方已经集成了视频播放功能,这是值得欣慰的。但是欣慰过后的悲剧在于,官方的文档一直跟不上版本的更新速度。虽然集成了这个功能,但是郁闷的是你要花费很大的力气去尝试使用技巧(仅限于类似我这种菜鸟)。

以下为我整了好久才摸到的使用方法,其实使用不难,难的是一定要注意这个集成的播放器(VideoPlayer)是有平台限制的。一些代码只有在android平台和IOS平台有效。废话不多说了,直接上实例代码:

HelloWorldScene.h文件

[cpp] view
plaincopyprint?

#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__



#include "cocos2d.h"

//务必引入以下2个.h文件

#include "ui/UIVideoPlayer.h"

#include "ui/CocosGUI.h"

USING_NS_CC;

class HelloWorld : public Layer

{

public:

static Scene* createScene();



virtual bool init();



void onEnter();



void videoPlayOverCallback();



void showVideo();

/**

* 视频播放状态,只有在android和ios平台有效

*/

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

void videoEventCallback(Ref* sender, cocos2d::experimental::ui::VideoPlayer::EventType eventType);

#endif



CREATE_FUNC(HelloWorld);

};

#endif

HelloWorldScene.cpp文件

[cpp] view
plaincopyprint?

#include "HelloWorldScene.h"



USING_NS_CC;



Scene* HelloWorld::createScene()

{

auto scene = Scene::create();

auto layer = HelloWorld::create();

scene->addChild(layer);

return scene;

}

bool HelloWorld::init()

{

if ( !Layer::init() )

{

return false;

}

return true;

}



void HelloWorld::onEnter(){

Layer::onEnter();

showVideo();

}



void HelloWorld::showVideo(){

Size size = Director::getInstance()->getVisibleSize();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

auto videoPlayer = cocos2d::experimental::ui::VideoPlayer::create();

videoPlayer->setPosition(Point(size.width / 2, size.height / 2));

videoPlayer->setAnchorPoint(Vec2::ANCHOR_MIDDLE);

videoPlayer->setContentSize(Size(size.width , size.height));

this->addChild(videoPlayer);

if (videoPlayer)

{

videoPlayer->setFileName("1111.mp4");

videoPlayer->play();

}

videoPlayer->addEventListener(CC_CALLBACK_2(HelloWorld::videoEventCallback, this));

#endif

}



/**

* 视频播放完成的回调函数

*/

void HelloWorld::videoPlayOverCallback()

{



}

/**

* 视频播放的状态

* 注意这里的代码,此处代码只有在android平台和Ios平台有效

*/

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

void HelloWorld::videoEventCallback(Ref* sender, cocos2d::experimental::ui::VideoPlayer::EventType eventType){

switch (eventType) {

case cocos2d::experimental::ui::VideoPlayer::EventType::PLAYING:

break;

case cocos2d::experimental::ui::VideoPlayer::EventType::PAUSED:

break;

case cocos2d::experimental::ui::VideoPlayer::EventType::STOPPED:

break;

case cocos2d::experimental::ui::VideoPlayer::EventType::COMPLETED:

videoPlayOverCallback();

break;

default:

break;

}

}

#endif

如此即可实现视频播放了,对视频的控制请参考官方demo

================================下面是另一篇博客的记录========

Cocos2d-x v2.2.1版本

下面简单实现Cocos2d-x一个视频播放的模块,需要播放视频时,不用到处乱改了,一句代码搞定!

一. IOS播放本地视频

对于IOS平台的视频播放,这里直接使用MediaPlayer.framework来播放视频

注意:MediaPlayer.framework播放视频格式有限,可能需要转换为指定的视频格式才能播放!

1.添加MediaPalyer框架到项目中

2.简单写三个类

VideoPlatform ,IOSPlayVideo,IOSVideoController

1)VideoPlatform 这个类用来判断播放视频的平台,从而调用各自平台的视频播放接口

VideoPlatform.h

[cpp] view
plaincopy





#ifndef __Platform_H_H__

#define __Platform_H_H__

#include "cocos2d.h"

using namespace cocos2d;

class VideoPlatform

{

public:

//在当前的layer上播放视频,视频完毕或者点击跳过视频会跳转到指定的layer上(默认为空,也就是停留在当前layer上)

static void playVideo(const char * filename,CCLayer *layer =NULL);

};



#endif // __Platform_H_H__

VideoPlatform.cpp

[cpp] view
plaincopy





#include "VideoPlatform.h"

#include "../../cocos2dx/platform/CCPlatformConfig.h"

#if (CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)

#include <jni.h>

#include "../../cocos2dx/platform/android/jni/JniHelper.h"

#include <android/log.h>

#elif(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)

#include "IOSPlayVideo.h"

#endif



void VideoPlatform::playVideo(const char * filename,CCLayer *layer)

{



#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

//Android视频播放代码

JniMethodInfo minfo;

bool isHave = JniHelper::getMethodInfo(minfo,"org/cocos2dx/video/video","playVideo", "()V");

if (isHave) {

minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);

}

#elif(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)

//iOS视频播放代码

IOSPlayVideo::playVideoForIOS(filename,layer);



#endif



}

2) IOSPlayVideo是IOS平台播放视频的接口

IOSPlayVideo.h

[cpp] view
plaincopy





#ifndef __IOSPlayVideo_H_H__

#define __IOSPlayVideo_H_H__



#include "cocos2d.h"

using namespace cocos2d;

class IOSPlayVideo

{

public:

static void playVideoForIOS(const char * filename,CCLayer *layer);



};



#endif // __IOSPlayVideo_H_H__

IOSPlayVideo.mm

[cpp] view
plaincopy





#include "IOSPlayVideo.h"

#include "IOSVideoController.h"



void IOSPlayVideo::playVideoForIOS(const char * filename,CCLayer *layer)

{

// char * 转化为 NSString

NSString *audioname=[NSString stringWithUTF8String:filename];

IOSVideoController *app = [[IOSVideoController alloc] init];

[app playVideo:audioname :layer];



}

3)最后IOSVideoController这个类就是ios播放视频的具体实现了

IOSVideoController.h

[cpp] view
plaincopy





#import "MediaPlayer/MediaPlayer.h"

#import "cocos2d.h"

#include "SimpleAudioEngine.h"

using namespace cocos2d;

using namespace CocosDenshion;



@interface IOSVideoController :MPMoviePlayerViewController

{

MPMoviePlayerController *movePlayer;

UIWindow *window;

CCLayer *TargetLayer;

}



//播放网络视频

-(void)playUrlVideo;



//在当前场景上播放视频,播完或者点击跳过视频 到指定的场景

-(void)playVideo:(NSString *)filename :(CCLayer *)targetLayer;

@end

IOSVideoController.mm

[cpp] view
plaincopy





#import "IOSVideoController.h"

#import "AppController.h"

@implementation IOSVideoController



//播放网络视频

-(void)playUrlVideo

{







}

-(void)playVideo:(NSString *)filename :(CCLayer *)targetLayer

{

TargetLayer =targetLayer;

//跳转Layer非空

if (targetLayer) {

TargetLayer->retain();

}



SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();

SimpleAudioEngine::sharedEngine()->pauseAllEffects();



NSString *myFilePath = [[NSBundle mainBundle] pathForResource:filename ofType:nil inDirectory:nil];

NSURL *url = [NSURL fileURLWithPath:myFilePath];



movePlayer=[[MPMoviePlayerController alloc] initWithContentURL:url];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:movePlayer];



if([movePlayer respondsToSelector:@selector(setFullscreen:animated:)])

{

movePlayer.shouldAutoplay=YES;



CCSize winSize=CCDirector::sharedDirector()->getWinSize();

CCLog("winSize.width====%f winSize.height====%f",winSize.width,winSize.height);

// 这里iPad2和ipad3 视频位置调整是正确的,Iphone 可能需要细微调整



if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)

{

movePlayer.view.frame=CGRectMake(-80,80, 480, 320);

}

else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)

{

movePlayer.view.frame=CGRectMake(-128, 128, winSize.width, winSize.height);

}

else

{

movePlayer.view.frame=CGRectMake(-80,80, 480, 320);



}



// 强制横屏

CGAffineTransform landscapeTransform;

UIDevice *device = [UIDevice currentDevice] ;

if (device.orientation==UIDeviceOrientationLandscapeLeft)

{

landscapeTransform = CGAffineTransformMakeRotation(M_PI / 2);

}

else

{

landscapeTransform = CGAffineTransformMakeRotation(-M_PI / 2);

}

movePlayer.view.transform = landscapeTransform;



// 新建一个window,添加视频这个UIView

window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];



[window addSubview:movePlayer.view];

[window makeKeyAndVisible];

// 在视频上方添加“跳过”按钮

CGRect frame = CGRectMake(768-100, 100, 100, 50);

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

button.frame = frame;

[button setTitle:@"跳过" forState: UIControlStateNormal];



button.transform =landscapeTransform;

button.backgroundColor = [UIColor clearColor];

button.tag = 2000;

[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

[window addSubview:button];





// 设置是否带控制条

movePlayer.controlStyle = MPMovieControlStyleNone;

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];



}

else

{

movePlayer.controlStyle=MPMovieControlModeHidden;

}



[self playMovie];





}

//跳过视频

-(IBAction) buttonClicked:(id)sender {

[movePlayer stop];



[movePlayer.view removeFromSuperview];

[movePlayer release];

[window release];

SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();

SimpleAudioEngine::sharedEngine()->resumeAllEffects();



if (!TargetLayer) {

return;

}

TargetLayer->removeAllChildrenWithCleanup(true);

TargetLayer->removeFromParent();



CCScene * scene =CCScene::create();

scene->addChild(TargetLayer,10);

CCDirector::sharedDirector()->replaceScene(scene);





}

//播放开始

-(void) playMovie

{

MPMoviePlaybackState state=movePlayer.playbackState;

if(state==MPMoviePlaybackStatePlaying)

{

NSLog(@"Movie is already playing.");

return;

}

[movePlayer play];

}

//退出全屏

-(void)exitFullScreen:(NSNotification *)notification{

CCLOG("exitFullScreen");

movePlayer.controlStyle=MPMovieControlStyleDefault;

[movePlayer.view removeFromSuperview];

}

//视频播放结束

- (void) movieFinished:(NSNotificationCenter *)notification{

// CCLOG("moviePlaybackFinished");

//视频播放完毕



movePlayer.controlStyle=MPMovieControlStyleDefault;

MPMoviePlaybackState state=movePlayer.playbackState;

if(state==MPMoviePlaybackStateStopped){

NSLog(@"Movie is already stopped.");

return;

}

[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:movePlayer];

if([movePlayer respondsToSelector:@selector(setFullscreen:animated:)])

{



[movePlayer.view removeFromSuperview];

[window release];



SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();

SimpleAudioEngine::sharedEngine()->resumeAllEffects();



if (!TargetLayer) {

return;

}

TargetLayer->removeAllChildrenWithCleanup(true);

TargetLayer->removeFromParent();

CCScene * scene =CCScene::create();

scene->addChild(TargetLayer,10);

CCDirector::sharedDirector()->replaceScene(scene);



}



}



- (void)dealloc {

[super dealloc];

if (TargetLayer) {

TargetLayer->release();

}



}

@end



IOS项目里只需在需要的地方调用接口

//只在当前layer上播放视频,播完不跳转就调这个

VideoPlatform::playVideo("test.mp4");

//当前layer上播放视频,播完跳转到指定layer就调这个

VideoPlatform::playVideo("test.mp4",TestLayer::create());

就可以播放视频了!有没有发觉世界瞬间变得美好了一点呢?

二.IOS播放网络视频

只需将

[cpp] view
plaincopy





NSURL *url = [NSURL fileURLWithPath:myFilePath];

类似改为:

[cpp] view
plaincopy





NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/test.mp4"];

(后面填写视频地址就OK!)

三.Android 播放本地视频

至于Android就稍微麻烦一点,需要用到Jni 技术, C++调用java

1) 添加一个VideoActivity

[java] view
plaincopy





package org.cocos2dx.video;



import android.app.Activity;

import android.content.pm.ActivityInfo;

import android.media.MediaPlayer;

import android.net.Uri;

import android.os.Bundle;

import android.view.Window;

import android.view.WindowManager;

import android.widget.MediaController;

import android.widget.VideoView;





public class VideoActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//强制为横屏

setContentView(R.layout.videoview);



final VideoView videoView = (VideoView)findViewById(R.id.VideoView01);

videoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" +R.raw.theme));

videoView.start();

// 视频播控制条设置

MediaController controller = new MediaController(VideoActivity.this);

videoView.setMediaController(controller);

// 播放完成监听

videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()

{

@Override

public void onCompletion(MediaPlayer mp)

{

//播放结束后的动作,返回点击播放视频的那个页面

finish();

}

});



}





}

2) 修改AndroidManifest.xml,添加一个Activity

[html] view
plaincopy





<activity android:name="VideoActivity"

android:label="@string/app_name"

android:screenOrientation="landscape"

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

android:configChanges="orientation">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

3) 在res /layout添加一个 videoview.xml

[html] view
plaincopy





<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center"

tools:context=".VideoActivity" >



<VideoView

android:id="@+id/VideoView01"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_alignParentLeft="true"

android:layout_alignParentRight="true"

android:layout_alignParentTop="true"

android:orientation="horizontal"

android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />



</RelativeLayout>

4)在res 下添加一个raw文件夹,里面放你要播放的视频,例如:theme.mp4,这里我的视频文件名为theme

5)修改video.java (我的Android 项目包名为 org.cocos2dx.video)

[java] view
plaincopy





package org.cocos2dx.video;



import org.cocos2dx.lib.Cocos2dxActivity;

import org.cocos2dx.lib.Cocos2dxGLSurfaceView;



import android.content.Intent;

import android.os.Bundle;



public class video extends Cocos2dxActivity{

public static video instance;

public static Intent intent;

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

instance =this;

intent = new Intent(video.this, VideoActivity.class);



}

void playVideo()

{

instance.startActivity(intent);

}

public Cocos2dxGLSurfaceView onCreateView() {

Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);

// video should create stencil buffer

glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);



return glSurfaceView;

}

static {

System.loadLibrary("cocos2dcpp");

}

}

至此 Android播放本地视频就OK了!

四.Android 播放网络视频

新添加一个如下方法即可(同样也可以使用JNI C++调Java)

[java] view
plaincopy





void playURLVideo()

{

Intent intent = new Intent(Intent.ACTION_VIEW);

String type = "video/* ";

Uri uri = Uri.parse("http://forum.ea3w.com/coll_ea3w/attach/2008_10/12237832415.3gp");

intent.setDataAndType(uri, type);

instance.startActivity(intent);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: