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

mga.c

00001 /*****************************************************************************
00002  * mga.c : Matrox Graphic Array plugin for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2000, 2001 the VideoLAN team
00005  * $Id: mga.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Aaron Holtzman <[email protected]>
00008  *          Samuel Hocevar <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <errno.h>                                                 /* ENOMEM */
00029 #include <unistd.h>                                               /* close() */
00030 #include <stdlib.h>                                                /* free() */
00031 #include <string.h>                                            /* strerror() */
00032 #include <fcntl.h>                                                 /* open() */
00033 #include <sys/ioctl.h>                                            /* ioctl() */
00034 #include <sys/mman.h>                                          /* PROT_WRITE */
00035 
00036 #include <vlc/vlc.h>
00037 #include <vlc/vout.h>
00038 
00039 #ifdef SYS_BSD
00040 #include <sys/types.h>                                     /* typedef ushort */
00041 #endif
00042 
00043 /*****************************************************************************
00044  * Local prototypes
00045  *****************************************************************************/
00046 static int  Create    ( vlc_object_t * );
00047 static void Destroy   ( vlc_object_t * );
00048 
00049 static int  Init      ( vout_thread_t * );
00050 static void End       ( vout_thread_t * );
00051 static void Display   ( vout_thread_t *, picture_t * );
00052 
00053 static int  NewPicture     ( vout_thread_t *, picture_t * );
00054 
00055 /*****************************************************************************
00056  * Module descriptor
00057  *****************************************************************************/
00058 vlc_module_begin();
00059     set_description( _("Matrox Graphic Array video output") );
00060     set_capability( "video output", 10 );
00061     set_callbacks( Create, Destroy );
00062 vlc_module_end();
00063 
00064 /*****************************************************************************
00065  * vout_sys_t: video output MGA method descriptor
00066  *****************************************************************************
00067  * This structure is part of the video output thread descriptor.
00068  * It describes the MGA specific properties of an output thread.
00069  *****************************************************************************/
00070 #ifndef __LINUX_MGAVID_H
00071 #   define __LINUX_MGAVID_H
00072 
00073 #   define MGA_VID_CONFIG _IOR('J', 1, mga_vid_config_t)
00074 #   define MGA_VID_ON     _IO ('J', 2)
00075 #   define MGA_VID_OFF    _IO ('J', 3)
00076 #   define MGA_VID_FSEL   _IOR('J', 4, int)
00077 #   define MGA_G200 0x1234
00078 #   define MGA_G400 0x5678
00079 
00080 #   define MGA_VID_FORMAT_YV12 0x32315659
00081 #   define MGA_VID_FORMAT_IYUV (('I'<<24)|('Y'<<16)|('U'<<8)|'V')
00082 #   define MGA_VID_FORMAT_I420 (('I'<<24)|('4'<<16)|('2'<<8)|'0')
00083 #   define MGA_VID_FORMAT_YUY2 (('Y'<<24)|('U'<<16)|('Y'<<8)|'2')
00084 #   define MGA_VID_FORMAT_UYVY (('U'<<24)|('Y'<<16)|('V'<<8)|'Y')
00085 
00086 #   define MGA_VID_VERSION     0x0201
00087 
00088 #   define MGA_NUM_FRAMES      1
00089 
00090 typedef struct mga_vid_config_t
00091 {
00092     uint16_t version;
00093     uint16_t card_type;
00094     uint32_t ram_size;
00095     uint32_t src_width;
00096     uint32_t src_height;
00097     uint32_t dest_width;
00098     uint32_t dest_height;
00099     uint32_t x_org;
00100     uint32_t y_org;
00101     uint8_t  colkey_on;
00102     uint8_t  colkey_red;
00103     uint8_t  colkey_green;
00104     uint8_t  colkey_blue;
00105     uint32_t format;
00106     uint32_t frame_size;
00107     uint32_t num_frames;
00108 } mga_vid_config_t;
00109 #endif
00110 
00111 struct vout_sys_t
00112 {
00113     mga_vid_config_t    mga;
00114     int                 i_fd;
00115     byte_t *            p_video;
00116 };
00117 
00118 struct picture_sys_t
00119 {
00120     int     i_frame;
00121 };
00122 
00123 #define CEIL32(x) (((x)+31)&~31)
00124 
00125 /*****************************************************************************
00126  * Create: allocates dummy video thread output method
00127  *****************************************************************************
00128  * This function allocates and initializes a dummy vout method.
00129  *****************************************************************************/
00130 static int Create( vlc_object_t *p_this )
00131 {
00132     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00133 
00134     /* Allocate structure */
00135     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00136     if( p_vout->p_sys == NULL )
00137     {
00138         msg_Err( p_vout, "out of memory" );
00139         return( 1 );
00140     }
00141 
00142     p_vout->p_sys->i_fd = open( "/dev/mga_vid", O_RDWR );
00143     if( p_vout->p_sys->i_fd == -1 )
00144     {
00145         msg_Err( p_vout, "cannot open MGA driver /dev/mga_vid" );
00146         free( p_vout->p_sys );
00147         return( 1 );
00148     }
00149 
00150     p_vout->pf_init = Init;
00151     p_vout->pf_end = End;
00152     p_vout->pf_manage = NULL;
00153     p_vout->pf_render = NULL;
00154     p_vout->pf_display = Display;
00155 
00156     return( 0 );
00157 }
00158 
00159 /*****************************************************************************
00160  * Init: initialize dummy video thread output method
00161  *****************************************************************************/
00162 static int Init( vout_thread_t *p_vout )
00163 {
00164     int i_index;
00165     picture_t *p_pic;
00166 
00167     I_OUTPUTPICTURES = 0;
00168 
00169     /* create the MGA output */
00170     p_vout->output.i_width = p_vout->render.i_width;
00171     p_vout->output.i_height = p_vout->render.i_height;
00172     p_vout->output.i_aspect = p_vout->render.i_aspect;
00173 
00174     /* Set coordinates and aspect ratio */
00175     p_vout->p_sys->mga.src_width = CEIL32(p_vout->output.i_width);
00176     p_vout->p_sys->mga.src_height = p_vout->output.i_height;
00177     vout_PlacePicture( p_vout, 1024, 768,
00178                        &p_vout->p_sys->mga.x_org, &p_vout->p_sys->mga.y_org,
00179                        &p_vout->p_sys->mga.dest_width,
00180                        &p_vout->p_sys->mga.dest_height );
00181 
00182     /* Initialize a video buffer */
00183     p_vout->p_sys->mga.colkey_on = 0;
00184     p_vout->p_sys->mga.num_frames = MGA_NUM_FRAMES;
00185     p_vout->p_sys->mga.frame_size = CEIL32(p_vout->output.i_width)
00186                                      * p_vout->output.i_height * 2;
00187     p_vout->p_sys->mga.version = MGA_VID_VERSION;
00188 
00189     /* Assume we only do YMGA for the moment. XXX: mga_vid calls this
00190      * YV12, but it's actually some strange format with packed UV. */
00191     p_vout->output.i_chroma = VLC_FOURCC('Y','M','G','A');
00192     p_vout->p_sys->mga.format = MGA_VID_FORMAT_YV12;
00193 
00194     if( ioctl(p_vout->p_sys->i_fd, MGA_VID_CONFIG, &p_vout->p_sys->mga) )
00195     {
00196         msg_Err( p_vout, "MGA config ioctl failed" );
00197         return -1;
00198     }
00199 
00200     if( p_vout->p_sys->mga.card_type == MGA_G200 )
00201     {
00202         msg_Dbg( p_vout, "detected MGA G200 (%d MB Ram)",
00203                          p_vout->p_sys->mga.ram_size );
00204     }
00205     else
00206     {
00207         msg_Dbg( p_vout, "detected MGA G400/G450 (%d MB Ram)",
00208                          p_vout->p_sys->mga.ram_size );
00209     }
00210 
00211     p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->mga.frame_size
00212                                        * MGA_NUM_FRAMES,
00213                                    PROT_WRITE, MAP_SHARED,
00214                                    p_vout->p_sys->i_fd, 0 );
00215 
00216     /* Try to initialize up to MGA_NUM_FRAMES direct buffers */
00217     while( I_OUTPUTPICTURES < MGA_NUM_FRAMES )
00218     {
00219         p_pic = NULL;
00220 
00221         /* Find an empty picture slot */
00222         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00223         {
00224             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00225             {
00226                 p_pic = p_vout->p_picture + i_index;
00227                 break;
00228             }
00229         }
00230 
00231         /* Allocate the picture */
00232         if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
00233         {
00234             break;
00235         }
00236 
00237         p_pic->i_status = DESTROYED_PICTURE;
00238         p_pic->i_type   = DIRECT_PICTURE;
00239 
00240         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00241 
00242         I_OUTPUTPICTURES++;
00243     }
00244 
00245     /* Blank the windows */
00246     for( i_index = 0; i_index < I_OUTPUTPICTURES; i_index++ )
00247     {
00248         memset( p_vout->p_sys->p_video
00249                  + p_vout->p_sys->mga.frame_size * i_index,
00250                 0x00, p_vout->p_sys->mga.frame_size / 2 );
00251         memset( p_vout->p_sys->p_video
00252                  + p_vout->p_sys->mga.frame_size * ( 2*i_index + 1 ) / 2,
00253                 0x80, p_vout->p_sys->mga.frame_size / 2 );
00254     }
00255 
00256     /* Display the image */
00257     ioctl( p_vout->p_sys->i_fd, MGA_VID_ON, 0 );
00258 
00259     return( 0 );
00260 }
00261 
00262 /*****************************************************************************
00263  * End: terminate dummy video thread output method
00264  *****************************************************************************/
00265 static void End( vout_thread_t *p_vout )
00266 {
00267     int i_index;
00268 
00269     ioctl( p_vout->p_sys->i_fd, MGA_VID_OFF, 0 );
00270 
00271     /* Free the output buffers we allocated */
00272     for( i_index = I_OUTPUTPICTURES ; i_index ; )
00273     {
00274         i_index--;
00275     }
00276 }
00277 
00278 /*****************************************************************************
00279  * Destroy: destroy dummy video thread output method
00280  *****************************************************************************
00281  * Terminate an output method created by DummyCreateOutputMethod
00282  *****************************************************************************/
00283 static void Destroy( vlc_object_t *p_this )
00284 {
00285     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00286     close( p_vout->p_sys->i_fd );
00287     free( p_vout->p_sys );
00288 }
00289 
00290 /*****************************************************************************
00291  * Display: displays previously rendered output
00292  *****************************************************************************/
00293 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00294 {
00295     ioctl( p_vout->p_sys->i_fd, MGA_VID_FSEL, &p_pic->p_sys->i_frame );
00296 }
00297 
00298 /* Following functions are local */
00299 
00300 /*****************************************************************************
00301  * NewPicture: allocate a picture
00302  *****************************************************************************
00303  * Returns 0 on success, -1 otherwise
00304  *****************************************************************************/
00305 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
00306 {
00307     /* We know the chroma, allocate a buffer which will be used
00308      * directly by the decoder */
00309     p_pic->p_data = p_vout->p_sys->p_video + I_OUTPUTPICTURES
00310                                               * p_vout->p_sys->mga.frame_size;
00311 
00312     p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00313 
00314     if( p_pic->p_sys == NULL )
00315     {
00316         return -1;
00317     }
00318 
00319     p_pic->Y_PIXELS = p_pic->p_data;
00320     p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
00321     p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
00322     p_pic->p[Y_PLANE].i_pitch = CEIL32( p_vout->output.i_width );
00323     p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00324     p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width;
00325 
00326     p_pic->U_PIXELS = p_pic->p_data + p_vout->p_sys->mga.frame_size * 2/4;
00327     p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
00328     p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
00329     p_pic->p[U_PLANE].i_pitch = CEIL32( p_vout->output.i_width ) / 2;
00330     p_pic->p[U_PLANE].i_pixel_pitch = 1;
00331     p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
00332 
00333     p_pic->V_PIXELS = p_pic->p_data + p_vout->p_sys->mga.frame_size * 3/4;
00334     p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
00335     p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
00336     p_pic->p[V_PLANE].i_pitch = CEIL32( p_vout->output.i_width ) / 2;
00337     p_pic->p[V_PLANE].i_pixel_pitch = 1;
00338     p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
00339 
00340     p_pic->p_sys->i_frame = I_OUTPUTPICTURES;
00341 
00342     p_pic->i_planes = 3;
00343 
00344     return 0;
00345 }
00346 

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