diff options
author | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
commit | 98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch) | |
tree | ebc6ec71f44bff8c42e4eefced61948623df02fc /modules/sdl | |
parent | e6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff) |
baresip 0.4.10
Diffstat (limited to 'modules/sdl')
-rw-r--r-- | modules/sdl/module.mk | 19 | ||||
-rw-r--r-- | modules/sdl/sdl.c | 319 | ||||
-rw-r--r-- | modules/sdl/sdl.h | 9 | ||||
-rw-r--r-- | modules/sdl/util.c | 54 |
4 files changed, 401 insertions, 0 deletions
diff --git a/modules/sdl/module.mk b/modules/sdl/module.mk new file mode 100644 index 0000000..bf100e5 --- /dev/null +++ b/modules/sdl/module.mk @@ -0,0 +1,19 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := sdl +$(MOD)_SRCS += sdl.c +$(MOD)_SRCS += util.c + +CFLAGS += -DUSE_SDL +$(MOD)_LFLAGS += -lSDL +ifeq ($(OS),darwin) +# note: APP_LFLAGS is needed, as main.o links to -lSDLmain +APP_LFLAGS += -lSDL -lSDLmain -lobjc \ + -framework CoreFoundation -framework Foundation -framework Cocoa +endif + +include mk/mod.mk diff --git a/modules/sdl/sdl.c b/modules/sdl/sdl.c new file mode 100644 index 0000000..eb902b3 --- /dev/null +++ b/modules/sdl/sdl.c @@ -0,0 +1,319 @@ +/** + * @file sdl/sdl.c SDL - Simple DirectMedia Layer v1.2 + * + * Copyright (C) 2010 Creytiv.com + */ +#include <SDL/SDL.h> +#include <string.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include "sdl.h" + + +/** Local constants */ +enum { + KEY_RELEASE_VAL = 250 /**< Key release value in [ms] */ +}; + +struct vidisp_st { + struct vidisp *vd; /* inheritance */ +}; + +/** Global SDL data */ +static struct { + struct tmr tmr; + SDL_Surface *screen; /**< SDL Surface */ + SDL_Overlay *bmp; /**< SDL YUV Overlay */ + struct vidsz size; /**< Current size */ + vidisp_resize_h *resizeh; /**< Screen resize handler */ + void *arg; /**< Handler argument */ + bool fullscreen; + bool open; +} sdl; + + +static struct vidisp *vid; + + +static void event_handler(void *arg); + + +static void sdl_reset(void) +{ + if (sdl.bmp) { + SDL_FreeYUVOverlay(sdl.bmp); + sdl.bmp = NULL; + } + + if (sdl.screen) { + SDL_FreeSurface(sdl.screen); + sdl.screen = NULL; + } +} + + +static void handle_resize(int w, int h) +{ + struct vidsz size; + + size.w = w; + size.h = h; + + /* notify app */ + if (sdl.resizeh) + sdl.resizeh(&size, sdl.arg); +} + + +static void timeout(void *arg) +{ + (void)arg; + + tmr_start(&sdl.tmr, 1, event_handler, NULL); + + /* Emulate key-release */ + ui_input(0x00); +} + + +static void event_handler(void *arg) +{ + SDL_Event event; + char ch; + + (void)arg; + + tmr_start(&sdl.tmr, 100, event_handler, NULL); + + while (SDL_PollEvent(&event)) { + + switch (event.type) { + + case SDL_KEYDOWN: + + switch (event.key.keysym.sym) { + + case SDLK_ESCAPE: + if (!sdl.fullscreen) + break; + + sdl.fullscreen = false; + sdl_reset(); + break; + + case SDLK_f: + if (sdl.fullscreen) + break; + + sdl.fullscreen = true; + sdl_reset(); + break; + + default: + ch = event.key.keysym.unicode & 0x7f; + + /* Relay key-press to UI subsystem */ + if (isprint(ch)) { + tmr_start(&sdl.tmr, KEY_RELEASE_VAL, + timeout, NULL); + ui_input(ch); + } + break; + } + + break; + + case SDL_VIDEORESIZE: + handle_resize(event.resize.w, event.resize.h); + break; + + case SDL_QUIT: + ui_input('q'); + break; + + default: + break; + } + } +} + + +static int sdl_open(void) +{ + if (sdl.open) + return 0; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + warning("sdl: unable to init SDL: %s\n", SDL_GetError()); + return ENODEV; + } + + SDL_EnableUNICODE(1); + + tmr_start(&sdl.tmr, 100, event_handler, NULL); + sdl.open = true; + + return 0; +} + + +static void sdl_close(void) +{ + tmr_cancel(&sdl.tmr); + sdl_reset(); + + if (sdl.open) { + SDL_Quit(); + sdl.open = false; + } +} + + +static void destructor(void *arg) +{ + struct vidisp_st *st = arg; + + mem_deref(st->vd); + sdl_close(); +} + + +static int alloc(struct vidisp_st **stp, struct vidisp *vd, + struct vidisp_prm *prm, const char *dev, + vidisp_resize_h *resizeh, void *arg) +{ + struct vidisp_st *st; + int err; + + /* Not used by SDL */ + (void)prm; + (void)dev; + + if (sdl.open) + return EBUSY; + + st = mem_zalloc(sizeof(*st), destructor); + if (!st) + return ENOMEM; + + st->vd = mem_ref(vd); + + sdl.resizeh = resizeh; + sdl.arg = arg; + + err = sdl_open(); + + if (err) + mem_deref(st); + else + *stp = st; + + return err; +} + + +/** + * Display a video frame + * + * @param st Video display state + * @param title Window title + * @param frame Video frame + * + * @return 0 if success, otherwise errorcode + * + * @note: On Darwin, this must be called from the main thread + */ +static int display(struct vidisp_st *st, const char *title, + const struct vidframe *frame) +{ + SDL_Rect rect; + + if (!st || !sdl.open) + return EINVAL; + + if (!vidsz_cmp(&sdl.size, &frame->size)) { + if (sdl.size.w && sdl.size.h) { + info("sdl: reset size %u x %u ---> %u x %u\n", + sdl.size.w, sdl.size.h, + frame->size.w, frame->size.h); + } + sdl_reset(); + } + + if (!sdl.screen) { + int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; + char capt[256]; + + if (sdl.fullscreen) + flags |= SDL_FULLSCREEN; + else if (sdl.resizeh) + flags |= SDL_RESIZABLE; + + if (title) { + re_snprintf(capt, sizeof(capt), "%s - %u x %u", + title, frame->size.w, frame->size.h); + } + else { + re_snprintf(capt, sizeof(capt), "%u x %u", + frame->size.w, frame->size.h); + } + + SDL_WM_SetCaption(capt, capt); + + sdl.screen = SDL_SetVideoMode(frame->size.w, frame->size.h, + 0, flags); + if (!sdl.screen) { + warning("sdl: unable to get video screen: %s\n", + SDL_GetError()); + return ENODEV; + } + + sdl.size = frame->size; + } + + if (!sdl.bmp) { + sdl.bmp = SDL_CreateYUVOverlay(frame->size.w, frame->size.h, + SDL_YV12_OVERLAY, sdl.screen); + if (!sdl.bmp) { + warning("sdl: unable to create overlay: %s\n", + SDL_GetError()); + return ENODEV; + } + } + + SDL_LockYUVOverlay(sdl.bmp); + picture_copy(sdl.bmp->pixels, sdl.bmp->pitches, frame); + SDL_UnlockYUVOverlay(sdl.bmp); + + rect.x = 0; + rect.y = 0; + rect.w = sdl.size.w; + rect.h = sdl.size.h; + + SDL_DisplayYUVOverlay(sdl.bmp, &rect); + + return 0; +} + + +static int module_init(void) +{ + return vidisp_register(&vid, "sdl", alloc, NULL, display, NULL); +} + + +static int module_close(void) +{ + vid = mem_deref(vid); + + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(sdl) = { + "sdl", + "vidisp", + module_init, + module_close, +}; diff --git a/modules/sdl/sdl.h b/modules/sdl/sdl.h new file mode 100644 index 0000000..992f70d --- /dev/null +++ b/modules/sdl/sdl.h @@ -0,0 +1,9 @@ +/** + * @file sdl.h Simple DirectMedia Layer module -- internal interface + * + * Copyright (C) 2010 Creytiv.com + */ + + +void picture_copy(uint8_t *data[4], uint16_t linesize[4], + const struct vidframe *frame); diff --git a/modules/sdl/util.c b/modules/sdl/util.c new file mode 100644 index 0000000..59a1cdd --- /dev/null +++ b/modules/sdl/util.c @@ -0,0 +1,54 @@ +/** + * @file util.c Simple DirectMedia Layer module -- utilities + * + * Copyright (C) 2010 Creytiv.com + */ +#include <string.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include "sdl.h" + + +static void img_copy_plane(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + if (!dst || !src) + return; + + for (;height > 0; height--) { + memcpy(dst, src, width); + dst += dst_wrap; + src += src_wrap; + } +} + + +static int get_plane_bytewidth(int width, int plane) +{ + if (plane == 1 || plane == 2) + width = -((-width) >> 1); + + return (width * 8 + 7) >> 3; +} + + +void picture_copy(uint8_t *data[4], uint16_t linesize[4], + const struct vidframe *frame) +{ + const int map[3] = {0, 2, 1}; + int i; + + for (i=0; i<3; i++) { + int h; + int bwidth = get_plane_bytewidth(frame->size.w, i); + h = frame->size.h; + if (i == 1 || i == 2) { + h = -((-frame->size.h) >> 1); + } + img_copy_plane(data[map[i]], linesize[map[i]], + frame->data[i], frame->linesize[i], + bwidth, h); + } +} |