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
Developer
Posts: 37
Registered: ‎05-30-2009
My Device: Not Specified

Playing Video on Secondary HDMI screen using Native API

Hello:

 

I have been attempting to play video on a detected secondary screen (HDMI in this case) but I have not been successful. The code plays fine when the screen in the primary device screen. However  when I switch the context to the secondary window I only get the audio portion.

 

I have used code from : 

https://github.com/blackberry/NDK-Samples/tree/master/VideoPlayback 

 

As well as adding code to detect a secondary display which seems to work fine. This is the code that initializes the secondary window:

 

The code that plays it is identical to what is shown in the project above. If anyone has insight or exampes of doing something like this I would really appreciate it.

 

Thanks

 

KM

 

voidHDMIVideoPlayer::initWindow() {

 

    int displayCount;

    // Merge with https://github.com/blackberry/NDK-Samples/tree/master/VideoWindow

 

    int rect[4] = { 0, 0,0,0 };

    screen_create_context(&m_screenContextPrimary, SCREEN_APPLICATION_CONTEXT);

    screen_get_context_property_iv(m_screenContextPrimary, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);

    if ( displayCount > 1 )

    {

        screen_display_t *screen_dpy = (screen_display_t *)calloc(displayCount, sizeof(screen_display_t));

        screen_get_context_property_pv(m_screenContextPrimary, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy);

        int active = 0;

        screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_ATTACHED, &active);

        screen_create_context(&m_screenContextSecondary, SCREEN_APPLICATION_CONTEXT);

        screen_get_context_property_pv(m_screenContextSecondary, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy);

        screen_create_window(&m_screenWindowSecondary, m_screenContextSecondary);

        screen_set_window_property_pv(m_screenWindowSecondary, SCREEN_PROPERTY_DISPLAY, (void **) &screen_dpy[1]);

 

        int usage = SCREEN_USAGE_NATIVE;

        int format = SCREEN_FORMAT_RGBA8888;

        int sensitivity = SCREEN_SENSITIVITY_ALWAYS;

 

        QString id = "screenWindowID";

        screen_set_window_property_cv(m_screenWindowSecondary, SCREEN_PROPERTY_ID_STRING, id.length(), "screenWindowID");

        screen_set_window_property_iv(m_screenWindowSecondary, SCREEN_PROPERTY_USAGE, &usage);

        screen_set_window_property_iv(m_screenWindowSecondary, SCREEN_PROPERTY_FORMAT, &format);

        screen_set_window_property_iv(m_screenWindowSecondary, SCREEN_PROPERTY_SENSITIVITY, &sensitivity);

        screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_SIZE, rect + 2);

        screen_set_window_property_iv(m_screenWindowSecondary, SCREEN_PROPERTY_BUFFER_SIZE, rect + 2);

        screen_create_window_buffers(m_screenWindowSecondary, 2);

        screen_buffer_t screen_buf[2];

        screen_get_window_property_pv(m_screenWindowSecondary, SCREEN_PROPERTY_RENDER_BUFFERS, (void **) screen_buf);

        screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_SIZE, rect + 2);

        // Colour the secondary screen with Macadamian Orange

        int bg[] = { SCREEN_BLIT_COLOR, 0xffE85623, SCREEN_BLIT_END };

        screen_fill(m_screenContextSecondary, screen_buf[0], bg);

        screen_post_window(m_screenWindowSecondary, screen_buf[0], 1, rect, 0);

        free(screen_dpy);

    }

}

 

 

 

 

 

 

BlackBerry Development Advisor
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Playing Video on Secondary HDMI screen using Native API

do you at least get an orange window on the secondary display when you run that code you shared?

 

Developer
Posts: 37
Registered: ‎05-30-2009
My Device: Not Specified

Re: Playing Video on Secondary HDMI screen using Native API

Yes I do get the orange screen on the secondary display. I can also gen openGL code to render on the secondary display but I am unable to get the video to play.

BlackBerry Development Advisor
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Playing Video on Secondary HDMI screen using Native API

ok thanks.  I have an inquiry out to the multimedia lead here and will let you know what he says.

there's likely a configuration setting that has to be passed to mm-renderer in order to make it create its window on that display.  Or perhaps a window can be moved between displays after creation.

BlackBerry Development Advisor
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Playing Video on Secondary HDMI screen using Native API

so, one note... mm-renderer's window will be created as a child window.  if the parent window is on the 2nd display, then the mm-renderer window should also appear there.

It doesn't look like you are joining that hdmi window to a group.. you would need to make sure you create a new window group, join the orange window to that group, and then instruct mm-renderer to join the video window to that same group.

see here for how to specify the window_group using mmr_output_attach():

https://developer.blackberry.com/native/reference/core/mmrenderer_libref/topic/mmr_api/mmr_output_at...

 

 

Contributor
Posts: 19
Registered: ‎02-14-2013
My Device: Red Z10

Re: Playing Video on Secondary HDMI screen using Native API

We do call mmr_output_attach, but the video does not render on that device.

The simpliest test project we have is a modified version of:
https://github.com/blackberry/NDK-Samples/tree/master/VideoWindow

After the call to mmr_input_attach I set the initial speed so it starts playing automatically:
int video_speed = 1000;

Then after the call to: screen_create_window
I call screen_set_window_property_pv with the SCREEN_PROPERTY_DISPLAY property with this code:

int displayCount;
screen_get_context_property_iv(g_screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount); // Get Display count
if(displayCount > 1) { // If there is more than 1 display
fprintf(stderr, "Display count %d\n", displayCount);

screen_display_t *screen_dpy = (screen_display_t *)calloc(displayCount, sizeof(screen_display_t));
screen_get_context_property_pv(g_screen_ctx, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy); // Get the displays

int active = 0;
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_ATTACHED, &active);
if(active) {
// If the secondary display is attached
fprintf(stderr, "2nd display active\n");
screen_set_window_property_pv(g_screen_win, SCREEN_PROPERTY_DISPLAY, (void **) &screen_dpy[1]); // Set the Window on the 2nd display
} else {
fprintf(stderr, "2nd display NOT active\n");
}

free(screen_dpy);
}

This makes the Green play button display on the secondary screen, and the phone's display stays at the BlackBerry splash screen as expected.
I can also change the color of the 2nd screen by changing the glClearColor line.

The audio plays on the default audio device as expected, so we know the video is played.
But the video does not render anywhere.

--
Martin Larochelle
Macadamian
http://bb10ize.me
BlackBerry Development Advisor
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Playing Video on Secondary HDMI screen using Native API

as I mentioned, you need to make sure the mm-renderer window is parented by the window you parked on the hdmi display.

this requires that both windows belong to the same group.

so: create a window group, join your parent window to that group, and then tell mm-renderer to create its window in that same group.

Contributor
Posts: 19
Registered: ‎02-14-2013
My Device: Red Z10

Re: Playing Video on Secondary HDMI screen using Native API

I tried that, and still can't get it to work. 

Do you have a working Sample demonstrating that? 

For example, a modified version of https://github.com/blackberry/NDK-Samples/tree/master/VideoPlayback

--
Martin Larochelle
Macadamian
http://bb10ize.me
BlackBerry Development Advisor
Posts: 668
Registered: ‎11-29-2011
My Device: developer

Re: Playing Video on Secondary HDMI screen using Native API

I don't have any code showing how to do this.

Can you post your window-group related code here?

eg. the hdmi-window creation code and the mm-renderer setup code?

Contributor
Posts: 19
Registered: ‎02-14-2013
My Device: Red Z10

Re: Playing Video on Secondary HDMI screen using Native API

Sure, I started from: https://github.com/blackberry/NDK-Samples/tree/master/VideoPlayback

After screen_create_window_group I do:

// screen_create_window_group should set the window in the group, do we need to call this too?
if (screen_join_window_group(screen_window, window_group_name) != 0) {
fprintf(stderr, "screen_join_window_group\n");
return EXIT_FAILURE;
}
// Move the Window to the 2nd screen if it is active
int displayCount;
screen_get_context_property_iv(screen_context, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount); // Get Display count
if(displayCount > 1) { // If there is more than 1 display
fprintf(stderr, "Display count %d\n", displayCount);
screen_display_t *screen_dpy = (screen_display_t *)calloc(displayCount, sizeof(screen_display_t));
screen_get_context_property_pv(screen_context, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy); // Get the displays
int active = 0;
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_ATTACHED, &active);
if(active) {
// If the secondary display is attached
fprintf(stderr, "2nd display active\n");
screen_set_window_property_pv(screen_window, SCREEN_PROPERTY_DISPLAY, (void **) &screen_dpy[1]); // Set the Window on the 2nd display
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_SIZE, screen_size);
} else {
fprintf(stderr, "2nd display NOT active\n");
screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_SIZE, screen_size);
}
if(screen_size[0] < screen_size[1]) {
int tmp = screen_size[1];
screen_size[1] = screen_size[0];
screen_size[0] = tmp;
}
fprintf(stderr, "screen_size %dx%d\n", screen_size[0], screen_size[1]);
free(screen_dpy);
}

 

Then I added a call to:
// screen_fill does not work on the HDMI screen if we do not set SCREEN_PROPERTY_BUFFER_SIZE
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_BUFFER_SIZE, screen_size) != 0) {
fprintf(stderr, "SCREEN_PROPERTY_BUFFER_SIZE failed\n");
return EXIT_FAILURE;
}

 

In the event loop I also tried to listen to SCREEN_EVENT_CREATE, and set the window to the 2nd screen there too, but that did not change anything.

The full code with the edits is:

 

// I/O devices
staticconstchar *video_device_url = "screen:?winid=videosamplewindowgroup&wingrp=videosamplewindowgroup";
staticconstchar *audio_device_url = "audio:default";

// Name of video context
staticconstchar *video_context_name = "samplevideocontextname";

// Window group name
staticconstchar *window_group_name = "videosamplewindowgroup";

/*
* Display the video full screen
*/
strm_dict_t* calculate_rect(int width, int height) {
char buffer[16];
strm_dict_t *dict = strm_dict_new();

if (NULL == dict) {
return NULL;
}

//fullscreen is the default.
dict = strm_dict_set(dict, "video_dest_x", "0");
if (NULL == dict)
goto fail;
dict = strm_dict_set(dict, "video_dest_y", "0");
if (NULL == dict)
goto fail;
dict = strm_dict_set(dict, "video_dest_w", itoa(width, buffer, 10));
if (NULL == dict)
goto fail;
dict = strm_dict_set(dict, "video_dest_h", itoa(height, buffer, 10));
if (NULL == dict)
goto fail;

return dict;

fail:
strm_dict_destroy(dict);
return NULL;
}

int main(int argc, char *argv[])
{
int rc;
int exit_application = 0;

// Screen variables
screen_context_t screen_context = 0;
screen_window_t screen_window = 0;

int screen_size[2] = {0,0};

// Renderer variables
mmr_connection_t* mmr_connection = 0;
mmr_context_t* mmr_context = 0;
strm_dict_t* dict = NULL;

// I/O variables
int video_device_output_id = -1;
int audio_device_output_id = -1;

bps_initialize();

/*
* Create the window used for video output.
*/
if (screen_create_context(&screen_context, SCREEN_APPLICATION_CONTEXT) != 0) {
returnEXIT_FAILURE;
}

if (screen_create_window(&screen_window, screen_context) != 0) {
screen_destroy_context(screen_context);
returnEXIT_FAILURE;
}

if (screen_create_window_group(screen_window, window_group_name) != 0) {
returnEXIT_FAILURE;
}

// screen_create_window_group should set the window in the group, do we need to call this too?
if (screen_join_window_group(screen_window, window_group_name) != 0) {
fprintf(stderr, "screen_join_window_group\n");
returnEXIT_FAILURE;
}

// Move the Window to the 2nd screen if it is active
int displayCount;

screen_get_context_property_iv(screen_context, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount); // Get Display count
if(displayCount > 1) { // If there is more than 1 display
fprintf(stderr, "Display count %d\n", displayCount);

screen_display_t *screen_dpy = (screen_display_t *)calloc(displayCount, sizeof(screen_display_t));
screen_get_context_property_pv(screen_context, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy); // Get the displays

int active = 0;
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_ATTACHED, &active);
if(active) {
// If the secondary display is attached
fprintf(stderr, "2nd display active\n");
screen_set_window_property_pv(screen_window, SCREEN_PROPERTY_DISPLAY, (void **) &screen_dpy[1]); // Set the Window on the 2nd display
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_SIZE, screen_size);
} else {
fprintf(stderr, "2nd display NOT active\n");
screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_SIZE, screen_size);
}

if(screen_size[0] < screen_size[1]) {
int tmp = screen_size[1];
screen_size[1] = screen_size[0];
screen_size[0] = tmp;
}

fprintf(stderr, "screen_size %dx%d\n", screen_size[0], screen_size[1]);
free(screen_dpy);
}

int format = SCREEN_FORMAT_RGBA8888;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_FORMAT, &format) != 0) {
returnEXIT_FAILURE;
}

int usage = SCREEN_USAGE_NATIVE;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_USAGE, &usage) != 0) {
returnEXIT_FAILURE;
}

// screen_fill does not work on the HDMI screen if we do not set SCREEN_PROPERTY_BUFFER_SIZE
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_BUFFER_SIZE, screen_size) != 0) {
fprintf(stderr, "SCREEN_PROPERTY_BUFFER_SIZE failed\n");
returnEXIT_FAILURE;
}

if (screen_create_window_buffers(screen_window, 1) != 0) {
fprintf(stderr, "screen_create_window_buffers failed\n");
returnEXIT_FAILURE;
}

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

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

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

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

// Get the render buffer
screen_buffer_t temp_buffer[1];
if (screen_get_window_property_pv( screen_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)temp_buffer) != 0) {
returnEXIT_FAILURE;
}

// Fill the buffer with a solid color (black)
//int fill_attributes[3] = {SCREEN_BLIT_COLOR, 0xffE85623, SCREEN_BLIT_END}; // Able to full the secondary screen with Macadamian Orange
int fill_attributes[3] = {SCREEN_BLIT_COLOR, 0x0, SCREEN_BLIT_END};
if (screen_fill(screen_context, temp_buffer[0], fill_attributes) != 0) {
returnEXIT_FAILURE;
}

// Make the window visible
int temp_rectangle[4] = {0, 0, screen_size[0], screen_size[1]};
if (screen_post_window(screen_window, temp_buffer[0], 1, temp_rectangle, 0) != 0) {
returnEXIT_FAILURE;
}

// Prevent the backlight from going off
int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0) {
returnEXIT_FAILURE;
}

// 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/app/native/pb_sample.mp4", cwd);
if ((rc == -1) || (rc >= PATH_MAX)) {
fprintf(stderr, "file does not exit\n");
returnEXIT_FAILURE;
}

/*
* Start the playback.
*/
if (mmr_input_attach(mmr_context, media_file, "track") != 0) {
fprintf(stderr, "mmr_input_attach failed\n");
returnEXIT_FAILURE;
}

if (mmr_play(mmr_context) != 0) {
fprintf(stderr, "mmr_play failed\n");
returnEXIT_FAILURE;
}

/* Do some work to make the aspect ratio correct.
*/
dict = calculate_rect(screen_size[0], screen_size[1]);
if (NULL == dict) {
fprintf(stderr, "calculate_rect failed\n");
returnEXIT_FAILURE;
}

if (mmr_output_parameters(mmr_context, video_device_output_id, dict) != 0) {
fprintf(stderr, "mmr_output_parameters failed\n");
returnEXIT_FAILURE;
}

/* Note that we allocated memory for the dictionary, but the call to
* mmr_output_parameters() deallocates that memory even on failure.
*/
dict = NULL;

screen_request_events(screen_context);
navigator_request_events(0);

fprintf(stderr, "Success\n");

/*
* Handle keyboard events and stop playback upon user request.
*/
for (;:smileywink: {
bps_event_t *event = NULL;
if (bps_get_event(&event, -1) != BPS_SUCCESS) {
return EXIT_FAILURE;
}

if (event) {

if (bps_event_get_domain(event) == navigator_get_domain() &&
bps_event_get_code(event) == NAVIGATOR_EXIT) {

exit_application = 1;
} elseif (bps_event_get_domain(event) == screen_get_domain()) {
screen_event_t screen_event = screen_event_get_event(event);
int event_type;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &event_type);

if (event_type == SCREEN_EVENT_CREATE) {
// Trying to re-move the Window after it is created does not work either.
char id[256];
fprintf(stderr, "SCREEN_EVENT_CREATE\n");
screen_window_t newWindow;
rc = screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&newWindow);
if (rc != 0) {
fprintf(stderr, "screen_get_event_property(WINDOW) failed\n");
break;
}

rc = screen_get_window_property_cv(newWindow, SCREEN_PROPERTY_ID_STRING, 256, id);
if (rc != 0) {
fprintf(stderr, "screen_get_window_property(ID) failed\n");
break;
}
fprintf(stderr, "window ID is %s\n", id);

int displayCount;
screen_get_context_property_iv(screen_context, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount); // Get Display count
if(displayCount > 1) { // If there is more than 1 display
fprintf(stderr, "Display count %d\n", displayCount);

screen_display_t *screen_dpy = (screen_display_t *)calloc(displayCount, sizeof(screen_display_t));
screen_get_context_property_pv(screen_context, SCREEN_PROPERTY_DISPLAYS, (void **) screen_dpy); // Get the displays

int active = 0;
screen_get_display_property_iv(screen_dpy[1], SCREEN_PROPERTY_ATTACHED, &active);
if(active) {
// If the secondary display is attached
fprintf(stderr, "2nd display active\n");
screen_set_window_property_pv(newWindow, SCREEN_PROPERTY_DISPLAY, (void **) &screen_dpy[1]); // Set the Window on the 2nd display
} else {
fprintf(stderr, "2nd display NOT active\n");
}

free(screen_dpy);
}
}
}

if (exit_application) {
break;
}
}
}

screen_stop_events(screen_context);

if (mmr_stop(mmr_context) != 0) {
returnEXIT_FAILURE;
}

if (mmr_output_detach(mmr_context, audio_device_output_id) != 0) {
returnEXIT_FAILURE;
}

if (mmr_output_detach(mmr_context, video_device_output_id) != 0) {
returnEXIT_FAILURE;
}

if (mmr_context_destroy(mmr_context) != 0) {
returnEXIT_FAILURE;
}

mmr_context = 0;
video_device_output_id = -1;
audio_device_output_id = -1;

mmr_disconnect(mmr_connection);
mmr_connection = 0;

bps_shutdown();

if (screen_destroy_window(screen_window) != 0) {
returnEXIT_FAILURE;
}

if (screen_destroy_context(screen_context) != 0) {
returnEXIT_FAILURE;
}

screen_context = 0;
screen_window = 0;

returnEXIT_SUCCESS;
}

 

--
Martin Larochelle
Macadamian
http://bb10ize.me