aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-10-03 15:37:20 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-10-03 15:37:20 +0200
commitc61253adbd5bed1d7393a3153f9c865517280431 (patch)
treef13e3d561129b2e9824895fbee82d9f65322b257
parentbca127f7f24f6a4b70e8797639619913e945b62b (diff)
downloadosc-graphics-c61253adbd5bed1d7393a3153f9c865517280431.tar.gz
added video recorder based on SDL_ffmpeg
-rw-r--r--chuck/OSCGraphics.ck18
-rw-r--r--configure.ac7
-rw-r--r--src/Makefile.am1
-rw-r--r--src/main.cpp10
-rw-r--r--src/recorder.cpp125
-rw-r--r--src/recorder.h38
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