00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <errno.h>
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <fcntl.h>
00033 #include <sys/ioctl.h>
00034 #include <sys/mman.h>
00035
00036 #include <vlc/vlc.h>
00037 #include <vlc/vout.h>
00038
00039 #ifdef SYS_BSD
00040 #include <sys/types.h>
00041 #endif
00042
00043
00044
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
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
00066
00067
00068
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
00127
00128
00129
00130 static int Create( vlc_object_t *p_this )
00131 {
00132 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00133
00134
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
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
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
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
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
00190
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
00217 while( I_OUTPUTPICTURES < MGA_NUM_FRAMES )
00218 {
00219 p_pic = NULL;
00220
00221
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
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
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
00257 ioctl( p_vout->p_sys->i_fd, MGA_VID_ON, 0 );
00258
00259 return( 0 );
00260 }
00261
00262
00263
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
00272 for( i_index = I_OUTPUTPICTURES ; i_index ; )
00273 {
00274 i_index--;
00275 }
00276 }
00277
00278
00279
00280
00281
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
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
00299
00300
00301
00302
00303
00304
00305 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
00306 {
00307
00308
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