vout.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:39k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * vout.c: QNX RTOS video output display method
  3.  *****************************************************************************
  4.  * Copyright (C) 2001, 2002 VideoLAN
  5.  *
  6.  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  7.  *          Pascal Levesque <Pascal.Levesque@mindready.com>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <errno.h>                                                 /* ENOMEM */
  27. #include <stdlib.h>                                                /* free() */
  28. #include <string.h>                                            /* strerror() */
  29. #include <photon/PtWidget.h>
  30. #include <photon/PtWindow.h>
  31. #include <photon/PtLabel.h>
  32. #include <photon/PdDirect.h>
  33. #include <vlc/vlc.h>
  34. #include <vlc/intf.h>
  35. #include <vlc/vout.h>
  36. /*****************************************************************************
  37.  * vout_sys_t: video output QNX method descriptor
  38.  *****************************************************************************
  39.  * This structure is part of the video output thread descriptor.
  40.  * It describes the QNX specific properties of an output thread. QNX video
  41.  * output is performed through regular resizable windows. Windows can be
  42.  * dynamically resized to adapt to the size of the streams.
  43.  *****************************************************************************/
  44. #define MAX_DIRECTBUFFERS 2
  45. #define MODE_NORMAL_MEM     0
  46. #define MODE_SHARED_MEM     1
  47. #define MODE_VIDEO_MEM      2
  48. #define MODE_VIDEO_OVERLAY  3
  49. struct vout_sys_t
  50. {
  51.     /* video mode */
  52.     int                     i_mode;
  53.     /* internal stuff */
  54.     PtWidget_t *            p_window;
  55.     /* Color palette for 8bpp */
  56.     PgColor_t p_colors[255];
  57.     /* [shared] memory blit */
  58.     int                     i_img_type;
  59.     /* video memory blit */
  60.     /* video overlay */
  61.     PgVideoChannel_t *      p_channel;
  62.     int                     i_vc_flags;
  63.     int                     i_vc_format;
  64.     int                 i_screen_depth;
  65.     int                 i_bytes_per_pixel;
  66.     int                 i_bytes_per_line;
  67.     /* position & dimensions */
  68.     PhPoint_t               pos;
  69.     PhDim_t                 dim;
  70.     PhPoint_t               old_pos;
  71.     PhDim_t                 old_dim;
  72.     PhDim_t                 screen_dim;
  73.     PhRect_t                frame;
  74. };
  75. /*****************************************************************************
  76.  * picture_sys_t: direct buffer method descriptor
  77.  *****************************************************************************
  78.  * This structure is part of the picture descriptor, it describes the
  79.  * XVideo specific properties of a direct buffer.
  80.  *****************************************************************************/
  81. struct picture_sys_t
  82. {
  83.     /* [shared] memory blit */
  84.     PhImage_t *             p_image;
  85.     /* video memory blit and video overlay */
  86.     PdOffscreenContext_t *  p_ctx[3];   /* 0: y, 1: u, 2: v */
  87.     char *                  p_buf[3];
  88. };
  89. /*****************************************************************************
  90.  * Local prototypes
  91.  *****************************************************************************/
  92. static int  QNXInit      ( vout_thread_t * );
  93. static void QNXEnd       ( vout_thread_t * );
  94. static int  QNXManage    ( vout_thread_t * );
  95. static void QNXDisplay   ( vout_thread_t *, picture_t * );
  96. static int  QNXInitDisplay ( vout_thread_t * );
  97. static int  QNXCreateWnd   ( vout_thread_t * );
  98. static int  QNXDestroyWnd  ( vout_thread_t * );
  99. static int  NewPicture     ( vout_thread_t *, picture_t *, int );
  100. static void FreePicture    ( vout_thread_t *, picture_t * );
  101. static int  ResizeOverlayOutput ( vout_thread_t * );
  102. static void SetPalette     ( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
  103. /*****************************************************************************
  104.  * OpenVideo: allocate QNX video thread output method
  105.  *****************************************************************************
  106.  * This function allocate and initialize a QNX vout method. It uses some of the
  107.  * vout properties to choose the window size, and change them according to the
  108.  * actual properties of the display.
  109.  *****************************************************************************/
  110. int E_(OpenVideo) ( vlc_object_t *p_this )
  111. {
  112.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  113.     /* init connection to photon */
  114.     if( PtInit( "/dev/photon" ) != 0 )
  115.     {
  116.         msg_Err( p_vout, "unable to connect to photon" );
  117.         return( 1 );
  118.     }
  119.     /* allocate structure */
  120.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  121.     if( p_vout->p_sys == NULL )
  122.     {
  123.         msg_Err( p_vout, "out of memory" );
  124.         return( 1 );
  125.     }
  126.     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
  127.     p_vout->b_fullscreen = config_GetInt( p_vout, "fullscreen" );
  128.     p_vout->p_sys->i_mode = config_GetInt( p_vout, "overlay" ) ?
  129.                                 MODE_VIDEO_OVERLAY : MODE_VIDEO_MEM;
  130.     p_vout->p_sys->dim.w = p_vout->i_window_width;
  131.     p_vout->p_sys->dim.h = p_vout->i_window_height;
  132.     /* init display and create window */
  133.     if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
  134.     {
  135.         free( p_vout->p_sys );
  136.         return( 1 );
  137.     }
  138.     p_vout->pf_init = QNXInit;
  139.     p_vout->pf_end = QNXEnd;
  140.     p_vout->pf_manage = QNXManage;
  141.     p_vout->pf_render = NULL;
  142.     p_vout->pf_display = QNXDisplay;
  143.     return( 0 );
  144. }
  145. /*****************************************************************************
  146.  * QNXInit: initialize QNX video thread output method
  147.  *****************************************************************************
  148.  * This function create the buffers needed by the output thread. It is called
  149.  * at the beginning of the thread, but also each time the window is resized.
  150.  *****************************************************************************/
  151. static int QNXInit( vout_thread_t *p_vout )
  152. {
  153.     int i_index;
  154.     picture_t *p_pic;
  155.     I_OUTPUTPICTURES = 0;
  156.     switch( p_vout->p_sys->i_mode )
  157.     {
  158.     case MODE_NORMAL_MEM:
  159.     case MODE_SHARED_MEM:
  160.         p_vout->output.i_width = p_vout->p_sys->dim.w;
  161.         p_vout->output.i_height = p_vout->p_sys->dim.h;
  162.         /* Assume we have square pixels */
  163.         p_vout->output.i_aspect = p_vout->p_sys->dim.w
  164.                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
  165.         break;
  166.     case MODE_VIDEO_MEM:
  167.         p_vout->output.i_width = p_vout->p_sys->dim.w;
  168.         p_vout->output.i_height = p_vout->p_sys->dim.h;
  169.         /* Assume we have square pixels */
  170.         p_vout->output.i_aspect = p_vout->p_sys->dim.w
  171.                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
  172.         break;
  173.     case MODE_VIDEO_OVERLAY:
  174.         p_vout->output.i_width  = p_vout->render.i_width;
  175.         p_vout->output.i_height = p_vout->render.i_height;
  176.         p_vout->output.i_aspect = p_vout->render.i_aspect;
  177.         if (ResizeOverlayOutput(p_vout))
  178.         {
  179.             return (1);
  180.         }
  181.         break;
  182.     default:
  183.         /* This shouldn't happen ! */
  184.         break;
  185.     }
  186.     /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
  187.     while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
  188.     {
  189.         p_pic = NULL;
  190.         /* Find an empty picture slot */
  191.         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
  192.         {
  193.             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
  194.             {
  195.                 p_pic = p_vout->p_picture + i_index;
  196.                 break;
  197.             }
  198.         }
  199.         /* Allocate the picture */
  200.         if( p_pic == NULL || NewPicture( p_vout, p_pic, I_OUTPUTPICTURES ) )
  201.         {
  202.             break;
  203.         }
  204.         p_pic->i_status = DESTROYED_PICTURE;
  205.         p_pic->i_type   = DIRECT_PICTURE;
  206.         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
  207.         I_OUTPUTPICTURES++;
  208.     }
  209.     return( 0 );
  210. }
  211. /*****************************************************************************
  212.  * QNXEnd: terminate QNX video thread output method
  213.  *****************************************************************************
  214.  * Destroy the buffers created by QNXInit. It is called at the end of
  215.  * the thread, but also each time the window is resized.
  216.  *****************************************************************************/
  217. static void QNXEnd( vout_thread_t *p_vout )
  218. {
  219.     int i_index;
  220.     /* Free the direct buffers we allocated */
  221.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  222.     {
  223.         i_index--;
  224.         FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
  225.     }
  226. }
  227. /*****************************************************************************
  228.  * CloseVideo: destroy QNX video thread output method
  229.  *****************************************************************************
  230.  * Terminate an output method created by QNXCreate
  231.  *****************************************************************************/
  232. void E_(CloseVideo) ( vlc_object_t *p_this )
  233. {
  234.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  235.     /* destroy the window */
  236.     QNXDestroyWnd( p_vout );
  237.     /* destroy structure */
  238.     free( p_vout->p_sys );
  239. }
  240. /*****************************************************************************
  241.  * QNXManage: handle QNX events
  242.  *****************************************************************************
  243.  * This function should be called regularly by video output thread. It allows
  244.  * window resizing. It returns a non null value on error.
  245.  *****************************************************************************/
  246. static int QNXManage( vout_thread_t *p_vout )
  247. {
  248.     int i_ev,  i_buflen;
  249.     PhEvent_t *p_event;
  250.     vlc_bool_t b_repos = 0;
  251.     if (p_vout->b_die == 1)
  252.     {
  253.         return ( 0 );
  254.     }
  255.     /* allocate buffer for event */
  256.     i_buflen = sizeof( PhEvent_t ) * 4;
  257.     if( ( p_event = malloc( i_buflen ) ) == NULL )
  258.     {
  259.         msg_Err( p_vout, "out of memory" );
  260.         return( 1 );
  261.     }
  262.     /* event loop */
  263.     do
  264.     {
  265.         memset( p_event, 0, i_buflen );
  266.         i_ev = PhEventPeek( p_event, i_buflen );
  267.         if( i_ev == Ph_RESIZE_MSG )
  268.         {
  269.             i_buflen = PhGetMsgSize( p_event );
  270.             if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
  271.             {
  272.                 msg_Err( p_vout, "out of memory" );
  273.                 return( 1 );
  274.             }
  275.         }
  276.         else if( i_ev == Ph_EVENT_MSG )
  277.         {
  278.             PtEventHandler( p_event );
  279.             if( p_event->type == Ph_EV_WM )
  280.             {
  281.                 PhWindowEvent_t *p_ev = PhGetData( p_event );
  282.                 switch( p_ev->event_f )
  283.                 {
  284.                 case Ph_WM_CLOSE:
  285.                     p_vout->p_vlc->b_die = 1;
  286.                     break;
  287.                 case Ph_WM_MOVE:
  288.                     p_vout->p_sys->pos.x = p_ev->pos.x;
  289.                     p_vout->p_sys->pos.y = p_ev->pos.y;
  290.                     b_repos = 1;
  291.                     break;
  292.                 case Ph_WM_RESIZE:
  293.                     p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
  294.                     p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
  295.                     p_vout->p_sys->dim.w = p_ev->size.w;
  296.                     p_vout->p_sys->dim.h = p_ev->size.h;
  297.                     p_vout->i_changes |= VOUT_SIZE_CHANGE;
  298.                     break;
  299.                 }
  300.             }
  301.             else if( p_event->type == Ph_EV_KEY )
  302.             {
  303.                 PhKeyEvent_t *p_ev = PhGetData( p_event );
  304.                 long i_key = p_ev->key_sym;
  305.                 if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
  306.                     ( p_ev->key_flags & Pk_KF_Sym_Valid ) )
  307.                 {
  308.                     switch( i_key )
  309.                     {
  310.                     case Pk_q:
  311.                     case Pk_Q:
  312.                         p_vout->p_vlc->b_die = 1;
  313.                         break;
  314.                     case Pk_f:
  315.                     case Pk_F:
  316.                         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
  317.                         break;
  318.                     case Pk_c:
  319.                     case Pk_C:
  320.                         p_vout->b_grayscale = ! p_vout->b_grayscale;
  321.                         p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
  322.                         break;
  323.                     default:
  324.                         break;
  325.                     }
  326.                 }
  327.             }
  328.         }
  329.     } while( i_ev != -1 && i_ev != 0 );
  330.     free( p_event );
  331.     /*
  332.      * fullscreen
  333.      */
  334.     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
  335.     {
  336.         PhDim_t dim;
  337.         p_vout->b_fullscreen = !p_vout->b_fullscreen;
  338.         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  339.         if( p_vout->b_fullscreen )
  340.         {
  341.             p_vout->p_sys->old_pos.x = p_vout->p_sys->pos.x;
  342.             p_vout->p_sys->old_pos.y = p_vout->p_sys->pos.y;
  343.             p_vout->p_sys->pos.x = p_vout->p_sys->pos.y = 0;
  344.             dim.w = p_vout->p_sys->screen_dim.w + 1;
  345.             dim.h = p_vout->p_sys->screen_dim.h + 1;
  346.         }
  347.         else
  348.         {
  349.             p_vout->p_sys->pos.x = p_vout->p_sys->old_pos.x;
  350.             p_vout->p_sys->pos.y = p_vout->p_sys->old_pos.y;
  351.             dim.w = p_vout->p_sys->old_dim.w + 1;
  352.             dim.h = p_vout->p_sys->old_dim.h + 1;
  353.         }
  354.         /* modify render flags, border */
  355.         PtSetResource( p_vout->p_sys->p_window,
  356.             Pt_ARG_WINDOW_RENDER_FLAGS,
  357.             p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
  358.             Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
  359.         /* set position and dimension */
  360.         PtSetResource( p_vout->p_sys->p_window,
  361.                        Pt_ARG_POS, &p_vout->p_sys->pos, 0 );
  362.         PtSetResource( p_vout->p_sys->p_window,
  363.                        Pt_ARG_DIM, &dim, 0 );
  364.         /* mark as damaged to force redraw */
  365.         PtDamageWidget( p_vout->p_sys->p_window );
  366.     }
  367.     /*
  368.      * size change
  369.      */
  370.     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
  371.     {
  372.         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
  373.         if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
  374.         {
  375.             ResizeOverlayOutput(p_vout);
  376.         }
  377. #if 0
  378.         else
  379.         {
  380.             p_vout->output.i_width = p_vout->p_sys->dim.w;
  381.             p_vout->output.i_height = p_vout->p_sys->dim.h;
  382.             p_vout->i_changes |= VOUT_YUV_CHANGE;
  383.             QNXEnd( p_vout );
  384.             if( QNXInit( p_vout ) )
  385.             {
  386.                 msg_Err( p_vout, "cannot resize display" );
  387.                 return( 1 );
  388.             }
  389.         }
  390. #endif
  391.         msg_Dbg( p_vout, "video display resized (%dx%d)",
  392.                          p_vout->p_sys->dim.w, p_vout->p_sys->dim.h );
  393.     }
  394.     /*
  395.      * position change, move video channel
  396.      */
  397.     if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
  398.     {
  399.         ResizeOverlayOutput(p_vout);
  400.     }
  401.     return( i_ev == -1 );
  402. }
  403. /*****************************************************************************
  404.  * QNXDisplay: displays previously rendered output
  405.  *****************************************************************************
  406.  * This function send the currently rendered image to QNX server, wait until
  407.  * it is displayed and switch the two rendering buffer, preparing next frame.
  408.  *****************************************************************************/
  409. static void QNXDisplay( vout_thread_t *p_vout, picture_t *p_pic )
  410. {
  411.     if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
  412.         p_vout->p_sys->i_mode == MODE_SHARED_MEM )
  413.     {
  414.         PhPoint_t pos = { 0, 0 };
  415.         PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
  416.         if (p_vout->p_sys->i_screen_depth == 8)
  417.         {
  418.             PgSetPalette( p_vout->p_sys->p_colors, 0, 0, 255, Pg_PALSET_SOFT, 0);
  419.         }
  420.         PgDrawPhImagemx( &pos, p_pic->p_sys->p_image, 0 );
  421.         PgFlush();
  422.     }
  423.     else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
  424.     {
  425.         PhRect_t rc = { { 0, 0 }, { p_vout->output.i_width, p_vout->output.i_height } };
  426. //        PgSetRegion( PtWidgetRid ( p_vout->p_sys->p_window ) );
  427.         PgContextBlit( p_pic->p_sys->p_ctx[0], &rc, NULL, &rc );
  428.         PgFlush();
  429.     }
  430. }
  431. /*****************************************************************************
  432.  * QNXInitDisplay: check screen resolution, depth, amount of video ram, etc
  433.  *****************************************************************************/
  434. static int QNXInitDisplay( vout_thread_t * p_vout )
  435. {
  436.     PgHWCaps_t hwcaps;
  437.     PgDisplaySettings_t cfg;
  438.     PgVideoModeInfo_t minfo;
  439.     /* get graphics card hw capabilities */
  440.     if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
  441.     {
  442.         msg_Err( p_vout, "unable to get gfx card capabilities" );
  443.         return( 1 );
  444.     }
  445.     /* get current video mode */
  446.     if( PgGetVideoMode( &cfg ) != 0 )
  447.     {
  448.         msg_Err( p_vout, "unable to get current video mode" );
  449.         return( 1 );
  450.     }
  451.     /* get video mode info */
  452.     if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
  453.     {
  454.         msg_Err( p_vout, "unable to get info for video mode" );
  455.         return( 1 );
  456.     }
  457.     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
  458.     {
  459.         int i = 0;
  460.         PgScalerCaps_t vcaps;
  461.         if( ( p_vout->p_sys->p_channel =
  462.             PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
  463.         {
  464.             msg_Err( p_vout, "unable to create video channel" );
  465.             printf("errno = %dn", errno);
  466.             p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
  467.         }
  468.         else
  469.         {
  470.             vcaps.size = sizeof( vcaps );
  471.             while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
  472.                                             i++, &vcaps ) == 0 )
  473.             {
  474.                 printf("vcaps.format = 0x%xn", vcaps.format);
  475.                 if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
  476.                     vcaps.format == Pg_VIDEO_FORMAT_YUV420 ||
  477.                     vcaps.format == Pg_VIDEO_FORMAT_YUY2 ||
  478.                     vcaps.format == Pg_VIDEO_FORMAT_UYVY ||
  479.                     vcaps.format == Pg_VIDEO_FORMAT_RGB555 ||
  480.                     vcaps.format == Pg_VIDEO_FORMAT_RGB565 ||
  481.                     vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
  482.                 {
  483.                     p_vout->p_sys->i_vc_flags  = vcaps.flags;
  484.                     p_vout->p_sys->i_vc_format = vcaps.format;
  485.                 }
  486.                 vcaps.size = sizeof( vcaps );
  487.             }
  488.             if( p_vout->p_sys->i_vc_format == 0 )
  489.             {
  490.                 msg_Warn( p_vout, "need YV12, YUY2 or RGB8888 overlay" );
  491.                 p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
  492.             }
  493.         }
  494.     }
  495.     /* use video ram if we have enough available */
  496.     if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
  497.         (minfo.bits_per_pixel != 8) &&
  498.         hwcaps.currently_available_video_ram >=
  499.         ( ( minfo.width * minfo.height * minfo.bits_per_pixel * MAX_DIRECTBUFFERS) / 8 ) )
  500.     {
  501.         p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
  502.         printf("Using video memory...n");
  503.     }
  504.     p_vout->p_sys->i_img_type = minfo.type;
  505.     p_vout->p_sys->screen_dim.w = minfo.width;
  506.     p_vout->p_sys->screen_dim.h = minfo.height;
  507.     p_vout->p_sys->i_screen_depth = minfo.bits_per_pixel;
  508.     switch( p_vout->p_sys->i_screen_depth )
  509.     {
  510.         case 8:
  511.             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
  512.             p_vout->p_sys->i_bytes_per_pixel = 1;
  513.             p_vout->output.pf_setpalette = SetPalette;
  514.             break;
  515.         case 15:
  516.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
  517.             p_vout->p_sys->i_bytes_per_pixel = 2;
  518.             p_vout->output.i_rmask = 0x7c00;
  519.             p_vout->output.i_gmask = 0x03e0;
  520.             p_vout->output.i_bmask = 0x001f;
  521.             break;
  522.         case 16:
  523.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
  524.             p_vout->p_sys->i_bytes_per_pixel = 2;
  525.             p_vout->output.i_rmask = 0xf800;
  526.             p_vout->output.i_gmask = 0x07e0;
  527.             p_vout->output.i_bmask = 0x001f;
  528.             break;
  529.         case 24:
  530.             p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
  531.             p_vout->p_sys->i_bytes_per_pixel = 3;
  532.             p_vout->output.i_rmask = 0xff0000;
  533.             p_vout->output.i_gmask = 0x00ff00;
  534.             p_vout->output.i_bmask = 0x0000ff;
  535.             break;
  536.         case 32:
  537.         default:
  538.             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
  539.             p_vout->p_sys->i_bytes_per_pixel = 4;
  540.             p_vout->output.i_rmask = 0xff0000;
  541.             p_vout->output.i_gmask = 0x00ff00;
  542.             p_vout->output.i_bmask = 0x0000ff;
  543.             break;
  544.     }
  545.     return( 0 );
  546. }
  547. /*****************************************************************************
  548.  * QNXCreateWnd: create and realize the main window
  549.  *****************************************************************************/
  550. static int QNXCreateWnd( vout_thread_t * p_vout )
  551. {
  552.     PtArg_t args[8];
  553.     PhPoint_t pos = { 0, 0 };
  554.     PgColor_t color = Pg_BLACK;
  555.     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
  556.     {
  557.         if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
  558.         {
  559.             color = PgGetOverlayChromaColor();
  560.         }
  561.     }
  562.     /* fullscreen, set dimension */
  563.     if( p_vout->b_fullscreen )
  564.     {
  565.         p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
  566.         p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
  567.         p_vout->output.i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
  568.         p_vout->output.i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
  569.     }
  570.     /* set window parameters */
  571.     PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
  572.     PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
  573.     PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
  574.     PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VLC media player", 0 );
  575.     PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
  576.     PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
  577.               Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
  578.     PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
  579.               p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
  580.               Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
  581.     /* create window */
  582.     p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
  583.     if( p_vout->p_sys->p_window == NULL )
  584.     {
  585.         msg_Err( p_vout, "unable to create window" );
  586.         return( 1 );
  587.     }
  588.     /* realize the window widget */
  589.     if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
  590.     {
  591.         msg_Err( p_vout, "unable to realize window widget" );
  592.         PtDestroyWidget( p_vout->p_sys->p_window );
  593.         return( 1 );
  594.     }
  595.     /* get window frame size */
  596.     if( PtWindowFrameSize( NULL, p_vout->p_sys->p_window,
  597.                            &p_vout->p_sys->frame ) != 0 )
  598.     {
  599.         msg_Err( p_vout, "unable to get window frame size" );
  600.         PtDestroyWidget( p_vout->p_sys->p_window );
  601.         return( 1 );
  602.     }
  603.     return( 0 );
  604. }
  605. /*****************************************************************************
  606.  * QNXDestroyWnd: unrealize and destroy the main window
  607.  *****************************************************************************/
  608. static int QNXDestroyWnd( vout_thread_t * p_vout )
  609. {
  610.     /* destroy the window widget */
  611.     PtUnrealizeWidget( p_vout->p_sys->p_window );
  612. //    PtDestroyWidget( p_vout->p_sys->p_window );
  613.     /* destroy video channel */
  614.     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
  615.     {
  616.         PgDestroyVideoChannel( p_vout->p_sys->p_channel );
  617.     }
  618.     return( 0 );
  619. }
  620. /*****************************************************************************
  621.  * NewPicture: allocate a picture
  622.  *****************************************************************************
  623.  * Returns 0 on success, -1 otherwise
  624.  *****************************************************************************/
  625. static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic, int index )
  626. {
  627.     /* We know the chroma, allocate a buffer which will be used
  628.      * directly by the decoder */
  629.     p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
  630.     if( p_pic->p_sys == NULL )
  631.     {
  632.         return -1;
  633.     }
  634.     switch( p_vout->p_sys->i_mode )
  635.     {
  636.     case MODE_NORMAL_MEM:
  637.     case MODE_SHARED_MEM:
  638.         /* create images for [shared] memory blit */
  639.         if( !( p_pic->p_sys->p_image = PhCreateImage( NULL,
  640.                     p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
  641.                     p_vout->p_sys->i_img_type, NULL, 0,
  642.                     p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
  643.             msg_Err( p_vout, "cannot create image" );
  644.             free( p_pic->p_sys );
  645.             return( -1 );
  646.         }
  647.         p_pic->p->p_pixels = p_pic->p_sys->p_image->image;
  648.         p_pic->p->i_lines = p_pic->p_sys->p_image->size.h;
  649.         p_pic->p->i_visible_lines = p_pic->p_sys->p_image->size.h;
  650.         p_pic->p->i_pitch = p_pic->p_sys->p_image->bpl;
  651.         p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
  652.         p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
  653.                                      * p_pic->p_sys->p_image->size.w;
  654.         p_pic->i_planes = 1;
  655.         break;
  656.     case MODE_VIDEO_MEM:
  657.         /* create offscreen contexts for video memory blit */
  658.         if( ( p_pic->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
  659.                         p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
  660.                        Pg_OSC_MEM_PAGE_ALIGN) ) == NULL )
  661.         {
  662.             msg_Err( p_vout, "unable to create offscreen context" );
  663.             free( p_pic->p_sys );
  664.             return( -1 );
  665.         }
  666.         /* get context pointers */
  667.         if( (  p_pic->p_sys->p_buf[0] =
  668.             PdGetOffscreenContextPtr ( p_pic->p_sys->p_ctx[0] ) ) == NULL )
  669.         {
  670.             msg_Err( p_vout, "unable to get offscreen context ptr" );
  671.             PhDCRelease ( p_pic->p_sys->p_ctx[0] );
  672.             p_pic->p_sys->p_ctx[0] = NULL;
  673.             free( p_pic->p_sys );
  674.             return( -1 );
  675.         }
  676.         p_vout->p_sys->i_bytes_per_line = p_pic->p_sys->p_ctx[0]->pitch;
  677.         memset( p_pic->p_sys->p_buf[0], 0,
  678.             p_vout->p_sys->i_bytes_per_line * p_vout->p_sys->dim.h );
  679.         p_pic->p->p_pixels = p_pic->p_sys->p_buf[0];
  680.         p_pic->p->i_lines = p_pic->p_sys->p_ctx[0]->dim.h;
  681.         p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[0]->dim.h;
  682.         p_pic->p->i_pitch = p_pic->p_sys->p_ctx[0]->pitch;
  683.         p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
  684.         p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
  685.                                      * p_pic->p_sys->p_ctx[0]->dim.w;
  686.         p_pic->i_planes = 1;
  687.         break;
  688.     case MODE_VIDEO_OVERLAY:
  689.         if (index == 0)
  690.         {
  691.             p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane1;
  692.             p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane1;
  693.             p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane1;
  694.         }
  695.         else
  696.         {
  697.             p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane2;
  698.             p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane2;
  699.             p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane2;
  700.         }
  701.         p_pic->p_sys->p_buf[Y_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[Y_PLANE] );
  702.         if( p_pic->p_sys->p_buf[Y_PLANE] == NULL )
  703.         {
  704.             msg_Err( p_vout, "unable to get video channel ctx ptr" );
  705.             return( 1 );
  706.         }
  707.         switch (p_vout->p_sys->i_vc_format)
  708.         {
  709.             case Pg_VIDEO_FORMAT_YUV420:
  710.                 p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
  711.                 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
  712.                 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
  713.                 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
  714.                     p_pic->p_sys->p_buf[V_PLANE] == NULL )
  715.                 {
  716.                     msg_Err( p_vout, "unable to get video channel ctx ptr" );
  717.                     return( 1 );
  718.                 }
  719.                 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
  720.                 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  721.                 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  722.                 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  723.                 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
  724.                 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
  725.                 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
  726.                 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
  727.                 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
  728.                 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
  729.                 p_pic->p[U_PLANE].i_pixel_pitch = 1;
  730.                 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
  731.                 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
  732.                 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
  733.                 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
  734.                 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
  735.                 p_pic->p[V_PLANE].i_pixel_pitch = 1;
  736.                 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
  737.                 p_pic->i_planes = 3;
  738.                 break;
  739.             case Pg_VIDEO_FORMAT_YV12:
  740.                 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
  741.                 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
  742.                 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
  743.                 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
  744.                     p_pic->p_sys->p_buf[V_PLANE] == NULL )
  745.                 {
  746.                     msg_Err( p_vout, "unable to get video channel ctx ptr" );
  747.                     return( 1 );
  748.                 }
  749.                 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
  750.                 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  751.                 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  752.                 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  753.                 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
  754.                 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
  755.                 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
  756.                 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
  757.                 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
  758.                 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
  759.                 p_pic->p[U_PLANE].i_pixel_pitch = 1;
  760.                 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
  761.                 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
  762.                 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
  763.                 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
  764.                 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
  765.                 p_pic->p[V_PLANE].i_pixel_pitch = 1;
  766.                 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
  767.                 p_pic->i_planes = 3;
  768.                 break;
  769.             case Pg_VIDEO_FORMAT_UYVY:
  770.             case Pg_VIDEO_FORMAT_YUY2:
  771.                 if (p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_UYVY)
  772.                 {
  773.                     p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
  774.                 }
  775.                 else
  776.                 {
  777.                     p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
  778.                 }
  779.                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
  780.                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  781.                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  782.                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  783.                 p_pic->p->i_pixel_pitch = 4;
  784.                 p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  785.                 p_pic->i_planes = 1;
  786.                 break;
  787.             case Pg_VIDEO_FORMAT_RGB555:
  788.                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
  789.                 p_vout->output.i_rmask = 0x001f;
  790.                 p_vout->output.i_gmask = 0x03e0;
  791.                 p_vout->output.i_bmask = 0x7c00;
  792.                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
  793.                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  794.                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  795.                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  796.                 p_pic->p->i_pixel_pitch = 2;
  797.                 p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
  798.                 p_pic->i_planes = 1;
  799.                 break;
  800.             case Pg_VIDEO_FORMAT_RGB565:
  801.                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
  802.                 p_vout->output.i_rmask = 0x001f;
  803.                 p_vout->output.i_gmask = 0x07e0;
  804.                 p_vout->output.i_bmask = 0xf800;
  805.                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
  806.                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  807.                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  808.                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  809.                 p_pic->p->i_pixel_pitch = 4;
  810.                 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
  811.                 p_pic->i_planes = 1;
  812.                 break;
  813.             case Pg_VIDEO_FORMAT_RGB8888:
  814.                 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
  815.                 p_vout->output.i_rmask = 0x000000ff;
  816.                 p_vout->output.i_gmask = 0x0000ff00;
  817.                 p_vout->output.i_bmask = 0x00ff0000;
  818.                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
  819.                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  820.                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
  821.                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
  822.                 p_pic->p->i_pixel_pitch = 4;
  823.                 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
  824.                 p_pic->i_planes = 1;
  825.                 break;
  826.         }
  827. #if 0
  828.     switch( p_vout->output.i_chroma )
  829.     {
  830. #ifdef MODULE_NAME_IS_xvideo
  831.         case VLC_FOURCC('Y','2','1','1'):
  832.             p_pic->p->p_pixels = p_pic->p_sys->p_image->data
  833.                                   + p_pic->p_sys->p_image->offsets[0];
  834.             p_pic->p->i_lines = p_vout->output.i_height;
  835.             p_pic->p->i_visible_lines = p_vout->output.i_height;
  836.             /* XXX: this just looks so plain wrong... check it out ! */
  837.             p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
  838.             p_pic->p->i_pixel_pitch = 4;
  839.             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
  840.             p_pic->i_planes = 1;
  841.             break;
  842. #endif
  843. #endif
  844.     default:
  845.         /* This shouldn't happen ! */
  846.         break;
  847.     }
  848.     return 0;
  849. }
  850. /*****************************************************************************
  851.  * FreePicture: destroy a picture allocated with NewPicture
  852.  *****************************************************************************
  853.  * Destroy XImage AND associated data. If using Shm, detach shared memory
  854.  * segment from server and process, then free it. The XDestroyImage manpage
  855.  * says that both the image structure _and_ the data pointed to by the
  856.  * image structure are freed, so no need to free p_image->data.
  857.  *****************************************************************************/
  858. static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
  859. {
  860.     if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
  861.         p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
  862.         p_pic->p_sys->p_image )
  863.     {
  864.         PhReleaseImage( p_pic->p_sys->p_image );
  865.         free( p_pic->p_sys->p_image );
  866.     }
  867.     else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
  868.              p_pic->p_sys->p_ctx[0] )
  869.     {
  870.         PhDCRelease( p_pic->p_sys->p_ctx[0] );
  871.     }
  872.     free( p_pic->p_sys );
  873. }
  874. static int ResizeOverlayOutput(vout_thread_t *p_vout)
  875. {
  876.     int i_width, i_height, i_x, i_y;
  877.     int i_ret;
  878.     PgScalerProps_t props;
  879.     props.size   = sizeof( props );
  880.     props.format = p_vout->p_sys->i_vc_format;
  881.     props.flags  = Pg_SCALER_PROP_SCALER_ENABLE |
  882.                           Pg_SCALER_PROP_DOUBLE_BUFFER;
  883.     /* enable chroma keying if available */
  884.     if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
  885.     {
  886.         props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
  887.     }
  888.     /* set viewport position */
  889.     props.viewport.ul.x = p_vout->p_sys->pos.x;
  890.     props.viewport.ul.y = p_vout->p_sys->pos.y;
  891.     if( !p_vout->b_fullscreen )
  892.     {
  893.         props.viewport.ul.x += p_vout->p_sys->frame.ul.x;
  894.         props.viewport.ul.y += p_vout->p_sys->frame.ul.y;
  895.     }
  896.     /* set viewport dimension */
  897.     vout_PlacePicture( p_vout, p_vout->p_sys->dim.w,
  898.                            p_vout->p_sys->dim.h,
  899.                            &i_x, &i_y, &i_width, &i_height );
  900.     props.viewport.ul.x += i_x;
  901.     props.viewport.ul.y += i_y;
  902.     props.viewport.lr.x = i_width + props.viewport.ul.x;
  903.     props.viewport.lr.y = i_height + props.viewport.ul.y;
  904.     /* set source dimension */
  905.     props.src_dim.w = p_vout->output.i_width;
  906.     props.src_dim.h = p_vout->output.i_height;
  907.     /* configure scaler channel */
  908.     i_ret = PgConfigScalerChannel( p_vout->p_sys->p_channel, &props );
  909.     if( i_ret == -1 )
  910.     {
  911.         msg_Err( p_vout, "unable to configure video channel" );
  912.         return( 1 );
  913.     }
  914.     return ( 0 );
  915. }
  916. /*****************************************************************************
  917.  * SetPalette: sets an 8 bpp palette
  918.  *****************************************************************************
  919.  * This function sets the palette given as an argument. It does not return
  920.  * anything, but could later send information on which colors it was unable
  921.  * to set.
  922.  *****************************************************************************/
  923. static void SetPalette( vout_thread_t *p_vout,
  924.                         uint16_t *red, uint16_t *green, uint16_t *blue )
  925. {
  926.     int i;
  927.     /* allocate palette */
  928.     for( i = 0; i < 255; i++ )
  929.     {
  930.         /* kludge: colors are indexed reversely because color 255 seems
  931.          * to be reserved for black even if we try to set it to white */
  932.         p_vout->p_sys->p_colors[ i ] = PgRGB( red[ i ] >> 8, green[ i ] >> 8, blue[ i ] >> 8 );
  933.     }
  934. }