diff options
Diffstat (limited to 'src/audio.c')
-rw-r--r-- | src/audio.c | 72 |
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; } |