Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

vout.c

00001 /*****************************************************************************
00002  * vout.c: QNX RTOS video output display method
00003  *****************************************************************************
00004  * Copyright (C) 2001, 2002 the VideoLAN team
00005  *
00006  * Authors: Jon Lech Johansen <[email protected]>
00007  *          Pascal Levesque <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <errno.h>                                                 /* ENOMEM */
00028 #include <stdlib.h>                                                /* free() */
00029 #include <string.h>                                            /* strerror() */
00030 
00031 #include <photon/PtWidget.h>
00032 #include <photon/PtWindow.h>
00033 #include <photon/PtLabel.h>
00034 #include <photon/PdDirect.h>
00035 
00036 #include <vlc/vlc.h>
00037 #include <vlc/intf.h>
00038 #include <vlc/vout.h>
00039 
00040 /*****************************************************************************
00041  * vout_sys_t: video output QNX method descriptor
00042  *****************************************************************************
00043  * This structure is part of the video output thread descriptor.
00044  * It describes the QNX specific properties of an output thread. QNX video
00045  * output is performed through regular resizable windows. Windows can be
00046  * dynamically resized to adapt to the size of the streams.
00047  *****************************************************************************/
00048 #define MAX_DIRECTBUFFERS 2
00049 
00050 #define MODE_NORMAL_MEM     0
00051 #define MODE_SHARED_MEM     1
00052 #define MODE_VIDEO_MEM      2
00053 #define MODE_VIDEO_OVERLAY  3
00054 
00055 struct vout_sys_t
00056 {
00057     /* video mode */
00058     int                     i_mode;
00059 
00060     /* internal stuff */
00061     PtWidget_t *            p_window;
00062 
00063     /* Color palette for 8bpp */
00064     PgColor_t p_colors[255];
00065 
00066     /* [shared] memory blit */
00067     int                     i_img_type;
00068 
00069     /* video memory blit */
00070 
00071     /* video overlay */
00072     PgVideoChannel_t *      p_channel;
00073     int                     i_vc_flags;
00074     int                     i_vc_format;
00075 
00076     int                 i_screen_depth;
00077     int                 i_bytes_per_pixel;
00078     int                 i_bytes_per_line;
00079 
00080     /* position & dimensions */
00081     PhPoint_t               pos;
00082     PhDim_t                 dim;
00083     PhPoint_t               old_pos;
00084     PhDim_t                 old_dim;
00085     PhDim_t                 screen_dim;
00086     PhRect_t                frame;
00087 };
00088 
00089 
00090 /*****************************************************************************
00091  * picture_sys_t: direct buffer method descriptor
00092  *****************************************************************************
00093  * This structure is part of the picture descriptor, it describes the
00094  * XVideo specific properties of a direct buffer.
00095  *****************************************************************************/
00096 struct picture_sys_t
00097 {
00098     /* [shared] memory blit */
00099     PhImage_t *             p_image;
00100 
00101     /* video memory blit and video overlay */
00102     PdOffscreenContext_t *  p_ctx[3];   /* 0: y, 1: u, 2: v */
00103     char *                  p_buf[3];
00104 };
00105 
00106 
00107 /*****************************************************************************
00108  * Local prototypes
00109  *****************************************************************************/
00110 static int  QNXInit      ( vout_thread_t * );
00111 static void QNXEnd       ( vout_thread_t * );
00112 static int  QNXManage    ( vout_thread_t * );
00113 static void QNXDisplay   ( vout_thread_t *, picture_t * );
00114 
00115 static int  QNXInitDisplay ( vout_thread_t * );
00116 static int  QNXCreateWnd   ( vout_thread_t * );
00117 static int  QNXDestroyWnd  ( vout_thread_t * );
00118 
00119 static int  NewPicture     ( vout_thread_t *, picture_t *, int );
00120 static void FreePicture    ( vout_thread_t *, picture_t * );
00121 static int  ResizeOverlayOutput ( vout_thread_t * );
00122 static void SetPalette     ( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
00123 
00124 /*****************************************************************************
00125  * OpenVideo: allocate QNX video thread output method
00126  *****************************************************************************
00127  * This function allocate and initialize a QNX vout method. It uses some of the
00128  * vout properties to choose the window size, and change them according to the
00129  * actual properties of the display.
00130  *****************************************************************************/
00131 int E_(OpenVideo) ( vlc_object_t *p_this )
00132 {
00133     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00134 
00135     /* init connection to photon */
00136     if( PtInit( "/dev/photon" ) != 0 )
00137     {
00138         msg_Err( p_vout, "unable to connect to photon" );
00139         return( 1 );
00140     }
00141 
00142     /* allocate structure */
00143     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00144     if( p_vout->p_sys == NULL )
00145     {
00146         msg_Err( p_vout, "out of memory" );
00147         return( 1 );
00148     }
00149 
00150     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
00151 
00152     p_vout->b_fullscreen = config_GetInt( p_vout, "fullscreen" );
00153     p_vout->p_sys->i_mode = config_GetInt( p_vout, "overlay" ) ?
00154                                 MODE_VIDEO_OVERLAY : MODE_VIDEO_MEM;
00155     p_vout->p_sys->dim.w = p_vout->i_window_width;
00156     p_vout->p_sys->dim.h = p_vout->i_window_height;
00157 
00158     /* init display and create window */
00159     if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
00160     {
00161         free( p_vout->p_sys );
00162         return( 1 );
00163     }
00164 
00165     p_vout->pf_init = QNXInit;
00166     p_vout->pf_end = QNXEnd;
00167     p_vout->pf_manage = QNXManage;
00168     p_vout->pf_render = NULL;
00169     p_vout->pf_display = QNXDisplay;
00170 
00171     return( 0 );
00172 }
00173 
00174 /*****************************************************************************
00175  * QNXInit: initialize QNX video thread output method
00176  *****************************************************************************
00177  * This function create the buffers needed by the output thread. It is called
00178  * at the beginning of the thread, but also each time the window is resized.
00179  *****************************************************************************/
00180 static int QNXInit( vout_thread_t *p_vout )
00181 {
00182     int i_index;
00183     picture_t *p_pic;
00184 
00185     I_OUTPUTPICTURES = 0;
00186 
00187     switch( p_vout->p_sys->i_mode )
00188     {
00189     case MODE_NORMAL_MEM:
00190     case MODE_SHARED_MEM:
00191         p_vout->output.i_width = p_vout->p_sys->dim.w;
00192         p_vout->output.i_height = p_vout->p_sys->dim.h;
00193 
00194         /* Assume we have square pixels */
00195         p_vout->output.i_aspect = p_vout->p_sys->dim.w
00196                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
00197         break;
00198 
00199     case MODE_VIDEO_MEM:
00200         p_vout->output.i_width = p_vout->p_sys->dim.w;
00201         p_vout->output.i_height = p_vout->p_sys->dim.h;
00202 
00203         /* Assume we have square pixels */
00204         p_vout->output.i_aspect = p_vout->p_sys->dim.w
00205                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
00206         break;
00207 
00208     case MODE_VIDEO_OVERLAY:
00209         p_vout->output.i_width  = p_vout->render.i_width;
00210         p_vout->output.i_height = p_vout->render.i_height;
00211         p_vout->output.i_aspect = p_vout->render.i_aspect;
00212 
00213         if (ResizeOverlayOutput(p_vout))
00214         {
00215             return (1);
00216         }
00217         break;
00218 
00219     default:
00220         /* This shouldn't happen ! */
00221         break;
00222     }
00223 
00224     /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
00225     while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
00226     {
00227         p_pic = NULL;
00228 
00229         /* Find an empty picture slot */
00230         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00231         {
00232             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00233             {
00234                 p_pic = p_vout->p_picture + i_index;
00235                 break;
00236             }
00237         }
00238 
00239         /* Allocate the picture */
00240         if( p_pic == NULL || NewPicture( p_vout, p_pic, I_OUTPUTPICTURES ) )
00241         {
00242             break;
00243         }
00244 
00245         p_pic->i_status = DESTROYED_PICTURE;
00246         p_pic->i_type   = DIRECT_PICTURE;
00247 
00248         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00249 
00250         I_OUTPUTPICTURES++;
00251     }
00252 
00253     return( 0 );
00254 }
00255 
00256 /*****************************************************************************
00257  * QNXEnd: terminate QNX video thread output method
00258  *****************************************************************************
00259  * Destroy the buffers created by QNXInit. It is called at the end of
00260  * the thread, but also each time the window is resized.
00261  *****************************************************************************/
00262 static void QNXEnd( vout_thread_t *p_vout )
00263 {
00264     int i_index;
00265 
00266     /* Free the direct buffers we allocated */
00267     for( i_index = I_OUTPUTPICTURES ; i_index ; )
00268     {
00269         i_index--;
00270         FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
00271     }
00272 }
00273 
00274 /*****************************************************************************
00275  * CloseVideo: destroy QNX video thread output method
00276  *****************************************************************************
00277  * Terminate an output method created by QNXCreate
00278  *****************************************************************************/
00279 void E_(CloseVideo) ( vlc_object_t *p_this )
00280 {
00281     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00282 
00283     /* destroy the window */
00284     QNXDestroyWnd( p_vout );
00285 
00286     /* destroy structure */
00287     free( p_vout->p_sys );
00288 }
00289 
00290 /*****************************************************************************
00291  * QNXManage: handle QNX events
00292  *****************************************************************************
00293  * This function should be called regularly by video output thread. It allows
00294  * window resizing. It returns a non null value on error.
00295  *****************************************************************************/
00296 static int QNXManage( vout_thread_t *p_vout )
00297 {
00298     int i_ev,  i_buflen;
00299     PhEvent_t *p_event;
00300     vlc_bool_t b_repos = 0;
00301 
00302     if (p_vout->b_die == 1)
00303     {
00304         return ( 0 );
00305     }
00306 
00307     /* allocate buffer for event */
00308     i_buflen = sizeof( PhEvent_t ) * 4;
00309     if( ( p_event = malloc( i_buflen ) ) == NULL )
00310     {
00311         msg_Err( p_vout, "out of memory" );
00312         return( 1 );
00313     }
00314 
00315     /* event loop */
00316     do
00317     {
00318         memset( p_event, 0, i_buflen );
00319         i_ev = PhEventPeek( p_event, i_buflen );
00320 
00321         if( i_ev == Ph_RESIZE_MSG )
00322         {
00323             i_buflen = PhGetMsgSize( p_event );
00324             if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
00325             {
00326                 msg_Err( p_vout, "out of memory" );
00327                 return( 1 );
00328             }
00329         }
00330         else if( i_ev == Ph_EVENT_MSG )
00331         {
00332             PtEventHandler( p_event );
00333 
00334             if( p_event->type == Ph_EV_WM )
00335             {
00336                 PhWindowEvent_t *p_ev = PhGetData( p_event );
00337 
00338                 switch( p_ev->event_f )
00339                 {
00340                 case Ph_WM_CLOSE:
00341                     p_vout->p_vlc->b_die = 1;
00342                     break;
00343 
00344                 case Ph_WM_MOVE:
00345                     p_vout->p_sys->pos.x = p_ev->pos.x;
00346                     p_vout->p_sys->pos.y = p_ev->pos.y;
00347                     b_repos = 1;
00348                     break;
00349 
00350                 case Ph_WM_RESIZE:
00351                     p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
00352                     p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
00353                     p_vout->p_sys->dim.w = p_ev->size.w;
00354                     p_vout->p_sys->dim.h = p_ev->size.h;
00355                     p_vout->i_changes |= VOUT_SIZE_CHANGE;
00356                     break;
00357                 }
00358             }
00359             else if( p_event->type == Ph_EV_KEY )
00360             {
00361                 PhKeyEvent_t *p_ev = PhGetData( p_event );
00362                 long i_key = p_ev->key_sym;
00363 
00364                 if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
00365                     ( p_ev->key_flags & Pk_KF_Sym_Valid ) )
00366                 {
00367                     switch( i_key )
00368                     {
00369                     case Pk_q:
00370                     case Pk_Q:
00371                         p_vout->p_vlc->b_die = 1;
00372                         break;
00373 
00374                     case Pk_f:
00375                     case Pk_F:
00376                         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00377                         break;
00378 
00379                     case Pk_c:
00380                     case Pk_C:
00381                         p_vout->b_grayscale = ! p_vout->b_grayscale;
00382                         p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
00383                         break;
00384 
00385                     default:
00386                         break;
00387                     }
00388                 }
00389             }
00390         }
00391     } while( i_ev != -1 && i_ev != 0 );
00392 
00393     free( p_event );
00394 
00395     /*
00396      * fullscreen
00397      */
00398     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
00399     {
00400         PhDim_t dim;
00401 
00402         p_vout->b_fullscreen = !p_vout->b_fullscreen;
00403         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00404 
00405         if( p_vout->b_fullscreen )
00406         {
00407             p_vout->p_sys->old_pos.x = p_vout->p_sys->pos.x;
00408             p_vout->p_sys->old_pos.y = p_vout->p_sys->pos.y;
00409             p_vout->p_sys->pos.x = p_vout->p_sys->pos.y = 0;
00410             dim.w = p_vout->p_sys->screen_dim.w + 1;
00411             dim.h = p_vout->p_sys->screen_dim.h + 1;
00412         }
00413         else
00414         {
00415             p_vout->p_sys->pos.x = p_vout->p_sys->old_pos.x;
00416             p_vout->p_sys->pos.y = p_vout->p_sys->old_pos.y;
00417             dim.w = p_vout->p_sys->old_dim.w + 1;
00418             dim.h = p_vout->p_sys->old_dim.h + 1;
00419         }
00420 
00421         /* modify render flags, border */
00422         PtSetResource( p_vout->p_sys->p_window,
00423             Pt_ARG_WINDOW_RENDER_FLAGS,
00424             p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
00425             Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
00426 
00427         /* set position and dimension */
00428         PtSetResource( p_vout->p_sys->p_window,
00429                        Pt_ARG_POS, &p_vout->p_sys->pos, 0 );
00430         PtSetResource( p_vout->p_sys->p_window,
00431                        Pt_ARG_DIM, &dim, 0 );
00432 
00433         /* mark as damaged to force redraw */
00434         PtDamageWidget( p_vout->p_sys->p_window );
00435     }
00436 
00437     /*
00438      * size change
00439      */
00440     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
00441     {
00442         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
00443 
00444         if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00445         {
00446             ResizeOverlayOutput(p_vout);
00447         }
00448 #if 0
00449         else
00450         {
00451             p_vout->output.i_width = p_vout->p_sys->dim.w;
00452             p_vout->output.i_height = p_vout->p_sys->dim.h;
00453             p_vout->i_changes |= VOUT_YUV_CHANGE;
00454 
00455             QNXEnd( p_vout );
00456             if( QNXInit( p_vout ) )
00457             {
00458                 msg_Err( p_vout, "cannot resize display" );
00459                 return( 1 );
00460             }
00461         }
00462 #endif
00463 
00464         msg_Dbg( p_vout, "video display resized (%dx%d)",
00465                          p_vout->p_sys->dim.w, p_vout->p_sys->dim.h );
00466     }
00467 
00468     /*
00469      * position change, move video channel
00470      */
00471     if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00472     {
00473         ResizeOverlayOutput(p_vout);
00474     }
00475 
00476     return( i_ev == -1 );
00477 }
00478 
00479 /*****************************************************************************
00480  * QNXDisplay: displays previously rendered output
00481  *****************************************************************************
00482  * This function send the currently rendered image to QNX server, wait until
00483  * it is displayed and switch the two rendering buffer, preparing next frame.
00484  *****************************************************************************/
00485 static void QNXDisplay( vout_thread_t *p_vout, picture_t *p_pic )
00486 {
00487     if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
00488         p_vout->p_sys->i_mode == MODE_SHARED_MEM )
00489     {
00490         PhPoint_t pos = { 0, 0 };
00491 
00492         PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
00493         if (p_vout->p_sys->i_screen_depth == 8)
00494         {
00495             PgSetPalette( p_vout->p_sys->p_colors, 0, 0, 255, Pg_PALSET_SOFT, 0);
00496         }
00497         PgDrawPhImagemx( &pos, p_pic->p_sys->p_image, 0 );
00498         PgFlush();
00499     }
00500     else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
00501     {
00502         PhRect_t rc = { { 0, 0 }, { p_vout->output.i_width, p_vout->output.i_height } };
00503 
00504 //        PgSetRegion( PtWidgetRid ( p_vout->p_sys->p_window ) );
00505         PgContextBlit( p_pic->p_sys->p_ctx[0], &rc, NULL, &rc );
00506         PgFlush();
00507     }
00508 }
00509 
00510 /*****************************************************************************
00511  * QNXInitDisplay: check screen resolution, depth, amount of video ram, etc
00512  *****************************************************************************/
00513 static int QNXInitDisplay( vout_thread_t * p_vout )
00514 {
00515     PgHWCaps_t hwcaps;
00516     PgDisplaySettings_t cfg;
00517     PgVideoModeInfo_t minfo;
00518 
00519     /* get graphics card hw capabilities */
00520     if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
00521     {
00522         msg_Err( p_vout, "unable to get gfx card capabilities" );
00523         return( 1 );
00524     }
00525 
00526     /* get current video mode */
00527     if( PgGetVideoMode( &cfg ) != 0 )
00528     {
00529         msg_Err( p_vout, "unable to get current video mode" );
00530         return( 1 );
00531     }
00532 
00533     /* get video mode info */
00534     if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
00535     {
00536         msg_Err( p_vout, "unable to get info for video mode" );
00537         return( 1 );
00538     }
00539 
00540     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00541     {
00542         int i = 0;
00543         PgScalerCaps_t vcaps;
00544 
00545         if( ( p_vout->p_sys->p_channel =
00546             PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
00547         {
00548             msg_Err( p_vout, "unable to create video channel" );
00549             printf("errno = %d\n", errno);
00550             p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
00551         }
00552         else
00553         {
00554             vcaps.size = sizeof( vcaps );
00555             while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
00556                                             i++, &vcaps ) == 0 )
00557             {
00558                 printf("vcaps.format = 0x%x\n", vcaps.format);
00559                 if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
00560                     vcaps.format == Pg_VIDEO_FORMAT_YUV420 ||
00561                     vcaps.format == Pg_VIDEO_FORMAT_YUY2 ||
00562                     vcaps.format == Pg_VIDEO_FORMAT_UYVY ||
00563                     vcaps.format == Pg_VIDEO_FORMAT_RGB555 ||
00564                     vcaps.format == Pg_VIDEO_FORMAT_RGB565 ||
00565                     vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
00566                 {
00567                     p_vout->p_sys->i_vc_flags  = vcaps.flags;
00568                     p_vout->p_sys->i_vc_format = vcaps.format;
00569                 }
00570 
00571                 vcaps.size = sizeof( vcaps );
00572             }
00573 
00574             if( p_vout->p_sys->i_vc_format == 0 )
00575             {
00576                 msg_Warn( p_vout, "need YV12, YUY2 or RGB8888 overlay" );
00577 
00578                 p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
00579             }
00580         }
00581     }
00582 
00583     /* use video ram if we have enough available */
00584     if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
00585         (minfo.bits_per_pixel != 8) &&
00586         hwcaps.currently_available_video_ram >=
00587         ( ( minfo.width * minfo.height * minfo.bits_per_pixel * MAX_DIRECTBUFFERS) / 8 ) )
00588     {
00589         p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
00590         printf("Using video memory...\n");
00591     }
00592 
00593     p_vout->p_sys->i_img_type = minfo.type;
00594     p_vout->p_sys->screen_dim.w = minfo.width;
00595     p_vout->p_sys->screen_dim.h = minfo.height;
00596     p_vout->p_sys->i_screen_depth = minfo.bits_per_pixel;
00597 
00598     switch( p_vout->p_sys->i_screen_depth )
00599     {
00600         case 8:
00601             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
00602             p_vout->p_sys->i_bytes_per_pixel = 1;
00603             p_vout->output.pf_setpalette = SetPalette;
00604             break;
00605 
00606         case 15:
00607             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00608             p_vout->p_sys->i_bytes_per_pixel = 2;
00609             p_vout->output.i_rmask = 0x7c00;
00610             p_vout->output.i_gmask = 0x03e0;
00611             p_vout->output.i_bmask = 0x001f;
00612             break;
00613 
00614         case 16:
00615             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00616             p_vout->p_sys->i_bytes_per_pixel = 2;
00617             p_vout->output.i_rmask = 0xf800;
00618             p_vout->output.i_gmask = 0x07e0;
00619             p_vout->output.i_bmask = 0x001f;
00620             break;
00621 
00622         case 24:
00623             p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
00624             p_vout->p_sys->i_bytes_per_pixel = 3;
00625             p_vout->output.i_rmask = 0xff0000;
00626             p_vout->output.i_gmask = 0x00ff00;
00627             p_vout->output.i_bmask = 0x0000ff;
00628             break;
00629 
00630         case 32:
00631         default:
00632             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00633             p_vout->p_sys->i_bytes_per_pixel = 4;
00634             p_vout->output.i_rmask = 0xff0000;
00635             p_vout->output.i_gmask = 0x00ff00;
00636             p_vout->output.i_bmask = 0x0000ff;
00637             break;
00638     }
00639 
00640     return( 0 );
00641 }
00642 
00643 /*****************************************************************************
00644  * QNXCreateWnd: create and realize the main window
00645  *****************************************************************************/
00646 static int QNXCreateWnd( vout_thread_t * p_vout )
00647 {
00648     PtArg_t args[8];
00649     PhPoint_t pos = { 0, 0 };
00650     PgColor_t color = Pg_BLACK;
00651 
00652     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00653     {
00654         if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
00655         {
00656             color = PgGetOverlayChromaColor();
00657         }
00658     }
00659 
00660     /* fullscreen, set dimension */
00661     if( p_vout->b_fullscreen )
00662     {
00663         p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
00664         p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
00665         p_vout->output.i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
00666         p_vout->output.i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
00667     }
00668 
00669     /* set window parameters */
00670     PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
00671     PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
00672     PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
00673     PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VLC media player", 0 );
00674     PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
00675     PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
00676               Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
00677     PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
00678               p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
00679               Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
00680 
00681     /* create window */
00682     p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
00683     if( p_vout->p_sys->p_window == NULL )
00684     {
00685         msg_Err( p_vout, "unable to create window" );
00686         return( 1 );
00687     }
00688 
00689     /* realize the window widget */
00690     if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
00691     {
00692         msg_Err( p_vout, "unable to realize window widget" );
00693         PtDestroyWidget( p_vout->p_sys->p_window );
00694         return( 1 );
00695     }
00696 
00697     /* get window frame size */
00698     if( PtWindowFrameSize( NULL, p_vout->p_sys->p_window,
00699                            &p_vout->p_sys->frame ) != 0 )
00700     {
00701         msg_Err( p_vout, "unable to get window frame size" );
00702         PtDestroyWidget( p_vout->p_sys->p_window );
00703         return( 1 );
00704     }
00705 
00706     return( 0 );
00707 }
00708 
00709 /*****************************************************************************
00710  * QNXDestroyWnd: unrealize and destroy the main window
00711  *****************************************************************************/
00712 static int QNXDestroyWnd( vout_thread_t * p_vout )
00713 {
00714     /* destroy the window widget */
00715     PtUnrealizeWidget( p_vout->p_sys->p_window );
00716 //    PtDestroyWidget( p_vout->p_sys->p_window );
00717 
00718     /* destroy video channel */
00719     if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00720     {
00721         PgDestroyVideoChannel( p_vout->p_sys->p_channel );
00722     }
00723 
00724     return( 0 );
00725 }
00726 
00727 
00728 /*****************************************************************************
00729  * NewPicture: allocate a picture
00730  *****************************************************************************
00731  * Returns 0 on success, -1 otherwise
00732  *****************************************************************************/
00733 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic, int index )
00734 {
00735     /* We know the chroma, allocate a buffer which will be used
00736      * directly by the decoder */
00737     p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00738 
00739     if( p_pic->p_sys == NULL )
00740     {
00741         return -1;
00742     }
00743 
00744     switch( p_vout->p_sys->i_mode )
00745     {
00746     case MODE_NORMAL_MEM:
00747     case MODE_SHARED_MEM:
00748         /* create images for [shared] memory blit */
00749         if( !( p_pic->p_sys->p_image = PhCreateImage( NULL,
00750                     p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
00751                     p_vout->p_sys->i_img_type, NULL, 0,
00752                     p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
00753             msg_Err( p_vout, "cannot create image" );
00754             free( p_pic->p_sys );
00755             return( -1 );
00756         }
00757 
00758         p_pic->p->p_pixels = p_pic->p_sys->p_image->image;
00759         p_pic->p->i_lines = p_pic->p_sys->p_image->size.h;
00760         p_pic->p->i_visible_lines = p_pic->p_sys->p_image->size.h;
00761         p_pic->p->i_pitch = p_pic->p_sys->p_image->bpl;
00762         p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
00763         p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
00764                                      * p_pic->p_sys->p_image->size.w;
00765         p_pic->i_planes = 1;
00766         break;
00767 
00768     case MODE_VIDEO_MEM:
00769         /* create offscreen contexts for video memory blit */
00770         if( ( p_pic->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
00771                         p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
00772                        Pg_OSC_MEM_PAGE_ALIGN) ) == NULL )
00773         {
00774             msg_Err( p_vout, "unable to create offscreen context" );
00775             free( p_pic->p_sys );
00776             return( -1 );
00777         }
00778 
00779         /* get context pointers */
00780         if( (  p_pic->p_sys->p_buf[0] =
00781             PdGetOffscreenContextPtr ( p_pic->p_sys->p_ctx[0] ) ) == NULL )
00782         {
00783             msg_Err( p_vout, "unable to get offscreen context ptr" );
00784             PhDCRelease ( p_pic->p_sys->p_ctx[0] );
00785             p_pic->p_sys->p_ctx[0] = NULL;
00786             free( p_pic->p_sys );
00787             return( -1 );
00788         }
00789 
00790         p_vout->p_sys->i_bytes_per_line = p_pic->p_sys->p_ctx[0]->pitch;
00791         memset( p_pic->p_sys->p_buf[0], 0,
00792             p_vout->p_sys->i_bytes_per_line * p_vout->p_sys->dim.h );
00793 
00794         p_pic->p->p_pixels = p_pic->p_sys->p_buf[0];
00795         p_pic->p->i_lines = p_pic->p_sys->p_ctx[0]->dim.h;
00796         p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[0]->dim.h;
00797         p_pic->p->i_pitch = p_pic->p_sys->p_ctx[0]->pitch;
00798         p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
00799         p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
00800                                      * p_pic->p_sys->p_ctx[0]->dim.w;
00801         p_pic->i_planes = 1;
00802         break;
00803 
00804     case MODE_VIDEO_OVERLAY:
00805         if (index == 0)
00806         {
00807             p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane1;
00808             p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane1;
00809             p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane1;
00810         }
00811         else
00812         {
00813             p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane2;
00814             p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane2;
00815             p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane2;
00816         }
00817 
00818         p_pic->p_sys->p_buf[Y_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[Y_PLANE] );
00819         if( p_pic->p_sys->p_buf[Y_PLANE] == NULL )
00820         {
00821             msg_Err( p_vout, "unable to get video channel ctx ptr" );
00822             return( 1 );
00823         }
00824 
00825         switch (p_vout->p_sys->i_vc_format)
00826         {
00827             case Pg_VIDEO_FORMAT_YUV420:
00828                 p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
00829 
00830                 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
00831                 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
00832 
00833                 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
00834                     p_pic->p_sys->p_buf[V_PLANE] == NULL )
00835                 {
00836                     msg_Err( p_vout, "unable to get video channel ctx ptr" );
00837                     return( 1 );
00838                 }
00839 
00840                 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
00841                 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00842                 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00843                 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00844                 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00845                 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
00846 
00847                 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
00848                 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00849                 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00850                 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
00851                 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00852                 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
00853 
00854                 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
00855                 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00856                 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00857                 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
00858                 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00859                 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
00860 
00861                 p_pic->i_planes = 3;
00862                 break;
00863 
00864             case Pg_VIDEO_FORMAT_YV12:
00865                 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00866 
00867                 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
00868                 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
00869 
00870                 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
00871                     p_pic->p_sys->p_buf[V_PLANE] == NULL )
00872                 {
00873                     msg_Err( p_vout, "unable to get video channel ctx ptr" );
00874                     return( 1 );
00875                 }
00876 
00877                 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
00878                 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00879                 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00880                 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00881                 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00882                 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
00883 
00884                 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
00885                 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00886                 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00887                 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
00888                 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00889                 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
00890 
00891                 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
00892                 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00893                 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00894                 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
00895                 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00896                 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
00897 
00898                 p_pic->i_planes = 3;
00899                 break;
00900 
00901             case Pg_VIDEO_FORMAT_UYVY:
00902             case Pg_VIDEO_FORMAT_YUY2:
00903                 if (p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_UYVY)
00904                 {
00905                     p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
00906                 }
00907                 else
00908                 {
00909                     p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00910                 }
00911 
00912                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00913                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00914                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00915                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00916                 p_pic->p->i_pixel_pitch = 4;
00917                 p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
00918 
00919                 p_pic->i_planes = 1;
00920                 break;
00921 
00922             case Pg_VIDEO_FORMAT_RGB555:
00923                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00924                 p_vout->output.i_rmask = 0x001f;
00925                 p_vout->output.i_gmask = 0x03e0;
00926                 p_vout->output.i_bmask = 0x7c00;
00927 
00928                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00929                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00930                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00931                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00932                 p_pic->p->i_pixel_pitch = 2;
00933                 p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00934 
00935                 p_pic->i_planes = 1;
00936                 break;
00937 
00938             case Pg_VIDEO_FORMAT_RGB565:
00939                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00940                 p_vout->output.i_rmask = 0x001f;
00941                 p_vout->output.i_gmask = 0x07e0;
00942                 p_vout->output.i_bmask = 0xf800;
00943 
00944                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00945                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00946                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00947                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00948                 p_pic->p->i_pixel_pitch = 4;
00949                 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00950 
00951                 p_pic->i_planes = 1;
00952                 break;
00953 
00954             case Pg_VIDEO_FORMAT_RGB8888:
00955                 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00956                 p_vout->output.i_rmask = 0x000000ff;
00957                 p_vout->output.i_gmask = 0x0000ff00;
00958                 p_vout->output.i_bmask = 0x00ff0000;
00959 
00960                 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00961                 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00962                 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00963                 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00964                 p_pic->p->i_pixel_pitch = 4;
00965                 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00966 
00967                 p_pic->i_planes = 1;
00968                 break;
00969         }
00970 
00971 #if 0
00972     switch( p_vout->output.i_chroma )
00973     {
00974 #ifdef MODULE_NAME_IS_xvideo
00975         case VLC_FOURCC('Y','2','1','1'):
00976 
00977             p_pic->p->p_pixels = p_pic->p_sys->p_image->data
00978                                   + p_pic->p_sys->p_image->offsets[0];
00979             p_pic->p->i_lines = p_vout->output.i_height;
00980             p_pic->p->i_visible_lines = p_vout->output.i_height;
00981             /* XXX: this just looks so plain wrong... check it out ! */
00982             p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
00983             p_pic->p->i_pixel_pitch = 4;
00984             p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
00985 
00986             p_pic->i_planes = 1;
00987             break;
00988 #endif
00989 
00990 #endif
00991 
00992     default:
00993         /* This shouldn't happen ! */
00994         break;
00995     }
00996 
00997     return 0;
00998 }
00999 
01000 /*****************************************************************************
01001  * FreePicture: destroy a picture allocated with NewPicture
01002  *****************************************************************************
01003  * Destroy XImage AND associated data. If using Shm, detach shared memory
01004  * segment from server and process, then free it. The XDestroyImage manpage
01005  * says that both the image structure _and_ the data pointed to by the
01006  * image structure are freed, so no need to free p_image->data.
01007  *****************************************************************************/
01008 static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
01009 {
01010     if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
01011         p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
01012         p_pic->p_sys->p_image )
01013     {
01014         PhReleaseImage( p_pic->p_sys->p_image );
01015         free( p_pic->p_sys->p_image );
01016     }
01017     else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
01018              p_pic->p_sys->p_ctx[0] )
01019     {
01020         PhDCRelease( p_pic->p_sys->p_ctx[0] );
01021     }
01022 
01023     free( p_pic->p_sys );
01024 }
01025 
01026 
01027 static int ResizeOverlayOutput(vout_thread_t *p_vout)
01028 {
01029     int i_width, i_height, i_x, i_y;
01030     int i_ret;
01031     PgScalerProps_t props;
01032 
01033     props.size   = sizeof( props );
01034     props.format = p_vout->p_sys->i_vc_format;
01035     props.flags  = Pg_SCALER_PROP_SCALER_ENABLE |
01036                           Pg_SCALER_PROP_DOUBLE_BUFFER;
01037 
01038     /* enable chroma keying if available */
01039     if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
01040     {
01041         props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
01042     }
01043 
01044     /* set viewport position */
01045     props.viewport.ul.x = p_vout->p_sys->pos.x;
01046     props.viewport.ul.y = p_vout->p_sys->pos.y;
01047     if( !p_vout->b_fullscreen )
01048     {
01049         props.viewport.ul.x += p_vout->p_sys->frame.ul.x;
01050         props.viewport.ul.y += p_vout->p_sys->frame.ul.y;
01051     }
01052 
01053     /* set viewport dimension */
01054     vout_PlacePicture( p_vout, p_vout->p_sys->dim.w,
01055                            p_vout->p_sys->dim.h,
01056                            &i_x, &i_y, &i_width, &i_height );
01057 
01058     props.viewport.ul.x += i_x;
01059     props.viewport.ul.y += i_y;
01060     props.viewport.lr.x = i_width + props.viewport.ul.x;
01061     props.viewport.lr.y = i_height + props.viewport.ul.y;
01062 
01063     /* set source dimension */
01064     props.src_dim.w = p_vout->output.i_width;
01065     props.src_dim.h = p_vout->output.i_height;
01066 
01067     /* configure scaler channel */
01068     i_ret = PgConfigScalerChannel( p_vout->p_sys->p_channel, &props );
01069 
01070     if( i_ret == -1 )
01071     {
01072         msg_Err( p_vout, "unable to configure video channel" );
01073         return( 1 );
01074     }
01075 
01076     return ( 0 );
01077 }
01078 
01079 
01080 /*****************************************************************************
01081  * SetPalette: sets an 8 bpp palette
01082  *****************************************************************************
01083  * This function sets the palette given as an argument. It does not return
01084  * anything, but could later send information on which colors it was unable
01085  * to set.
01086  *****************************************************************************/
01087 static void SetPalette( vout_thread_t *p_vout,
01088                         uint16_t *red, uint16_t *green, uint16_t *blue )
01089 {
01090     int i;
01091 
01092     /* allocate palette */
01093     for( i = 0; i < 255; i++ )
01094     {
01095         /* kludge: colors are indexed reversely because color 255 seems
01096          * to be reserved for black even if we try to set it to white */
01097         p_vout->p_sys->p_colors[ i ] = PgRGB( red[ i ] >> 8, green[ i ] >> 8, blue[ i ] >> 8 );
01098     }
01099 }

Generated on Tue Dec 20 10:14:41 2005 for vlc-0.8.4a by  doxygen 1.4.2