home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / LINUX / gopchop-1.1.7.tar.tar / gopchop-1.1.7.tar / gopchop-1.1.7 / libvo / video_out_x11.c < prev    next >
C/C++ Source or Header  |  2005-04-30  |  19KB  |  675 lines

  1. /*
  2.  * video_out_x11.c
  3.  * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
  4.  * Copyright (C) 2003      Regis Duchesne <hpreg@zoy.org>
  5.  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  6.  *
  7.  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
  8.  * See http://libmpeg2.sourceforge.net/ for updates.
  9.  *
  10.  * mpeg2dec is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * mpeg2dec is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24.  
  25. #include "config.h"
  26.  
  27. #ifdef LIBVO_X11
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <X11/Xlib.h>
  32. #include <X11/Xutil.h>
  33. #include <sys/ipc.h>
  34. #include <sys/shm.h>
  35. #include <X11/extensions/XShm.h>
  36. #include <inttypes.h>
  37. /* since it doesn't seem to be defined on some platforms */
  38. int XShmGetEventBase (Display *);
  39.  
  40. #ifdef LIBVO_XV
  41. #include <string.h>    /* strcmp */
  42. #include <X11/extensions/Xvlib.h>
  43. #define FOURCC_YV12 0x32315659
  44. #define FOURCC_UYVY 0x59565955
  45. #endif
  46.  
  47. #include <mpeg2dec/mpeg2.h>
  48. #include "video_out.h"
  49. #include <mpeg2dec/mpeg2convert.h>
  50.  
  51. typedef struct {
  52.     void * data;
  53.     int wait_completion;
  54.     XImage * ximage;
  55. #ifdef LIBVO_XV
  56.     XvImage * xvimage;
  57. #endif
  58. } x11_frame_t;
  59.  
  60. typedef struct x11_instance_s {
  61.     vo_instance_t vo;
  62.     x11_frame_t frame[3];
  63.     int index;
  64.     int width;
  65.     int height;
  66.     int display_width;
  67.     int display_height;
  68.     Display * display;
  69.     Window window;
  70.     GC gc;
  71.     XVisualInfo vinfo;
  72.     XShmSegmentInfo shminfo;
  73.     int has_xshm;
  74.     int completion_type;
  75. #ifdef LIBVO_XV
  76.     unsigned int adaptors;
  77.     XvAdaptorInfo * adaptorInfo;
  78.     XvPortID port;
  79.     int xv;
  80. #endif
  81.     void (* teardown) (struct x11_instance_s * instance);
  82. } x11_instance_t;
  83.  
  84. static int open_display (x11_instance_t * instance, int width, int height)
  85. {
  86.     int major;
  87.     int minor;
  88.     Bool pixmaps;
  89.     XVisualInfo visualTemplate;
  90.     XVisualInfo * XvisualInfoTable;
  91.     XVisualInfo * XvisualInfo;
  92.     int number;
  93.     int i;
  94.     XSetWindowAttributes attr;
  95.     XGCValues gcValues;
  96.  
  97.     instance->display = XOpenDisplay (NULL);
  98.     if (! (instance->display)) {
  99.     fprintf (stderr, "Can not open display\n");
  100.     return 1;
  101.     }
  102.  
  103.     if ((XShmQueryVersion (instance->display, &major, &minor,
  104.                &pixmaps) == 0) ||
  105.     (major < 1) || ((major == 1) && (minor < 1))) {
  106.     fprintf (stderr, "No xshm extension\n");
  107.     instance->has_xshm = 0;
  108.     /* return 1; */
  109.     }
  110.     else
  111.     instance->has_xshm = 1;
  112.  
  113.     instance->completion_type =
  114.     XShmGetEventBase (instance->display) + ShmCompletion;
  115.  
  116.     /* list truecolor visuals for the default screen */
  117. #ifdef __cplusplus
  118.     visualTemplate.c_class = TrueColor;
  119. #else
  120.     visualTemplate.class = TrueColor;
  121. #endif
  122.     visualTemplate.screen = DefaultScreen (instance->display);
  123.     XvisualInfoTable = XGetVisualInfo (instance->display,
  124.                        VisualScreenMask | VisualClassMask,
  125.                        &visualTemplate, &number);
  126.     if (XvisualInfoTable == NULL) {
  127.     fprintf (stderr, "No truecolor visual\n");
  128.     return 1;
  129.     }
  130.  
  131.     /* find the visual with the highest depth */
  132.     XvisualInfo = XvisualInfoTable;
  133.     for (i = 1; i < number; i++)
  134.     if (XvisualInfoTable[i].depth > XvisualInfo->depth)
  135.         XvisualInfo = XvisualInfoTable + i;
  136.  
  137.     instance->vinfo = *XvisualInfo;
  138.     XFree (XvisualInfoTable);
  139.  
  140.     attr.background_pixmap = None;
  141.     attr.backing_store = NotUseful;
  142.     attr.border_pixel = 0;
  143.     attr.event_mask = 0;
  144.     /* fucking sun blows me - you have to create a colormap there... */
  145.     attr.colormap = XCreateColormap (instance->display,
  146.                      RootWindow (instance->display,
  147.                          instance->vinfo.screen),
  148.                      instance->vinfo.visual, AllocNone);
  149.     instance->window =
  150.     XCreateWindow (instance->display,
  151.                DefaultRootWindow (instance->display),
  152.                0 /* x */, 0 /* y */, width, height,
  153.                0 /* border_width */, instance->vinfo.depth,
  154.                InputOutput, instance->vinfo.visual,
  155.                (CWBackPixmap | CWBackingStore | CWBorderPixel |
  156.             CWEventMask | CWColormap), &attr);
  157.  
  158.     instance->gc = XCreateGC (instance->display, instance->window, 0,
  159.                   &gcValues);
  160.  
  161. #ifdef LIBVO_XV
  162.     instance->adaptors = 0;
  163.     instance->adaptorInfo = NULL;
  164. #endif
  165.  
  166.     return 0;
  167. }
  168.  
  169. static int shmerror = 0;
  170.  
  171. static int handle_xshm_error (Display * display, XErrorEvent * error)
  172. {
  173.     shmerror = 1;
  174.     return 0;
  175. }
  176.  
  177. static void * create_shm (x11_instance_t * instance, int size)
  178. {
  179.     if (instance->has_xshm)
  180.     {
  181.         instance->shminfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
  182.         if (instance->shminfo.shmid == -1)
  183.             goto error;
  184.  
  185.         instance->shminfo.shmaddr = (char *) shmat (instance->shminfo.shmid, 0, 0);
  186.         if (instance->shminfo.shmaddr == (char *)-1) {
  187.             shmctl (instance->shminfo.shmid, IPC_RMID, 0);
  188.             goto error;
  189.         }
  190.  
  191. /* on linux the IPC_RMID only kicks off once everyone detaches the shm */
  192. /* doing this early avoids shm leaks when we are interrupted. */
  193. /* this would break the solaris port though :-/ */
  194. #ifndef SOLARIS
  195.         shmctl (instance->shminfo.shmid, IPC_RMID, 0);
  196. #endif
  197.  
  198.         /* 
  199.      * XShmAttach fails on remote displays,
  200.      * so we have to catch this event
  201.      */
  202.         XSync (instance->display, False);
  203.         XSetErrorHandler (handle_xshm_error);
  204.  
  205.         instance->shminfo.readOnly = True;
  206.         if (! (XShmAttach (instance->display, &(instance->shminfo))))
  207.             shmerror = 1;
  208.  
  209.         XSync (instance->display, False);
  210.         XSetErrorHandler (NULL);
  211.     if (!shmerror)
  212.             return instance->shminfo.shmaddr;
  213.  
  214.     /* if we fail, clean up, report it, and fall back to non-shm */
  215.         shmdt (instance->shminfo.shmaddr);
  216. #ifdef SOLARIS
  217.         shmctl (instance->shminfo.shmid, IPC_RMID, 0);
  218. #endif
  219. error:
  220.     fprintf (stderr, "cannot create shared memory\n");
  221.     instance->has_xshm = 0;
  222.     }
  223.  
  224.     instance->shminfo.shmaddr = malloc(size);
  225.     return instance->shminfo.shmaddr;
  226. }
  227.  
  228. static void destroy_shm (x11_instance_t * instance)
  229. {
  230.     if (instance->has_xshm)
  231.     {
  232.         XShmDetach (instance->display, &(instance->shminfo));
  233.         shmdt (instance->shminfo.shmaddr);
  234. #ifdef SOLARIS
  235.         shmctl (instance->shminfo.shmid, IPC_RMID, 0);
  236. #endif
  237.     }
  238.     else
  239.     {
  240.         free(instance->shminfo.shmaddr);
  241.     }
  242. }
  243.  
  244. static void x11_event (x11_instance_t * instance)    /* XXXXXXXXXXX */
  245. {
  246.     XEvent event;
  247.     char * addr;
  248.     int i;
  249.  
  250.     XNextEvent (instance->display, &event);
  251.     if (event.type == instance->completion_type) {
  252.     addr = (instance->shminfo.shmaddr +
  253.         ((XShmCompletionEvent *)&event)->offset);
  254.     for (i = 0; i < 3; i++)
  255.         if (addr == instance->frame[i].data)
  256.         instance->frame[i].wait_completion = 0;
  257.     }
  258. }
  259.  
  260. static void x11_start_fbuf (vo_instance_t * _instance,
  261.                 uint8_t * const * buf, void * id)
  262. {
  263.     x11_instance_t * instance = (x11_instance_t *) _instance;
  264.     x11_frame_t * frame = (x11_frame_t *) id;
  265.  
  266.     while (frame->wait_completion)
  267.     x11_event (instance);
  268. }
  269.  
  270. static void x11_setup_fbuf (vo_instance_t * _instance,
  271.                 uint8_t ** buf, void ** id)
  272. {
  273.     x11_instance_t * instance = (x11_instance_t *) _instance;
  274.  
  275.     buf[0] = (uint8_t *) instance->frame[instance->index].data;
  276.     buf[1] = buf[2] = NULL;
  277.     *id = instance->frame + instance->index++;
  278. }
  279.  
  280. static void x11_draw_frame (vo_instance_t * _instance,
  281.                 uint8_t * const * buf, void * id)
  282. {
  283.     x11_frame_t * frame;
  284.     x11_instance_t * instance;
  285.  
  286.     frame = (x11_frame_t *) id;
  287.     instance = (x11_instance_t *) _instance;
  288.     if (instance->has_xshm) {
  289.         XShmPutImage (instance->display, instance->window, instance->gc,
  290.           frame->ximage, 0, 0, 0, 0, instance->width, instance->height,
  291.           True);
  292.         XFlush (instance->display);
  293.         frame->wait_completion = 1;
  294.     }
  295.     else {
  296.         XPutImage(instance->display, instance->window, instance->gc,
  297.                   frame->ximage, 0, 0, 0, 0, instance->width, instance->height);
  298.         XFlush (instance->display);
  299.         frame->wait_completion = 0;
  300.     }
  301. }
  302.  
  303. static int x11_alloc_frames (x11_instance_t * instance)
  304. {
  305.     int size;
  306.     char * alloc;
  307.     int i;
  308.  
  309.     size = 0;
  310.     alloc = NULL;
  311.     for (i = 0; i < 3; i++) {
  312.     instance->frame[i].wait_completion = 0;
  313.     if (instance->has_xshm)
  314.     {
  315.             instance->frame[i].ximage =
  316.         XShmCreateImage (instance->display, instance->vinfo.visual,
  317.                  instance->vinfo.depth, ZPixmap, NULL /* data */,
  318.                  &(instance->shminfo),
  319.                  instance->width, instance->height);
  320.     }
  321.     else
  322.     {
  323.         instance->frame[i].ximage = XCreateImage(instance->display,
  324.                         instance->vinfo.visual,
  325.                         instance->vinfo.depth, ZPixmap,
  326.                         (int)NULL /* data */,
  327.                         NULL,
  328.                         instance->width,
  329.                         instance->height, 8, 0);
  330.     }
  331.     if (instance->frame[i].ximage == NULL) {
  332.         fprintf (stderr, "Cannot create ximage\n");
  333.         return 1;
  334.     } else if (i == 0) {
  335.         size = (instance->frame[0].ximage->bytes_per_line *
  336.             instance->frame[0].ximage->height);
  337.         alloc = (char *) create_shm (instance, 3 * size);
  338.         if (alloc == NULL) {
  339.         XDestroyImage (instance->frame[i].ximage);
  340.         return 1;
  341.         }
  342.     } else if (size != (instance->frame[i].ximage->bytes_per_line *
  343.                 instance->frame[i].ximage->height)) {
  344.         fprintf (stderr, "unexpected ximage data size\n");
  345.         return 1;
  346.     }
  347.  
  348.     instance->frame[i].data = instance->frame[i].ximage->data = alloc;
  349.     alloc += size;
  350.     }
  351.  
  352.     return 0;
  353. }
  354.  
  355. static void x11_teardown (x11_instance_t * instance)
  356. {
  357.     int i;
  358.  
  359.     for (i = 0; i < 3; i++) {
  360.     while (instance->frame[i].wait_completion)
  361.         x11_event (instance);
  362.     XDestroyImage (instance->frame[i].ximage);
  363.     }
  364.     destroy_shm (instance);
  365. }
  366.  
  367. static void x11_close (vo_instance_t * _instance)
  368. {
  369.     x11_instance_t * instance = (x11_instance_t *) _instance;
  370.  
  371.     if (instance->teardown != NULL)
  372.     instance->teardown (instance);
  373.     XFreeGC (instance->display, instance->gc);
  374.     XDestroyWindow (instance->display, instance->window);
  375. #ifdef LIBVO_XV
  376.     if (instance->adaptors)
  377.     XvFreeAdaptorInfo (instance->adaptorInfo);
  378. #endif
  379.     XCloseDisplay (instance->display);
  380.     free (instance);
  381. }
  382.  
  383. #ifdef LIBVO_XV
  384. static void xv_setup_fbuf (vo_instance_t * _instance,
  385.                uint8_t ** buf, void ** id)
  386. {
  387.     x11_instance_t * instance = (x11_instance_t *) _instance;
  388.     uint8_t * data;
  389.  
  390.     data = (uint8_t *) instance->frame[instance->index].xvimage->data;
  391.     buf[0] = data + instance->frame[instance->index].xvimage->offsets[0];
  392.     buf[1] = data + instance->frame[instance->index].xvimage->offsets[2];
  393.     buf[2] = data + instance->frame[instance->index].xvimage->offsets[1];
  394.     *id = instance->frame + instance->index++;
  395. }
  396.  
  397. static void xv_draw_frame (vo_instance_t * _instance,
  398.                uint8_t * const * buf, void * id)
  399. {
  400.     x11_frame_t * frame = (x11_frame_t *) id;
  401.     x11_instance_t * instance = (x11_instance_t *) _instance;
  402.  
  403.     if (instance->has_xshm) {
  404.         XvShmPutImage (instance->display, instance->port, instance->window,
  405.                        instance->gc, frame->xvimage, 0, 0,
  406.                        instance->width, instance->height, 0, 0,
  407.                        instance->display_width, instance->display_height, True);
  408.         XFlush (instance->display);
  409.         frame->wait_completion = 1;
  410.     }
  411.     else {
  412.         XvPutImage(instance->display, instance->port, instance->window,
  413.                    instance->gc, frame->xvimage, 0, 0,
  414.            instance->width, instance->height, 0, 0,
  415.            instance->display_width, instance->display_height);
  416.         XFlush (instance->display);
  417.         frame->wait_completion = 0;
  418.     }
  419. }
  420.  
  421. static int xv_check_fourcc (x11_instance_t * instance, XvPortID port,
  422.                 int fourcc, const char * fourcc_str)
  423. {
  424.     XvImageFormatValues * formatValues;
  425.     int formats;
  426.     int i;
  427.  
  428.     formatValues = XvListImageFormats (instance->display, port, &formats);
  429.     for (i = 0; i < formats; i++)
  430.     if ((formatValues[i].id == fourcc) &&
  431.         (! (strcmp (formatValues[i].guid, fourcc_str)))) {
  432.         XFree (formatValues);
  433.         return 0;
  434.     }
  435.     XFree (formatValues);
  436.     return 1;
  437. }
  438.  
  439. static int xv_check_extension (x11_instance_t * instance,
  440.                    int fourcc, const char * fourcc_str)
  441. {
  442.     unsigned int i;
  443.     unsigned long j;
  444.  
  445.     if (!instance->adaptorInfo) {
  446.     unsigned int version;
  447.     unsigned int release;
  448.     unsigned int dummy;
  449.  
  450.     if ((XvQueryExtension (instance->display, &version, &release,
  451.                    &dummy, &dummy, &dummy) != Success) ||
  452.         (version < 2) || ((version == 2) && (release < 2))) {
  453.         fprintf (stderr, "No xv extension\n");
  454.         return 1;
  455.     }
  456.  
  457.     XvQueryAdaptors (instance->display, instance->window,
  458.              &instance->adaptors, &instance->adaptorInfo);
  459.     }
  460.  
  461.     for (i = 0; i < instance->adaptors; i++)
  462.     if (instance->adaptorInfo[i].type & XvImageMask)
  463.         for (j = 0; j < instance->adaptorInfo[i].num_ports; j++)
  464.         if ((! (xv_check_fourcc (instance,
  465.                      instance->adaptorInfo[i].base_id + j,
  466.                      fourcc, fourcc_str))) &&
  467.             (XvGrabPort (instance->display,
  468.                  instance->adaptorInfo[i].base_id + j,
  469.                  0) == Success)) {
  470.             instance->port = instance->adaptorInfo[i].base_id + j;
  471.             return 0;
  472.         }
  473.  
  474.     fprintf (stderr, "Cannot find xv %s port\n", fourcc_str);
  475.     return 1;
  476. }
  477.  
  478. static int xv_alloc_frames (x11_instance_t * instance, int size,
  479.                 int fourcc)
  480. {
  481.     char * alloc;
  482.     int i = 0;
  483.  
  484.     alloc = (char *) create_shm (instance, 3 * size);
  485.     if (alloc == NULL)
  486.     return 1;
  487.  
  488.     while (i < 3) {
  489.     instance->frame[i].wait_completion = 0;
  490.     instance->frame[i].xvimage =
  491.         XvShmCreateImage (instance->display, instance->port, fourcc,
  492.                   alloc, instance->width, instance->height,
  493.                   &(instance->shminfo));
  494.     instance->frame[i].data = alloc;
  495.     alloc += size;
  496.     if ((instance->frame[i].xvimage == NULL) ||
  497.         (instance->frame[i++].xvimage->data_size != size)) {
  498.         while (--i >= 0)
  499.         XFree (instance->frame[i].xvimage);
  500.         destroy_shm (instance);
  501.         return 1;
  502.     }
  503.     }
  504.  
  505.     return 0;
  506. }
  507.  
  508. static void xv_teardown (x11_instance_t * instance)
  509. {
  510.     int i;
  511.  
  512.     for (i = 0; i < 3; i++) {
  513.     while (instance->frame[i].wait_completion)
  514.         x11_event (instance);
  515.     XFree (instance->frame[i].xvimage);
  516.     }
  517.     destroy_shm (instance);
  518.     XvUngrabPort (instance->display, instance->port, 0);
  519. }
  520. #endif
  521.  
  522. static void * x11_window_handle (vo_instance_t * _instance)
  523. {
  524.     x11_instance_t * instance = (x11_instance_t *) _instance;
  525.  
  526.     if (!instance || !instance->window) return NULL;
  527.  
  528.     return (void*)instance->window;
  529. }
  530.  
  531. static int common_setup (vo_instance_t * _instance,
  532.              unsigned int width, unsigned int height,
  533.              unsigned int display_width, unsigned int display_height,
  534.              unsigned int chroma_width, unsigned int chroma_height,
  535.              vo_setup_result_t * result)
  536. {
  537.     x11_instance_t * instance = (x11_instance_t *) _instance;
  538.     unsigned int window_width  = width;
  539.     unsigned int window_height = height;
  540. #ifdef LIBVO_XV
  541.     if (instance->xv == 1) {
  542.         window_width  = display_width;
  543.         window_height = display_height;
  544.     }
  545. #endif
  546.  
  547.     if (instance->display != NULL) {
  548.     /* Already setup, just adjust to the new size */
  549.     if (instance->teardown != NULL)
  550.         instance->teardown (instance);
  551.         XResizeWindow (instance->display, instance->window,
  552.                        window_width, window_height);
  553.     } else {
  554.     /* Not setup yet, do the full monty */
  555.         if (open_display (instance, window_width, window_height))
  556.             return 1;
  557.         XMapWindow (instance->display, instance->window);
  558.     }
  559.     instance->vo.setup_fbuf = NULL;
  560.     instance->vo.start_fbuf = NULL;
  561.     instance->vo.set_fbuf = NULL;
  562.     instance->vo.draw = NULL;
  563.     instance->vo.discard = NULL;
  564.     instance->vo.close = x11_close;
  565.     instance->vo.window_handle = x11_window_handle;
  566.     instance->width = width;
  567.     instance->height = height;
  568.     instance->display_width = display_width;
  569.     instance->display_height = display_height;
  570.     instance->index = 0;
  571.     instance->teardown = NULL;
  572.     result->convert = NULL;
  573.  
  574. #ifdef LIBVO_XV
  575.     if (instance->xv == 1 &&
  576.     (chroma_width == width >> 1) && (chroma_height == height >> 1) &&
  577.     !xv_check_extension (instance, FOURCC_YV12, "YV12") &&
  578.     !xv_alloc_frames (instance, 3 * width * height / 2, FOURCC_YV12)) {
  579.     instance->vo.setup_fbuf = xv_setup_fbuf;
  580.     instance->vo.start_fbuf = x11_start_fbuf;
  581.     instance->vo.draw = xv_draw_frame;
  582.     instance->teardown = xv_teardown;
  583.     } else if (instance->xv && (chroma_width == width >> 1) &&
  584.            !xv_check_extension (instance, FOURCC_UYVY, "UYVY") &&
  585.            !xv_alloc_frames (instance, 2 * width * height, FOURCC_UYVY)) {
  586.     instance->vo.setup_fbuf = x11_setup_fbuf;
  587.     instance->vo.start_fbuf = x11_start_fbuf;
  588.     instance->vo.draw = xv_draw_frame;
  589.     instance->teardown = xv_teardown;
  590.     result->convert = mpeg2convert_uyvy;
  591.     } else
  592. #endif
  593.     if (!x11_alloc_frames (instance)) {
  594.     int bpp;
  595.  
  596.     instance->vo.setup_fbuf = x11_setup_fbuf;
  597.     instance->vo.start_fbuf = x11_start_fbuf;
  598.     instance->vo.draw = x11_draw_frame;
  599.     instance->teardown = x11_teardown;
  600.  
  601. #ifdef WORDS_BIGENDIAN
  602.     if (instance->frame[0].ximage->byte_order != MSBFirst) {
  603.         fprintf (stderr, "No support for non-native byte order\n");
  604.         return 1;
  605.     }
  606. #else
  607.     if (instance->frame[0].ximage->byte_order != LSBFirst) {
  608.         fprintf (stderr, "No support for non-native byte order\n");
  609.         return 1;
  610.     }
  611. #endif
  612.  
  613.     /*
  614.      * depth in X11 terminology land is the number of bits used to
  615.      * actually represent the colour.
  616.      *
  617.      * bpp in X11 land means how many bits in the frame buffer per
  618.      * pixel.
  619.      *
  620.      * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit
  621.      *     color is 24 bit depth, but can be 24 bpp or 32 bpp.
  622.      *
  623.      * If we have blue in the lowest bit then "obviously" RGB
  624.      * (the guy who wrote this convention never heard of endianness ?)
  625.      */
  626.  
  627.     bpp = ((instance->vinfo.depth == 24) ?
  628.            instance->frame[0].ximage->bits_per_pixel :
  629.            instance->vinfo.depth);
  630.     result->convert =
  631.         mpeg2convert_rgb (((instance->frame[0].ximage->blue_mask & 1) ?
  632.                    MPEG2CONVERT_RGB : MPEG2CONVERT_BGR), bpp);
  633.     if (result->convert == NULL) {
  634.         fprintf (stderr, "%dbpp not supported\n", bpp);
  635.         return 1;
  636.     }
  637.     }
  638.  
  639.     return 0;
  640. }
  641.  
  642. static vo_instance_t * common_open (int xv)
  643. {
  644.     x11_instance_t * instance;
  645.  
  646.     instance = (x11_instance_t *) calloc (1, sizeof (x11_instance_t));
  647.     if (instance == NULL)
  648.     return NULL;
  649.  
  650.     instance->vo.setup = common_setup;
  651.     instance->vo.close = (void (*) (vo_instance_t *)) free;
  652. #ifdef LIBVO_XV
  653.     instance->xv = xv;
  654. #endif
  655.     return (vo_instance_t *) instance;
  656. }
  657.  
  658. vo_instance_t * vo_x11_open (void)
  659. {
  660.     return common_open (0);
  661. }
  662.  
  663. #ifdef LIBVO_XV
  664. vo_instance_t * vo_xv_open (void)
  665. {
  666.     return common_open (1);
  667. }
  668.  
  669. vo_instance_t * vo_xv2_open (void)
  670. {
  671.     return common_open (2);
  672. }
  673. #endif
  674. #endif
  675.