summaryrefslogtreecommitdiff
path: root/src/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio.c')
-rw-r--r--src/audio.c72
1 files changed, 64 insertions, 8 deletions
diff --git a/src/audio.c b/src/audio.c
index 01a5dab..e40b1c2 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -15,13 +15,73 @@
void
cmumble_audio_push(struct cmumble *cm, struct cmumble_user *user,
- const guint8 *data, gsize size)
+ const guint8 *data, gsize size, gint64 sequence)
{
GstBuffer *gstbuf;
+ GstClock *clock;
+ GstClockTime time = 0;
+ GstClockTime base, now = 0;
+
+ if (cm->verbose)
+ g_print("%s: sequence: %ld\n", __func__, sequence);
+
+ base = gst_element_get_base_time(GST_ELEMENT(user->src));
+
+ clock = gst_element_get_clock(GST_ELEMENT(user->src));
+ if (clock) {
+ now = gst_clock_get_time(clock);
+ g_object_unref(clock);
+ }
+
+ /* FIXME: What to do when sequence is a bad value?
+ * e.g to little in value, to be uptodate?
+ * - just drop?
+ * - enqueue as now?
+ */
gstbuf = gst_buffer_new_wrapped(g_memdup(data, size), size);
GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_LIVE);
+ /* Asume packets are in order, since we're using tcp tunnel only atm.
+ * FIXME: This assumption is probably wrong, since the packets may have
+ * been received out of order at the server? */
+
+ if (user->last_sequence < 0 || sequence == 0 ||
+ sequence < (user->last_sequence + 1)) {
+ GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_DISCONT);
+ GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_RESYNC);
+ time = now - base;
+ if (cm->verbose)
+ g_print("%s: set time to now\n", __func__);
+ } else if (sequence >= user->last_sequence + 1) {
+ gint64 num = sequence - (user->last_sequence + 1);
+ time = user->last_time_end;
+ if (num > 0) {
+ time += gst_util_uint64_scale_int(num, GST_SECOND, 100);
+ GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_DISCONT);
+ }
+ if (cm->verbose)
+ g_print("%s: set time by sequence: %lu, now: %lu\n",
+ __func__, time, now - base);
+
+ }
+
+ if (time < (now - base)) {
+ GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_DISCONT);
+ GST_BUFFER_FLAG_SET(gstbuf, GST_BUFFER_FLAG_RESYNC);
+ time = now - base;
+ if (cm->verbose)
+ g_print("%s: time is in the past, setting to now\n",
+ __func__);
+ }
+
+ GST_BUFFER_DTS(gstbuf) = now - base;
+ GST_BUFFER_PTS(gstbuf) = time;
+ GST_BUFFER_DURATION(gstbuf) = gst_util_uint64_scale_int (1, GST_SECOND, 100);
+
+ user->last_time_end = time + GST_BUFFER_DURATION(gstbuf);
+ user->last_sequence = sequence;
+
gst_app_src_push_buffer(user->src, gstbuf);
}
@@ -123,6 +183,7 @@ setup_recording_gst_pipeline(struct cmumble *cm)
cm->audio.record_pipeline = pipeline;
cutter = gst_bin_get_by_name(GST_BIN(pipeline), "cutter");
+ /* FIXME: The threshold should be configurable. */
g_object_set(G_OBJECT(cutter),
"threshold_dB", -45.0, "leaky", TRUE, NULL);
@@ -229,15 +290,8 @@ cmumble_audio_create_playback_pipeline(struct cmumble *cm,
user->pipeline = pipeline;
user->src = GST_APP_SRC(gst_bin_get_by_name(GST_BIN(pipeline), "src"));
-
- /* Important! */
- gst_base_src_set_live(GST_BASE_SRC(user->src), TRUE);
- gst_base_src_set_do_timestamp(GST_BASE_SRC(user->src), TRUE);
- gst_base_src_set_format(GST_BASE_SRC(user->src), GST_FORMAT_TIME);
add_celt_streamheader(cm, user->src);
- gst_app_src_set_stream_type(user->src, GST_APP_STREAM_TYPE_STREAM);
-
gst_element_set_state(pipeline, GST_STATE_PLAYING);
/* FIXME: Use a recursive name for sink-actual-sink-pluse instead? like:
@@ -247,6 +301,8 @@ cmumble_audio_create_playback_pipeline(struct cmumble *cm,
gst_iterator_foreach(it, set_pulse_states, user);
gst_iterator_free(it);
+ user->last_sequence = -1;
+
return 0;
}