diff options
-rw-r--r-- | chuck/OSCGraphics.ck | 18 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/main.cpp | 10 | ||||
-rw-r--r-- | src/recorder.cpp | 125 | ||||
-rw-r--r-- | src/recorder.h | 38 |
6 files changed, 196 insertions, 3 deletions
diff --git a/chuck/OSCGraphics.ck b/chuck/OSCGraphics.ck index 6c2fcec..82da22e 100644 --- a/chuck/OSCGraphics.ck +++ b/chuck/OSCGraphics.ck @@ -1,6 +1,6 @@ public class OSCGraphics { static OscSend @osc_send; - 1 => static int free_id; + static int free_id; fun static void clear() @@ -8,6 +8,20 @@ public class OSCGraphics { osc_send.startMsg("/layer/*/delete", ""); } + fun static string + record(string file) + { + osc_send.startMsg("/recorder/start", "s"); + file => osc_send.addString; + + return file; + } + fun static void + stopRecord() + { + osc_send.startMsg("/recorder/stop", ""); + } + fun static OSCGraphicsImage @ getImage(string name) { @@ -165,3 +179,5 @@ public class OSCGraphics { /* static initialization */ new OscSend @=> OSCGraphics.osc_send; OSCGraphics.osc_send.setHost("localhost", 7770); + +1 => OSCGraphics.free_id; diff --git a/configure.ac b/configure.ac index 3597213..fbd57a5 100644 --- a/configure.ac +++ b/configure.ac @@ -78,6 +78,13 @@ AC_CHECK_HEADERS([SDL_ttf.h], , [ AC_MSG_ERROR([Required libSDL_ttf header missing!]) ]) +AC_CHECK_LIB(SDL_ffmpeg, SDL_ffmpegOpen, , [ + AC_MSG_ERROR([Required libSDL_ffmpeg missing!]) +]) +AC_CHECK_HEADERS([SDL/SDL_ffmpeg.h], , [ + AC_MSG_ERROR([Required libSDL_ffmpeg header missing!]) +]) + PKG_CHECK_MODULES(LIBVLC, [libvlc >= 1.1.10], [ CFLAGS="$CFLAGS $LIBVLC_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBVLC_CFLAGS" diff --git a/src/Makefile.am b/src/Makefile.am index 5c1a23c..3b1ba79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ LDADD = -lsupc++ bin_PROGRAMS = osc-graphics osc_graphics_SOURCES = main.cpp osc_graphics.h \ osc_server.cpp osc_server.h \ + recorder.cpp recorder.h \ layer.cpp layer.h \ layer_box.cpp layer_box.h \ layer_text.cpp layer_text.h \ diff --git a/src/main.cpp b/src/main.cpp index f9c3eb8..8fd714f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "osc_graphics.h" #include "osc_server.h" +#include "recorder.h" #include "layer.h" #include "layer_box.h" @@ -50,8 +51,9 @@ static void cleanup(void); SDL_Surface *screen; -OSCServer osc_server; -LayerList layers; +OSCServer osc_server; +static Recorder recorder; +LayerList layers; int config_dump_osc = 0; @@ -267,6 +269,8 @@ main(int argc, char **argv) osc_server.open(port); + recorder.register_methods(); + REGISTER_LAYER(LayerImage); REGISTER_LAYER(LayerVideo); REGISTER_LAYER(LayerBox); @@ -282,6 +286,8 @@ main(int argc, char **argv) layers.render(screen); + recorder.record(screen); + SDL_Flip(screen); SDL_framerateDelay(&fpsm); } diff --git a/src/recorder.cpp b/src/recorder.cpp new file mode 100644 index 0000000..13e2b13 --- /dev/null +++ b/src/recorder.cpp @@ -0,0 +1,125 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> + +#include <SDL.h> +#include <SDL/SDL_ffmpeg.h> + +#include "osc_graphics.h" +#include "osc_server.h" + +#include "recorder.h" + +/* + * Macros + */ +#define SDL_FFMPEGFREE_SAFE(FILE) do { \ + if (FILE) { \ + SDL_ffmpegFree(FILE); \ + FILE = NULL; \ + } \ +} while (0) + +#define SDL_FFMPEG_ERROR(FMT, ...) do { \ + fprintf(stderr, "%s(%d): " FMT ": %s\n", \ + __FILE__, __LINE__, ##__VA_ARGS__, \ + SDL_ffmpegGetError()); \ +} while (0) + +extern "C" { + +static int start_handler(const char *path, const char *types, + lo_arg **argv, int argc, + void *data, void *user_data); +static int stop_handler(const char *path, const char *types, + lo_arg **argv, int argc, + void *data, void *user_data); + +} + +void +Recorder::register_methods() +{ + osc_server.add_method("s", start_handler, this, "/recorder/start"); + osc_server.add_method("", stop_handler, this, "/recorder/stop"); +} + +static int +start_handler(const char *path, const char *types, + lo_arg **argv, int argc, void *data, void *user_data) +{ + Recorder *obj = (Recorder *)user_data; + + obj->start(&argv[0]->s); + + return 0; +} + +void +Recorder::start(const char *filename) +{ + SDL_ffmpegCodec codec = { + -1, /* video codec based on file name */ + screen->w, screen->h, + 1, 20 /* FIXME */, /* framerate */ + 6000000, -1, -1, + -1, 0, -1, -1, -1, -1 /* no audio */ + }; + + lock(); + + SDL_FFMPEGFREE_SAFE(file); + + file = SDL_ffmpegCreate(filename); + if (!file) { + SDL_FFMPEG_ERROR("SDL_ffmpegCreate"); + exit(EXIT_FAILURE); + } + + SDL_ffmpegAddVideoStream(file, codec); + SDL_ffmpegSelectVideoStream(file, 0); + + unlock(); +} + +static int +stop_handler(const char *path, const char *types, + lo_arg **argv, int argc, void *data, void *user_data) +{ + Recorder *obj = (Recorder *)user_data; + + obj->stop(); + + return 0; +} + +void +Recorder::stop() +{ + lock(); + SDL_FFMPEGFREE_SAFE(file); + unlock(); +} + +void +Recorder::record(SDL_Surface *surf) +{ + lock(); + + if (file) + SDL_ffmpegAddVideoFrame(file, surf); + + unlock(); +} + +Recorder::~Recorder() +{ + osc_server.del_method("s", "/recorder/start"); + osc_server.del_method("", "/recorder/stop"); + + SDL_FFMPEGFREE_SAFE(file); + SDL_DestroyMutex(mutex); +} diff --git a/src/recorder.h b/src/recorder.h new file mode 100644 index 0000000..b2ee5e6 --- /dev/null +++ b/src/recorder.h @@ -0,0 +1,38 @@ +#ifndef __RECORDER_H +#define __RECORDER_H + +#include <SDL.h> +#include <SDL_thread.h> +#include <SDL/SDL_ffmpeg.h> + +#include "osc_graphics.h" + +class Recorder { + SDL_ffmpegFile *file; + + SDL_mutex *mutex; + + inline void + lock() + { + SDL_LockMutex(mutex); + } + inline void + unlock() + { + SDL_UnlockMutex(mutex); + } + +public: + Recorder() : file(NULL), mutex(SDL_CreateMutex()) {} + ~Recorder(); + + void register_methods(); + + void start(const char *filename); + void stop(); + + void record(SDL_Surface *surf); +}; + +#endif |