From f69a59ca61e1bc8dbbd14e67b48ac0fd35b93be3 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 19 Nov 2013 08:29:51 +0100 Subject: Fix buffer timestamps * fix to start sequence at 0, if needed * do own buffer timestamping TODO: Sound is still choppy --- src/audio.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/audio.h | 2 +- src/cmumble.c | 3 ++- src/cmumble.h | 5 +++- 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; }; -- cgit