Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
b089f25b
Commit
b089f25b
authored
Aug 05, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted vout sdl to "vout display" API.
parent
4e34f941
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
528 additions
and
907 deletions
+528
-907
modules/video_output/sdl.c
modules/video_output/sdl.c
+528
-907
No files found.
modules/video_output/sdl.c
View file @
b089f25b
/*****************************************************************************
* sdl.c: SDL video output display method
*****************************************************************************
* Copyright (C) 1998-200
1
the VideoLAN team
* Copyright (C) 1998-200
9
the VideoLAN team
* $Id$
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Pierre Baillet <oct@zoy.org>
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -32,619 +33,645 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_playlist.h>
#include <vlc_vout.h>
#include <vlc_keys.h>
#include <vlc_vout_display.h>
#include <vlc_picture_pool.h>
#include <sys/types.h>
#ifndef WIN32
# include <netinet/in.h>
/* BSD: struct in_addr */
#endif
#include <assert.h>
#include SDL_INCLUDE_FILE
/* SDL is not able to crop overlays - so use only 1 direct buffer */
#define SDL_MAX_DIRECTBUFFERS 1
#define SDL_DEFAULT_BPP 16
/* FIXME add a configure check */
#if !SDL_VERSION_ATLEAST(1,2,10)
# error "Too old SDL"
#endif
/*****************************************************************************
* vout_sys_t: video output SDL method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the SDL specific properties of an output thread.
* Module descriptor
*****************************************************************************/
struct
vout_sys_t
{
SDL_Surface
*
p_display
;
/* display device */
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
int
i_width
;
int
i_height
;
#define CHROMA_TEXT N_("SDL chroma format")
#define CHROMA_LONGTEXT N_(\
"Force the SDL renderer to use a specific chroma format instead of " \
"trying to improve performances by using the most efficient one.")
#if SDL_VERSION_ATLEAST(1,2,10)
unsigned
int
i_desktop_width
;
unsigned
int
i_desktop_height
;
#define DRIVER_TEXT N_("SDL video driver name")
#define DRIVER_LONGTEXT N_(\
"Force a specific SDL video output driver.")
vlc_module_begin
()
set_shortname
(
"SDL"
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_description
(
N_
(
"Simple DirectMedia Layer video output"
))
set_capability
(
"vout display"
,
60
)
add_shortcut
(
"sdl"
)
add_string
(
"sdl-chroma"
,
NULL
,
NULL
,
CHROMA_TEXT
,
CHROMA_LONGTEXT
,
true
)
#ifdef HAVE_SETENV
add_string
(
"sdl-video-driver"
,
NULL
,
NULL
,
DRIVER_TEXT
,
DRIVER_LONGTEXT
,
true
)
#endif
set_callbacks
(
Open
,
Close
)
#if defined(__i386__) || defined(__x86_64__)
/* On i386, SDL is linked against svgalib */
linked_with_a_crap_library_which_uses_atexit
()
#endif
vlc_module_end
()
/* For YUV output */
SDL_Overlay
*
p_overlay
;
/* An overlay we keep to grab the XVideo port */
/* For RGB output */
int
i_surfaces
;
bool
b_cursor
;
bool
b_cursor_autohidden
;
mtime_t
i_lastmoved
;
mtime_t
i_mouse_hide_timeout
;
mtime_t
i_lastpressed
;
/* to track dbl-clicks */
};
/*****************************************************************************
* picture_sys_t: direct buffer method descriptor
*****************************************************************************
* This structure is part of the picture descriptor, it describes the
* SDL specific properties of a direct buffer.
*****************************************************************************/
struct
picture_sys_t
{
SDL_Overlay
*
p_overlay
;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
static
int
Init
(
vout_thread_t
*
);
static
void
End
(
vout_thread_t
*
);
static
int
Manage
(
vout_thread_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
static
picture_t
*
Get
(
vout_display_t
*
);
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
static
void
Manage
(
vout_display_t
*
);
static
int
OpenDisplay
(
vout_thread_t
*
);
static
void
CloseDisplay
(
vout_thread_t
*
);
static
int
NewPicture
(
vout_thread_t
*
,
picture_t
*
);
static
void
SetPalette
(
vout_thread_t
*
,
uint16_t
*
,
uint16_t
*
,
uint16_t
*
);
static
int
ConvertKey
(
SDLKey
);
/* */
static
int
ConvertKey
(
SDLKey
);
/* */
static
vlc_mutex_t
sdl_lock
=
VLC_STATIC_MUTEX
;
#define CHROMA_TEXT N_("SDL chroma format")
#define CHROMA_LONGTEXT N_( \
"Force the SDL renderer to use a specific chroma format instead of " \
"trying to improve performances by using the most efficient one.")
/* */
struct
vout_display_sys_t
{
vout_display_place_t
place
;
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
()
set_shortname
(
"SDL"
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_description
(
N_
(
"Simple DirectMedia Layer video output"
)
)
set_capability
(
"video output"
,
60
)
add_shortcut
(
"sdl"
)
add_string
(
"sdl-chroma"
,
NULL
,
NULL
,
CHROMA_TEXT
,
CHROMA_LONGTEXT
,
true
)
set_callbacks
(
Open
,
Close
)
#if defined( __i386__ ) || defined( __x86_64__ )
/* On i386, SDL is linked against svgalib */
linked_with_a_crap_library_which_uses_atexit
()
#endif
vlc_module_end
()
SDL_Surface
*
display
;
int
display_bpp
;
uint32_t
display_flags
;
static
vlc_mutex_t
sdl_lock
=
VLC_STATIC_MUTEX
;
unsigned
int
desktop_width
;
unsigned
int
desktop_height
;
/*****************************************************************************
* OpenVideo: allocate SDL video thread output method
*****************************************************************************
* This function allocate and initialize a SDL vout method. It uses some of the
* vout properties to choose the correct mode, and change them according to the
* mode actually used.
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
/* XXX: check for conflicts with the SDL audio output */
vlc_mutex_lock
(
&
sdl_lock
);
/* For YUV output */
SDL_Overlay
*
overlay
;
bool
is_uv_swapped
;
#ifdef HAVE_SETENV
char
*
psz_method
;
#endif
/* */
picture_pool_t
*
pool
;
};
p_vout
->
p_sys
=
malloc
(
sizeof
(
vout_sys_t
)
);
if
(
p_vout
->
p_sys
==
NULL
)
{
vlc_mutex_unlock
(
&
sdl_lock
);
return
VLC_ENOMEM
;
}
/**
* This function initializes SDL vout method.
*/
static
int
Open
(
vlc_object_t
*
object
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
;
memset
(
p_vout
->
p_sys
,
0
,
sizeof
(
vout_sys_t
)
);
/* XXX: check for conflicts with the SDL audio output */
vlc_mutex_lock
(
&
sdl_lock
);
/* Check if SDL video module has been initialized */
if
(
SDL_WasInit
(
SDL_INIT_VIDEO
)
!=
0
)
{
vlc_mutex_unlock
(
&
sdl_lock
);
free
(
p_vout
->
p_sys
);
if
(
SDL_WasInit
(
SDL_INIT_VIDEO
)
!=
0
)
{
vlc_mutex_unlock
(
&
sdl_lock
);
return
VLC_EGENERIC
;
}
/* Allocate structure */
p_vout
->
pf_init
=
Init
;
p_vout
->
pf_end
=
End
;
p_vout
->
pf_manage
=
Manage
;
p_vout
->
pf_render
=
NULL
;
p_vout
->
pf_display
=
Display
;
p_vout
->
pf_control
=
NULL
;
vd
->
sys
=
sys
=
calloc
(
1
,
sizeof
(
*
sys
));
if
(
!
sys
)
{
vlc_mutex_unlock
(
&
sdl_lock
);
return
VLC_ENOMEM
;
}
#ifdef HAVE_SETENV
char
*
psz
=
psz_method
=
config_GetPsz
(
p_vout
,
"vout"
);
if
(
psz_method
)
{
while
(
*
psz_method
&&
*
psz_method
!=
':'
)
{
psz_method
++
;
}
if
(
*
psz_method
)
{
setenv
(
"SDL_VIDEODRIVER"
,
psz_method
+
1
,
1
);
}
char
*
psz_driver
=
var_CreateGetNonEmptyString
(
vd
,
"sdl-video-driver"
);
if
(
psz_driver
)
{
setenv
(
"SDL_VIDEODRIVER"
,
psz_driver
,
1
);
free
(
psz_driver
);
}
free
(
psz
);
#endif
/*
Initialize library
*/
i
f
(
SDL_Init
(
SDL_INIT_VIDEO
/* */
i
nt
sdl_flags
=
SDL_INIT_VIDEO
;
#ifndef WIN32
/* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
|
SDL_INIT_EVENTTHREAD
sdl_flags
|=
SDL_INIT_EVENTTHREAD
;
#endif
#ifndef NDEBUG
/* In debug mode you may want vlc to dump a core instead of staying
* stuck */
|
SDL_INIT_NOPARACHUTE
/* In debug mode you may want vlc to dump a core instead of staying stuck */
sdl_flags
|=
SDL_INIT_NOPARACHUTE
;
#endif
)
<
0
)
{
msg_Err
(
p_vout
,
"cannot initialize SDL (%s)"
,
SDL_GetError
()
);
free
(
p_vout
->
p_sys
);
vlc_mutex_unlock
(
&
sdl_lock
);
/* Initialize library */
if
(
SDL_Init
(
sdl_flags
)
<
0
)
{
vlc_mutex_unlock
(
&
sdl_lock
);
msg_Err
(
vd
,
"cannot initialize SDL (%s)"
,
SDL_GetError
());
free
(
sys
);
return
VLC_EGENERIC
;
}
vlc_mutex_unlock
(
&
sdl_lock
);
vlc_mutex_unlock
(
&
sdl_lock
);
/* Translate keys into unicode */
SDL_EnableUNICODE
(
1
);
/* Get the desktop resolution */
#if SDL_VERSION_ATLEAST(1,2,10)
/* FIXME: SDL has a problem with virtual desktop */
p_vout
->
p_sys
->
i_desktop_width
=
SDL_GetVideoInfo
()
->
current_w
;
p_vout
->
p_sys
->
i_desktop_height
=
SDL_GetVideoInfo
()
->
current_h
;
#endif
sys
->
desktop_width
=
SDL_GetVideoInfo
()
->
current_w
;
sys
->
desktop_height
=
SDL_GetVideoInfo
()
->
current_h
;
/* Create the cursor */
p_vout
->
p_sys
->
b_cursor
=
1
;
p_vout
->
p_sys
->
b_cursor_autohidden
=
0
;
p_vout
->
p_sys
->
i_lastmoved
=
p_vout
->
p_sys
->
i_lastpressed
=
mdate
();
p_vout
->
p_sys
->
i_mouse_hide_timeout
=
var_GetInteger
(
p_vout
,
"mouse-hide-timeout"
)
*
1000
;
if
(
OpenDisplay
(
p_vout
)
)
{
msg_Err
(
p_vout
,
"cannot set up SDL (%s)"
,
SDL_GetError
()
);
SDL_QuitSubSystem
(
SDL_INIT_VIDEO
);
free
(
p_vout
->
p_sys
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Init: initialize SDL video thread output method
*****************************************************************************
* This function initialize the SDL display device.
*****************************************************************************/
static
int
Init
(
vout_thread_t
*
p_vout
)
{
int
i_index
;
picture_t
*
p_pic
;
/* */
video_format_t
fmt
=
vd
->
fmt
;
p_vout
->
p_sys
->
i_surfaces
=
0
;
/* */
vout_display_info_t
info
=
vd
->
info
;
I_OUTPUTPICTURES
=
0
;
/* Set main window's size */
int
display_width
;
int
display_height
;
if
(
vd
->
cfg
->
is_fullscreen
)
{
display_width
=
sys
->
desktop_width
;
display_height
=
sys
->
desktop_height
;
}
else
{
display_width
=
vd
->
cfg
->
display
.
width
;
display_height
=
vd
->
cfg
->
display
.
height
;
}
/* Initialize
the output structure
*/
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
/* All we have is an RGB image with square pixels */
p_vout
->
output
.
i_width
=
p_vout
->
p_sys
->
i_width
;
p_vout
->
output
.
i_height
=
p_vout
->
p_sys
->
i_height
;
p_vout
->
output
.
i_aspect
=
p_vout
->
output
.
i_width
*
VOUT_ASPECT_FACTOR
/
p_vout
->
output
.
i_height
;
/* Initialize
flags and cursor
*/
sys
->
display_flags
=
SDL_ANYFORMAT
|
SDL_HWPALETTE
|
SDL_HWSURFACE
|
SDL_DOUBLEBUF
;
sys
->
display_flags
|=
vd
->
cfg
->
is_fullscreen
?
SDL_FULLSCREEN
:
SDL_RESIZABLE
;
sys
->
display_bpp
=
SDL_VideoModeOK
(
display_width
,
display_height
,
16
,
sys
->
display_flags
)
;
if
(
sys
->
display_bpp
==
0
)
{
msg_Err
(
vd
,
"no video mode available"
);
goto
error
;
}
else
{
/* We may need to convert the chroma, but at least we keep the
* aspect ratio */
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
sys
->
display
=
SDL_SetVideoMode
(
display_width
,
display_height
,
sys
->
display_bpp
,
sys
->
display_flags
);
if
(
!
sys
->
display
)
{
msg_Err
(
vd
,
"cannot set video mode"
);
goto
error
;
}
/* Try to initialize SDL_MAX_DIRECTBUFFERS direct buffers */
while
(
I_OUTPUTPICTURES
<
SDL_MAX_DIRECTBUFFERS
)
{
p_pic
=
NULL
;
/* We keep the surface locked forever */
SDL_LockSurface
(
sys
->
display
);
/* */
vlc_fourcc_t
forced_chroma
=
0
;
char
*
psz_chroma
=
var_CreateGetNonEmptyString
(
vd
,
"sdl-chroma"
);
if
(
psz_chroma
)
{
forced_chroma
=
vlc_fourcc_GetCodecFromString
(
VIDEO_ES
,
psz_chroma
);
if
(
forced_chroma
)
msg_Dbg
(
vd
,
"Forcing chroma to 0x%.8x (%4.4s)"
,
forced_chroma
,
(
const
char
*
)
&
forced_chroma
);
free
(
psz_chroma
);
}
/* Find an empty picture slot */
for
(
i_index
=
0
;
i_index
<
VOUT_MAX_PICTURES
;
i_index
++
)
/* Try to open an overlay if requested */
sys
->
overlay
=
NULL
;
const
bool
is_overlay
=
var_CreateGetBool
(
vd
,
"overlay"
);
if
(
is_overlay
)
{
static
const
struct
{
if
(
p_vout
->
p_picture
[
i_index
].
i_status
==
FREE_PICTURE
)
{
p_pic
=
p_vout
->
p_picture
+
i_index
;
break
;
vlc_fourcc_t
vlc
;
uint32_t
sdl
;
}
vlc_to_sdl
[]
=
{
{
VLC_CODEC_YV12
,
SDL_YV12_OVERLAY
},
{
VLC_CODEC_I420
,
SDL_IYUV_OVERLAY
},
{
VLC_CODEC_YUYV
,
SDL_YUY2_OVERLAY
},
{
VLC_CODEC_UYVY
,
SDL_UYVY_OVERLAY
},
{
VLC_CODEC_YVYU
,
SDL_YVYU_OVERLAY
},
{
0
,
0
}
};
const
vlc_fourcc_t
forced_chromas
[]
=
{
forced_chroma
,
0
};
const
vlc_fourcc_t
*
fallback_chromas
=
vlc_fourcc_GetYUVFallback
(
fmt
.
i_chroma
);
const
vlc_fourcc_t
*
chromas
=
forced_chroma
?
forced_chromas
:
fallback_chromas
;
for
(
int
pass
=
forced_chroma
?
1
:
0
;
pass
<
2
&&
!
sys
->
overlay
;
pass
++
)
{
for
(
int
i
=
0
;
chromas
[
i
]
!=
0
;
i
++
)
{
const
vlc_fourcc_t
vlc
=
chromas
[
i
];
uint32_t
sdl
=
0
;
for
(
int
j
=
0
;
vlc_to_sdl
[
j
].
vlc
!=
0
&&
!
sdl
;
j
++
)
{
if
(
vlc_to_sdl
[
j
].
vlc
==
vlc
)
sdl
=
vlc_to_sdl
[
j
].
sdl
;
}
if
(
!
sdl
)
continue
;
sys
->
overlay
=
SDL_CreateYUVOverlay
(
fmt
.
i_width
,
fmt
.
i_height
,
sdl
,
sys
->
display
);
if
(
sys
->
overlay
&&
!
sys
->
overlay
->
hw_overlay
&&
pass
==
0
)
{
/* Ignore non hardware overlay surface in first pass */
SDL_FreeYUVOverlay
(
sys
->
overlay
);
sys
->
overlay
=
NULL
;
}
if
(
sys
->
overlay
)
{
/* We keep the surface locked forever */
SDL_LockYUVOverlay
(
sys
->
overlay
);
fmt
.
i_chroma
=
vlc
;
sys
->
is_uv_swapped
=
vlc_fourcc_AreUVPlanesSwapped
(
fmt
.
i_chroma
,
vd
->
fmt
.
i_chroma
);
if
(
sys
->
is_uv_swapped
)
fmt
.
i_chroma
=
vd
->
fmt
.
i_chroma
;
break
;
}
}
}
}
else
{
msg_Warn
(
vd
,
"SDL overlay disabled by the user"
);
}
/* Allocate the picture if we found one */
if
(
p_pic
==
NULL
||
NewPicture
(
p_vout
,
p_pic
)
)
{
/* */
vout_display_cfg_t
place_cfg
=
*
vd
->
cfg
;
place_cfg
.
display
.
width
=
display_width
;
place_cfg
.
display
.
height
=
display_height
;
vout_display_PlacePicture
(
&
sys
->
place
,
&
vd
->
source
,
&
place_cfg
,
!
sys
->
overlay
);
/* If no overlay, fallback to software output */
if
(
!
sys
->
overlay
)
{
/* */
switch
(
sys
->
display
->
format
->
BitsPerPixel
)
{
case
8
:
fmt
.
i_chroma
=
VLC_CODEC_RGB8
;
break
;
case
15
:
fmt
.
i_chroma
=
VLC_CODEC_RGB15
;
break
;
case
16
:
fmt
.
i_chroma
=
VLC_CODEC_RGB16
;
break
;
case
24
:
fmt
.
i_chroma
=
VLC_CODEC_RGB24
;
break
;
case
32
:
fmt
.
i_chroma
=
VLC_CODEC_RGB32
;
break
;
default:
msg_Err
(
vd
,
"unknown screen depth %i"
,
sys
->
display
->
format
->
BitsPerPixel
);
goto
error
;
}
p_pic
->
i_status
=
DESTROYED_PICTURE
;
p_pic
->
i_type
=
DIRECT_PICTURE
;
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
]
=
p_pic
;
/* All we have is an RGB image with square pixels */
fmt
.
i_width
=
display_width
;
fmt
.
i_height
=
display_height
;
fmt
.
i_rmask
=
sys
->
display
->
format
->
Rmask
;
fmt
.
i_gmask
=
sys
->
display
->
format
->
Gmask
;
fmt
.
i_bmask
=
sys
->
display
->
format
->
Bmask
;
I_OUTPUTPICTURES
++
;
info
.
has_pictures_invalid
=
true
;
}
if
(
vd
->
cfg
->
display
.
title
)
SDL_WM_SetCaption
(
vd
->
cfg
->
display
.
title
,
vd
->
cfg
->
display
.
title
);
else
if
(
!
sys
->
overlay
)
SDL_WM_SetCaption
(
VOUT_TITLE
" (software RGB SDL output)"
,
VOUT_TITLE
" (software RGB SDL output)"
);
else
if
(
sys
->
overlay
->
hw_overlay
)
SDL_WM_SetCaption
(
VOUT_TITLE
" (hardware YUV SDL output)"
,
VOUT_TITLE
" (hardware YUV SDL output)"
);
else
SDL_WM_SetCaption
(
VOUT_TITLE
" (software YUV SDL output)"
,
VOUT_TITLE
" (software YUV SDL output)"
);
/* Setup events */
SDL_EventState
(
SDL_KEYUP
,
SDL_IGNORE
);
/* ignore keys up */
/* Setup vout_display now that everything is fine */
vd
->
fmt
=
fmt
;
vd
->
info
=
info
;
vd
->
get
=
Get
;
vd
->
prepare
=
NULL
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* */
vout_display_SendEventDisplaySize
(
vd
,
display_width
,
display_height
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* End: terminate Sys video thread output method
*****************************************************************************
* Terminate an output method created by OpenVideo
*****************************************************************************/
static
void
End
(
vout_thread_t
*
p_vout
)
{
int
i_index
;
error:
msg_Err
(
vd
,
"cannot set up SDL (%s)"
,
SDL_GetError
());
/* Free the output buffers we allocated */
for
(
i_index
=
I_OUTPUTPICTURES
;
i_index
;
)
{
i_index
--
;
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
/* RGB picture */
}
else
{
SDL_UnlockYUVOverlay
(
PP_OUTPUTPICTURE
[
i_index
]
->
p_sys
->
p_overlay
);
SDL_FreeYUVOverlay
(
PP_OUTPUTPICTURE
[
i_index
]
->
p_sys
->
p_overlay
);
}
free
(
PP_OUTPUTPICTURE
[
i_index
]
->
p_sys
);
if
(
sys
->
display
)
{
SDL_UnlockSurface
(
sys
->
display
);
SDL_FreeSurface
(
sys
->
display
);
}
vlc_mutex_lock
(
&
sdl_lock
);
SDL_QuitSubSystem
(
SDL_INIT_VIDEO
);
vlc_mutex_unlock
(
&
sdl_lock
);
free
(
sys
);
return
VLC_EGENERIC
;
}
/*****************************************************************************
* CloseVideo: destroy Sys video thread output method
*****************************************************************************
* Terminate an output method created by vout_SDLCreate
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
/**
* Close a SDL video output
*/
static
void
Close
(
vlc_object_t
*
object
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
sys
->
pool
)
picture_pool_Delete
(
sys
->
pool
);
CloseDisplay
(
p_vout
);
SDL_QuitSubSystem
(
SDL_INIT_VIDEO
);
if
(
sys
->
overlay
)
{
SDL_LockYUVOverlay
(
sys
->
overlay
);
SDL_FreeYUVOverlay
(
sys
->
overlay
);
}
SDL_UnlockSurface
(
sys
->
display
);
SDL_FreeSurface
(
sys
->
display
);
vlc_mutex_lock
(
&
sdl_lock
);
SDL_QuitSubSystem
(
SDL_INIT_VIDEO
);
vlc_mutex_unlock
(
&
sdl_lock
);
free
(
p_vout
->
p_sys
);
free
(
sys
);
}
/*****************************************************************************
* Manage: handle Sys events
*****************************************************************************
* This function should be called regularly by video output thread. It returns
* a non null value if an error occurred.
*****************************************************************************/
static
int
Manage
(
vout_thread_t
*
p_vout
)
/**
* Return a direct buffer
*/
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
SDL_Event
event
;
/* SDL event */
vlc_value_t
val
;
unsigned
int
i_width
,
i_height
,
i_x
,
i_y
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
/* Process events */
while
(
SDL_PollEvent
(
&
event
)
)
{
switch
(
event
.
type
)
{
/* Resizing of window */
case
SDL_VIDEORESIZE
:
p_vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
p_vout
->
i_window_width
=
p_vout
->
p_sys
->
i_width
=
event
.
resize
.
w
;
p_vout
->
i_window_height
=
p_vout
->
p_sys
->
i_height
=
event
.
resize
.
h
;
break
;
if
(
!
sys
->
pool
)
{
picture_resource_t
rsc
;
/* Mouse move */
case
SDL_MOUSEMOTION
:
vout_PlacePicture
(
p_vout
,
p_vout
->
p_sys
->
i_width
,
p_vout
->
p_sys
->
i_height
,
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
/* Compute the x coordinate and check if the value is
in [0,p_vout->fmt_in.i_visible_width] */
val
.
i_int
=
(
event
.
motion
.
x
-
i_x
)
*
p_vout
->
fmt_in
.
i_visible_width
/
i_width
+
p_vout
->
fmt_in
.
i_x_offset
;
if
(
(
int
)(
event
.
motion
.
x
-
i_x
)
<
0
)
val
.
i_int
=
0
;
else
if
(
(
unsigned
int
)
val
.
i_int
>
p_vout
->
fmt_in
.
i_visible_width
)
val
.
i_int
=
p_vout
->
fmt_in
.
i_visible_width
;
var_Set
(
p_vout
,
"mouse-x"
,
val
);
/* compute the y coordinate and check if the value is
in [0,p_vout->fmt_in.i_visible_height] */
val
.
i_int
=
(
event
.
motion
.
y
-
i_y
)
*
p_vout
->
fmt_in
.
i_visible_height
/
i_height
+
p_vout
->
fmt_in
.
i_y_offset
;
if
(
(
int
)(
event
.
motion
.
y
-
i_y
)
<
0
)
val
.
i_int
=
0
;
else
if
(
(
unsigned
int
)
val
.
i_int
>
p_vout
->
fmt_in
.
i_visible_height
)
val
.
i_int
=
p_vout
->
fmt_in
.
i_visible_height
;
var_Set
(
p_vout
,
"mouse-y"
,
val
);
var_SetBool
(
p_vout
,
"mouse-moved"
,
true
);
if
(
p_vout
->
p_sys
->
b_cursor
)
{
if
(
p_vout
->
p_sys
->
b_cursor_autohidden
)
{
p_vout
->
p_sys
->
b_cursor_autohidden
=
0
;
SDL_ShowCursor
(
1
);
}
else
{
p_vout
->
p_sys
->
i_lastmoved
=
mdate
();
}
}
break
;
memset
(
&
rsc
,
0
,
sizeof
(
rsc
));
/* Mouse button released */
case
SDL_MOUSEBUTTONUP
:
switch
(
event
.
button
.
button
)
{
case
SDL_BUTTON_LEFT
:
{
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
&=
~
1
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
var_SetBool
(
p_vout
,
"mouse-clicked"
,
true
);
var_SetBool
(
p_vout
->
p_libvlc
,
"intf-popupmenu"
,
false
);
}
break
;
if
(
sys
->
overlay
)
{
SDL_Overlay
*
ol
=
sys
->
overlay
;
case
SDL_BUTTON_MIDDLE
:
{
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
&=
~
2
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
for
(
int
i
=
0
;
i
<
ol
->
planes
;
i
++
)
{
rsc
.
p
[
i
].
p_pixels
=
ol
->
pixels
[
i
>
0
&&
sys
->
is_uv_swapped
?
(
3
-
i
)
:
i
];
rsc
.
p
[
i
].
i_pitch
=
ol
->
pitches
[
i
>
0
&&
sys
->
is_uv_swapped
?
(
3
-
i
)
:
i
];
rsc
.
p
[
i
].
i_lines
=
ol
->
h
;
if
(
ol
->
format
==
SDL_YV12_OVERLAY
||
ol
->
format
==
SDL_IYUV_OVERLAY
)
rsc
.
p
[
i
].
i_lines
/=
2
;
var_Get
(
p_vout
->
p_libvlc
,
"intf-show"
,
&
val
);
val
.
b_bool
=
!
val
.
b_bool
;
var_Set
(
p_vout
->
p_libvlc
,
"intf-show"
,
val
);
}
break
;
}
}
else
{
const
int
x
=
sys
->
place
.
x
;
const
int
y
=
sys
->
place
.
y
;
case
SDL_BUTTON_RIGHT
:
{
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
&=
~
4
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
SDL_Surface
*
sf
=
sys
->
display
;
SDL_FillRect
(
sf
,
NULL
,
0
);
var_SetBool
(
p_vout
->
p_libvlc
,
"intf-popupmenu"
,
true
);
}
break
;
}
break
;
assert
(
x
>=
0
&&
y
>=
0
);
rsc
.
p
[
0
].
p_pixels
=
(
uint8_t
*
)
sf
->
pixels
+
y
*
sf
->
pitch
+
x
*
((
sf
->
format
->
BitsPerPixel
+
7
)
/
8
);
rsc
.
p
[
0
].
i_pitch
=
sf
->
pitch
;
rsc
.
p
[
0
].
i_lines
=
vd
->
fmt
.
i_height
;
}
/* Mouse button pressed */
case
SDL_MOUSEBUTTONDOWN
:
switch
(
event
.
button
.
button
)
{
case
SDL_BUTTON_LEFT
:
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
|=
1
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
/* detect double-clicks */
if
(
(
mdate
()
-
p_vout
->
p_sys
->
i_lastpressed
)
<
300000
)
p_vout
->
i_changes
|=
VOUT_FULLSCREEN_CHANGE
;
p_vout
->
p_sys
->
i_lastpressed
=
mdate
();
break
;
picture_t
*
picture
=
picture_NewFromResource
(
&
vd
->
fmt
,
&
rsc
);;
if
(
!
picture
)
return
NULL
;
case
SDL_BUTTON_MIDDLE
:
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
|=
2
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
break
;
sys
->
pool
=
picture_pool_New
(
1
,
&
picture
);
if
(
!
sys
->
pool
)
return
NULL
;
}
case
SDL_BUTTON_RIGHT
:
var_Get
(
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
|=
4
;
var_Set
(
p_vout
,
"mouse-button-down"
,
val
);
break
;
}
break
;
return
picture_pool_Get
(
sys
->
pool
);
}
/* Quit event (close the window) */
case
SDL_QUIT
:
{
#if 0
playlist_t *p_playlist = pl_Hold( p_vout );
if( p_playlist != NULL )
{
playlist_Stop( p_playlist );
pl_Release( p_vout );
}
#else
#warning FIXME FIXME ?
#endif
}
break
;
/**
* Display a picture
*/
static
void
Display
(
vout_display_t
*
vd
,
picture_t
*
p_pic
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
sys
->
overlay
)
{
SDL_Rect
disp
;
disp
.
x
=
sys
->
place
.
x
;
disp
.
y
=
sys
->
place
.
y
;
disp
.
w
=
sys
->
place
.
width
;
disp
.
h
=
sys
->
place
.
height
;
SDL_UnlockYUVOverlay
(
sys
->
overlay
);
SDL_DisplayYUVOverlay
(
sys
->
overlay
,
&
disp
);
SDL_LockYUVOverlay
(
sys
->
overlay
);
}
else
{
SDL_Flip
(
sys
->
display
);
}
/* Key pressed */
case
SDL_KEYDOWN
:
/* convert the key if possible */
val
.
i_int
=
ConvertKey
(
event
.
key
.
keysym
.
sym
);
picture_Release
(
p_pic
);
}
if
(
!
val
.
i_int
)
{
/* Find the right caracter */
if
(
(
event
.
key
.
keysym
.
unicode
&
0xff80
)
==
0
)
{
val
.
i_int
=
event
.
key
.
keysym
.
unicode
&
0x7f
;
/* FIXME: find a better solution than this
hack to find the right caracter */
if
(
val
.
i_int
>=
1
&&
val
.
i_int
<=
26
)
val
.
i_int
+=
96
;
else
if
(
val
.
i_int
>=
65
&&
val
.
i_int
<=
90
)
val
.
i_int
+=
32
;
}
}
if
(
val
.
i_int
)
{
if
(
(
event
.
key
.
keysym
.
mod
&
KMOD_SHIFT
)
)
{
val
.
i_int
|=
KEY_MODIFIER_SHIFT
;
}
if
(
(
event
.
key
.
keysym
.
mod
&
KMOD_CTRL
)
)
{
val
.
i_int
|=
KEY_MODIFIER_CTRL
;
}
if
(
(
event
.
key
.
keysym
.
mod
&
KMOD_ALT
)
)
{
val
.
i_int
|=
KEY_MODIFIER_ALT
;
}
var_Set
(
p_vout
->
p_libvlc
,
"key-pressed"
,
val
);
}
/**
* Control for vout display
*/
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
default:
break
;
switch
(
query
)
{
case
VOUT_DISPLAY_HIDE_MOUSE
:
SDL_ShowCursor
(
0
);
return
VLC_SUCCESS
;
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
{
const
vout_display_cfg_t
*
cfg
=
va_arg
(
args
,
const
vout_display_cfg_t
*
);
/* */
sys
->
display
=
SDL_SetVideoMode
(
cfg
->
display
.
width
,
cfg
->
display
.
height
,
sys
->
display_bpp
,
sys
->
display_flags
);
if
(
!
sys
->
display
)
{
sys
->
display
=
SDL_SetVideoMode
(
vd
->
cfg
->
display
.
width
,
vd
->
cfg
->
display
.
height
,
sys
->
display_bpp
,
sys
->
display_flags
);
return
VLC_EGENERIC
;
}
if
(
sys
->
overlay
)
vout_display_PlacePicture
(
&
sys
->
place
,
&
vd
->
source
,
cfg
,
!
sys
->
overlay
);
else
vout_display_SendEventPicturesInvalid
(
vd
);
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_FULLSCREEN
:
{
vout_display_cfg_t
cfg
=
*
va_arg
(
args
,
const
vout_display_cfg_t
*
);
/* Fullscreen change */
if
(
p_vout
->
i_changes
&
VOUT_FULLSCREEN_CHANGE
)
{
vlc_value_t
val_fs
;
/* Fix flags */
sys
->
display_flags
&=
~
(
SDL_FULLSCREEN
|
SDL_RESIZABLE
);
sys
->
display_flags
|=
cfg
.
is_fullscreen
?
SDL_FULLSCREEN
:
SDL_RESIZABLE
;
/* Update the object variable and trigger callback */
val_fs
.
b_bool
=
!
p_vout
->
b_fullscreen
;
p_vout
->
b_fullscreen
=
!
p_vout
->
b_fullscreen
;
var_Set
(
p_vout
,
"fullscreen"
,
val_fs
);
if
(
cfg
.
is_fullscreen
)
{
cfg
.
display
.
width
=
sys
->
desktop_width
;
cfg
.
display
.
height
=
sys
->
desktop_height
;
}
/*TODO: add the "always on top" code here !*/
if
(
sys
->
overlay
)
{
sys
->
display
=
SDL_SetVideoMode
(
cfg
.
display
.
width
,
cfg
.
display
.
height
,
sys
->
display_bpp
,
sys
->
display_flags
);
p_vout
->
p_sys
->
b_cursor_autohidden
=
0
;
SDL_ShowCursor
(
p_vout
->
p_sys
->
b_cursor
&&
!
p_vout
->
p_sys
->
b_cursor_autohidden
);
vout_display_PlacePicture
(
&
sys
->
place
,
&
vd
->
source
,
&
cfg
,
!
sys
->
overlay
);
}
vout_display_SendEventDisplaySize
(
vd
,
cfg
.
display
.
width
,
cfg
.
display
.
height
);
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_ZOOM
:
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
{
const
vout_display_cfg_t
*
cfg
;
const
video_format_t
*
source
;
if
(
query
==
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
)
{
source
=
va_arg
(
args
,
const
video_format_t
*
);
cfg
=
vd
->
cfg
;
}
else
{
source
=
&
vd
->
source
;
cfg
=
va_arg
(
args
,
const
vout_display_cfg_t
*
);
}
if
(
sys
->
overlay
)
{
sys
->
display
=
SDL_SetVideoMode
(
cfg
->
display
.
width
,
cfg
->
display
.
height
,
sys
->
display_bpp
,
sys
->
display_flags
);
p_vout
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
p_vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
vout_display_PlacePicture
(
&
sys
->
place
,
source
,
cfg
,
!
sys
->
overlay
);
}
else
{
vout_display_SendEventPicturesInvalid
(
vd
);
}
return
VLC_SUCCESS
;
}
/* autoscale toggle */
if
(
p_vout
->
i_changes
&
VOUT_SCALE_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_SCALE_CHANGE
;
case
VOUT_DISPLAY_RESET_PICTURES
:
{
/* */
assert
(
!
sys
->
overlay
);
p_vout
->
b_autoscale
=
var_GetBool
(
p_vout
,
"autoscale"
);
p_vout
->
i_zoom
=
(
int
)
ZOOM_FP_FACTOR
;
/* */
if
(
sys
->
pool
)
picture_pool_Delete
(
sys
->
pool
);
sys
->
pool
=
NULL
;
p_vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
vout_display_PlacePicture
(
&
sys
->
place
,
&
vd
->
source
,
vd
->
cfg
,
!
sys
->
overlay
);
/* scaling factor (if no-autoscale) */
if
(
p_vout
->
i_changes
&
VOUT_ZOOM_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_ZOOM_CHANGE
;
/* */
vd
->
fmt
.
i_width
=
sys
->
place
.
width
;
vd
->
fmt
.
i_height
=
sys
->
place
.
height
;
return
VLC_SUCCESS
;
}
p_vout
->
b_autoscale
=
false
;
p_vout
->
i_zoom
=
(
int
)(
ZOOM_FP_FACTOR
*
var_GetFloat
(
p_vout
,
"scale"
)
);
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
case
VOUT_DISPLAY_CHANGE_ON_TOP
:
/* I don't think it is possible to support with SDL:
* - crop
* - on top
*/
return
VLC_EGENERIC
;
p_vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
default:
msg_Err
(
vd
,
"Unsupported query in vout display SDL"
);
return
VLC_EGENERIC
;
}
}
/* Crop or Aspect Ratio Changes */
if
(
p_vout
->
i_changes
&
VOUT_CROP_CHANGE
||
p_vout
->
i_changes
&
VOUT_ASPECT_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_CROP_CHANGE
;
p_vout
->
i_changes
&=
~
VOUT_ASPECT_CHANGE
;
p_vout
->
fmt_out
.
i_x_offset
=
p_vout
->
fmt_in
.
i_x_offset
;
p_vout
->
fmt_out
.
i_y_offset
=
p_vout
->
fmt_in
.
i_y_offset
;
p_vout
->
fmt_out
.
i_visible_width
=
p_vout
->
fmt_in
.
i_visible_width
;
p_vout
->
fmt_out
.
i_visible_height
=
p_vout
->
fmt_in
.
i_visible_height
;
p_vout
->
fmt_out
.
i_aspect
=
p_vout
->
fmt_in
.
i_aspect
;
p_vout
->
fmt_out
.
i_sar_num
=
p_vout
->
fmt_in
.
i_sar_num
;
p_vout
->
fmt_out
.
i_sar_den
=
p_vout
->
fmt_in
.
i_sar_den
;
p_vout
->
output
.
i_aspect
=
p_vout
->
fmt_in
.
i_aspect
;
p_vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
/**
* Proccess pending event
*/
static
void
Manage
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
SDL_Event
event
;
/* Size change */
if
(
p_vout
->
i_changes
&
VOUT_SIZE_CHANGE
)
{
msg_Dbg
(
p_vout
,
"video display resized (%dx%d)"
,
p_vout
->
p_sys
->
i_width
,
p_vout
->
p_sys
->
i_height
);
/* */
while
(
SDL_PollEvent
(
&
event
))
{
switch
(
event
.
type
)
{
case
SDL_QUIT
:
vout_display_SendEventClose
(
vd
);
break
;
CloseDisplay
(
p_vout
);
OpenDisplay
(
p_vout
);
case
SDL_KEYDOWN
:
{
/* convert the key if possible */
int
key
=
ConvertKey
(
event
.
key
.
keysym
.
sym
);
/* We don't need to signal the vout thread about the size change if
* we can handle rescaling ourselves */
if
(
p_vout
->
p_sys
->
p_overlay
!=
NULL
)
p_vout
->
i_changes
&=
~
VOUT_SIZE_CHANGE
;
}
if
(
!
key
)
{
/* Find the right caracter */
if
((
event
.
key
.
keysym
.
unicode
&
0xff80
)
==
0
)
{
key
=
event
.
key
.
keysym
.
unicode
&
0x7f
;
/* FIXME: find a better solution than this
hack to find the right caracter */
if
(
key
>=
1
&&
key
<=
26
)
key
+=
96
;
else
if
(
key
>=
65
&&
key
<=
90
)
key
+=
32
;
}
}
if
(
!
key
)
break
;
/* Pointer change */
if
(
!
p_vout
->
p_sys
->
b_cursor_autohidden
&&
(
mdate
()
-
p_vout
->
p_sys
->
i_lastmoved
>
p_vout
->
p_sys
->
i_mouse_hide_timeout
)
)
{
/* Hide the mouse automatically */
p_vout
->
p_sys
->
b_cursor_autohidden
=
1
;
SDL_ShowCursor
(
0
);
if
(
event
.
key
.
keysym
.
mod
&
KMOD_SHIFT
)
key
|=
KEY_MODIFIER_SHIFT
;
if
(
event
.
key
.
keysym
.
mod
&
KMOD_CTRL
)
key
|=
KEY_MODIFIER_CTRL
;
if
(
event
.
key
.
keysym
.
mod
&
KMOD_ALT
)
key
|=
KEY_MODIFIER_ALT
;
vout_display_SendEventKey
(
vd
,
key
);
break
;
}
case
SDL_MOUSEBUTTONDOWN
:
case
SDL_MOUSEBUTTONUP
:
{
static
const
struct
{
int
sdl
;
int
vlc
;
}
buttons
[]
=
{
{
SDL_BUTTON_LEFT
,
MOUSE_BUTTON_LEFT
},
{
SDL_BUTTON_MIDDLE
,
MOUSE_BUTTON_CENTER
},
{
SDL_BUTTON_RIGHT
,
MOUSE_BUTTON_RIGHT
},
{
SDL_BUTTON_WHEELUP
,
MOUSE_BUTTON_WHEEL_UP
},
{
SDL_BUTTON_WHEELDOWN
,
MOUSE_BUTTON_WHEEL_DOWN
},
{
-
1
,
-
1
},
};
SDL_ShowCursor
(
1
);
for
(
int
i
=
0
;
buttons
[
i
].
sdl
!=
-
1
;
i
++
)
{
if
(
buttons
[
i
].
sdl
==
event
.
button
.
button
)
{
if
(
event
.
type
==
SDL_MOUSEBUTTONDOWN
)
vout_display_SendEventMousePressed
(
vd
,
buttons
[
i
].
vlc
);
else
vout_display_SendEventMouseReleased
(
vd
,
buttons
[
i
].
vlc
);
}
}
break
;
}
case
SDL_MOUSEMOTION
:
{
if
(
sys
->
place
.
width
<=
0
||
sys
->
place
.
height
<=
0
)
break
;
const
int
x
=
(
int64_t
)(
event
.
motion
.
x
-
sys
->
place
.
x
)
*
vd
->
source
.
i_width
/
sys
->
place
.
width
;
const
int
y
=
(
int64_t
)(
event
.
motion
.
y
-
sys
->
place
.
y
)
*
vd
->
source
.
i_height
/
sys
->
place
.
height
;
SDL_ShowCursor
(
1
);
if
(
x
>=
0
&&
x
<
vd
->
source
.
i_width
&&
y
>=
0
&&
y
<
vd
->
source
.
i_height
)
vout_display_SendEventMouseMoved
(
vd
,
x
,
y
);
break
;
}
case
SDL_VIDEORESIZE
:
vout_display_SendEventDisplaySize
(
vd
,
event
.
resize
.
w
,
event
.
resize
.
h
);
break
;
default:
break
;
}
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Key events handling
*****************************************************************************/
static
const
struct
{
static
const
struct
{
SDLKey
sdl_key
;
int
i_
vlckey
;
}
sdlkeys_to_vlckeys
[]
=
{
int
vlckey
;
}
sdlkeys_to_vlckeys
[]
=
{
{
SDLK_F1
,
KEY_F1
},
{
SDLK_F2
,
KEY_F2
},
{
SDLK_F3
,
KEY_F3
},
...
...
@@ -688,418 +715,12 @@ static const struct
{
0
,
0
}
};
static
int
ConvertKey
(
SDLKey
sdl_key
)
static
int
ConvertKey
(
SDLKey
sdl_key
)
{
int
i
;
for
(
i
=
0
;
sdlkeys_to_vlckeys
[
i
].
sdl_key
!=
0
;
i
++
)
{
if
(
sdlkeys_to_vlckeys
[
i
].
sdl_key
==
sdl_key
)
{
return
sdlkeys_to_vlckeys
[
i
].
i_vlckey
;
}
for
(
int
i
=
0
;
sdlkeys_to_vlckeys
[
i
].
sdl_key
!=
0
;
i
++
)
{
if
(
sdlkeys_to_vlckeys
[
i
].
sdl_key
==
sdl_key
)
return
sdlkeys_to_vlckeys
[
i
].
vlckey
;
}
return
0
;
}
/*****************************************************************************
* Display: displays previously rendered output
*****************************************************************************
* This function sends the currently rendered image to the display.
*****************************************************************************/
static
void
Display
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
unsigned
int
x
,
y
,
w
,
h
;
SDL_Rect
disp
;
vout_PlacePicture
(
p_vout
,
p_vout
->
p_sys
->
i_width
,
p_vout
->
p_sys
->
i_height
,
&
x
,
&
y
,
&
w
,
&
h
);
disp
.
x
=
x
;
disp
.
y
=
y
;
disp
.
w
=
w
;
disp
.
h
=
h
;
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
/* RGB picture */
SDL_Flip
(
p_vout
->
p_sys
->
p_display
);
}
else
{
/* Overlay picture */
SDL_UnlockYUVOverlay
(
p_pic
->
p_sys
->
p_overlay
);
SDL_DisplayYUVOverlay
(
p_pic
->
p_sys
->
p_overlay
,
&
disp
);
SDL_LockYUVOverlay
(
p_pic
->
p_sys
->
p_overlay
);
}
}
/* following functions are local */
/*****************************************************************************
* OpenDisplay: open and initialize SDL device
*****************************************************************************
* Open and initialize display according to preferences specified in the vout
* thread fields.
*****************************************************************************/
static
int
OpenDisplay
(
vout_thread_t
*
p_vout
)
{
uint32_t
i_flags
;
int
i_bpp
;
/* SDL fucked up fourcc definitions on bigendian machines */
uint32_t
i_sdl_chroma
;
char
*
psz_chroma
=
NULL
;
vlc_fourcc_t
i_chroma
=
0
;
bool
b_overlay
=
config_GetInt
(
p_vout
,
"overlay"
);
/* Set main window's size */
#if SDL_VERSION_ATLEAST(1,2,10)
p_vout
->
p_sys
->
i_width
=
p_vout
->
b_fullscreen
?
p_vout
->
p_sys
->
i_desktop_width
:
p_vout
->
i_window_width
;
p_vout
->
p_sys
->
i_height
=
p_vout
->
b_fullscreen
?
p_vout
->
p_sys
->
i_desktop_height
:
p_vout
->
i_window_height
;
#else
p_vout
->
p_sys
->
i_width
=
p_vout
->
b_fullscreen
?
p_vout
->
output
.
i_width
:
p_vout
->
i_window_width
;
p_vout
->
p_sys
->
i_height
=
p_vout
->
b_fullscreen
?
p_vout
->
output
.
i_height
:
p_vout
->
i_window_height
;
#endif
/* Initialize flags and cursor */
i_flags
=
SDL_ANYFORMAT
|
SDL_HWPALETTE
|
SDL_HWSURFACE
|
SDL_DOUBLEBUF
;
i_flags
|=
p_vout
->
b_fullscreen
?
SDL_FULLSCREEN
:
SDL_RESIZABLE
;
i_bpp
=
SDL_VideoModeOK
(
p_vout
->
p_sys
->
i_width
,
p_vout
->
p_sys
->
i_height
,
SDL_DEFAULT_BPP
,
i_flags
);
if
(
i_bpp
==
0
)
{
msg_Err
(
p_vout
,
"no video mode available"
);
return
VLC_EGENERIC
;
}
p_vout
->
p_sys
->
p_display
=
SDL_SetVideoMode
(
p_vout
->
p_sys
->
i_width
,
p_vout
->
p_sys
->
i_height
,
i_bpp
,
i_flags
);
if
(
p_vout
->
p_sys
->
p_display
==
NULL
)
{
msg_Err
(
p_vout
,
"cannot set video mode"
);
return
VLC_EGENERIC
;
}
SDL_LockSurface
(
p_vout
->
p_sys
->
p_display
);
if
(
(
psz_chroma
=
config_GetPsz
(
p_vout
,
"sdl-chroma"
)
)
)
{
i_chroma
=
vlc_fourcc_GetCodecFromString
(
VIDEO_ES
,
psz_chroma
);
if
(
i_chroma
)
{
msg_Dbg
(
p_vout
,
"Forcing chroma to 0x%.8x (%4.4s)"
,
i_chroma
,
(
char
*
)
&
i_chroma
);
}
else
{
free
(
psz_chroma
);
psz_chroma
=
NULL
;
}
}
if
(
b_overlay
)
{
/* Choose the chroma we will try first. */
do
{
if
(
!
psz_chroma
)
i_chroma
=
0
;
switch
(
i_chroma
?
i_chroma
:
p_vout
->
render
.
i_chroma
)
{
case
VLC_CODEC_YUYV
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YUYV
;
i_sdl_chroma
=
SDL_YUY2_OVERLAY
;
break
;
case
VLC_CODEC_UYVY
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_UYVY
;
i_sdl_chroma
=
SDL_UYVY_OVERLAY
;
break
;
case
VLC_CODEC_YVYU
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YVYU
;
i_sdl_chroma
=
SDL_YVYU_OVERLAY
;
break
;
case
VLC_CODEC_YV12
:
case
VLC_CODEC_I420
:
default:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YV12
;
i_sdl_chroma
=
SDL_YV12_OVERLAY
;
break
;
}
free
(
psz_chroma
);
psz_chroma
=
NULL
;
p_vout
->
p_sys
->
p_overlay
=
SDL_CreateYUVOverlay
(
32
,
32
,
i_sdl_chroma
,
p_vout
->
p_sys
->
p_display
);
/* FIXME: if the first overlay we find is software, don't stop,
* because we may find a hardware one later ... */
}
while
(
i_chroma
&&
!
p_vout
->
p_sys
->
p_overlay
);
/* If this best choice failed, fall back to other chromas */
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
p_vout
->
output
.
i_chroma
=
VLC_CODEC_I420
;
p_vout
->
p_sys
->
p_overlay
=
SDL_CreateYUVOverlay
(
32
,
32
,
SDL_IYUV_OVERLAY
,
p_vout
->
p_sys
->
p_display
);
}
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YV12
;
p_vout
->
p_sys
->
p_overlay
=
SDL_CreateYUVOverlay
(
32
,
32
,
SDL_YV12_OVERLAY
,
p_vout
->
p_sys
->
p_display
);
}
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YUYV
;
p_vout
->
p_sys
->
p_overlay
=
SDL_CreateYUVOverlay
(
32
,
32
,
SDL_YUY2_OVERLAY
,
p_vout
->
p_sys
->
p_display
);
}
}
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
if
(
b_overlay
)
msg_Warn
(
p_vout
,
"no SDL overlay for 0x%.8x (%4.4s)"
,
p_vout
->
render
.
i_chroma
,
(
char
*
)
&
p_vout
->
render
.
i_chroma
);
else
msg_Warn
(
p_vout
,
"SDL overlay disabled by the user"
);
switch
(
p_vout
->
p_sys
->
p_display
->
format
->
BitsPerPixel
)
{
case
8
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB8
;
p_vout
->
output
.
pf_setpalette
=
SetPalette
;
break
;
case
15
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB15
;
break
;
case
16
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB16
;
break
;
case
24
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB24
;
break
;
case
32
:
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB32
;
break
;
default:
msg_Err
(
p_vout
,
"unknown screen depth %i"
,
p_vout
->
p_sys
->
p_display
->
format
->
BitsPerPixel
);
SDL_UnlockSurface
(
p_vout
->
p_sys
->
p_display
);
SDL_FreeSurface
(
p_vout
->
p_sys
->
p_display
);
return
VLC_EGENERIC
;
}
p_vout
->
output
.
i_rmask
=
p_vout
->
p_sys
->
p_display
->
format
->
Rmask
;
p_vout
->
output
.
i_gmask
=
p_vout
->
p_sys
->
p_display
->
format
->
Gmask
;
p_vout
->
output
.
i_bmask
=
p_vout
->
p_sys
->
p_display
->
format
->
Bmask
;
SDL_WM_SetCaption
(
VOUT_TITLE
" (software RGB SDL output)"
,
VOUT_TITLE
" (software RGB SDL output)"
);
}
else
{
if
(
p_vout
->
p_sys
->
p_overlay
->
hw_overlay
)
{
SDL_WM_SetCaption
(
VOUT_TITLE
" (hardware YUV SDL output)"
,
VOUT_TITLE
" (hardware YUV SDL output)"
);
}
else
{
SDL_WM_SetCaption
(
VOUT_TITLE
" (software YUV SDL output)"
,
VOUT_TITLE
" (software YUV SDL output)"
);
}
}
SDL_EventState
(
SDL_KEYUP
,
SDL_IGNORE
);
/* ignore keys up */
return
VLC_SUCCESS
;
}
/*****************************************************************************
* CloseDisplay: close and reset SDL device
*****************************************************************************
* This function returns all resources allocated by OpenDisplay and restore
* the original state of the device.
*****************************************************************************/
static
void
CloseDisplay
(
vout_thread_t
*
p_vout
)
{
SDL_FreeYUVOverlay
(
p_vout
->
p_sys
->
p_overlay
);
SDL_UnlockSurface
(
p_vout
->
p_sys
->
p_display
);
SDL_FreeSurface
(
p_vout
->
p_sys
->
p_display
);
}
/*****************************************************************************
* NewPicture: allocate a picture
*****************************************************************************
* Returns 0 on success, -1 otherwise
*****************************************************************************/
static
int
NewPicture
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
int
i_width
=
p_vout
->
output
.
i_width
;
int
i_height
=
p_vout
->
output
.
i_height
;
if
(
p_vout
->
p_sys
->
p_overlay
==
NULL
)
{
/* RGB picture */
if
(
p_vout
->
p_sys
->
i_surfaces
)
{
/* We already allocated this surface, return */
return
VLC_EGENERIC
;
}
p_pic
->
p_sys
=
malloc
(
sizeof
(
picture_sys_t
)
);
if
(
p_pic
->
p_sys
==
NULL
)
{
return
VLC_ENOMEM
;
}
switch
(
p_vout
->
p_sys
->
p_display
->
format
->
BitsPerPixel
)
{
case
8
:
p_pic
->
p
->
i_pixel_pitch
=
1
;
break
;
case
15
:
case
16
:
p_pic
->
p
->
i_pixel_pitch
=
2
;
break
;
case
24
:
case
32
:
p_pic
->
p
->
i_pixel_pitch
=
4
;
break
;
default:
return
VLC_EGENERIC
;
}
p_pic
->
p
->
p_pixels
=
p_vout
->
p_sys
->
p_display
->
pixels
;
p_pic
->
p
->
i_lines
=
p_vout
->
p_sys
->
p_display
->
h
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
p_sys
->
p_display
->
h
;
p_pic
->
p
->
i_pitch
=
p_vout
->
p_sys
->
p_display
->
pitch
;
p_pic
->
p
->
i_visible_pitch
=
p_pic
->
p
->
i_pixel_pitch
*
p_vout
->
p_sys
->
p_display
->
w
;
p_vout
->
p_sys
->
i_surfaces
++
;
p_pic
->
i_planes
=
1
;
}
else
{
p_pic
->
p_sys
=
malloc
(
sizeof
(
picture_sys_t
)
);
if
(
p_pic
->
p_sys
==
NULL
)
{
return
VLC_ENOMEM
;
}
p_pic
->
p_sys
->
p_overlay
=
SDL_CreateYUVOverlay
(
i_width
,
i_height
,
p_vout
->
output
.
i_chroma
,
p_vout
->
p_sys
->
p_display
);
if
(
p_pic
->
p_sys
->
p_overlay
==
NULL
)
{
free
(
p_pic
->
p_sys
);
return
VLC_EGENERIC
;
}
SDL_LockYUVOverlay
(
p_pic
->
p_sys
->
p_overlay
);
p_pic
->
Y_PIXELS
=
p_pic
->
p_sys
->
p_overlay
->
pixels
[
0
];
p_pic
->
p
[
Y_PLANE
].
i_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
;
p_pic
->
p
[
Y_PLANE
].
i_visible_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
;
p_pic
->
p
[
Y_PLANE
].
i_pitch
=
p_pic
->
p_sys
->
p_overlay
->
pitches
[
0
];
switch
(
p_vout
->
output
.
i_chroma
)
{
case
SDL_YV12_OVERLAY
:
p_pic
->
p
[
Y_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
;
p_pic
->
U_PIXELS
=
p_pic
->
p_sys
->
p_overlay
->
pixels
[
2
];
p_pic
->
p
[
U_PLANE
].
i_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
U_PLANE
].
i_visible_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
U_PLANE
].
i_pitch
=
p_pic
->
p_sys
->
p_overlay
->
pitches
[
2
];
p_pic
->
p
[
U_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
U_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
/
2
;
p_pic
->
V_PIXELS
=
p_pic
->
p_sys
->
p_overlay
->
pixels
[
1
];
p_pic
->
p
[
V_PLANE
].
i_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
V_PLANE
].
i_visible_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
V_PLANE
].
i_pitch
=
p_pic
->
p_sys
->
p_overlay
->
pitches
[
1
];
p_pic
->
p
[
V_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
V_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
/
2
;
p_pic
->
i_planes
=
3
;
break
;
case
SDL_IYUV_OVERLAY
:
p_pic
->
p
[
Y_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
Y_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
;
p_pic
->
U_PIXELS
=
p_pic
->
p_sys
->
p_overlay
->
pixels
[
1
];
p_pic
->
p
[
U_PLANE
].
i_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
U_PLANE
].
i_visible_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
U_PLANE
].
i_pitch
=
p_pic
->
p_sys
->
p_overlay
->
pitches
[
1
];
p_pic
->
p
[
U_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
U_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
/
2
;
p_pic
->
V_PIXELS
=
p_pic
->
p_sys
->
p_overlay
->
pixels
[
2
];
p_pic
->
p
[
V_PLANE
].
i_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
V_PLANE
].
i_visible_lines
=
p_pic
->
p_sys
->
p_overlay
->
h
/
2
;
p_pic
->
p
[
V_PLANE
].
i_pitch
=
p_pic
->
p_sys
->
p_overlay
->
pitches
[
2
];
p_pic
->
p
[
V_PLANE
].
i_pixel_pitch
=
1
;
p_pic
->
p
[
V_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
/
2
;
p_pic
->
i_planes
=
3
;
break
;
default:
p_pic
->
p
[
Y_PLANE
].
i_pixel_pitch
=
2
;
p_pic
->
p
[
U_PLANE
].
i_visible_pitch
=
p_pic
->
p_sys
->
p_overlay
->
w
*
2
;
p_pic
->
i_planes
=
1
;
break
;
}
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* SetPalette: sets an 8 bpp palette
*****************************************************************************/
static
void
SetPalette
(
vout_thread_t
*
p_vout
,
uint16_t
*
red
,
uint16_t
*
green
,
uint16_t
*
blue
)
{
SDL_Color
colors
[
256
];
int
i
;
/* Fill colors with color information */
for
(
i
=
0
;
i
<
256
;
i
++
)
{
colors
[
i
].
r
=
red
[
i
]
>>
8
;
colors
[
i
].
g
=
green
[
i
]
>>
8
;
colors
[
i
].
b
=
blue
[
i
]
>>
8
;
}
/* Set palette */
if
(
SDL_SetColors
(
p_vout
->
p_sys
->
p_display
,
colors
,
0
,
256
)
==
0
)
{
msg_Err
(
p_vout
,
"failed to set palette"
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment