aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-helper-audio-record-gst.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/gnunet-helper-audio-record-gst.c')
-rw-r--r--src/conversation/gnunet-helper-audio-record-gst.c385
1 files changed, 197 insertions, 188 deletions
diff --git a/src/conversation/gnunet-helper-audio-record-gst.c b/src/conversation/gnunet-helper-audio-record-gst.c
index f41f529ea..a3607014e 100644
--- a/src/conversation/gnunet-helper-audio-record-gst.c
+++ b/src/conversation/gnunet-helper-audio-record-gst.c
@@ -102,61 +102,63 @@ static int dump_pure_ogg;
102#endif 102#endif
103 103
104static void 104static void
105quit() 105quit ()
106{ 106{
107 if (NULL != pipeline) 107 if (NULL != pipeline)
108 gst_element_set_state(pipeline, GST_STATE_NULL); 108 gst_element_set_state (pipeline, GST_STATE_NULL);
109} 109}
110 110
111static gboolean 111static gboolean
112bus_call(GstBus *bus, GstMessage *msg, gpointer data) 112bus_call (GstBus *bus, GstMessage *msg, gpointer data)
113{ 113{
114 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Bus message\n"); 114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bus message\n");
115 switch (GST_MESSAGE_TYPE(msg)) 115 switch (GST_MESSAGE_TYPE (msg))
116 { 116 {
117 case GST_MESSAGE_EOS: 117 case GST_MESSAGE_EOS:
118 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "End of stream\n"); 118 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "End of stream\n");
119 quit(); 119 quit ();
120 break; 120 break;
121 121
122 case GST_MESSAGE_ERROR: 122 case GST_MESSAGE_ERROR:
123 { 123 {
124 gchar *debug; 124 gchar *debug;
125 GError *error; 125 GError *error;
126 126
127 gst_message_parse_error(msg, &error, &debug); 127 gst_message_parse_error (msg, &error, &debug);
128 g_free(debug); 128 g_free (debug);
129 129
130 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message); 130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message);
131 g_error_free(error); 131 g_error_free (error);
132 132
133 quit(); 133 quit ();
134 break; 134 break;
135 } 135 }
136 136
137 default: 137 default:
138 break; 138 break;
139 } 139 }
140 140
141 return TRUE; 141 return TRUE;
142} 142}
143 143
144void 144void
145source_child_added(GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data) 145source_child_added (GstChildProxy *child_proxy, GObject *object, gchar *name,
146 gpointer user_data)
146{ 147{
147 if (GST_IS_AUDIO_BASE_SRC(object)) 148 if (GST_IS_AUDIO_BASE_SRC (object))
148 g_object_set(object, "buffer-time", (gint64)BUFFER_TIME, "latency-time", (gint64)LATENCY_TIME, NULL); 149 g_object_set (object, "buffer-time", (gint64) BUFFER_TIME, "latency-time",
150 (gint64) LATENCY_TIME, NULL);
149} 151}
150 152
151static void 153static void
152signalhandler(int s) 154signalhandler (int s)
153{ 155{
154 quit(); 156 quit ();
155} 157}
156 158
157 159
158int 160int
159main(int argc, char **argv) 161main (int argc, char **argv)
160{ 162{
161 GstElement *source, *filter, *encoder, *conv, *resampler, *sink, *oggmux; 163 GstElement *source, *filter, *encoder, *conv, *resampler, *sink, *oggmux;
162 GstCaps *caps; 164 GstCaps *caps;
@@ -168,214 +170,221 @@ main(int argc, char **argv)
168 typedef void (*SignalHandlerPointer) (int); 170 typedef void (*SignalHandlerPointer) (int);
169 171
170 SignalHandlerPointer inthandler, termhandler; 172 SignalHandlerPointer inthandler, termhandler;
171 inthandler = signal(SIGINT, signalhandler); 173 inthandler = signal (SIGINT, signalhandler);
172 termhandler = signal(SIGTERM, signalhandler); 174 termhandler = signal (SIGTERM, signalhandler);
173 175
174#ifdef DEBUG_RECORD_PURE_OGG 176#ifdef DEBUG_RECORD_PURE_OGG
175 dump_pure_ogg = getenv("GNUNET_RECORD_PURE_OGG") ? 1 : 0; 177 dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0;
176#endif 178#endif
177 179
178 /* Initialisation */ 180 /* Initialisation */
179 gst_init(&argc, &argv); 181 gst_init (&argc, &argv);
180 182
181 GNUNET_assert(GNUNET_OK == 183 GNUNET_assert (GNUNET_OK ==
182 GNUNET_log_setup("gnunet-helper-audio-record", 184 GNUNET_log_setup ("gnunet-helper-audio-record",
183 "WARNING", 185 "WARNING",
184 NULL)); 186 NULL));
185 187
186 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "Audio source starts\n"); 189 "Audio source starts\n");
188 190
189 audio_message.header.type = htons(GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); 191 audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
190 192
191 /* Create gstreamer elements */ 193 /* Create gstreamer elements */
192 pipeline = gst_pipeline_new("audio-recorder"); 194 pipeline = gst_pipeline_new ("audio-recorder");
193 source = gst_element_factory_make("autoaudiosrc", "audiosource"); 195 source = gst_element_factory_make ("autoaudiosrc", "audiosource");
194 filter = gst_element_factory_make("capsfilter", "filter"); 196 filter = gst_element_factory_make ("capsfilter", "filter");
195 conv = gst_element_factory_make("audioconvert", "converter"); 197 conv = gst_element_factory_make ("audioconvert", "converter");
196 resampler = gst_element_factory_make("audioresample", "resampler"); 198 resampler = gst_element_factory_make ("audioresample", "resampler");
197 encoder = gst_element_factory_make("opusenc", "opus-encoder"); 199 encoder = gst_element_factory_make ("opusenc", "opus-encoder");
198 oggmux = gst_element_factory_make("oggmux", "ogg-muxer"); 200 oggmux = gst_element_factory_make ("oggmux", "ogg-muxer");
199 sink = gst_element_factory_make("appsink", "audio-output"); 201 sink = gst_element_factory_make ("appsink", "audio-output");
200 202
201 if (!pipeline || !filter || !source || !conv || !resampler || !encoder || !oggmux || !sink) 203 if (! pipeline || ! filter || ! source || ! conv || ! resampler ||
202 { 204 ! encoder || ! oggmux || ! sink)
203 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 205 {
204 "One element could not be created. Exiting.\n"); 206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
205 return -1; 207 "One element could not be created. Exiting.\n");
206 } 208 return -1;
207 209 }
208 g_signal_connect(source, "child-added", G_CALLBACK(source_child_added), NULL); 210
211 g_signal_connect (source, "child-added", G_CALLBACK (source_child_added),
212 NULL);
209 213
210 /* Set up the pipeline */ 214 /* Set up the pipeline */
211 215
212 caps = gst_caps_new_simple("audio/x-raw", 216 caps = gst_caps_new_simple ("audio/x-raw",
213 "format", G_TYPE_STRING, "S16LE", 217 "format", G_TYPE_STRING, "S16LE",
214/* "rate", G_TYPE_INT, SAMPLING_RATE,*/ 218/* "rate", G_TYPE_INT, SAMPLING_RATE,*/
215 "channels", G_TYPE_INT, OPUS_CHANNELS, 219 "channels", G_TYPE_INT, OPUS_CHANNELS,
216/* "layout", G_TYPE_STRING, "interleaved",*/ 220/* "layout", G_TYPE_STRING, "interleaved",*/
217 NULL); 221 NULL);
218 g_object_set(G_OBJECT(filter), 222 g_object_set (G_OBJECT (filter),
219 "caps", caps, 223 "caps", caps,
220 NULL); 224 NULL);
221 gst_caps_unref(caps); 225 gst_caps_unref (caps);
222 226
223 g_object_set(G_OBJECT(encoder), 227 g_object_set (G_OBJECT (encoder),
224/* "bitrate", 64000, */ 228/* "bitrate", 64000, */
225/* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */ 229/* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */
226 "inband-fec", INBAND_FEC_MODE, 230 "inband-fec", INBAND_FEC_MODE,
227 "packet-loss-percentage", PACKET_LOSS_PERCENTAGE, 231 "packet-loss-percentage", PACKET_LOSS_PERCENTAGE,
228 "max-payload-size", MAX_PAYLOAD_SIZE, 232 "max-payload-size", MAX_PAYLOAD_SIZE,
229 "audio", FALSE, /* VoIP, not audio */ 233 "audio", FALSE, /* VoIP, not audio */
230 "frame-size", OPUS_FRAME_SIZE, 234 "frame-size", OPUS_FRAME_SIZE,
231 NULL); 235 NULL);
232 236
233 g_object_set(G_OBJECT(oggmux), 237 g_object_set (G_OBJECT (oggmux),
234 "max-delay", OGG_MAX_DELAY, 238 "max-delay", OGG_MAX_DELAY,
235 "max-page-delay", OGG_MAX_PAGE_DELAY, 239 "max-page-delay", OGG_MAX_PAGE_DELAY,
236 NULL); 240 NULL);
237 241
238 /* we add a message handler */ 242 /* we add a message handler */
239 bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); 243 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
240 bus_watch_id = gst_bus_add_watch(bus, bus_call, pipeline); 244 bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline);
241 gst_object_unref(bus); 245 gst_object_unref (bus);
242 246
243 /* we add all elements into the pipeline */ 247 /* we add all elements into the pipeline */
244 /* audiosource | converter | resampler | opus-encoder | audio-output */ 248 /* audiosource | converter | resampler | opus-encoder | audio-output */
245 gst_bin_add_many(GST_BIN(pipeline), source, filter, conv, resampler, encoder, 249 gst_bin_add_many (GST_BIN (pipeline), source, filter, conv, resampler,
246 oggmux, sink, NULL); 250 encoder,
251 oggmux, sink, NULL);
247 252
248 /* we link the elements together */ 253 /* we link the elements together */
249 gst_element_link_many(source, filter, conv, resampler, encoder, oggmux, sink, NULL); 254 gst_element_link_many (source, filter, conv, resampler, encoder, oggmux, sink,
255 NULL);
250 256
251 /* Set the pipeline to "playing" state*/ 257 /* Set the pipeline to "playing" state*/
252 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Now playing\n"); 258 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n");
253 gst_element_set_state(pipeline, GST_STATE_PLAYING); 259 gst_element_set_state (pipeline, GST_STATE_PLAYING);
254 260
255 261
256 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Running...\n"); 262 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running...\n");
257 /* Iterate */ 263 /* Iterate */
258 while (!abort_send) 264 while (! abort_send)
265 {
266 GstSample *s;
267 GstBuffer *b;
268 GstMapInfo m;
269 size_t len, msg_size;
270 const char *ptr;
271 int phase;
272
273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n");
274 s = gst_app_sink_pull_sample (GST_APP_SINK (sink));
275 if (NULL == s)
276 {
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n");
278 break;
279 }
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
259 { 281 {
260 GstSample *s; 282 const GstStructure *si;
261 GstBuffer *b; 283 char *si_str;
262 GstMapInfo m; 284 GstCaps *s_caps;
263 size_t len, msg_size; 285 char *caps_str;
264 const char *ptr; 286 si = gst_sample_get_info (s);
265 int phase; 287 if (si)
266 288 {
267 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "pulling...\n"); 289 si_str = gst_structure_to_string (si);
268 s = gst_app_sink_pull_sample(GST_APP_SINK(sink)); 290 if (si_str)
269 if (NULL == s)
270 { 291 {
271 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n"); 292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
272 break; 293 g_free (si_str);
273 } 294 }
274 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
275 {
276 const GstStructure *si;
277 char *si_str;
278 GstCaps *s_caps;
279 char *caps_str;
280 si = gst_sample_get_info(s);
281 if (si)
282 {
283 si_str = gst_structure_to_string(si);
284 if (si_str)
285 {
286 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
287 g_free(si_str);
288 }
289 }
290 else
291 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
292 s_caps = gst_sample_get_caps(s);
293 if (s_caps)
294 {
295 caps_str = gst_caps_to_string(s_caps);
296 if (caps_str)
297 {
298 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str);
299 g_free(caps_str);
300 }
301 }
302 else
303 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
304 } 295 }
305 b = gst_sample_get_buffer(s); 296 else
306 if (NULL == b || !gst_buffer_map(b, &m, GST_MAP_READ)) 297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
298 s_caps = gst_sample_get_caps (s);
299 if (s_caps)
300 {
301 caps_str = gst_caps_to_string (s_caps);
302 if (caps_str)
307 { 303 {
308 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b); 304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n",
309 gst_sample_unref(s); 305 caps_str);
310 continue; 306 g_free (caps_str);
311 } 307 }
308 }
309 else
310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
311 }
312 b = gst_sample_get_buffer (s);
313 if ((NULL == b) || ! gst_buffer_map (b, &m, GST_MAP_READ))
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "got NULL buffer %p or failed to map the buffer\n", b);
317 gst_sample_unref (s);
318 continue;
319 }
312 320
313 len = m.size; 321 len = m.size;
314 if (len > UINT16_MAX - sizeof(struct AudioMessage)) 322 if (len > UINT16_MAX - sizeof(struct AudioMessage))
315 { 323 {
316 GNUNET_break(0); 324 GNUNET_break (0);
317 len = UINT16_MAX - sizeof(struct AudioMessage); 325 len = UINT16_MAX - sizeof(struct AudioMessage);
318 } 326 }
319 msg_size = sizeof(struct AudioMessage) + len; 327 msg_size = sizeof(struct AudioMessage) + len;
320 audio_message.header.size = htons((uint16_t)msg_size); 328 audio_message.header.size = htons ((uint16_t) msg_size);
321 329
322 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
323 "Sending %u bytes of audio data\n", (unsigned int)msg_size); 331 "Sending %u bytes of audio data\n", (unsigned int) msg_size);
324 for (phase = 0; phase < 2; phase++) 332 for (phase = 0; phase < 2; phase++)
325 { 333 {
326 size_t offset; 334 size_t offset;
327 size_t to_send; 335 size_t to_send;
328 ssize_t ret; 336 ssize_t ret;
329 if (0 == phase) 337 if (0 == phase)
330 { 338 {
331#ifdef DEBUG_RECORD_PURE_OGG 339#ifdef DEBUG_RECORD_PURE_OGG
332 if (dump_pure_ogg) 340 if (dump_pure_ogg)
333 continue; 341 continue;
334#endif 342#endif
335 ptr = (const char *)&audio_message; 343 ptr = (const char *) &audio_message;
336 to_send = sizeof(audio_message); 344 to_send = sizeof(audio_message);
337 } 345 }
338 else 346 else
339 { 347 {
340 ptr = (const char *)m.data; 348 ptr = (const char *) m.data;
341 to_send = len; 349 to_send = len;
342 } 350 }
343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
344 "Sending %u bytes on phase %d\n", (unsigned int)to_send, phase); 352 "Sending %u bytes on phase %d\n", (unsigned int) to_send,
345 for (offset = 0; offset < to_send; offset += ret) 353 phase);
346 { 354 for (offset = 0; offset < to_send; offset += ret)
347 ret = write(1, &ptr[offset], to_send - offset); 355 {
348 if (0 >= ret) 356 ret = write (1, &ptr[offset], to_send - offset);
349 { 357 if (0 >= ret)
350 if (-1 == ret) 358 {
351 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 359 if (-1 == ret)
352 "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n", 360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
353 (unsigned int)(to_send - offset), 361 "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n",
354 (unsigned int)offset, 362 (unsigned int) (to_send - offset),
355 (unsigned int)(to_send + offset), 363 (unsigned int) offset,
356 phase, 364 (unsigned int) (to_send + offset),
357 strerror(errno)); 365 phase,
358 abort_send = 1; 366 strerror (errno));
359 break; 367 abort_send = 1;
360 } 368 break;
361 }
362 if (abort_send)
363 break;
364 } 369 }
365 gst_buffer_unmap(b, &m); 370 }
366 gst_sample_unref(s); 371 if (abort_send)
372 break;
367 } 373 }
374 gst_buffer_unmap (b, &m);
375 gst_sample_unref (s);
376 }
368 377
369 signal(SIGINT, inthandler); 378 signal (SIGINT, inthandler);
370 signal(SIGINT, termhandler); 379 signal (SIGINT, termhandler);
371 380
372 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Returned, stopping playback\n"); 381 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returned, stopping playback\n");
373 quit(); 382 quit ();
374 383
375 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deleting pipeline\n"); 384 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleting pipeline\n");
376 gst_object_unref(GST_OBJECT(pipeline)); 385 gst_object_unref (GST_OBJECT (pipeline));
377 pipeline = NULL; 386 pipeline = NULL;
378 g_source_remove(bus_watch_id); 387 g_source_remove (bus_watch_id);
379 388
380 return 0; 389 return 0;
381} 390}