aboutsummaryrefslogtreecommitdiff
path: root/src/recorder.cpp
blob: 13e2b1327bdfd2f93833f78d6aeec1094a77edd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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);
}