Index: Makefile.in =================================================================== --- Makefile.in (Revision 444) +++ Makefile.in (Arbeitskopie) @@ -37,7 +37,7 @@ OBJ = motion.o logger.o conf.o draw.o jpegutils.o vloopback_motion.o $(VIDEO_OBJ) \ netcam.o netcam_ftp.o netcam_jpeg.o netcam_wget.o track.o \ alg.o event.o picture.o rotate.o webhttpd.o \ - stream.o @FFMPEG_OBJ@ + stream.o @FFMPEG_OBJ@ @SDL_OBJ@ SRC = $(OBJ:.o=.c) DOC = CHANGELOG COPYING CREDITS INSTALL README motion_guide.html EXAMPLES = *.conf motion.init-Debian motion.init-RH motion.init-FreeBSD.sh Index: sdl.c =================================================================== --- sdl.c (Revision 0) +++ sdl.c (Revision 0) @@ -0,0 +1,173 @@ +/* + * sdl.c + * + * sdl functions for motion. + * Copyright 2009 by Peter Holik (peter@holik.at) + * This software is distributed under the GNU public license version 2 + * See also the file 'COPYING'. + */ +#include "sdl.h" +#include + +static int cur_width; +static int cur_height; +static int is_full_screen; +static int fs_screen_width; +static int fs_screen_height; + +static SDL_Surface *screen; +static SDL_Overlay *overlay; + +static int sdl_video_open(int width, int height) +{ + int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; + int w,h; + + if (is_full_screen) flags |= SDL_FULLSCREEN; + else flags |= SDL_RESIZABLE; + + if (is_full_screen && fs_screen_width) { + w = fs_screen_width; + h = fs_screen_height; + } else if (width > fs_screen_width || height > fs_screen_height) { + w = fs_screen_width; + h = fs_screen_height; + } else { + w = width; + h = height; + } + /* 32 because framebuffer is usually initalized to 8 and + you have to use fbset with -depth to make it working */ + screen = SDL_SetVideoMode(w, h, 32, flags); + + if (!screen) { + motion_log(LOG_ERR, 1,"Unable to set video mode: %s\n",SDL_GetError()); + return -1; + } + motion_log(LOG_INFO, 0, "SDL dimension %d x %d fullscreen %d BytesPerPixel %d", + screen->w, screen->h, is_full_screen, screen->format->BytesPerPixel); + + SDL_WM_SetCaption("motion", "motion"); + SDL_ShowCursor(SDL_DISABLE); + + if (cur_width != width || cur_height != height) { + cur_width = width; + cur_height = height; + + if (overlay) SDL_FreeYUVOverlay(overlay); + + overlay = SDL_CreateYUVOverlay(cur_width, cur_height, + SDL_YV12_OVERLAY, screen); + if (!overlay) { + motion_log(LOG_ERR, 1, "Could not create overlay: %s", SDL_GetError()); + sdl_stop(); + } else + motion_log(LOG_INFO, 0, "SDL created %dx%dx%d %s overlay", + overlay->w,overlay->h,overlay->planes, + overlay->hw_overlay?"hardware":"software"); + } + return overlay == NULL; +} + +int sdl_start(int width, int height) +{ + putenv("SDL_NOMOUSE=1"); + + if (screen) return 0; + + motion_log(LOG_INFO, 0, "SDL start"); + + if (SDL_Init(SDL_INIT_VIDEO)) { + motion_log(LOG_ERR, 1, "Could not initialize SDL - %s",SDL_GetError()); + return -1; + } + const SDL_VideoInfo *vi = SDL_GetVideoInfo(); + fs_screen_width = vi->current_w; + fs_screen_height = vi->current_h; + + if (sdl_video_open(width, height)) return -1; + + SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); + SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); + SDL_EventState(SDL_USEREVENT, SDL_IGNORE); + SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE); + SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE); + SDL_EventState(SDL_KEYUP, SDL_IGNORE); + SDL_EventState(SDL_JOYBUTTONDOWN, SDL_IGNORE); + SDL_EventState(SDL_JOYBUTTONUP, SDL_IGNORE); + SDL_EventState(SDL_JOYAXISMOTION, SDL_IGNORE); + SDL_EventState(SDL_JOYBALLMOTION, SDL_IGNORE); + SDL_EventState(SDL_JOYHATMOTION, SDL_IGNORE); + + return 0; +} + +void sdl_put(unsigned char *image, int width, int height) +{ + SDL_Event event; + + if (screen && overlay) { + SDL_Rect rect; + float aspect_ratio = (float)width / height; + int pic_width, pic_height; + + if (width != cur_width || height != cur_height) + sdl_video_open(width, height); + + if (SDL_MUSTLOCK(screen)) + if (SDL_LockSurface(screen) < 0) return; + + SDL_LockYUVOverlay(overlay); + memcpy(overlay->pixels[0], image, width * height); + memcpy(overlay->pixels[2], image + (width * height), (width * height / 4)); + memcpy(overlay->pixels[1], image + (width * height * 5 / 4), (width * height / 4)); + SDL_UnlockYUVOverlay(overlay); + + if (SDL_MUSTLOCK(screen)) + SDL_UnlockSurface(screen); + + pic_height = screen->h; + pic_width = pic_height * aspect_ratio; + if (pic_width > screen->w) { + pic_width = screen->w; + pic_height = pic_width / aspect_ratio; + } + rect.x = (screen->w - pic_width) / 2; + rect.y = (screen->h - pic_height) / 2; + rect.w = pic_width; + rect.h = pic_height; + + if (SDL_DisplayYUVOverlay(overlay, &rect)) + motion_log(LOG_ERR, 1, "SDL_DisplayYUVOverlay: %s", SDL_GetError()); + + if (SDL_PollEvent(&event)) { + if ((event.type == SDL_QUIT || + (event.type == SDL_KEYDOWN && + event.key.keysym.sym == SDLK_ESCAPE))) + sdl_stop(); + else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_f) { + is_full_screen = !is_full_screen; + sdl_video_open(width, height); + } + else if (event.type == SDL_VIDEORESIZE) + screen = SDL_SetVideoMode(event.resize.w, event.resize.h, + screen->format->BitsPerPixel, + screen->flags); + } + } +} + +void sdl_stop(void) +{ + if (screen) { + motion_log(LOG_INFO, 0, "SDL quit"); + SDL_ShowCursor(SDL_ENABLE); + if (overlay) { + SDL_FreeYUVOverlay(overlay); + overlay = NULL; + } + SDL_Quit(); + screen = NULL; + } +} Index: conf.c =================================================================== --- conf.c (Revision 444) +++ conf.c (Arbeitskopie) @@ -86,6 +86,9 @@ ffmpeg_bps: DEF_FFMPEG_BPS, ffmpeg_vbr: DEF_FFMPEG_VBR, ffmpeg_video_codec: DEF_FFMPEG_CODEC, +#ifdef HAVE_SDL + sdl_threadnr: 0, +#endif stream_port: 0, stream_quality: 50, stream_motion: 0, @@ -931,7 +934,20 @@ print_string }, #endif /* HAVE_FFMPEG */ +#ifdef HAVE_SDL { + "sdl_threadnr", + "\n############################################################\n" + "# SDL Window\n" + "############################################################\n\n" + "# Number of motion thread to show in SDL Window (default: 0 = disabled)", + 1, + CONF_OFFSET(sdl_threadnr), + copy_int, + print_int + }, +#endif + { "stream_port", "\n############################################################\n" "# Live Stream Server\n" Index: sdl.h =================================================================== --- sdl.h (Revision 0) +++ sdl.h (Revision 0) @@ -0,0 +1,17 @@ +/* sdl.h + * + * Include file for sdl.c + * Copyright 2009 by Peter Holik (peter@holik.at) + * This software is distributed under the GNU public license version 2 + * See also the file 'COPYING'. + */ +#ifndef _INCLUDE_SDL_H +#define _INCLUDE_SDL_H + +#include "motion.h" + +int sdl_start(int width, int height); +void sdl_put(unsigned char *image, int width, int height); +void sdl_stop(void); + +#endif Index: conf.h =================================================================== --- conf.h (Revision 444) +++ conf.h (Arbeitskopie) @@ -62,6 +62,9 @@ int ffmpeg_vbr; int ffmpeg_deinterlace; const char *ffmpeg_video_codec; +#ifdef HAVE_SDL + int sdl_threadnr; +#endif int stream_port; int stream_quality; int stream_motion; Index: configure.in =================================================================== --- configure.in (Revision 444) +++ configure.in (Arbeitskopie) @@ -286,6 +286,44 @@ fi +# +# Check for sdl library +# +SDL_SUPPORT="no" +AC_ARG_WITH(sdl, +[ --with-sdl Compile with sdl support.], +[], +[withval="no"]) +AC_MSG_CHECKING(for sdl) +if test "x$withval" = "xno"; then + AC_MSG_RESULT(skipped) +else + if test "${FreeBSD}" != ""; then + CONFIG_SDL='sdl11-config' + else + CONFIG_SDL='sdl-config' + fi + if test -z "`($CONFIG_SDL --version) 2>/dev/null`" ;then + AC_MSG_RESULT(no) + if test "$withval" = "yes"; then + echo "" + echo "****************************************************" + echo "* sdl-config could not be found. Please install it *" + echo "* and remove the --with-sdl configure argument. *" + echo "* libSDL can be found at http://www.libsdl.org *" + echo "****************************************************" + echo "" + fi + else + AC_MSG_RESULT(yes) + SDL_SUPPORT="yes" + TEMP_LIBS="$TEMP_LIBS `${CONFIG_SDL} --libs`" + TEMP_CFLAGS="${TEMP_CFLAGS} `${CONFIG_SDL} --cflags`" + AC_DEFINE([HAVE_SDL],1,[Define to 1 if you have SDL support]) + SDL_OBJ="sdl.o" + AC_SUBST(SDL_OBJ) + fi +fi # # Check for libavcodec and libavformat from ffmpeg @@ -1193,6 +1231,12 @@ fi fi +if test "${SDL_SUPPORT}" = "yes"; then + echo "SDL Support: Yes" +else + echo "SDL Support: No" +fi + if test "${FFMPEG_OK}" = "found"; then echo "FFmpeg Support: Yes" else Index: motion.c =================================================================== --- motion.c (Revision 444) +++ motion.c (Arbeitskopie) @@ -1948,6 +1948,10 @@ if (cnt->conf.setup_mode) { event(cnt, EVENT_IMAGE, cnt->imgs.out, NULL, &cnt->pipe, cnt->currenttime_tm); event(cnt, EVENT_STREAM, cnt->imgs.out, NULL, NULL, cnt->currenttime_tm); +#ifdef HAVE_SDL + if (cnt_list[0]->conf.sdl_threadnr == cnt->threadnr) + event(cnt, EVENT_SDL_PUT, cnt->imgs.out, NULL, NULL, cnt->currenttime_tm); +#endif } else { event(cnt, EVENT_IMAGE, cnt->current_image->image, NULL, &cnt->pipe, &cnt->current_image->timestamp_tm); @@ -1955,6 +1959,11 @@ if (!cnt->conf.stream_motion || cnt->shots == 1) event(cnt, EVENT_STREAM, cnt->current_image->image, NULL, NULL, &cnt->current_image->timestamp_tm); +#ifdef HAVE_SDL + if (cnt_list[0]->conf.sdl_threadnr == cnt->threadnr) + event(cnt, EVENT_SDL_PUT, cnt->current_image->image, NULL, NULL, + &cnt->current_image->timestamp_tm); +#endif } event(cnt, EVENT_IMAGEM, cnt->imgs.out, NULL, &cnt->mpipe, cnt->currenttime_tm); @@ -2530,6 +2554,11 @@ start_motion_thread(cnt_list[i], &thread_attr); } +#ifdef HAVE_SDL + if (cnt_list[0]->conf.sdl_threadnr > 0) + sdl_start(cnt_list[cnt_list[1] != NULL ? cnt_list[0]->conf.sdl_threadnr : 0]->conf.width, + cnt_list[cnt_list[1] != NULL ? cnt_list[0]->conf.sdl_threadnr : 0]->conf.height); +#endif /* Create a thread for the control interface if requested. Create it * detached and with 'motion_web_control' as the thread function. */ @@ -2610,6 +2639,9 @@ } while (restart); /* loop if we're supposed to restart */ +#ifdef HAVE_SDL + sdl_stop(); +#endif // Be sure that http control exits fine cnt_list[0]->finish = 1; SLEEP(1, 0); Index: motion.h =================================================================== --- motion.h (Revision 444) +++ motion.h (Arbeitskopie) @@ -56,6 +58,9 @@ #include "stream.h" #include "webhttpd.h" +#ifdef HAVE_SDL +#include "sdl.h" +#endif /** * ATTRIBUTE_UNUSED: * Index: event.c =================================================================== --- event.c (Revision 444) +++ event.c (Arbeitskopie) @@ -16,6 +16,9 @@ #include "video.h" #endif +#ifdef HAVE_SDL +#include "sdl.h" +#endif /* * Various functions (most doing the actual action) */ @@ -227,6 +230,14 @@ stream_put(cnt, img); } +#ifdef HAVE_SDL +static void event_sdl_put(struct context *cnt, int type ATTRIBUTE_UNUSED, + unsigned char *img, char *dummy1 ATTRIBUTE_UNUSED, + void *dummy2 ATTRIBUTE_UNUSED, struct tm *tm ATTRIBUTE_UNUSED) +{ + sdl_put(img, cnt->imgs.width, cnt->imgs.height); +} +#endif #ifndef WITHOUT_V4L #if (!defined(BSD)) static void event_vid_putpipe(struct context *cnt, int type ATTRIBUTE_UNUSED, @@ -768,6 +779,12 @@ EVENT_IMAGE_SNAPSHOT, event_image_snapshot }, +#ifdef HAVE_SDL + { + EVENT_SDL_PUT, + event_sdl_put + }, +#endif #ifndef WITHOUT_V4L #if (!defined(BSD)) { Index: event.h =================================================================== --- event.h (Revision 444) +++ event.h (Arbeitskopie) @@ -30,6 +30,7 @@ #define EVENT_AREA_DETECTED 17 #define EVENT_CAMERA_LOST 18 #define EVENT_FFMPEG_PUT 19 +#define EVENT_SDL_PUT 20 typedef void(* event_handler)(struct context *, int, unsigned char *, char *, void *, struct tm *);