Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer
Accepted Solution

Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2)

Hi everyone,

 

I'm implementing video playback on a game that uses cocos2d-x on the PlayBook. The game has an intro, and I'd like to display it on full screen at the beginning of the game.

 

I'm having problems when trying to code the part to play the video. I began with the documentation which explains step by step the things you have to do to play video (https://developer.blackberry.com/native/documentation/Video_playback_overview_1935223_11.html).

 

There is also a very helpful VideoWindow example on Momentics which let me check if my video could be reproduced, and also draw some stuff with OpenGL on top.

 

I'm stuck with integrating this code with cocos2d-x. Cocos2d-x makes some initializations on its blackberry platform-specific CCEGLView class, and keeps the m_screenWindow member private, which is necesarry to create a window group to attach the renderer to.

 

I integrated the VideoWindow example code on cocos2dx, and I'm getting somewhere to play video, but I'm having a problem with the multimedia renderer, which won't allow to attach an input of the video I'm trying to play.

 

I also had to modify the blackberry CCEGLView object to make it expose the m_screenWindow property.

 

The init() function of the extended CCLayer that will play the video is at the end of this message.

 

The problem I'm having now with this code is that the mmr_input_attach function fails with a MMR_ERROR_UNKNOWN error code, which has quickly exhausted my options regarding on how to solve this issue. The CCEGLView object has only been modified to add the getScreenWindow() function which only returns the otherwise private m_screenWindow property.

 

Thanks for helping!

 

// on "init" you need to initialize your instance
bool VideoScene::init()
{
    int rc;
    I18n::init();

    if ( !CCLayer::init() )
    {
        return false;
    }
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    srand(time(0));
    app_id = rand();

    // I/O devices
    static char *audio_device_url = (char *)"audio:default";
    static char video_device_url[PATH_MAX];
    rc = snprintf(video_device_url, PATH_MAX, "screen:?winid=spdintrowindowgroup&wingrp=spdintrowindowgroup");
    if (rc >= PATH_MAX) {
        fprintf(stderr, "URL too long\n");
    }

    // Name of video context...with a random number appended.
    static char video_context_name[PATH_MAX];
    rc = snprintf(video_context_name, PATH_MAX, "spdintrocontextname");
    if (rc >= PATH_MAX) {
        fprintf(stderr, "Video context name too long\n");
    }

    // Window group name...with the same random number appended.
    static char window_group_name[PATH_MAX];
    rc = snprintf(window_group_name, PATH_MAX, "spdintrowindowgroup");
    if (rc >= PATH_MAX) {
        fprintf(stderr, "Video context name too long\n");
    }

    // Video file bundled with our app
    static const char *video_file_relative_path = "app/native/Resources/intro.mp4";

    /* Create the window group for our window, this is important, as we pass the group name
     * to MMR which uses it to 'parent' it's CHILD_WINDOW which contains the video
     */
    if (screen_create_window_group(CCEGLView::sharedOpenGLView()->getScreenWindow(), window_group_name) != 0) {
        return false;
    }

    /*
     * Configure mm-renderer.
     */
    mmr_connection = mmr_connect(NULL);
    if (mmr_connection == NULL) {
        return false;
    }

    mmr_context = mmr_context_create(mmr_connection, video_context_name, 0, S_IRWXU|S_IRWXG|S_IRWXO);
    if (mmr_context == NULL) {
        return false;
    }

    /*
     * Configure video and audio output.
     */
    video_device_output_id = mmr_output_attach(mmr_context, video_device_url, "video");
    if (video_device_output_id == -1) {
        return false;
    }

    audio_device_output_id = mmr_output_attach(mmr_context, audio_device_url, "audio");
    if (audio_device_output_id == -1) {
        return false;
    }

    // Build up the path where our bundled resource is.
    char cwd[PATH_MAX];
    char media_file[PATH_MAX];
    getcwd(cwd,PATH_MAX);

    rc = snprintf(media_file, PATH_MAX, "file://%s/%s", cwd, video_file_relative_path);
    if ((rc == -1) || (rc >= PATH_MAX)) {
        return false;
    }

    /*
     * Attach the input media.
     */
    if (mmr_input_attach(mmr_context, media_file, "track") != 0) {
        const mmr_error_info_t *mmr_error_code = mmr_error_info(mmr_context);
        printf("%d\n", *mmr_error_code);
        return false;
    }

    int video_speed = 1;
    /*
     * Set the speed to 0 to pause the video initially
     */
    if (mmr_speed_set(mmr_context, video_speed) != 0) {
        return false;
    }

    /*
     * Change to the play state, although speed is zero
     */
    if (mmr_play(mmr_context) != 0) {
        return false;
    }

    return true;
}
Please use plain text.
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2)

Just to let you know, this message has been posted to the appropiate cocos2d-x forum, but I haven't got any answers from there. (http://cocos2d-x.org/boards/6/topics/15683)
Please use plain text.
BlackBerry Development Advisor
lingBB10Dev
Posts: 35
Registered: ‎08-01-2012
My Carrier: T-Mobile

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2)

were u able to figure out what was the problem?

Please use plain text.
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2)

No, I haven't. I got back to this problem this week, and I'm still getting the MMR_UNKNOWN_ERROR. One thing I had not noticed, though, is this comment below the declaration of that enum

 

MMR_ERROR_UNKNOWN,
// Includes things that are not supposed to happen unless there's a bug
// or someone has messed with our PPS objects

 

To be honest, I don't have the faintest idea of what does a PPS object mean, but at least there's something there.

Please use plain text.
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

I finally could connect the video to a cocos2d-x node. Here's the thing. You have to modify a bit some internals of cocos2d-x.

 

Download the cocos2d-x from out of the box. You have to modify cocos2dx/platform/blackberry/CCEGLView.cpp to include this snippet (in bold) at the end of the CCEGLView::initGL() function.

 

bool CCEGLView::initGL()
{

  //...

  m_obScreenSize.width = width;
  m_obScreenSize.height = height;

  // Set vsync.
  // eglSwapInterval(m_eglDisplay, screenSwapInterval);

  if (screen_create_window_group(m_screenWindow, "videowindowgroup") != 0) {
    return false;
  }

  return true;
}

 

Have a node subclass with this code:

 

#include <mm/renderer.h>

#include <bps/navigator.h>
#include <bps/screen.h>
#include <unistd.h>
#include <bps/bps.h>
#include "VideoScene.h"

 

 

USING_NS_CC;

// on "init" you need to initialize your instance
bool VideoScene::init()
{
  int rc;

  I18n::init();

  if ( !CCLayer::init() )
  {
    return false;
  }
  CCSize size = CCDirector::sharedDirector()->getWinSize();

  // I/O devices
  static char *audio_device_url = (char *)"audio:default";
  static char video_device_url[PATH_MAX];
  rc = snprintf(video_device_url, PATH_MAX, "screen:?winid=%s&wingrp=%s", "videowindowgroup", "videowindowgroup");
  if (rc >= PATH_MAX) {
    fprintf(stderr, "URL too long\n");
  }

  // Name of video context...with a random number appended.
  static char video_context_name[PATH_MAX];
  rc = snprintf(video_context_name, PATH_MAX, "spdvideocontext");
  if (rc >= PATH_MAX) {
    fprintf(stderr, "Video context name too long\n");
  }

  /*
   * Configure mm-renderer.
   */
  mmr_connection = mmr_connect(NULL);
  if (mmr_connection == NULL) {
    return false;
  }

  mmr_context = mmr_context_create(mmr_connection, video_context_name, 0, S_IRWXU|S_IRWXG|S_IRWXO);
  if (mmr_context == NULL) {
    return false;
  }

  /*
   * Configure video and audio output.
   */
  video_device_output_id = mmr_output_attach(mmr_context, video_device_url, "video");
  if (video_device_output_id == -1) {
    return false;
  }

  audio_device_output_id = mmr_output_attach(mmr_context, audio_device_url, "audio");
  if (audio_device_output_id == -1) {
    return false;
  }

  // Build up the path where our bundled resource is.
  char cwd[PATH_MAX];
  char media_file[PATH_MAX];
  getcwd(cwd,PATH_MAX);

  rc = snprintf(media_file, PATH_MAX, "file://%s/%s", cwd, CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("yourvideo.mp4"));
  if ((rc == -1) || (rc >= PATH_MAX)) {
    return false;
  }

  /*
   * Attach the input media.
   */
  if (mmr_input_attach(mmr_context, media_file, "track") != 0) {
    return false;
  }

  int video_speed = 1000;
  /*
   * Set the speed to 1 to play the video initially
   */
  if (mmr_speed_set(mmr_context, video_speed) != 0) {
    return EXIT_FAILURE;
  }

  /*
   * Change to the play state, although speed is zero
   */
  if (mmr_play(mmr_context) != 0) {
    return false;
  }

  return true;
}

CCScene* VideoScene::scene()
{
  // 'scene' is an autorelease object
  CCScene *scene = CCScene::create();

  // 'layer' is an autorelease object
  VideoScene *layer = VideoScene::create();

  // add layer as a child to scene
  scene->addChild(layer);

  // return the scene
  return scene;
}

void VideoScene::draw() {
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //Video is behing OpenGL context
}

 

 

This is the corresponding header:

 

#ifndef VIDEOSCENE_H_
#define VIDEOSCENE_H_

#include <mm/renderer.h>

#include "cocos2d.h"

class VideoScene: public cocos2d::CCLayer {
public:
  // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
  virtual bool init();

  // there's no 'id' in cpp, so we recommand to return the exactly class pointer
  static cocos2d::CCScene* scene();

  virtual void draw();

  // implement the "static node()" method manually
  CREATE_FUNC(VideoScene);

  // Renderer variables
  mmr_connection_t* mmr_connection;
  mmr_context_t* mmr_context;

  // I/O variables
  int video_device_output_id;
  int audio_device_output_id;
};
#endif /* VIDEOSCENE_H_ */

 

You are free to move the "videowindowgroup" to a #include if you want to prevent repeating the string everywhere. You should also use the BB event system to capture when the video finishes playing, but that's outside of this post :-)

Please use plain text.
New Contributor
proudchild
Posts: 7
Registered: ‎09-25-2012
My Carrier: Claro

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

Hello,

 

I could compile straight forward what is here...
I needed to add #include <sys/stat.h> and obviously using namespace std;

Another thing this In18::init() its something yours right???

Please use plain text.
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

You're right, that was something that got past me, I will edit the code.

Please use plain text.
New Contributor
proudchild
Posts: 7
Registered: ‎09-25-2012
My Carrier: Claro

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

And yet, all i see is a blank screen...

 

Am i missing something???

Please use plain text.
New Contributor
proudchild
Posts: 7
Registered: ‎09-25-2012
My Carrier: Claro

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

I just noticed...

 

int temp_rectangle[4] = {0,0,size[0],size[1]};
screen_buffer_t temp_buffer[1];

screen_get_window_property_pv(m_screenWindow,  SCREEN_PROPERTY_RENDER_BUFFERS, (void**)temp_buffer);
int fill_attributes[3] = {SCREEN_BLIT_COLOR, 0x0, SCREEN_BLIT_END};
screen_fill(m_screenContext, temp_buffer[0], fill_attributes);
screen_post_window(m_screenWindow, temp_buffer[0], 1, temp_rectangle, 0);

 

this chunk of code is missing on your code, and its there on the example code:

https://developer.blackberry.com/native/documentation/video_playback_play_1935231_11.html

 

Apparently (as explained in the link) that is the part responsible for showing the video on the screen, and that's perhaps the reason why I can't see my video.

Where did you placed that chunk of code???

Please use plain text.
Contributor
chiguire
Posts: 23
Registered: ‎09-19-2012
My Carrier: Developer

Re: Playing video with cocos2d-x (cocos2d-2.0-x-2.0.2) [SOLVED]

That's probably the code you need to post your video when using the Playbook screen API.

 

That code you posted is not present in the VideoWindow example you can find bundled in Momentics. I used the code in that example to implement video in cocos2d-x.

 

Do a sanity check with the .mp4 video that is included in that example, in case you are testing with another video.

Please use plain text.