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 #include <errno.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include <vlc/vlc.h>
00034 #include <vlc/intf.h>
00035 #include <vlc/vout.h>
00036 #include <vlc/aout.h>
00037
00038 #include <sys/types.h>
00039 #ifndef WIN32
00040 # include <netinet/in.h>
00041 #endif
00042
00043 #include SDL_INCLUDE_FILE
00044
00045
00046 #define SDL_MAX_DIRECTBUFFERS 1
00047 #define SDL_DEFAULT_BPP 16
00048
00049
00050
00051
00052
00053
00054
00055 struct vout_sys_t
00056 {
00057 SDL_Surface * p_display;
00058
00059 int i_width;
00060 int i_height;
00061
00062
00063 SDL_Overlay * p_overlay;
00064
00065
00066 int i_surfaces;
00067
00068 vlc_bool_t b_cursor;
00069 vlc_bool_t b_cursor_autohidden;
00070 mtime_t i_lastmoved;
00071 mtime_t i_lastpressed;
00072 };
00073
00074
00075
00076
00077
00078
00079
00080 struct picture_sys_t
00081 {
00082 SDL_Overlay *p_overlay;
00083 };
00084
00085
00086
00087
00088 static int Open ( vlc_object_t * );
00089 static void Close ( vlc_object_t * );
00090 static int Init ( vout_thread_t * );
00091 static void End ( vout_thread_t * );
00092 static int Manage ( vout_thread_t * );
00093 static void Display ( vout_thread_t *, picture_t * );
00094
00095 static int OpenDisplay ( vout_thread_t * );
00096 static void CloseDisplay ( vout_thread_t * );
00097 static int NewPicture ( vout_thread_t *, picture_t * );
00098 static void SetPalette ( vout_thread_t *,
00099 uint16_t *, uint16_t *, uint16_t * );
00100
00101
00102
00103
00104 vlc_module_begin();
00105 set_shortname( "SDL" );
00106 set_category( CAT_VIDEO );
00107 set_subcategory( SUBCAT_VIDEO_VOUT );
00108 set_description( _("Simple DirectMedia Layer video output") );
00109 set_capability( "video output", 60 );
00110 add_shortcut( "sdl" );
00111 set_callbacks( Open, Close );
00112
00113 var_Create( p_module->p_libvlc, "sdl", VLC_VAR_MUTEX );
00114 #if defined( __i386__ ) || defined( __x86_64__ )
00115
00116 linked_with_a_crap_library_which_uses_atexit();
00117 #endif
00118 vlc_module_end();
00119
00120
00121
00122
00123
00124
00125
00126
00127 static int Open ( vlc_object_t *p_this )
00128 {
00129 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00130 vlc_value_t lockval;
00131
00132 #ifdef HAVE_SETENV
00133 char *psz_method;
00134 #endif
00135
00136 var_Get( p_this->p_libvlc, "sdl", &lockval );
00137 vlc_mutex_lock( lockval.p_address );
00138
00139 if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
00140 {
00141 vlc_mutex_unlock( lockval.p_address );
00142 return VLC_EGENERIC;
00143 }
00144
00145
00146 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00147 if( p_vout->p_sys == NULL )
00148 {
00149 msg_Err( p_vout, "out of memory" );
00150 vlc_mutex_unlock( lockval.p_address );
00151 return VLC_ENOMEM;
00152 }
00153
00154 p_vout->pf_init = Init;
00155 p_vout->pf_end = End;
00156 p_vout->pf_manage = Manage;
00157 p_vout->pf_render = NULL;
00158 p_vout->pf_display = Display;
00159
00160 #ifdef HAVE_SETENV
00161 psz_method = config_GetPsz( p_vout, "vout" );
00162 if( psz_method )
00163 {
00164 while( *psz_method && *psz_method != ':' )
00165 {
00166 psz_method++;
00167 }
00168
00169 if( *psz_method )
00170 {
00171 setenv( "SDL_VIDEODRIVER", psz_method + 1, 1 );
00172 }
00173 }
00174 #endif
00175
00176
00177 if( SDL_Init( SDL_INIT_VIDEO
00178 #ifndef WIN32
00179
00180 | SDL_INIT_EVENTTHREAD
00181 #endif
00182 #ifdef DEBUG
00183
00184
00185 | SDL_INIT_NOPARACHUTE
00186 #endif
00187 ) < 0 )
00188 {
00189 msg_Err( p_vout, "cannot initialize SDL (%s)", SDL_GetError() );
00190 free( p_vout->p_sys );
00191 vlc_mutex_unlock( lockval.p_address );
00192 return VLC_EGENERIC;
00193 }
00194
00195 vlc_mutex_unlock( lockval.p_address );
00196
00197 p_vout->p_sys->b_cursor = 1;
00198 p_vout->p_sys->b_cursor_autohidden = 0;
00199 p_vout->p_sys->i_lastmoved = mdate();
00200
00201 if( OpenDisplay( p_vout ) )
00202 {
00203 msg_Err( p_vout, "cannot set up SDL (%s)", SDL_GetError() );
00204 SDL_QuitSubSystem( SDL_INIT_VIDEO );
00205 free( p_vout->p_sys );
00206 return VLC_EGENERIC;
00207 }
00208
00209 return VLC_SUCCESS;
00210 }
00211
00212
00213
00214
00215
00216
00217 static int Init( vout_thread_t *p_vout )
00218 {
00219 int i_index;
00220 picture_t *p_pic;
00221
00222 p_vout->p_sys->i_surfaces = 0;
00223
00224 I_OUTPUTPICTURES = 0;
00225
00226
00227 if( p_vout->p_sys->p_overlay == NULL )
00228 {
00229
00230 p_vout->output.i_width = p_vout->p_sys->i_width;
00231 p_vout->output.i_height = p_vout->p_sys->i_height;
00232 p_vout->output.i_aspect = p_vout->output.i_width
00233 * VOUT_ASPECT_FACTOR
00234 / p_vout->output.i_height;
00235 }
00236 else
00237 {
00238
00239
00240 p_vout->output.i_width = p_vout->render.i_width;
00241 p_vout->output.i_height = p_vout->render.i_height;
00242 p_vout->output.i_aspect = p_vout->render.i_aspect;
00243 }
00244
00245
00246 while( I_OUTPUTPICTURES < SDL_MAX_DIRECTBUFFERS )
00247 {
00248 p_pic = NULL;
00249
00250
00251 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00252 {
00253 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00254 {
00255 p_pic = p_vout->p_picture + i_index;
00256 break;
00257 }
00258 }
00259
00260
00261 if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
00262 {
00263 break;
00264 }
00265
00266 p_pic->i_status = DESTROYED_PICTURE;
00267 p_pic->i_type = DIRECT_PICTURE;
00268
00269 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00270
00271 I_OUTPUTPICTURES++;
00272 }
00273
00274 return VLC_SUCCESS;
00275 }
00276
00277
00278
00279
00280
00281
00282 static void End( vout_thread_t *p_vout )
00283 {
00284 int i_index;
00285
00286
00287 for( i_index = I_OUTPUTPICTURES ; i_index ; )
00288 {
00289 i_index--;
00290 if( p_vout->p_sys->p_overlay == NULL )
00291 {
00292
00293 }
00294 else
00295 {
00296 SDL_UnlockYUVOverlay(
00297 PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
00298 SDL_FreeYUVOverlay(
00299 PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
00300 }
00301 free( PP_OUTPUTPICTURE[ i_index ]->p_sys );
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310 static void Close ( vlc_object_t *p_this )
00311 {
00312 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00313
00314 CloseDisplay( p_vout );
00315 SDL_QuitSubSystem( SDL_INIT_VIDEO );
00316
00317 free( p_vout->p_sys );
00318 }
00319
00320
00321
00322
00323
00324
00325
00326 static int Manage( vout_thread_t *p_vout )
00327 {
00328 SDL_Event event;
00329 vlc_value_t val;
00330 int i_width, i_height, i_x, i_y;
00331
00332
00333 while( SDL_PollEvent(&event) )
00334 {
00335 switch( event.type )
00336 {
00337 case SDL_VIDEORESIZE:
00338
00339 p_vout->i_changes |= VOUT_SIZE_CHANGE;
00340 p_vout->i_window_width = p_vout->p_sys->i_width = event.resize.w;
00341 p_vout->i_window_height = p_vout->p_sys->i_height = event.resize.h;
00342 break;
00343
00344 case SDL_MOUSEMOTION:
00345 vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
00346 p_vout->p_sys->i_height,
00347 &i_x, &i_y, &i_width, &i_height );
00348
00349 val.i_int = ( event.motion.x - i_x )
00350 * p_vout->render.i_width / i_width;
00351 var_Set( p_vout, "mouse-x", val );
00352 val.i_int = ( event.motion.y - i_y )
00353 * p_vout->render.i_height / i_height;
00354 var_Set( p_vout, "mouse-y", val );
00355
00356 val.b_bool = VLC_TRUE;
00357 var_Set( p_vout, "mouse-moved", val );
00358
00359 if( p_vout->p_sys->b_cursor &&
00360 (abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
00361 {
00362 if( p_vout->p_sys->b_cursor_autohidden )
00363 {
00364 p_vout->p_sys->b_cursor_autohidden = 0;
00365 SDL_ShowCursor( 1 );
00366 }
00367 else
00368 {
00369 p_vout->p_sys->i_lastmoved = mdate();
00370 }
00371 }
00372 break;
00373
00374 case SDL_MOUSEBUTTONUP:
00375 switch( event.button.button )
00376 {
00377 case SDL_BUTTON_LEFT:
00378 val.b_bool = VLC_TRUE;
00379 var_Set( p_vout, "mouse-clicked", val );
00380 break;
00381
00382 case SDL_BUTTON_RIGHT:
00383 {
00384 intf_thread_t *p_intf;
00385 p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
00386 FIND_ANYWHERE );
00387 if( p_intf )
00388 {
00389 p_intf->b_menu_change = 1;
00390 vlc_object_release( p_intf );
00391 }
00392 }
00393 break;
00394 }
00395 break;
00396
00397 case SDL_MOUSEBUTTONDOWN:
00398 switch( event.button.button )
00399 {
00400 case SDL_BUTTON_LEFT:
00401
00402
00403
00404
00405 if( ( mdate() - p_vout->p_sys->i_lastpressed ) < 300000 )
00406 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00407
00408 p_vout->p_sys->i_lastpressed = mdate();
00409 break;
00410
00411 case 4:
00412 break;
00413
00414 case 5:
00415 break;
00416 }
00417 break;
00418
00419 case SDL_QUIT:
00420 p_vout->p_vlc->b_die = 1;
00421 break;
00422
00423 case SDL_KEYDOWN:
00424
00425 switch( event.key.keysym.sym )
00426 {
00427 case SDLK_ESCAPE:
00428 if( p_vout->b_fullscreen )
00429 {
00430 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00431 }
00432 else
00433 {
00434 p_vout->p_vlc->b_die = 1;
00435 }
00436 break;
00437
00438 case SDLK_q:
00439 p_vout->p_vlc->b_die = 1;
00440 break;
00441
00442 case SDLK_f:
00443 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00444 break;
00445
00446 case SDLK_c:
00447 p_vout->b_grayscale = ! p_vout->b_grayscale;
00448 p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
00449 break;
00450
00451 case SDLK_i:
00452 p_vout->b_info = ! p_vout->b_info;
00453 p_vout->i_changes |= VOUT_INFO_CHANGE;
00454 break;
00455
00456 case SDLK_s:
00457 p_vout->b_scale = ! p_vout->b_scale;
00458 p_vout->i_changes |= VOUT_SCALE_CHANGE;
00459 break;
00460
00461 case SDLK_SPACE:
00462 p_vout->b_interface = ! p_vout->b_interface;
00463 p_vout->i_changes |= VOUT_INTF_CHANGE;
00464 break;
00465
00466 case SDLK_MENU:
00467 {
00468 intf_thread_t *p_intf;
00469 p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
00470 FIND_ANYWHERE );
00471 if( p_intf != NULL )
00472 {
00473 p_intf->b_menu_change = 1;
00474 vlc_object_release( p_intf );
00475 }
00476 }
00477 break;
00478
00479 case SDLK_LEFT:
00480 break;
00481
00482 case SDLK_RIGHT:
00483 break;
00484
00485 case SDLK_UP:
00486 break;
00487
00488 case SDLK_DOWN:
00489 break;
00490
00491 case SDLK_b:
00492 {
00493 audio_volume_t i_volume;
00494 if ( !aout_VolumeDown( p_vout, 1, &i_volume ) )
00495 {
00496 msg_Dbg( p_vout, "audio volume is now %d", i_volume );
00497 }
00498 else
00499 {
00500 msg_Dbg( p_vout, "audio volume: operation not supported" );
00501 }
00502 }
00503 break;
00504
00505 case SDLK_n:
00506 {
00507 audio_volume_t i_volume;
00508 if ( !aout_VolumeUp( p_vout, 1, &i_volume ) )
00509 {
00510 msg_Dbg( p_vout, "audio volume is now %d", i_volume );
00511 }
00512 else
00513 {
00514 msg_Dbg( p_vout, "audio volume: operation not supported" );
00515 }
00516 }
00517 break;
00518
00519 default:
00520 break;
00521 }
00522 break;
00523
00524 default:
00525 break;
00526 }
00527 }
00528
00529
00530 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
00531 {
00532 p_vout->b_fullscreen = ! p_vout->b_fullscreen;
00533
00534 p_vout->p_sys->b_cursor_autohidden = 0;
00535 SDL_ShowCursor( p_vout->p_sys->b_cursor &&
00536 ! p_vout->p_sys->b_cursor_autohidden );
00537
00538 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00539 p_vout->i_changes |= VOUT_SIZE_CHANGE;
00540 }
00541
00542
00543
00544
00545 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
00546 {
00547 msg_Dbg( p_vout, "video display resized (%dx%d)",
00548 p_vout->p_sys->i_width, p_vout->p_sys->i_height );
00549
00550 CloseDisplay( p_vout );
00551 OpenDisplay( p_vout );
00552
00553
00554
00555 if( p_vout->p_sys->p_overlay != NULL )
00556 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
00557
00558 }
00559
00560
00561 if( ! p_vout->p_sys->b_cursor_autohidden &&
00562 ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
00563 {
00564
00565 p_vout->p_sys->b_cursor_autohidden = 1;
00566 SDL_ShowCursor( 0 );
00567 }
00568
00569 return VLC_SUCCESS;
00570 }
00571
00572
00573
00574
00575
00576
00577 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00578 {
00579 int x, y, w, h;
00580 SDL_Rect disp;
00581
00582 vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
00583 &x, &y, &w, &h );
00584 disp.x = x;
00585 disp.y = y;
00586 disp.w = w;
00587 disp.h = h;
00588
00589 if( p_vout->p_sys->p_overlay == NULL )
00590 {
00591
00592 SDL_Flip( p_vout->p_sys->p_display );
00593 }
00594 else
00595 {
00596
00597 SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
00598 SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
00599 SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
00600 }
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 static int OpenDisplay( vout_thread_t *p_vout )
00612 {
00613 uint32_t i_flags;
00614 int i_bpp;
00615
00616
00617 uint32_t i_sdl_chroma;
00618
00619
00620 p_vout->p_sys->i_width = p_vout->b_fullscreen ? p_vout->output.i_width :
00621 p_vout->i_window_width;
00622 p_vout->p_sys->i_height = p_vout->b_fullscreen ? p_vout->output.i_height :
00623 p_vout->i_window_height;
00624
00625
00626 i_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
00627 i_flags |= p_vout->b_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
00628
00629 i_bpp = SDL_VideoModeOK( p_vout->p_sys->i_width, p_vout->p_sys->i_height,
00630 SDL_DEFAULT_BPP, i_flags );
00631 if( i_bpp == 0 )
00632 {
00633 msg_Err( p_vout, "no video mode available" );
00634 return VLC_EGENERIC;
00635 }
00636
00637 p_vout->p_sys->p_display = SDL_SetVideoMode( p_vout->p_sys->i_width,
00638 p_vout->p_sys->i_height,
00639 i_bpp, i_flags );
00640
00641 if( p_vout->p_sys->p_display == NULL )
00642 {
00643 msg_Err( p_vout, "cannot set video mode" );
00644 return VLC_EGENERIC;
00645 }
00646
00647 SDL_LockSurface( p_vout->p_sys->p_display );
00648
00649
00650 switch( p_vout->render.i_chroma )
00651 {
00652 case VLC_FOURCC('Y','U','Y','2'):
00653 case VLC_FOURCC('Y','U','N','V'):
00654 p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00655 i_sdl_chroma = SDL_YUY2_OVERLAY;
00656 break;
00657 case VLC_FOURCC('U','Y','V','Y'):
00658 case VLC_FOURCC('U','Y','N','V'):
00659 case VLC_FOURCC('Y','4','2','2'):
00660 p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
00661 i_sdl_chroma = SDL_UYVY_OVERLAY;
00662 break;
00663 case VLC_FOURCC('Y','V','Y','U'):
00664 p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
00665 i_sdl_chroma = SDL_YVYU_OVERLAY;
00666 break;
00667 case VLC_FOURCC('Y','V','1','2'):
00668 case VLC_FOURCC('I','4','2','0'):
00669 case VLC_FOURCC('I','Y','U','V'):
00670 default:
00671 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00672 i_sdl_chroma = SDL_YV12_OVERLAY;
00673 break;
00674 }
00675
00676 p_vout->p_sys->p_overlay =
00677 SDL_CreateYUVOverlay( 32, 32, i_sdl_chroma, p_vout->p_sys->p_display );
00678
00679
00680
00681
00682 if( p_vout->p_sys->p_overlay == NULL )
00683 {
00684 p_vout->output.i_chroma = VLC_FOURCC('I','Y','U','V');
00685 p_vout->p_sys->p_overlay =
00686 SDL_CreateYUVOverlay( 32, 32, SDL_IYUV_OVERLAY,
00687 p_vout->p_sys->p_display );
00688 }
00689
00690 if( p_vout->p_sys->p_overlay == NULL )
00691 {
00692 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00693 p_vout->p_sys->p_overlay =
00694 SDL_CreateYUVOverlay( 32, 32, SDL_YV12_OVERLAY,
00695 p_vout->p_sys->p_display );
00696 }
00697
00698 if( p_vout->p_sys->p_overlay == NULL )
00699 {
00700 p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00701 p_vout->p_sys->p_overlay =
00702 SDL_CreateYUVOverlay( 32, 32, SDL_YUY2_OVERLAY,
00703 p_vout->p_sys->p_display );
00704 }
00705
00706 if( p_vout->p_sys->p_overlay == NULL )
00707 {
00708 msg_Warn( p_vout, "no SDL overlay for 0x%.8x (%4.4s)",
00709 p_vout->render.i_chroma, (char*)&p_vout->render.i_chroma );
00710
00711 switch( p_vout->p_sys->p_display->format->BitsPerPixel )
00712 {
00713 case 8:
00714 p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
00715 p_vout->output.pf_setpalette = SetPalette;
00716 break;
00717 case 15:
00718 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00719 break;
00720 case 16:
00721 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00722 break;
00723 case 24:
00724 p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
00725 break;
00726 case 32:
00727 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00728 break;
00729 default:
00730 msg_Err( p_vout, "unknown screen depth %i",
00731 p_vout->p_sys->p_display->format->BitsPerPixel );
00732 SDL_UnlockSurface( p_vout->p_sys->p_display );
00733 SDL_FreeSurface( p_vout->p_sys->p_display );
00734 return VLC_EGENERIC;
00735 }
00736
00737 p_vout->output.i_rmask = p_vout->p_sys->p_display->format->Rmask;
00738 p_vout->output.i_gmask = p_vout->p_sys->p_display->format->Gmask;
00739 p_vout->output.i_bmask = p_vout->p_sys->p_display->format->Bmask;
00740
00741 SDL_WM_SetCaption( VOUT_TITLE " (software RGB SDL output)",
00742 VOUT_TITLE " (software RGB SDL output)" );
00743 }
00744 else
00745 {
00746 if( p_vout->p_sys->p_overlay->hw_overlay )
00747 {
00748 SDL_WM_SetCaption( VOUT_TITLE " (hardware YUV SDL output)",
00749 VOUT_TITLE " (hardware YUV SDL output)" );
00750 }
00751 else
00752 {
00753 SDL_WM_SetCaption( VOUT_TITLE " (software YUV SDL output)",
00754 VOUT_TITLE " (software YUV SDL output)" );
00755 }
00756 }
00757
00758 SDL_EventState( SDL_KEYUP, SDL_IGNORE );
00759
00760 return VLC_SUCCESS;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769 static void CloseDisplay( vout_thread_t *p_vout )
00770 {
00771 SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
00772 SDL_UnlockSurface ( p_vout->p_sys->p_display );
00773 SDL_FreeSurface( p_vout->p_sys->p_display );
00774 }
00775
00776
00777
00778
00779
00780
00781 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
00782 {
00783 int i_width = p_vout->output.i_width;
00784 int i_height = p_vout->output.i_height;
00785
00786 if( p_vout->p_sys->p_overlay == NULL )
00787 {
00788
00789 if( p_vout->p_sys->i_surfaces )
00790 {
00791
00792 return VLC_EGENERIC;
00793 }
00794
00795 p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00796
00797 if( p_pic->p_sys == NULL )
00798 {
00799 return VLC_ENOMEM;
00800 }
00801
00802 switch( p_vout->p_sys->p_display->format->BitsPerPixel )
00803 {
00804 case 8:
00805 p_pic->p->i_pixel_pitch = 1;
00806 break;
00807 case 15:
00808 case 16:
00809 p_pic->p->i_pixel_pitch = 2;
00810 break;
00811 case 24:
00812 case 32:
00813 p_pic->p->i_pixel_pitch = 4;
00814 break;
00815 default:
00816 return VLC_EGENERIC;
00817 }
00818
00819 p_pic->p->p_pixels = p_vout->p_sys->p_display->pixels;
00820 p_pic->p->i_lines = p_vout->p_sys->p_display->h;
00821 p_pic->p->i_visible_lines = p_vout->p_sys->p_display->h;
00822 p_pic->p->i_pitch = p_vout->p_sys->p_display->pitch;
00823 p_pic->p->i_visible_pitch =
00824 p_pic->p->i_pixel_pitch * p_vout->p_sys->p_display->w;
00825
00826 p_vout->p_sys->i_surfaces++;
00827
00828 p_pic->i_planes = 1;
00829 }
00830 else
00831 {
00832 p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00833
00834 if( p_pic->p_sys == NULL )
00835 {
00836 return VLC_ENOMEM;
00837 }
00838
00839 p_pic->p_sys->p_overlay =
00840 SDL_CreateYUVOverlay( i_width, i_height,
00841 p_vout->output.i_chroma,
00842 p_vout->p_sys->p_display );
00843
00844 if( p_pic->p_sys->p_overlay == NULL )
00845 {
00846 free( p_pic->p_sys );
00847 return VLC_EGENERIC;
00848 }
00849
00850 SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
00851
00852 p_pic->Y_PIXELS = p_pic->p_sys->p_overlay->pixels[0];
00853 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_overlay->h;
00854 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h;
00855 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[0];
00856
00857 switch( p_vout->output.i_chroma )
00858 {
00859 case SDL_YV12_OVERLAY:
00860 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00861 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
00862
00863 p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
00864 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00865 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00866 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
00867 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00868 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00869
00870 p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
00871 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00872 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00873 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
00874 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00875 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00876
00877 p_pic->i_planes = 3;
00878 break;
00879
00880 case SDL_IYUV_OVERLAY:
00881 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00882 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
00883
00884 p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
00885 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00886 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00887 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
00888 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00889 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00890
00891 p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
00892 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00893 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00894 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
00895 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00896 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00897
00898 p_pic->i_planes = 3;
00899 break;
00900
00901 default:
00902 p_pic->p[Y_PLANE].i_pixel_pitch = 2;
00903 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w * 2;
00904
00905 p_pic->i_planes = 1;
00906 break;
00907 }
00908 }
00909
00910 return VLC_SUCCESS;
00911 }
00912
00913
00914
00915
00916 static void SetPalette( vout_thread_t *p_vout,
00917 uint16_t *red, uint16_t *green, uint16_t *blue )
00918 {
00919 SDL_Color colors[256];
00920 int i;
00921
00922
00923 for( i = 0; i < 256; i++ )
00924 {
00925 colors[ i ].r = red[ i ] >> 8;
00926 colors[ i ].g = green[ i ] >> 8;
00927 colors[ i ].b = blue[ i ] >> 8;
00928 }
00929
00930
00931 if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
00932 {
00933 msg_Err( p_vout, "failed setting palette" );
00934 }
00935 }
00936