用Cocos2d-x和libvlc写一个跨平台播放器

简介:本文使用cocos2d-x和libvlc两大免费开源的跨平台框架,实现一个视频播放器。开发工具使用Visual Studio 2010,测试运行平台为Windows(其它平台暂时没测试)。cocos2d-x版本2.0.3,VLC版本2.0.5。

目前游戏程序开发者大部分在以下几个平台上开发游戏:Windows、Mac OS X、IOS和Android。开发2D游戏且跨平台,cocos2d-x是个非常不错的选择,而libvlc也提供了各大平台的支持,因此使用这两大框架基本可以做到一次编写,全平台运行的目的。

打开Visual Studio 2010,新建一个Cocos2d-win32 Application项目,我这里叫Cocos2dPlayer,配置好整个项目,直到可以编译通过且能运行(如何配置可以参考网上很多帖子教程,在此就不多说,见谅)。另外还要加上vlc头文件、库文件和动态链接库文件,我是直接下载vlc播放器的安装版本然后在sdk目录中把vlc文件夹拷贝到Visual Studio 2010的VC\include目录下,库文件和动态链接库文件则放在本项目的Debug.win32和Release.win32目录下。

接下来进入正题:
创建文件MoviePlayer.h和MoviePlayer.cpp

MoviePlayer.h

#ifndef __MOVIEPLAYER_H__
#define __MOVIEPLAYER_H__

/****************************************************************************
http://www.cnblogs.com/evan-cai/

Author: Evan-Cai
Date: 2013-01-25
****************************************************************************/

#include <vlc\vlc.h>
#include "sprite_nodes\CCSprite.h"

NS_CC_BEGIN

class MoviePlayer : public CCSprite
{
public:
    ~MoviePlayer();

    static MoviePlayer * instance(void);

    bool init(void);
    void play(char *path);
    void stop(void);
    void pause(void);
    void draw(void);
protected:
    MoviePlayer();

private:

    libvlc_instance_t *vlc;
    libvlc_media_player_t *vlc_player;

    unsigned int width;
    unsigned int height;

    static MoviePlayer * _instance; 
};

NS_CC_END

#endif

MoviePlayer.cpp

#include "MoviePlayer.h"
#include "CCDirector.h"

NS_CC_BEGIN

MoviePlayer * MoviePlayer::_instance = 0;

static char * videobuf = 0;

static void *lock(void *data, void **p_pixels)
{
    *p_pixels = videobuf;
    return NULL;
}

static void unlock(void *data, void *id, void *const *p_pixels)
{
    assert(id == NULL);
}

static void display(void *data, void *id)
{
    (void) data;
    assert(id == NULL);
}

MoviePlayer::MoviePlayer():
vlc(0), vlc_player(0)
{
    init();
}

MoviePlayer::~MoviePlayer()
{
    CCSprite::~CCSprite();
    free(videobuf);

    libvlc_media_player_stop(vlc_player);
    libvlc_media_player_release(vlc_player);
    libvlc_release(vlc);
}

bool MoviePlayer::init(void)
{
    vlc = libvlc_new(0, NULL);
    vlc_player = libvlc_media_player_new(vlc);

    CCSize size = CCDirector::sharedDirector()->getWinSize();
    width = size.width;
    height = size.height;
    videobuf = (char *)malloc((width * height) << 2);
    memset(videobuf, 0, (width * height) << 2);
    libvlc_video_set_callbacks(vlc_player, lock, unlock, display, NULL);
    libvlc_video_set_format(vlc_player, "RGBA", width, height, width << 2);
    
    CCTexture2D *texture = new CCTexture2D();
    texture->initWithData(videobuf, kCCTexture2DPixelFormat_RGBA8888, width, height, size);
    return initWithTexture(texture);
}

void MoviePlayer::play(char *path)
{
    libvlc_media_t *media = libvlc_media_new_path(vlc, path);
    libvlc_media_player_set_media(vlc_player, media);
    libvlc_media_release(media);
    libvlc_media_player_play(vlc_player);
}

void MoviePlayer::stop(void)
{
    libvlc_media_player_stop(vlc_player);
}

void MoviePlayer::pause(void)
{
    libvlc_media_player_pause(vlc_player);
}

void MoviePlayer::draw(void)
{

    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");

    CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");

    CC_NODE_DRAW_SETUP();

    ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );

    if (m_pobTexture != NULL)
    {
        ccGLBindTexture2D( m_pobTexture->getName() );
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,(uint8_t *) videobuf);
    }
    else
    {
        ccGLBindTexture2D(0);
    }

    //
    // Attributes
    //

    ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );

#define kQuadSize sizeof(m_sQuad.bl)
    long offset = (long)&m_sQuad;

    // vertex
    int diff = offsetof( ccV3F_C4B_T2F, vertices);
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

    // texCoods
    diff = offsetof( ccV3F_C4B_T2F, texCoords);
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

    // color
    diff = offsetof( ccV3F_C4B_T2F, colors);
    glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    CHECK_GL_ERROR_DEBUG();

    CC_INCREMENT_GL_DRAWS(1);

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}

MoviePlayer * MoviePlayer::instance()
{
    if(_instance == 0)
        _instance = new MoviePlayer();
    return _instance;
}

NS_CC_END

然后编辑HelloWorldScene.cpp文件的init函数,最后函数如下:
(说明:我把HelloWorld类改成了Cocos2dPlayer类,所以浏览本文章的朋友只要把下面的Cocos2dPlayer::init改成HelloWorld::init就可以编译运行了,另外Can't Wait.mp4是我在网络上下载下来的mp4文件,请朋友你自行更改名称_

bool Cocos2dPlayer::init()
{
    bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());

        //////////////////////////////////////////////////////////////////////////
        // add your codes below...
        //////////////////////////////////////////////////////////////////////////

        // 1. Add a menu item with "X" image, which is clicked to quit the program.

        // Create a "close" menu item with close icon, it's an auto release object.
        CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
            "CloseNormal.png",
            "CloseSelected.png",
            this,
            menu_selector(Cocos2dPlayer::menuCloseCallback));
        CC_BREAK_IF(! pCloseItem);

        // Place the menu item bottom-right conner.
        pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));

        // Create a menu with the "close" menu item, it's an auto release object.
        CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
        pMenu->setPosition(CCPointZero);
        CC_BREAK_IF(! pMenu);

        // Add the menu to Cocos2dPlayer layer as a child layer.
        this->addChild(pMenu, 1);

        // 2. Add a label shows "Hello World".

        // Create a label and initialize with string "Hello World".
        //CCLabelTTF* pLabel = CCLabelTTF::create("Let's PLAY!", "Arial", 24);
        //CC_BREAK_IF(! pLabel);

        // Get window size and place the label upper. 
        CCSize size = CCDirector::sharedDirector()->getWinSize();
        //pLabel->setPosition(ccp(size.width / 2, size.height - 50));

        // Add the label to Cocos2dPlayer layer as a child layer.
        //this->addChild(pLabel, 1);

        // 3. Add add a splash screen, show the cocos2d splash image.
        MoviePlayer* pPlayer = MoviePlayer::instance();

        // Place the sprite on the center of the screen
        pPlayer->setPosition(ccp(size.width/2, size.height/2));

        // Add the sprite to Cocos2dPlayer layer as a child layer.
        this->addChild(pPlayer, 0);

        pPlayer->play("Can't Wait.mp4");

        bRet = true;
    } while (0);

    return bRet;
}

转自:
http://www.cnblogs.com/evancai/archive/2013/01/25/2876803.html?utm_source=tuicool&utm_medium=referral

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • Cocos2d-x是一个开源的移动2D游戏框架,MIT许可证下发布的。这是一个C++ Cocos2d-iPhone...
    黄花菜已凉阅读 1,107评论 1 3
  • 我们非常荣幸地宣布 Visual Studio 2017 现已推出! 此次发布提供新的轻量模块式安装体验,可根据自...
    三梦哥阅读 7,713评论 0 6
  • 前言 我选择开发一个游戏有很多原因。我觉得自己是“核心”玩家,过去的大部分时间我都花在玩游戏,自己制作、阅读和游戏...
    月影檀香阅读 11,868评论 1 27
  • 如果你不说话 我会用沉默填满心房 牵着你的手 望着远方 如果你不说话 我会静静等待 残夜终将会过去 黎明笼罩四方 ...
    云中守望阅读 370评论 4 6
  • 朋友刚开一家广告公司,我在给他帮忙。可是不到一个月,今天电被物业给断了。他暴跳如雷。 原因是这间房子没有电表,这一...
    娴静雅之阅读 970评论 0 0