diff options
Diffstat (limited to 'src/conversation/gnunet-helper-audio-record-gst.c')
-rwxr-xr-x | src/conversation/gnunet-helper-audio-record-gst.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/src/conversation/gnunet-helper-audio-record-gst.c b/src/conversation/gnunet-helper-audio-record-gst.c index 8d7a88fab..808ad2034 100755 --- a/src/conversation/gnunet-helper-audio-record-gst.c +++ b/src/conversation/gnunet-helper-audio-record-gst.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <gst/audio/gstaudiobasesrc.h> | 34 | #include <gst/audio/gstaudiobasesrc.h> |
35 | #include <glib.h> | 35 | #include <glib.h> |
36 | 36 | ||
37 | #define DEBUG_RECORD_PURE_OGG 1 | ||
38 | |||
37 | /** | 39 | /** |
38 | * Number of channels. | 40 | * Number of channels. |
39 | * Must be one of the following (from libopusenc documentation): | 41 | * Must be one of the following (from libopusenc documentation): |
@@ -51,7 +53,7 @@ | |||
51 | * Must be one of the following (from libopus documentation): | 53 | * Must be one of the following (from libopus documentation): |
52 | * 2.5, 5, 10, 20, 40 or 60 | 54 | * 2.5, 5, 10, 20, 40 or 60 |
53 | */ | 55 | */ |
54 | #define OPUS_FRAME_SIZE 20 | 56 | #define OPUS_FRAME_SIZE 40 |
55 | 57 | ||
56 | /** | 58 | /** |
57 | * Expected packet loss to prepare for, in percents. | 59 | * Expected packet loss to prepare for, in percents. |
@@ -68,19 +70,37 @@ | |||
68 | * Max number of microseconds to buffer in audiosource. | 70 | * Max number of microseconds to buffer in audiosource. |
69 | * Default is 200000 | 71 | * Default is 200000 |
70 | */ | 72 | */ |
71 | #define BUFFER_TIME 1000 | 73 | #define BUFFER_TIME 1000 /* 1ms */ |
72 | 74 | ||
73 | /** | 75 | /** |
74 | * Min number of microseconds to buffer in audiosource. | 76 | * Min number of microseconds to buffer in audiosource. |
75 | * Default is 10000 | 77 | * Default is 10000 |
76 | */ | 78 | */ |
77 | #define LATENCY_TIME 1000 | 79 | #define LATENCY_TIME 1000 /* 1ms */ |
80 | |||
81 | /** | ||
82 | * Maximum delay in multiplexing streams, in ns. | ||
83 | * Setting this to 0 forces page flushing, which | ||
84 | * decreases delay, but increases overhead. | ||
85 | */ | ||
86 | #define OGG_MAX_DELAY 0 | ||
87 | |||
88 | /** | ||
89 | * Maximum delay for sending out a page, in ns. | ||
90 | * Setting this to 0 forces page flushing, which | ||
91 | * decreases delay, but increases overhead. | ||
92 | */ | ||
93 | #define OGG_MAX_PAGE_DELAY 0 | ||
78 | 94 | ||
79 | /** | 95 | /** |
80 | * Main pipeline. | 96 | * Main pipeline. |
81 | */ | 97 | */ |
82 | static GstElement *pipeline; | 98 | static GstElement *pipeline; |
83 | 99 | ||
100 | #ifdef DEBUG_RECORD_PURE_OGG | ||
101 | static int dump_pure_ogg; | ||
102 | #endif | ||
103 | |||
84 | static void | 104 | static void |
85 | quit () | 105 | quit () |
86 | { | 106 | { |
@@ -103,13 +123,13 @@ bus_call (GstBus *bus, GstMessage *msg, gpointer data) | |||
103 | { | 123 | { |
104 | gchar *debug; | 124 | gchar *debug; |
105 | GError *error; | 125 | GError *error; |
106 | 126 | ||
107 | gst_message_parse_error (msg, &error, &debug); | 127 | gst_message_parse_error (msg, &error, &debug); |
108 | g_free (debug); | 128 | g_free (debug); |
109 | 129 | ||
110 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message); | 130 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message); |
111 | g_error_free (error); | 131 | g_error_free (error); |
112 | 132 | ||
113 | quit (); | 133 | quit (); |
114 | break; | 134 | break; |
115 | } | 135 | } |
@@ -137,18 +157,23 @@ signalhandler (int s) | |||
137 | int | 157 | int |
138 | main (int argc, char **argv) | 158 | main (int argc, char **argv) |
139 | { | 159 | { |
140 | GstElement *source, *encoder, *conv, *resampler, *sink; | 160 | GstElement *source, *filter, *encoder, *conv, *resampler, *sink, *oggmux; |
161 | GstCaps *caps; | ||
141 | GstBus *bus; | 162 | GstBus *bus; |
142 | guint bus_watch_id; | 163 | guint bus_watch_id; |
143 | struct AudioMessage audio_message; | 164 | struct AudioMessage audio_message; |
144 | int abort_send = 0; | 165 | int abort_send = 0; |
145 | 166 | ||
146 | typedef void (*SignalHandlerPointer) (int); | 167 | typedef void (*SignalHandlerPointer) (int); |
147 | 168 | ||
148 | SignalHandlerPointer inthandler, termhandler; | 169 | SignalHandlerPointer inthandler, termhandler; |
149 | inthandler = signal (SIGINT, signalhandler); | 170 | inthandler = signal (SIGINT, signalhandler); |
150 | termhandler = signal (SIGTERM, signalhandler); | 171 | termhandler = signal (SIGTERM, signalhandler); |
151 | 172 | ||
173 | #ifdef DEBUG_RECORD_PURE_OGG | ||
174 | dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0; | ||
175 | #endif | ||
176 | |||
152 | #ifdef WINDOWS | 177 | #ifdef WINDOWS |
153 | setmode (1, _O_BINARY); | 178 | setmode (1, _O_BINARY); |
154 | #endif | 179 | #endif |
@@ -169,12 +194,14 @@ main (int argc, char **argv) | |||
169 | /* Create gstreamer elements */ | 194 | /* Create gstreamer elements */ |
170 | pipeline = gst_pipeline_new ("audio-recorder"); | 195 | pipeline = gst_pipeline_new ("audio-recorder"); |
171 | source = gst_element_factory_make ("autoaudiosrc", "audiosource"); | 196 | source = gst_element_factory_make ("autoaudiosrc", "audiosource"); |
197 | filter = gst_element_factory_make ("capsfilter", "filter"); | ||
172 | conv = gst_element_factory_make ("audioconvert", "converter"); | 198 | conv = gst_element_factory_make ("audioconvert", "converter"); |
173 | resampler= gst_element_factory_make ("audioresample", "resampler"); | 199 | resampler= gst_element_factory_make ("audioresample", "resampler"); |
174 | encoder = gst_element_factory_make ("opusenc", "opus-encoder"); | 200 | encoder = gst_element_factory_make ("opusenc", "opus-encoder"); |
201 | oggmux = gst_element_factory_make ("oggmux", "ogg-muxer"); | ||
175 | sink = gst_element_factory_make ("appsink", "audio-output"); | 202 | sink = gst_element_factory_make ("appsink", "audio-output"); |
176 | 203 | ||
177 | if (!pipeline || !source || !conv || !resampler || !encoder || !sink) | 204 | if (!pipeline || !filter || !source || !conv || !resampler || !encoder || !oggmux || !sink) |
178 | { | 205 | { |
179 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 206 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
180 | "One element could not be created. Exiting.\n"); | 207 | "One element could not be created. Exiting.\n"); |
@@ -185,6 +212,17 @@ main (int argc, char **argv) | |||
185 | 212 | ||
186 | /* Set up the pipeline */ | 213 | /* Set up the pipeline */ |
187 | 214 | ||
215 | caps = gst_caps_new_simple ("audio/x-raw", | ||
216 | "format", G_TYPE_STRING, "S16LE", | ||
217 | /* "rate", G_TYPE_INT, SAMPLING_RATE,*/ | ||
218 | "channels", G_TYPE_INT, OPUS_CHANNELS, | ||
219 | /* "layout", G_TYPE_STRING, "interleaved",*/ | ||
220 | NULL); | ||
221 | g_object_set (G_OBJECT (filter), | ||
222 | "caps", caps, | ||
223 | NULL); | ||
224 | gst_caps_unref (caps); | ||
225 | |||
188 | g_object_set (G_OBJECT (encoder), | 226 | g_object_set (G_OBJECT (encoder), |
189 | /* "bitrate", 64000, */ | 227 | /* "bitrate", 64000, */ |
190 | /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */ | 228 | /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */ |
@@ -194,7 +232,12 @@ main (int argc, char **argv) | |||
194 | "audio", FALSE, /* VoIP, not audio */ | 232 | "audio", FALSE, /* VoIP, not audio */ |
195 | "frame-size", OPUS_FRAME_SIZE, | 233 | "frame-size", OPUS_FRAME_SIZE, |
196 | NULL); | 234 | NULL); |
197 | 235 | ||
236 | g_object_set (G_OBJECT (oggmux), | ||
237 | "max-delay", OGG_MAX_DELAY, | ||
238 | "max-page-delay", OGG_MAX_PAGE_DELAY, | ||
239 | NULL); | ||
240 | |||
198 | /* we add a message handler */ | 241 | /* we add a message handler */ |
199 | bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); | 242 | bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); |
200 | bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline); | 243 | bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline); |
@@ -202,11 +245,11 @@ main (int argc, char **argv) | |||
202 | 245 | ||
203 | /* we add all elements into the pipeline */ | 246 | /* we add all elements into the pipeline */ |
204 | /* audiosource | converter | resampler | opus-encoder | audio-output */ | 247 | /* audiosource | converter | resampler | opus-encoder | audio-output */ |
205 | gst_bin_add_many (GST_BIN (pipeline), source, conv, resampler, encoder, | 248 | gst_bin_add_many (GST_BIN (pipeline), source, filter, conv, resampler, encoder, |
206 | sink, NULL); | 249 | oggmux, sink, NULL); |
207 | 250 | ||
208 | /* we link the elements together */ | 251 | /* we link the elements together */ |
209 | gst_element_link_many (source, conv, resampler, encoder, sink, NULL); | 252 | gst_element_link_many (source, filter, conv, resampler, encoder, oggmux, sink, NULL); |
210 | 253 | ||
211 | /* Set the pipeline to "playing" state*/ | 254 | /* Set the pipeline to "playing" state*/ |
212 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n"); | 255 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n"); |
@@ -288,6 +331,10 @@ main (int argc, char **argv) | |||
288 | ssize_t ret; | 331 | ssize_t ret; |
289 | if (0 == phase) | 332 | if (0 == phase) |
290 | { | 333 | { |
334 | #ifdef DEBUG_RECORD_PURE_OGG | ||
335 | if (dump_pure_ogg) | ||
336 | continue; | ||
337 | #endif | ||
291 | ptr = (const char *) &audio_message; | 338 | ptr = (const char *) &audio_message; |
292 | to_send = sizeof (audio_message); | 339 | to_send = sizeof (audio_message); |
293 | } | 340 | } |
@@ -308,7 +355,7 @@ main (int argc, char **argv) | |||
308 | "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n", | 355 | "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n", |
309 | (unsigned int) to_send - offset, (unsigned int) offset, | 356 | (unsigned int) to_send - offset, (unsigned int) offset, |
310 | (unsigned int) (to_send + offset), phase, strerror (errno)); | 357 | (unsigned int) (to_send + offset), phase, strerror (errno)); |
311 | abort_send = 1; | 358 | abort_send = 1; |
312 | break; | 359 | break; |
313 | } | 360 | } |
314 | } | 361 | } |