From c61253adbd5bed1d7393a3153f9c865517280431 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 3 Oct 2012 15:37:20 +0200 Subject: added video recorder based on SDL_ffmpeg --- src/Makefile.am | 1 + src/main.cpp | 10 ++++- src/recorder.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/recorder.h | 38 +++++++++++++++++ 4 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 src/recorder.cpp create mode 100644 src/recorder.h (limited to 'src') 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 +#include + +#include +#include + +#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 +#include +#include + +#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 -- cgit v1.2.3