Ticket #1744: 0002-lavd-sdl-add-event-handler-thread.patch
| File 0002-lavd-sdl-add-event-handler-thread.patch, 8.3 KB (added by , 13 years ago) |
|---|
-
doc/outdevs.texi
From 9a8f091d17c21daebcc1d1f922d1525a7ad891f6 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 SDL_Init() is called on the event handler thread, as required by SDL in Windows to avoid deadlocks. Should address ticket #1743 and #1744. TODO: bump micro --- doc/outdevs.texi | 10 ++++ libavdevice/sdl.c | 154 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 137 insertions(+), 27 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..91a2143 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 if (SDL_Init(SDL_INIT_VIDEO) != 0) { 96 av_log(s, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError()); 97 sdl->init_ret = AVERROR(EINVAL); 98 goto init_end; 99 } 100 101 SDL_WM_SetCaption(sdl->window_title, sdl->icon_title); 102 sdl->surface = SDL_SetVideoMode(sdl->window_width, sdl->window_height, 103 24, flags); 104 if (!sdl->surface) { 105 av_log(sdl, AV_LOG_ERROR, "Unable to set video mode: %s\n", SDL_GetError()); 106 sdl->init_ret = AVERROR(EINVAL); 107 goto init_end; 108 } 109 110 sdl->overlay = SDL_CreateYUVOverlay(encctx->width, encctx->height, 111 sdl->overlay_fmt, sdl->surface); 112 if (!sdl->overlay || sdl->overlay->pitches[0] < encctx->width) { 113 av_log(s, AV_LOG_ERROR, 114 "SDL does not support an overlay with size of %dx%d pixels\n", 115 encctx->width, encctx->height); 116 sdl->init_ret = AVERROR(EINVAL); 117 goto init_end; 118 } 119 120 sdl->init_ret = 0; 121 av_log(s, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d\n", 122 encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt), 123 sdl->overlay_width, sdl->overlay_height); 124 125 init_end: 126 SDL_LockMutex(sdl->mutex); 127 sdl->inited = 1; 128 SDL_UnlockMutex(sdl->mutex); 129 SDL_CondSignal(sdl->init_cond); 130 131 if (sdl->init_ret < 0) 132 return sdl->init_ret; 133 134 /* event loop */ 135 while (!sdl->quit) { 136 int ret; 137 SDL_Event event; 138 SDL_PumpEvents(); 139 ret = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_ALLEVENTS); 140 if (ret < 0) 141 av_log(s, AV_LOG_ERROR, "Error when getting SDL event: %s\n", SDL_GetError()); 142 if (ret <= 0) 143 continue; 144 145 switch (event.type) { 146 case SDL_KEYDOWN: 147 switch (event.key.keysym.sym) { 148 case SDLK_ESCAPE: 149 case SDLK_q: 150 sdl->quit = 1; 151 break; 152 } 153 break; 154 case SDL_QUIT: 155 sdl->quit = 1; 156 break; 157 default: 158 break; 159 } 160 } 161 162 return 0; 163 } 164 70 165 static int sdl_write_header(AVFormatContext *s) 71 166 { 72 167 SDLContext *sdl = s->priv_data; … … static int sdl_write_header(AVFormatContext *s) 74 169 AVCodecContext *encctx = st->codec; 75 170 AVRational sar, dar; /* sample and display aspect ratios */ 76 171 int i, ret; 77 int flags = SDL_SWSURFACE | sdl->window_fullscreen ? SDL_FULLSCREEN : 0;78 172 79 173 if (!sdl->window_title) 80 174 sdl->window_title = av_strdup(s->filename); … … static int sdl_write_header(AVFormatContext *s) 89 183 goto fail; 90 184 } 91 185 92 if (SDL_Init(SDL_INIT_VIDEO) != 0) {93 av_log(s, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError());94 ret = AVERROR(EINVAL);95 goto fail;96 }97 98 186 if ( s->nb_streams > 1 99 187 || encctx->codec_type != AVMEDIA_TYPE_VIDEO 100 188 || encctx->codec_id != AV_CODEC_ID_RAWVIDEO) { … … 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];
