/*
This file is part of GNUnet.
- (C) 2013 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2013 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* @file conversation/gnunet-helper-audio-record-gst.c
#include <gst/audio/gstaudiobasesrc.h>
#include <glib.h>
+#define DEBUG_RECORD_PURE_OGG 1
+
/**
* Number of channels.
* Must be one of the following (from libopusenc documentation):
* Must be one of the following (from libopus documentation):
* 2.5, 5, 10, 20, 40 or 60
*/
-#define OPUS_FRAME_SIZE 20
+#define OPUS_FRAME_SIZE 40
/**
* Expected packet loss to prepare for, in percents.
* Max number of microseconds to buffer in audiosource.
* Default is 200000
*/
-#define BUFFER_TIME 1000
+#define BUFFER_TIME 1000 /* 1ms */
/**
* Min number of microseconds to buffer in audiosource.
* Default is 10000
*/
-#define LATENCY_TIME 1000
+#define LATENCY_TIME 1000 /* 1ms */
+
+/**
+ * Maximum delay in multiplexing streams, in ns.
+ * Setting this to 0 forces page flushing, which
+ * decreases delay, but increases overhead.
+ */
+#define OGG_MAX_DELAY 0
+
+/**
+ * Maximum delay for sending out a page, in ns.
+ * Setting this to 0 forces page flushing, which
+ * decreases delay, but increases overhead.
+ */
+#define OGG_MAX_PAGE_DELAY 0
/**
* Main pipeline.
*/
static GstElement *pipeline;
+#ifdef DEBUG_RECORD_PURE_OGG
+static int dump_pure_ogg;
+#endif
+
static void
quit ()
{
{
gchar *debug;
GError *error;
-
+
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
-
+
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message);
g_error_free (error);
-
+
quit ();
break;
}
int
main (int argc, char **argv)
{
- GstElement *source, *encoder, *conv, *resampler, *sink;
+ GstElement *source, *filter, *encoder, *conv, *resampler, *sink, *oggmux;
+ GstCaps *caps;
GstBus *bus;
guint bus_watch_id;
struct AudioMessage audio_message;
int abort_send = 0;
typedef void (*SignalHandlerPointer) (int);
-
+
SignalHandlerPointer inthandler, termhandler;
inthandler = signal (SIGINT, signalhandler);
termhandler = signal (SIGTERM, signalhandler);
+#ifdef DEBUG_RECORD_PURE_OGG
+ dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0;
+#endif
+
#ifdef WINDOWS
setmode (1, _O_BINARY);
#endif
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-recorder");
source = gst_element_factory_make ("autoaudiosrc", "audiosource");
+ filter = gst_element_factory_make ("capsfilter", "filter");
conv = gst_element_factory_make ("audioconvert", "converter");
resampler= gst_element_factory_make ("audioresample", "resampler");
encoder = gst_element_factory_make ("opusenc", "opus-encoder");
+ oggmux = gst_element_factory_make ("oggmux", "ogg-muxer");
sink = gst_element_factory_make ("appsink", "audio-output");
- if (!pipeline || !source || !conv || !resampler || !encoder || !sink)
+ if (!pipeline || !filter || !source || !conv || !resampler || !encoder || !oggmux || !sink)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"One element could not be created. Exiting.\n");
/* Set up the pipeline */
+ caps = gst_caps_new_simple ("audio/x-raw",
+ "format", G_TYPE_STRING, "S16LE",
+/* "rate", G_TYPE_INT, SAMPLING_RATE,*/
+ "channels", G_TYPE_INT, OPUS_CHANNELS,
+/* "layout", G_TYPE_STRING, "interleaved",*/
+ NULL);
+ g_object_set (G_OBJECT (filter),
+ "caps", caps,
+ NULL);
+ gst_caps_unref (caps);
+
g_object_set (G_OBJECT (encoder),
/* "bitrate", 64000, */
/* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */
"audio", FALSE, /* VoIP, not audio */
"frame-size", OPUS_FRAME_SIZE,
NULL);
-
+
+ g_object_set (G_OBJECT (oggmux),
+ "max-delay", OGG_MAX_DELAY,
+ "max-page-delay", OGG_MAX_PAGE_DELAY,
+ NULL);
+
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline);
/* we add all elements into the pipeline */
/* audiosource | converter | resampler | opus-encoder | audio-output */
- gst_bin_add_many (GST_BIN (pipeline), source, conv, resampler, encoder,
- sink, NULL);
+ gst_bin_add_many (GST_BIN (pipeline), source, filter, conv, resampler, encoder,
+ oggmux, sink, NULL);
/* we link the elements together */
- gst_element_link_many (source, conv, resampler, encoder, sink, NULL);
+ gst_element_link_many (source, filter, conv, resampler, encoder, oggmux, sink, NULL);
/* Set the pipeline to "playing" state*/
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n");
ssize_t ret;
if (0 == phase)
{
+#ifdef DEBUG_RECORD_PURE_OGG
+ if (dump_pure_ogg)
+ continue;
+#endif
ptr = (const char *) &audio_message;
to_send = sizeof (audio_message);
}
"Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n",
(unsigned int) to_send - offset, (unsigned int) offset,
(unsigned int) (to_send + offset), phase, strerror (errno));
- abort_send = 1;
+ abort_send = 1;
break;
}
}