[SCM] libgroove/upstream: dummy player: avoid floating point error accumulation
andrewrk-guest at users.alioth.debian.org
andrewrk-guest at users.alioth.debian.org
Wed May 14 02:26:58 UTC 2014
The following commit has been merged in the upstream branch:
commit d226ce7abf7bb7ab66ab3c9978db89e3dd5e5378
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Tue May 13 17:36:25 2014 -0700
dummy player: avoid floating point error accumulation
diff --git a/grooveplayer/player.c b/grooveplayer/player.c
index 4d76db2..6f9d3b7 100644
--- a/grooveplayer/player.c
+++ b/grooveplayer/player.c
@@ -38,7 +38,8 @@ struct GroovePlayerPrivate {
// for dummy player
pthread_t thread_id;
int abort_request;
- double start_nanos;
+ uint64_t start_nanos;
+ uint64_t frames_consumed;
pthread_cond_t pause_cond;
pthread_condattr_t cond_attr;
int pause_cond_inited;
@@ -88,11 +89,10 @@ static void emit_event(struct GrooveQueue *queue, enum GroovePlayerEventType typ
av_log(NULL, AV_LOG_ERROR, "unable to put event on queue: out of memory\n");
}
-static double now_nanos(void) {
+static uint64_t now_nanos(void) {
struct timespec tms;
clock_gettime(CLOCK_MONOTONIC, &tms);
- uint64_t nanos = tms.tv_sec * 1000000000 + tms.tv_nsec;
- return nanos;
+ return tms.tv_sec * 1000000000 + tms.tv_nsec;
}
// this thread is started if the user selects a dummy device instead of a
@@ -109,7 +109,7 @@ static void *dummy_thread(void *arg) {
continue;
}
- double now = now_nanos();
+ uint64_t now = now_nanos();
int more = 1;
while (more) {
more = 0;
@@ -133,25 +133,25 @@ static void *dummy_thread(void *arg) {
// errors are treated the same as no buffer ready
emit_event(p->eventq, GROOVE_EVENT_BUFFERUNDERRUN);
p->start_nanos = now;
+ p->frames_consumed = 0;
pthread_mutex_unlock(&p->play_head_mutex);
break;
}
}
if (p->audio_buf) {
- double nanos_to_kill = now - p->start_nanos;
- double dbl_sample_rate = p->audio_buf->format.sample_rate;
- double nanos_per_frame = 1000000000.0 / dbl_sample_rate;
- int frames_to_kill = nanos_to_kill / nanos_per_frame;
+ uint64_t nanos_per_frame = 1000000000 / p->audio_buf->format.sample_rate;
+ uint64_t total_nanos = now - p->start_nanos;
+ uint64_t total_frames = total_nanos / nanos_per_frame;
+ int frames_to_kill = total_frames - p->frames_consumed;
int new_index = p->audio_buf_index + frames_to_kill;
if (new_index > p->audio_buf->frame_count) {
more = 1;
new_index = p->audio_buf->frame_count;
frames_to_kill = new_index - p->audio_buf_index;
}
- double nanos_killed = frames_to_kill * nanos_per_frame;
- p->start_nanos += nanos_killed;
+ p->frames_consumed += frames_to_kill;
p->audio_buf_index = new_index;
- p->play_pos += frames_to_kill / dbl_sample_rate;
+ p->play_pos += frames_to_kill / (double) p->audio_buf->format.sample_rate;
}
}
@@ -231,6 +231,7 @@ static void sink_purge(struct GrooveSink *sink, struct GroovePlaylistItem *item)
p->audio_buf_index = 0;
p->audio_buf_size = 0;
p->start_nanos = now_nanos();
+ p->frames_consumed = 0;
emit_event(p->eventq, GROOVE_EVENT_NOWPLAYING);
}
@@ -263,6 +264,7 @@ static void sink_play(struct GrooveSink *sink) {
// mark the position in time that we started playing at.
pthread_mutex_lock(&p->play_head_mutex);
p->start_nanos = now_nanos();
+ p->frames_consumed = 0;
p->paused = 0;
pthread_cond_signal(&p->pause_cond);
pthread_mutex_unlock(&p->play_head_mutex);
@@ -278,6 +280,7 @@ static void sink_flush(struct GrooveSink *sink) {
p->audio_buf_index = 0;
p->audio_buf_size = 0;
p->start_nanos = now_nanos();
+ p->frames_consumed = 0;
pthread_mutex_unlock(&p->play_head_mutex);
}
--
libgroove packaging
More information about the pkg-multimedia-commits
mailing list