summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2013-11-23 11:11:55 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2013-12-04 12:31:50 +0100
commitb210af1724838e7f69e297d3577996cdf4ab3f47 (patch)
treedba985a8f385b618ddc85e2fccc34d1011edd60d
parent17b574653fe3c0ff9973b2d2688f81ee30855389 (diff)
downloadcmumble-b210af1724838e7f69e297d3577996cdf4ab3f47.tar.gz
cmumble-b210af1724838e7f69e297d3577996cdf4ab3f47.tar.bz2
cmumble-b210af1724838e7f69e297d3577996cdf4ab3f47.zip
Timestamp playback buffers with appropriate flags
* GST_BUFFER_FLAG_DISCONT helps to play immediately after a pause (i.e. no talking) TODO: Not sure GST_BUFFER_FLAG_RESYNC does really help, but from the decoumentation it does what we want.
-rw-r--r--src/audio.c72
-rw-r--r--src/audio.h2
-rw-r--r--src/cmumble.c2
-rw-r--r--src/cmumble.h3
4 files changed, 69 insertions, 10 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;
}
diff --git a/src/audio.h b/src/audio.h
index 2fd86c4..8e47ca9 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -36,6 +36,6 @@ cmumble_audio_create_playback_pipeline(struct cmumble *cm,
void
cmumble_audio_push(struct cmumble *cm, struct cmumble_user *user,
- const guint8 *data, gsize size);
+ const guint8 *data, gsize size, gint64 sequence);
#endif /* _AUDIO_H_ */
diff --git a/src/cmumble.c b/src/cmumble.c
index 977e30a..1ca18bb 100644
--- a/src/cmumble.c
+++ b/src/cmumble.c
@@ -51,7 +51,7 @@ recv_udp_tunnel(mumble_udptunnel_t *tunnel, struct cmumble *cm)
if (frame_len < 2)
break;
- cmumble_audio_push(cm, user, &data[pos], frame_len);
+ cmumble_audio_push(cm, user, &data[pos], frame_len, sequence);
pos += frame_len;
sequence++;
diff --git a/src/cmumble.h b/src/cmumble.h
index b796d50..3997c8a 100644
--- a/src/cmumble.h
+++ b/src/cmumble.h
@@ -47,6 +47,9 @@ struct cmumble_user {
GstElement *pipeline;
GstAppSrc *src;
+
+ gint64 last_sequence;
+ guint64 last_time_end;
};
struct cmumble_channel {