summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Raghavan <arun@asymptotic.io>2020-10-22 10:12:03 -0400
committerArun Raghavan <arun@asymptotic.io>2020-10-23 12:11:35 -0400
commit314e97d9957677508203f8868042d698e427a270 (patch)
tree46de2ca39bfc6df4d3d7b56087163eed5183cdbf
parent5f12dde2f5dbc85c918ac469ef64866a96b70fa8 (diff)
downloadpulseaudio-314e97d9957677508203f8868042d698e427a270.tar.gz
rtp: gstreamer: Account for rounding errors in RTP timestamp conversion
Since the RTP timestamp is converted to time units and back, a small error can creep up, which then results in a single frame error in where we place the buffer in the output memblockq. This results in minor glitches, so we check for and eliminate the error.
-rw-r--r--src/modules/rtp/rtp-gstreamer.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/modules/rtp/rtp-gstreamer.c b/src/modules/rtp/rtp-gstreamer.c
index 1d253cfa0..28d367bfb 100644
--- a/src/modules/rtp/rtp-gstreamer.c
+++ b/src/modules/rtp/rtp-gstreamer.c
@@ -54,6 +54,7 @@ struct pa_rtp_context {
GstElement *appsink;
GstCaps *meta_reference;
+ bool first_buffer;
uint32_t last_timestamp;
uint8_t *send_buf;
@@ -482,6 +483,7 @@ pa_rtp_context* pa_rtp_context_new_recv(int fd, uint8_t payload, const pa_sample
c->fdsem = pa_fdsem_new();
c->ss = *ss;
c->send_buf = NULL;
+ c->first_buffer = true;
if (!gst_init_check(NULL, NULL, &error)) {
pa_log_error("Could not initialise GStreamer: %s", error->message);
@@ -598,6 +600,21 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
if (timestamp != GST_CLOCK_TIME_NONE)
pa_timeval_rtstore(tstamp, timestamp / PA_NSEC_PER_USEC, false);
+ if (c->first_buffer) {
+ c->first_buffer = false;
+ c->last_timestamp = *rtp_tstamp;
+ } else {
+ /* The RTP clock -> time domain -> RTP clock transformation above might
+ * add a ±1 rounding error, so let's get rid of that */
+ uint32_t expected = c->last_timestamp + (uint32_t) (data_len / pa_rtp_context_get_frame_size(c));
+ int delta = *rtp_tstamp - expected;
+
+ if (delta == 1 || delta == -1)
+ *rtp_tstamp -= delta;
+
+ c->last_timestamp = *rtp_tstamp;
+ }
+
gst_buffer_list_unref(buf_list);
gst_object_unref(adapter);