Ticket #1744: 0001-lavd-sdl-add-event-handler-thread.patch
| File 0001-lavd-sdl-add-event-handler-thread.patch, 7.6 KB (added by , 13 years ago) |
|---|
-
doc/outdevs.texi
From 68c91ee76c11e404af913a62113b206869633c3c Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <stefasab@gmail.com> Date: Sun, 24 Nov 2013 19:32:59 +0100 Subject: [PATCH] lavd/sdl: add event handler thread Untested on Windows, meant to address ticket #1743 and #1744. TODO: bump micro --- doc/outdevs.texi | 10 ++++ libavdevice/sdl.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 131 insertions(+), 21 deletions(-) diff --git a/doc/outdevs.texi b/doc/outdevs.texi index 8038def..6c8422c 100644
a b Set fullscreen mode when non-zero value is provided. 209 209 Default value is zero. 210 210 @end table 211 211 212 @subsection Interactive commands 213 214 The window created by the device can be controlled through the 215 following interactive commands. 216 217 @table @key 218 @item q, ESC 219 Quit the device immediately. 220 @end table 221 212 222 @subsection Examples 213 223 214 224 The following command shows the @command{ffmpeg} output is an -
libavdevice/sdl.c
diff --git a/libavdevice/sdl.c b/libavdevice/sdl.c index 0210ad2..0c0355a 100644
a b 24 24 */ 25 25 26 26 #include <SDL.h> 27 #include <SDL_thread.h> 28 27 29 #include "libavutil/avstring.h" 28 30 #include "libavutil/opt.h" 29 31 #include "libavutil/parseutils.h" 30 32 #include "libavutil/pixdesc.h" 33 #include "libavutil/time.h" 31 34 #include "avdevice.h" 32 35 33 36 typedef struct { … … typedef struct { 42 45 int overlay_x, overlay_y; 43 46 int overlay_fmt; 44 47 int sdl_was_already_inited; 48 SDL_Thread *event_thread; 49 SDL_mutex *mutex; 50 SDL_cond *init_cond; 51 int init_ret; /* return code used to signal initialization errors */ 52 int inited; 53 int quit; 45 54 } SDLContext; 46 55 47 56 static const struct sdl_overlay_pix_fmt_entry { … … static int sdl_write_trailer(AVFormatContext *s) 57 66 { 58 67 SDLContext *sdl = s->priv_data; 59 68 60 if (sdl->overlay) { 69 sdl->quit = 1; 70 71 if (sdl->overlay) 61 72 SDL_FreeYUVOverlay(sdl->overlay); 62 sdl->overlay = NULL; 63 } 73 if (sdl->event_thread) 74 SDL_WaitThread(sdl->event_thread, NULL); 75 if (sdl->mutex) 76 SDL_DestroyMutex(sdl->mutex); 77 if (sdl->init_cond) 78 SDL_DestroyCond(sdl->init_cond); 79 64 80 if (!sdl->sdl_was_already_inited) 65 81 SDL_Quit(); 66 82 67 83 return 0; 68 84 } 69 85 86 static int event_thread(void *arg) 87 { 88 AVFormatContext *s = arg; 89 SDLContext *sdl = s->priv_data; 90 int flags = SDL_SWSURFACE | sdl->window_fullscreen ? SDL_FULLSCREEN : 0; 91 AVStream *st = s->streams[0]; 92 AVCodecContext *encctx = st->codec; 93 94 /* initialization */ 95 SDL_WM_SetCaption(sdl->window_title, sdl->icon_title); 96 sdl->surface = SDL_SetVideoMode(sdl->window_width, sdl->window_height, 97 24, flags); 98 if (!sdl->surface) { 99 av_log(sdl, AV_LOG_ERROR, "Unable to set video mode: %s\n", SDL_GetError()); 100 sdl->init_ret = AVERROR(EINVAL); 101 goto init_end; 102 } 103 104 sdl->overlay = SDL_CreateYUVOverlay(encctx->width, encctx->height, 105 sdl->overlay_fmt, sdl->surface); 106 if (!sdl->overlay || sdl->overlay->pitches[0] < encctx->width) { 107 av_log(s, AV_LOG_ERROR, 108 "SDL does not support an overlay with size of %dx%d pixels\n", 109 encctx->width, encctx->height); 110 sdl->init_ret = AVERROR(EINVAL); 111 goto init_end; 112 } 113 114 sdl->init_ret = 0; 115 av_log(s, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d\n", 116 encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt), 117 sdl->overlay_width, sdl->overlay_height); 118 119 init_end: 120 SDL_LockMutex(sdl->mutex); 121 sdl->inited = 1; 122 SDL_UnlockMutex(sdl->mutex); 123 SDL_CondSignal(sdl->init_cond); 124 125 if (sdl->init_ret < 0) 126 return sdl->init_ret; 127 128 /* event loop */ 129 while (!sdl->quit) { 130 int ret; 131 SDL_Event event; 132 SDL_PumpEvents(); 133 ret = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_ALLEVENTS); 134 if (ret < 0) 135 av_log(s, AV_LOG_ERROR, "Error when getting SDL event: %s\n", SDL_GetError()); 136 if (ret <= 0) 137 continue; 138 139 switch (event.type) { 140 case SDL_KEYDOWN: 141 switch (event.key.keysym.sym) { 142 case SDLK_ESCAPE: 143 case SDLK_q: 144 sdl->quit = 1; 145 break; 146 } 147 break; 148 case SDL_QUIT: 149 sdl->quit = 1; 150 break; 151 default: 152 break; 153 } 154 } 155 156 return 0; 157 } 158 70 159 static int sdl_write_header(AVFormatContext *s) 71 160 { 72 161 SDLContext *sdl = s->priv_data; … … static int sdl_write_header(AVFormatContext *s) 74 163 AVCodecContext *encctx = st->codec; 75 164 AVRational sar, dar; /* sample and display aspect ratios */ 76 165 int i, ret; 77 int flags = SDL_SWSURFACE | sdl->window_fullscreen ? SDL_FULLSCREEN : 0;78 166 79 167 if (!sdl->window_title) 80 168 sdl->window_title = av_strdup(s->filename); … … static int sdl_write_header(AVFormatContext *s) 148 236 sdl->overlay_x = (sdl->window_width - sdl->overlay_width ) / 2; 149 237 sdl->overlay_y = (sdl->window_height - sdl->overlay_height) / 2; 150 238 151 SDL_WM_SetCaption(sdl->window_title, sdl->icon_title); 152 sdl->surface = SDL_SetVideoMode(sdl->window_width, sdl->window_height, 153 24, flags); 154 if (!sdl->surface) { 155 av_log(s, AV_LOG_ERROR, "Unable to set video mode: %s\n", SDL_GetError()); 156 ret = AVERROR(EINVAL); 239 sdl->init_cond = SDL_CreateCond(); 240 if (!sdl->init_cond) { 241 av_log(s, AV_LOG_ERROR, "Could not create SDL condition variable: %s\n", SDL_GetError()); 242 ret = AVERROR_EXTERNAL; 157 243 goto fail; 158 244 } 159 160 sdl->overlay = SDL_CreateYUVOverlay(encctx->width, encctx->height, 161 sdl->overlay_fmt, sdl->surface); 162 if (!sdl->overlay || sdl->overlay->pitches[0] < encctx->width) { 163 av_log(s, AV_LOG_ERROR, 164 "SDL does not support an overlay with size of %dx%d pixels\n", 165 encctx->width, encctx->height); 166 ret = AVERROR(EINVAL); 245 sdl->mutex = SDL_CreateMutex(); 246 if (!sdl->mutex) { 247 av_log(s, AV_LOG_ERROR, "Could not create SDL mutex: %s\n", SDL_GetError()); 248 ret = AVERROR_EXTERNAL; 249 goto fail; 250 } 251 sdl->event_thread = SDL_CreateThread(event_thread, s); 252 if (!sdl->event_thread) { 253 av_log(s, AV_LOG_ERROR, "Could not create SDL event thread: %s\n", SDL_GetError()); 254 ret = AVERROR_EXTERNAL; 167 255 goto fail; 168 256 } 169 257 170 av_log(s, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d\n", 171 encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt), sar.num, sar.den, 172 sdl->overlay_width, sdl->overlay_height); 258 /* wait until the video system has been inited */ 259 SDL_LockMutex(sdl->mutex); 260 if (!sdl->inited) { 261 SDL_CondWait(sdl->init_cond, sdl->mutex); 262 } 263 SDL_UnlockMutex(sdl->mutex); 264 if (sdl->init_ret < 0) { 265 ret = sdl->init_ret; 266 goto fail; 267 } 173 268 return 0; 174 269 175 270 fail: … … static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt) 185 280 AVPicture pict; 186 281 int i; 187 282 283 if (sdl->quit) 284 return AVERROR(EIO); 188 285 avpicture_fill(&pict, pkt->data, encctx->pix_fmt, encctx->width, encctx->height); 189 286 287 SDL_LockMutex(sdl->mutex); 190 288 SDL_FillRect(sdl->surface, &sdl->surface->clip_rect, 191 289 SDL_MapRGB(sdl->surface->format, 0, 0, 0)); 290 SDL_UnlockMutex(sdl->mutex); 291 192 292 SDL_LockYUVOverlay(sdl->overlay); 193 293 for (i = 0; i < 3; i++) { 194 294 sdl->overlay->pixels [i] = pict.data [i];
