summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2013-11-19 08:29:51 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2013-12-04 12:11:08 +0100
commitf69a59ca61e1bc8dbbd14e67b48ac0fd35b93be3 (patch)
treeef0fcd23947f7121de5653492dbd2c6e2d198a09 /src
parent0237dd789efd6ae676b6a599eaf823de2ef67349 (diff)
downloadcmumble-f69a59ca61e1bc8dbbd14e67b48ac0fd35b93be3.tar.gz
cmumble-f69a59ca61e1bc8dbbd14e67b48ac0fd35b93be3.tar.bz2
cmumble-f69a59ca61e1bc8dbbd14e67b48ac0fd35b93be3.zip
Fix buffer timestamps
* fix to start sequence at 0, if needed * do own buffer timestamping TODO: Sound is still choppy
Diffstat (limited to 'src')
-rw-r--r--src/audio.c74
-rw-r--r--src/audio.h2
-rw-r--r--src/cmumble.c3
-rw-r--r--src/cmumble.h5
4 files changed, 72 insertions, 12 deletions
diff --git a/src/audio.c b/src/audio.c
index 65af769..146fbf3 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -8,11 +8,71 @@
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?
+ */
+
+ /* 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 (sequence < 0) {
+ time = 0;
+ } else if (user->last_sequence < 0 || sequence == 0 ||
+ sequence < (user->last_sequence + 1)) {
+ time = now - base;
+ if (cm->verbose)
+ g_print("%s: set time to now\n", __func__);
+#if 0
+ /* FIXME: is this a good idea, in case the pipeline paused
+ * because we pushed no more buffers? */
+ gst_element_set_state(user->pipeline, GST_STATE_PLAYING);
+#endif
+ } else if (sequence >= user->last_sequence + 1) {
+ gint64 num = sequence - (user->last_sequence + 1);
+ time = user->last_time_end +
+ gst_util_uint64_scale_int(num, GST_SECOND, 100);
+ if (cm->verbose)
+ g_print("%s: set time by sequence: %lu, now: %lu\n",
+ __func__, time, now - base);
+
+ }
+
+ if (time < (now - base)) {
+ time = now - base;
+ if (cm->verbose)
+ g_print("%s: time is in the past, setting to now\n",
+ __func__);
+ }
gstbuf = gst_app_buffer_new(g_memdup(data, size), size, g_free, NULL);
+
+ GST_BUFFER_TIMESTAMP(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);
}
@@ -106,6 +166,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);
@@ -180,14 +241,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);
- 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:
@@ -197,11 +252,12 @@ cmumble_audio_create_playback_pipeline(struct cmumble *cm,
gst_iterator_foreach(it, set_pulse_states, user);
gst_iterator_free(it);
+ user->last_sequence = -2;
/* Setup Celt Decoder */
cmumble_audio_push(cm, user,
- cm->audio.celt_header_packet, sizeof(CELTHeader));
+ cm->audio.celt_header_packet, sizeof(CELTHeader), -2);
/* fake vorbiscomment buffer */
- cmumble_audio_push(cm, user, NULL, 0);
+ cmumble_audio_push(cm, user, NULL, 0, -2);
return 0;
}
diff --git a/src/audio.h b/src/audio.h
index 1e1c47c..6f91012 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -37,6 +37,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 730695f..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++;
@@ -186,6 +186,7 @@ recv_user_state(mumble_user_state_t *state, struct cmumble *cm)
exit(1);
}
+ /* FIXME: Verify values, that need to be available. */
user->session = state->session;
user->name = g_strdup(state->name);
user->id = state->user_id;
diff --git a/src/cmumble.h b/src/cmumble.h
index 7e83a73..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 {
@@ -54,7 +57,7 @@ struct cmumble_channel {
uint32_t parent;
char *name;
char *description;
-
+
gboolean temporary;
int32_t position;
};