@ -24,10 +24,13 @@
*/
# include <SDL.h>
# include <SDL_thread.h>
# include "libavutil/avstring.h"
# include "libavutil/opt.h"
# include "libavutil/parseutils.h"
# include "libavutil/pixdesc.h"
# include "libavutil/time.h"
# include "avdevice.h"
typedef struct {
@ -42,6 +45,12 @@ typedef struct {
int overlay_x , overlay_y ;
int overlay_fmt ;
int sdl_was_already_inited ;
SDL_Thread * event_thread ;
SDL_mutex * mutex ;
SDL_cond * init_cond ;
int init_ret ; /* return code used to signal initialization errors */
int inited ;
int quit ;
} SDLContext ;
static const struct sdl_overlay_pix_fmt_entry {
@ -57,16 +66,102 @@ static int sdl_write_trailer(AVFormatContext *s)
{
SDLContext * sdl = s - > priv_data ;
if ( sdl - > overlay ) {
sdl - > quit = 1 ;
if ( sdl - > overlay )
SDL_FreeYUVOverlay ( sdl - > overlay ) ;
sdl - > overlay = NULL ;
}
if ( sdl - > event_thread )
SDL_WaitThread ( sdl - > event_thread , NULL ) ;
if ( sdl - > mutex )
SDL_DestroyMutex ( sdl - > mutex ) ;
if ( sdl - > init_cond )
SDL_DestroyCond ( sdl - > init_cond ) ;
if ( ! sdl - > sdl_was_already_inited )
SDL_Quit ( ) ;
return 0 ;
}
static int event_thread ( void * arg )
{
AVFormatContext * s = arg ;
SDLContext * sdl = s - > priv_data ;
int flags = SDL_SWSURFACE | ( sdl - > window_fullscreen ? SDL_FULLSCREEN : 0 ) ;
AVStream * st = s - > streams [ 0 ] ;
AVCodecContext * encctx = st - > codec ;
/* initialization */
if ( SDL_Init ( SDL_INIT_VIDEO ) ! = 0 ) {
av_log ( s , AV_LOG_ERROR , " Unable to initialize SDL: %s \n " , SDL_GetError ( ) ) ;
sdl - > init_ret = AVERROR ( EINVAL ) ;
goto init_end ;
}
SDL_WM_SetCaption ( sdl - > window_title , sdl - > icon_title ) ;
sdl - > surface = SDL_SetVideoMode ( sdl - > window_width , sdl - > window_height ,
24 , flags ) ;
if ( ! sdl - > surface ) {
av_log ( sdl , AV_LOG_ERROR , " Unable to set video mode: %s \n " , SDL_GetError ( ) ) ;
sdl - > init_ret = AVERROR ( EINVAL ) ;
goto init_end ;
}
sdl - > overlay = SDL_CreateYUVOverlay ( encctx - > width , encctx - > height ,
sdl - > overlay_fmt , sdl - > surface ) ;
if ( ! sdl - > overlay | | sdl - > overlay - > pitches [ 0 ] < encctx - > width ) {
av_log ( s , AV_LOG_ERROR ,
" SDL does not support an overlay with size of %dx%d pixels \n " ,
encctx - > width , encctx - > height ) ;
sdl - > init_ret = AVERROR ( EINVAL ) ;
goto init_end ;
}
sdl - > init_ret = 0 ;
av_log ( s , AV_LOG_VERBOSE , " w:%d h:%d fmt:%s -> w:%d h:%d \n " ,
encctx - > width , encctx - > height , av_get_pix_fmt_name ( encctx - > pix_fmt ) ,
sdl - > overlay_width , sdl - > overlay_height ) ;
init_end :
SDL_LockMutex ( sdl - > mutex ) ;
sdl - > inited = 1 ;
SDL_UnlockMutex ( sdl - > mutex ) ;
SDL_CondSignal ( sdl - > init_cond ) ;
if ( sdl - > init_ret < 0 )
return sdl - > init_ret ;
/* event loop */
while ( ! sdl - > quit ) {
int ret ;
SDL_Event event ;
SDL_PumpEvents ( ) ;
ret = SDL_PeepEvents ( & event , 1 , SDL_GETEVENT , SDL_ALLEVENTS ) ;
if ( ret < 0 )
av_log ( s , AV_LOG_ERROR , " Error when getting SDL event: %s \n " , SDL_GetError ( ) ) ;
if ( ret < = 0 )
continue ;
switch ( event . type ) {
case SDL_KEYDOWN :
switch ( event . key . keysym . sym ) {
case SDLK_ESCAPE :
case SDLK_q :
sdl - > quit = 1 ;
break ;
}
break ;
case SDL_QUIT :
sdl - > quit = 1 ;
break ;
default :
break ;
}
}
return 0 ;
}
static int sdl_write_header ( AVFormatContext * s )
{
SDLContext * sdl = s - > priv_data ;
@ -74,7 +169,6 @@ static int sdl_write_header(AVFormatContext *s)
AVCodecContext * encctx = st - > codec ;
AVRational sar , dar ; /* sample and display aspect ratios */
int i , ret ;
int flags = SDL_SWSURFACE | sdl - > window_fullscreen ? SDL_FULLSCREEN : 0 ;
if ( ! sdl - > window_title )
sdl - > window_title = av_strdup ( s - > filename ) ;
@ -89,12 +183,6 @@ static int sdl_write_header(AVFormatContext *s)
goto fail ;
}
if ( SDL_Init ( SDL_INIT_VIDEO ) ! = 0 ) {
av_log ( s , AV_LOG_ERROR , " Unable to initialize SDL: %s \n " , SDL_GetError ( ) ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( s - > nb_streams > 1
| | encctx - > codec_type ! = AVMEDIA_TYPE_VIDEO
| | encctx - > codec_id ! = AV_CODEC_ID_RAWVIDEO ) {
@ -148,28 +236,35 @@ static int sdl_write_header(AVFormatContext *s)
sdl - > overlay_x = ( sdl - > window_width - sdl - > overlay_width ) / 2 ;
sdl - > overlay_y = ( sdl - > window_height - sdl - > overlay_height ) / 2 ;
SDL_WM_SetCaption ( sdl - > window_title , sdl - > icon_title ) ;
sdl - > surface = SDL_SetVideoMode ( sdl - > window_width , sdl - > window_height ,
24 , flags ) ;
if ( ! sdl - > surface ) {
av_log ( s , AV_LOG_ERROR , " Unable to set video mode: %s \n " , SDL_GetError ( ) ) ;
ret = AVERROR ( EINVAL ) ;
sdl - > init_cond = SDL_CreateCond ( ) ;
if ( ! sdl - > init_cond ) {
av_log ( s , AV_LOG_ERROR , " Could not create SDL condition variable: %s \n " , SDL_GetError ( ) ) ;
ret = AVERROR_EXTERNAL ;
goto fail ;
}
sdl - > overlay = SDL_CreateYUVOverlay ( encctx - > width , encctx - > height ,
sdl - > overlay_fmt , sdl - > surface ) ;
if ( ! sdl - > overlay | | sdl - > overlay - > pitches [ 0 ] < encctx - > width ) {
av_log ( s , AV_LOG_ERROR ,
" SDL does not support an overlay with size of %dx%d pixels \n " ,
encctx - > width , encctx - > height ) ;
ret = AVERROR ( EINVAL ) ;
sdl - > mutex = SDL_CreateMutex ( ) ;
if ( ! sdl - > mutex ) {
av_log ( s , AV_LOG_ERROR , " Could not create SDL mutex: %s \n " , SDL_GetError ( ) ) ;
ret = AVERROR_EXTERNAL ;
goto fail ;
}
sdl - > event_thread = SDL_CreateThread ( event_thread , s ) ;
if ( ! sdl - > event_thread ) {
av_log ( s , AV_LOG_ERROR , " Could not create SDL event thread: %s \n " , SDL_GetError ( ) ) ;
ret = AVERROR_EXTERNAL ;
goto fail ;
}
av_log ( s , AV_LOG_VERBOSE , " w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d \n " ,
encctx - > width , encctx - > height , av_get_pix_fmt_name ( encctx - > pix_fmt ) , sar . num , sar . den ,
sdl - > overlay_width , sdl - > overlay_height ) ;
/* wait until the video system has been inited */
SDL_LockMutex ( sdl - > mutex ) ;
if ( ! sdl - > inited ) {
SDL_CondWait ( sdl - > init_cond , sdl - > mutex ) ;
}
SDL_UnlockMutex ( sdl - > mutex ) ;
if ( sdl - > init_ret < 0 ) {
ret = sdl - > init_ret ;
goto fail ;
}
return 0 ;
fail :
@ -185,10 +280,15 @@ static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt)
AVPicture pict ;
int i ;
if ( sdl - > quit )
return AVERROR ( EIO ) ;
avpicture_fill ( & pict , pkt - > data , encctx - > pix_fmt , encctx - > width , encctx - > height ) ;
SDL_LockMutex ( sdl - > mutex ) ;
SDL_FillRect ( sdl - > surface , & sdl - > surface - > clip_rect ,
SDL_MapRGB ( sdl - > surface - > format , 0 , 0 , 0 ) ) ;
SDL_UnlockMutex ( sdl - > mutex ) ;
SDL_LockYUVOverlay ( sdl - > overlay ) ;
for ( i = 0 ; i < 3 ; i + + ) {
sdl - > overlay - > pixels [ i ] = pict . data [ i ] ;