From 7eb6d165ca2d8d2f63ef0b0c7e1245708608b27f Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 29 Jul 2022 16:23:47 +0200 Subject: [PATCH] aubuf: prevent faulty timestamps (#75) * aubuf: prevent faulty timestamps for partial read There are applications where a useful timestamp is not available. E.g. if audio files are read and decoded. Then audio frames are written to aubuf with `timestamp == 0`. In such cases a partial read with `aubuf_read_auframe()` set a wrong timestamp to the rest frame. * aubuf: set correct timestamps if app provides zero For partial read timestamps are changed for the rest frames. This works only if the timestamps are already set correctly during writing. This commit handles also the case correct if the application provides timestamps and the first frame has timestamp zero and the first read is partial. * aubuf,auframe: move auframe_bytes_to_timestamp() to auframe * aubuf: reset also written_sz in aubuf_flush() --- include/rem_auframe.h | 3 +++ src/aubuf/ajb.h | 2 -- src/aubuf/aubuf.c | 13 +++++++++++-- src/auframe/auframe.c | 8 ++++++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/include/rem_auframe.h b/include/rem_auframe.h index 5243bd0..cf8a063 100644 --- a/include/rem_auframe.h +++ b/include/rem_auframe.h @@ -2,6 +2,8 @@ * Audio frame */ +#define AUDIO_TIMEBASE 1000000U + /** * Defines a frame of audio samples */ @@ -42,3 +44,4 @@ static inline void auframe_update(struct auframe *af, void *sampv, size_t auframe_size(const struct auframe *af); void auframe_mute(struct auframe *af); double auframe_level(struct auframe *af); +size_t auframe_bytes_to_timestamp(const struct auframe *af, size_t n); diff --git a/src/aubuf/ajb.h b/src/aubuf/ajb.h index a03cb0a..1a5c5dd 100644 --- a/src/aubuf/ajb.h +++ b/src/aubuf/ajb.h @@ -4,8 +4,6 @@ * Copyright (C) 2022 Commend.com - c.spielberger@commend.com */ -#define AUDIO_TIMEBASE 1000000U - enum ajb_state { AJB_GOOD = 0, AJB_LOW, diff --git a/src/aubuf/aubuf.c b/src/aubuf/aubuf.c index 3685802..5a2bd8f 100644 --- a/src/aubuf/aubuf.c +++ b/src/aubuf/aubuf.c @@ -24,6 +24,7 @@ struct aubuf { size_t max_sz; size_t fill_sz; /**< To fill size */ size_t pkt_sz; /**< Packet size */ + size_t wr_sz; /**< Written size */ bool started; uint64_t ts; @@ -91,8 +92,9 @@ static void read_auframe(struct aubuf *ab, struct auframe *af) mem_deref(f); } else if (af->srate && af->ch && sample_size) { - f->af.timestamp += n * AUDIO_TIMEBASE / - (af->srate * af->ch * sample_size); + + f->af.timestamp += + auframe_bytes_to_timestamp(&f->af, n); } if (n == sz) @@ -235,8 +237,14 @@ int aubuf_append_auframe(struct aubuf *ab, struct mbuf *mb, if (ab->fill_sz >= ab->pkt_sz) ab->fill_sz -= ab->pkt_sz; + if (!f->af.timestamp && f->af.srate && f->af.ch) { + f->af.timestamp = + auframe_bytes_to_timestamp(&f->af, ab->wr_sz); + } + list_insert_sorted(&ab->afl, frame_less_equal, NULL, &f->le, f); ab->cur_sz += sz; + ab->wr_sz += sz; if (ab->max_sz && ab->cur_sz > ab->max_sz) { #if AUBUF_DEBUG @@ -446,6 +454,7 @@ void aubuf_flush(struct aubuf *ab) list_flush(&ab->afl); ab->fill_sz = ab->wish_sz; ab->cur_sz = 0; + ab->wr_sz = 0; ab->ts = 0; mtx_unlock(ab->lock); diff --git a/src/auframe/auframe.c b/src/auframe/auframe.c index 92dedc8..3b6ae85 100644 --- a/src/auframe/auframe.c +++ b/src/auframe/auframe.c @@ -101,3 +101,11 @@ double auframe_level(struct auframe *af) return af->level; } + + +size_t auframe_bytes_to_timestamp(const struct auframe *af, size_t n) +{ + size_t sample_size = aufmt_sample_size(af->fmt); + + return n * AUDIO_TIMEBASE / (af->srate * af->ch * sample_size); +}