From b210af1724838e7f69e297d3577996cdf4ab3f47 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Sat, 23 Nov 2013 11:11:55 +0100 Subject: 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. --- src/audio.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- src/audio.h | 2 +- src/cmumble.c | 2 +- src/cmumble.h | 3 +++ 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 { -- cgit