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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042
00043 #include <vlc/vlc.h>
00044 #include <vlc/vout.h>
00045 #include <vlc/intf.h>
00046 #include <snapshot.h>
00047
00048
00049
00050
00051 static int Create ( vlc_object_t * );
00052 static void Destroy ( vlc_object_t * );
00053
00054 static int Init ( vout_thread_t * );
00055 static void Display ( vout_thread_t *, picture_t * );
00056
00057
00058
00059
00060 #define WIDTH_TEXT N_( "snapshot width" )
00061 #define WIDTH_LONGTEXT N_( "Set the width of the snapshot image." )
00062
00063 #define HEIGHT_TEXT N_( "snapshot height" )
00064 #define HEIGHT_LONGTEXT N_( "Set the height of the snapshot image." )
00065
00066 #define CHROMA_TEXT N_( "chroma" )
00067 #define CHROMA_LONGTEXT N_( "Set the desired chroma for the snapshot image (a 4 character string)." )
00068
00069 #define CACHE_TEXT N_( "cache size (number of images)" )
00070 #define CACHE_LONGTEXT N_( "Set the cache size (number of images to keep)." )
00071
00072
00073 vlc_module_begin( );
00074 set_description( _( "snapshot module" ) );
00075 set_shortname( N_("Snapshot") );
00076
00077 set_category( CAT_VIDEO );
00078 set_subcategory( SUBCAT_VIDEO_VOUT );
00079 set_capability( "video output", 1 );
00080
00081 add_integer( "snapshot-width", 320, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, VLC_FALSE );
00082 add_integer( "snapshot-height", 200, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT, VLC_FALSE );
00083 add_string( "snapshot-chroma", "RV32", NULL, CHROMA_TEXT, CHROMA_LONGTEXT, VLC_TRUE );
00084 add_integer( "snapshot-cache-size", 50, NULL, CACHE_TEXT, CACHE_LONGTEXT, VLC_TRUE );
00085
00086 set_callbacks( Create, Destroy );
00087 vlc_module_end();
00088
00089
00090
00091
00092 struct vout_sys_t
00093 {
00094 snapshot_t **p_list;
00095 int i_index;
00096 int i_size;
00097 int i_datasize;
00098 input_thread_t *p_input;
00099 };
00100
00101
00102
00103
00104
00105
00106 static int Create( vlc_object_t *p_this )
00107 {
00108 vout_thread_t *p_vout = ( vout_thread_t * )p_this;
00109
00110
00111 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00112 if( ! p_vout->p_sys )
00113 return VLC_ENOMEM;
00114
00115 var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER );
00116 var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
00117 var_Create( p_vout, "snapshot-datasize", VLC_VAR_INTEGER );
00118 var_Create( p_vout, "snapshot-cache-size", VLC_VAR_INTEGER );
00119 var_Create( p_vout, "snapshot-list-pointer", VLC_VAR_ADDRESS );
00120
00121 p_vout->pf_init = Init;
00122 p_vout->pf_end = NULL;
00123 p_vout->pf_manage = NULL;
00124 p_vout->pf_render = NULL;
00125 p_vout->pf_display = Display;
00126
00127 return VLC_SUCCESS;
00128 }
00129
00130
00131
00132
00133 static int Init( vout_thread_t *p_vout )
00134 {
00135 int i_index;
00136 picture_t *p_pic;
00137 vlc_value_t val;
00138 char* psz_chroma;
00139 int i_chroma;
00140 int i_width;
00141 int i_height;
00142 int i_datasize;
00143
00144 i_width = config_GetInt( p_vout, "snapshot-width" );
00145 i_height = config_GetInt( p_vout, "snapshot-height" );
00146
00147 psz_chroma = config_GetPsz( p_vout, "snapshot-chroma" );
00148 if( psz_chroma )
00149 {
00150 if( strlen( psz_chroma ) < 4 )
00151 {
00152 msg_Err( p_vout, "snapshot-chroma should be 4 characters long." );
00153 return VLC_EGENERIC;
00154 }
00155 i_chroma = VLC_FOURCC( psz_chroma[0], psz_chroma[1],
00156 psz_chroma[2], psz_chroma[3] );
00157 free( psz_chroma );
00158 }
00159 else
00160 {
00161 msg_Err( p_vout, "Cannot find chroma information." );
00162 return VLC_EGENERIC;
00163 }
00164
00165 I_OUTPUTPICTURES = 0;
00166
00167
00168 p_vout->output.i_chroma = i_chroma;
00169 p_vout->output.pf_setpalette = NULL;
00170 p_vout->output.i_width = i_width;
00171 p_vout->output.i_height = i_height;
00172 p_vout->output.i_aspect = p_vout->output.i_width
00173 * VOUT_ASPECT_FACTOR / p_vout->output.i_height;
00174
00175
00176
00177 switch( i_chroma )
00178 {
00179 case VLC_FOURCC( 'R','V','1','5' ):
00180 p_vout->output.i_rmask = 0x001f;
00181 p_vout->output.i_gmask = 0x03e0;
00182 p_vout->output.i_bmask = 0x7c00;
00183 break;
00184
00185 case VLC_FOURCC( 'R','V','1','6' ):
00186 p_vout->output.i_rmask = 0x001f;
00187 p_vout->output.i_gmask = 0x07e0;
00188 p_vout->output.i_bmask = 0xf800;
00189 break;
00190
00191 case VLC_FOURCC( 'R','V','2','4' ):
00192 p_vout->output.i_rmask = 0xff0000;
00193 p_vout->output.i_gmask = 0x00ff00;
00194 p_vout->output.i_bmask = 0x0000ff;
00195 break;
00196
00197 case VLC_FOURCC( 'R','V','3','2' ):
00198 p_vout->output.i_rmask = 0xff0000;
00199 p_vout->output.i_gmask = 0x00ff00;
00200 p_vout->output.i_bmask = 0x0000ff;
00201 break;
00202 }
00203
00204
00205 p_pic = NULL;
00206
00207
00208 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00209 {
00210 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00211 {
00212 p_pic = p_vout->p_picture + i_index;
00213 break;
00214 }
00215 }
00216
00217
00218 if( p_pic == NULL )
00219 {
00220 return VLC_SUCCESS;
00221 }
00222
00223 vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma,
00224 p_vout->output.i_width, p_vout->output.i_height,
00225 p_vout->output.i_aspect );
00226
00227 if( p_pic->i_planes == 0 )
00228 {
00229 return VLC_EGENERIC;
00230 }
00231
00232 p_pic->i_status = DESTROYED_PICTURE;
00233 p_pic->i_type = DIRECT_PICTURE;
00234
00235 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00236
00237 I_OUTPUTPICTURES++;
00238
00239
00240
00241 i_datasize = i_width * i_height * p_pic->p->i_pixel_pitch;
00242
00243 p_vout->p_sys->i_datasize = i_datasize;
00244 p_vout->p_sys->i_index = 0;
00245 p_vout->p_sys->i_size = config_GetInt( p_vout, "snapshot-cache-size" );
00246
00247 if( p_vout->p_sys->i_size < 2 )
00248 {
00249 msg_Err( p_vout, "snapshot-cache-size must be at least 1." );
00250 return VLC_EGENERIC;
00251 }
00252
00253 p_vout->p_sys->p_list = malloc( p_vout->p_sys->i_size * sizeof( snapshot_t * ) );
00254
00255 if( p_vout->p_sys->p_list == NULL )
00256 return VLC_ENOMEM;
00257
00258
00259 for( i_index = 0; i_index < p_vout->p_sys->i_size; i_index++ )
00260 {
00261 snapshot_t *p_snapshot = malloc( sizeof( snapshot_t ) );
00262
00263 if( p_snapshot == NULL )
00264 return VLC_ENOMEM;
00265
00266 p_snapshot->i_width = i_width;
00267 p_snapshot->i_height = i_height;
00268 p_snapshot->i_datasize = i_datasize;
00269 p_snapshot->date = 0;
00270 p_snapshot->p_data = ( char* ) malloc( i_datasize );
00271 if( p_snapshot->p_data == NULL )
00272 return VLC_ENOMEM;
00273 p_vout->p_sys->p_list[i_index] = p_snapshot;
00274 }
00275
00276 val.i_int = i_width;
00277 var_Set( p_vout, "snapshot-width", val );
00278 val.i_int = i_height;
00279 var_Set( p_vout, "snapshot-height", val );
00280 val.i_int = i_datasize;
00281 var_Set( p_vout, "snapshot-datasize", val );
00282
00283 val.i_int = p_vout->p_sys->i_size;
00284 var_Set( p_vout, "snapshot-cache-size", val );
00285
00286 val.p_address = p_vout->p_sys->p_list;
00287 var_Set( p_vout, "snapshot-list-pointer", val );
00288
00289
00290 p_vout->p_sys->p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT,
00291 FIND_PARENT );
00292
00293 if( !p_vout->p_sys->p_input )
00294 return VLC_ENOOBJ;
00295
00296 if( var_Create( p_vout->p_sys->p_input, "snapshot-id", VLC_VAR_INTEGER ) )
00297 {
00298 msg_Err( p_vout, "Cannot create snapshot-id variable in p_input (%d).",
00299 p_vout->p_sys->p_input->i_object_id );
00300 return VLC_EGENERIC;
00301 }
00302
00303
00304 val.i_int = p_vout->i_object_id;
00305
00306 if( var_Set( p_vout->p_sys->p_input, "snapshot-id", val ) )
00307 {
00308 msg_Err( p_vout, "Cannot register snapshot-id in p_input (%d).",
00309 p_vout->p_sys->p_input->i_object_id );
00310 return VLC_EGENERIC;
00311 }
00312
00313 return VLC_SUCCESS;
00314 }
00315
00316
00317
00318
00319
00320
00321 static void Destroy( vlc_object_t *p_this )
00322 {
00323 vout_thread_t *p_vout = ( vout_thread_t * )p_this;
00324 vlc_object_t *p_vlc;
00325 int i_index;
00326
00327 vlc_object_release( p_vout->p_sys->p_input );
00328 var_Destroy( p_this, "snapshot-width" );
00329 var_Destroy( p_this, "snapshot-height" );
00330 var_Destroy( p_this, "snapshot-datasize" );
00331
00332 p_vlc = vlc_object_find( p_this, VLC_OBJECT_ROOT, FIND_PARENT );
00333 if( p_vlc )
00334 {
00335
00336
00337 var_Destroy( p_this->p_libvlc, "snapshot-id" );
00338 vlc_object_release( p_vlc );
00339 }
00340
00341 for( i_index = 0 ; i_index < p_vout->p_sys->i_size ; i_index++ )
00342 {
00343 free( p_vout->p_sys->p_list[ i_index ]->p_data );
00344 }
00345 free( p_vout->p_sys->p_list );
00346
00347 free( p_vout->p_sys );
00348 }
00349
00350
00351 static mtime_t snapshot_GetMovietime( vout_thread_t *p_vout )
00352 {
00353 input_thread_t* p_input;
00354 vlc_value_t val;
00355 mtime_t i_result;
00356
00357 p_input = p_vout->p_sys->p_input;
00358 if( !p_input )
00359 return 0;
00360
00361 var_Get( p_input, "time", &val );
00362
00363 i_result = val.i_time - p_input->i_pts_delay;
00364
00365 return( i_result / 1000 );
00366 }
00367
00368
00369
00370
00371
00372
00373 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00374 {
00375 int i_index;
00376 mtime_t i_date;
00377
00378 i_index = p_vout->p_sys->i_index;
00379
00380 p_vout->p_vlc->pf_memcpy( p_vout->p_sys->p_list[i_index]->p_data,
00381 p_pic->p->p_pixels,
00382 p_vout->p_sys->i_datasize );
00383
00384 i_date = snapshot_GetMovietime( p_vout );
00385
00386 p_vout->p_sys->p_list[i_index]->date = i_date;
00387
00388 i_index++;
00389
00390 if( i_index >= p_vout->p_sys->i_size )
00391 {
00392 i_index = 0;
00393 }
00394
00395 p_vout->p_sys->i_index = i_index;
00396 }
00397