Ticket #1744: 0001-lavd-sdl-add-event-handler-thread.patch

File 0001-lavd-sdl-add-event-handler-thread.patch, 7.6 KB (added by saste, 6 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. 
    209209Default value is zero.
    210210@end table
    211211
     212@subsection Interactive commands
     213
     214The window created by the device can be controlled through the
     215following interactive commands.
     216
     217@table @key
     218@item q, ESC
     219Quit the device immediately.
     220@end table
     221
    212222@subsection Examples
    213223
    214224The 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  
    2424 */
    2525
    2626#include <SDL.h>
     27#include <SDL_thread.h>
     28
    2729#include "libavutil/avstring.h"
    2830#include "libavutil/opt.h"
    2931#include "libavutil/parseutils.h"
    3032#include "libavutil/pixdesc.h"
     33#include "libavutil/time.h"
    3134#include "avdevice.h"
    3235
    3336typedef struct {
    typedef struct { 
    4245    int overlay_x, overlay_y;
    4346    int overlay_fmt;
    4447    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;
    4554} SDLContext;
    4655
    4756static const struct sdl_overlay_pix_fmt_entry {
    static int sdl_write_trailer(AVFormatContext *s) 
    5766{
    5867    SDLContext *sdl = s->priv_data;
    5968
    60     if (sdl->overlay) {
     69    sdl->quit = 1;
     70
     71    if (sdl->overlay)
    6172        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
    6480    if (!sdl->sdl_was_already_inited)
    6581        SDL_Quit();
    6682
    6783    return 0;
    6884}
    6985
     86static 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
     119init_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
    70159static int sdl_write_header(AVFormatContext *s)
    71160{
    72161    SDLContext *sdl = s->priv_data;
    static int sdl_write_header(AVFormatContext *s) 
    74163    AVCodecContext *encctx = st->codec;
    75164    AVRational sar, dar; /* sample and display aspect ratios */
    76165    int i, ret;
    77     int flags = SDL_SWSURFACE | sdl->window_fullscreen ? SDL_FULLSCREEN : 0;
    78166
    79167    if (!sdl->window_title)
    80168        sdl->window_title = av_strdup(s->filename);
    static int sdl_write_header(AVFormatContext *s) 
    148236    sdl->overlay_x = (sdl->window_width  - sdl->overlay_width ) / 2;
    149237    sdl->overlay_y = (sdl->window_height - sdl->overlay_height) / 2;
    150238
    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;
    157243        goto fail;
    158244    }
    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;
    167255        goto fail;
    168256    }
    169257
    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    }
    173268    return 0;
    174269
    175270fail:
    static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt) 
    185280    AVPicture pict;
    186281    int i;
    187282
     283    if (sdl->quit)
     284        return AVERROR(EIO);
    188285    avpicture_fill(&pict, pkt->data, encctx->pix_fmt, encctx->width, encctx->height);
    189286
     287    SDL_LockMutex(sdl->mutex);
    190288    SDL_FillRect(sdl->surface, &sdl->surface->clip_rect,
    191289                 SDL_MapRGB(sdl->surface->format, 0, 0, 0));
     290    SDL_UnlockMutex(sdl->mutex);
     291
    192292    SDL_LockYUVOverlay(sdl->overlay);
    193293    for (i = 0; i < 3; i++) {
    194294        sdl->overlay->pixels [i] = pict.data    [i];