Feed on Posts or Comments

Free Software & Hacking & Linux Gustavo Sverzut Barbieri on 13 Nov 2006 05:28 pm

Playing videos with MPlayer and GStreamer inside SDL Applications

Both MPlayer and GStreamer can output video to some X11 Window given its ID, this is done using mplayer -wid or gst_x_overlay_set_xwindow_id(). But if you are developing an SDL application and tried it, you may have faced the same problem as I did: You can just output to whole SDL window, not just part of it.

Why does this happen?

The X Window System uses the term “Window” for any rectangular area, not just toplevel windows as we know. Toolkits often use X Windows as base for everything visible: buttons, labels, text areas and the window background itself. Every window is attached to another window, the parent window, except by the root window (that one that holds desktop wallpaper).

However, SDL is composed of just one X window and you don’t have any way to create more using SDL itself. So if you want to output your video to just part of window, you need to create another X Window with desired geometry and position, using SDL’s as parent.

How to work around this?

As I said, there is no SDL functions to create X Window. You need to create it yourself using Xlib functions. Xlib is the C implementation for the X protocol, a client-server. It’s not that hard to develop, but you need to understand some things beforehand (You can see more information on Christophe Tronche - The Xlib Manual or Guy Keren - Basic Graphics Programming With The Xlib Library):

Display
Structure representing the connection to X server. You can get this from SDL using SDL_SysWMinfo.info.x11.display or you can create your own using XOpenDisplay().
Window
Integer that identifies some window inside a display. You can create windows using XCreateSimpleWindow() using a parent window, which you can get from SDL using SDL_SysWMinfo.info.x11.window.
XMapWindow()
XCreateSimpleWindow() doesn’t display the window, you need to do it yourself. The X way to do it is call XMapWindow(). Note that X window is asynchronous and you need to wait until server process and replies. First, you need to select what events you want to listen using XSelectInput(). Then you need to have client to send commands to server, this is done by XFlush() or any call that does this, in this case we use XNextEvent(), which already waits for events from X server.

Show me the code!

Updates

17 Responses to “Playing videos with MPlayer and GStreamer inside SDL Applications”

  1. on 06 Dec 2006 at 7:43 am 1.akw said …

    Hi Gustavo!

    This is great, can you mail me the code for your MPlayer-Embedding?
    Your SVN Link does not seem to work anymore.

    Regards,
    akw

  2. on 06 Dec 2006 at 9:12 am 2.Gustavo Sverzut Barbieri said …

    Sorry, I’m moving my servers and some svn are still pending.

    I’ll mail it to you.

  3. on 15 Jan 2007 at 4:18 pm 3.smartuser said …

    Dear Gustavo!
    This is something I was looking for. As your svn does not work yet I presume can you mail me the code for your MPlayer-Embedding?

    Regards,
    Smartuser

  4. on 17 Jan 2007 at 11:04 am 4.sebastian said …

    Hi, your code it’s great, I simplified it in order to just play a video, not using the controls, but I wanted to make it fullscreen. If I use SDL_WM_ToggleFullScreen, it doesn’t works, otherwise it works perfect. Can you figure out why this could be happen? Thanks

  5. on 17 Jan 2007 at 11:05 am 5.sebastian said …

    by the way, I didn’t find your code here, but I used a copy inside Google’s cache.

  6. on 17 Jan 2007 at 12:27 pm 6.Gustavo Sverzut Barbieri said …

    @sebastian:

    What doesn’t work? I tried it here and the SDL window becomes fullscreen, with a small margin and the mplayer window inside, with the same margin as before.

    If you want to make MPlayer window fullscreen (without the margin), probably you’ll have to use XMoveResizeWindow, with x and y being 0 and width and height being the SDL window size, which you can get with XGetWindowAttributes.

    You can use XGetWindowAttributes + XMoveResizeWindow to do great things, like moving or resizing the player window inside SDL.

  7. on 18 Jan 2007 at 11:20 am 7.sebastian said …

    I see, I have asked in a wrong way. I have a little mplayer window inside an SDL window. The SDL window is 640×480. When I do SDL_WM_ToggleFullScreen. The mplayer window desapears, but the audio continues playing. That is the problem.

  8. on 18 Jan 2007 at 11:22 am 8.sebastian said …

    I see, I have asked in a wrong way. I have a little mplayer window inside an SDL window. The SDL window is 640×480. When I do SDL_WM_ToggleFullScreen. The mplayer window desapears, but the audio continues playing. That is the problem. In fact, I want to go fullscreen and keep the mplayer playing inside.

  9. on 18 Jan 2007 at 11:30 am 9.sebastian said …

    ups, your code does flawlessly, when I modified it, but mine is wrong. Sorry I keep investigating, thanks

  10. on 07 Mar 2007 at 2:55 am 10.psmaker said …

    Hi Gustavo!
    This sounds interesting indeed… as your svn is still down, can you please email me the sdl/gstreamer embedding code ?

    Regards,
    psmaker

  11. on 07 Mar 2007 at 9:03 am 11.Gustavo Sverzut Barbieri said …

    Guys, I moved my repository to Google Code:
    http://barbieri-playground.googlecode.com/svn/sdl/

    I’ll edit this post to refer to new URL.

  12. on 20 Jul 2007 at 11:41 am 12.tripzero said …

    Hi Gustavo,

    I’ve been trying to figure out how to do this for a long time. You’re the best! Thanks!

  13. on 05 May 2008 at 12:55 pm 13.flowolf said …

    Did you notice that if the mouse pointer is on the video then SDL will ignore input? I’m looking for a way to fix this…

  14. on 05 May 2008 at 2:31 pm 14.flowolf said …

    Ok, I found the problem:
    with XSelectInput (dpy, win, NoEventMask); you say “ignore all events” to the X11 subwindow so changing it to XSelectInput(dpy, win, KeyPressMask); will fix the problem.
    As described here http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming-2.html#hierarchy_events ignoring events in a subwindow will make them pass to the parent window (the SDL window in our case) so if you ask for input events to be notified to the subwindow and then you ignore those events in the subwindow you will get the SDL parent window to recognize them.
    Of course there are many event masks, take a look here http://maben.homeip.net:8217/static/computers/xwindows/xlib/10-03.html#P191_6231 and set them as you wish.

  15. on 15 Aug 2008 at 10:16 pm 15.NDR008 said …

    Cool stuff, my crap skills are getting me somewhere thanks to your work.

    Could I have some help with this? I tried incorporating it into my own program (with some changes).

    The main current problem I have, is when I go back to business as usual in my application, I am left with the black window made through your code. How can I remove it?

    I tried XDestorySubwindows(dpy, win);

    but that closes everything.

  16. on 16 Aug 2008 at 12:37 am 16.Gustavo Sverzut Barbieri said …

    You should use XDestroyWindow(dpy, win), but win in this case is the newly created window that video is mapped to, not the SDL window!

    [PS: I have not tried this, and there is some time I don't work with that, so I might be wrong]

  17. on 16 Aug 2008 at 10:11 am 17.NDR008 said …

    play_win is win. You return win to play_win:

    in Window create_x11_subwindow :
    win = XCreateSimpleWindow (dpy, parent, x, y, width, height, black, black);
    return win;

    and Window_create_x11_subwindow was called by:
    play_win = create_x11_subwindow (sdl_info.info.x11.display, sdl_info.info.x11.window, x, y, width, height);

    XDestroyWindow(dpy, play_win) destorys everything and causes a segment fault in my program (actually now yours, went to loading purely your tutorial).

    I am stuck on this one problem. If I use xine instead of mplayer, this problem disappears because xine closes the window behind it somehow. The problem I have with xine is, that xine becomes the active window and hence, key events are no longer handled by the parent process. Which to some extent I can live with and figure out how to solve later.
    But the problem I have with xine is I cannot use fprintf(mplayer_fp, “quit/n”);

    So I have no way of closing xine from the parent application.

    My major issue is that my final program, won’t have a keyboard or mouse. So preferably I would like to control which window is active and control things from the parent process/window.

    Any help appreciated. If you want drop me an e-mail and I can send you a link to my source.

    Thanks.

Trackback This Post | Subscribe to the comments through RSS Feed

Leave a Reply

You must be logged in to post a comment.