MT#56471 mix_buffer: support time-based delay

... as an extra offset for newly added sources, based on the difference
between the last runtime (read time) of the buffer and the current time.

Change-Id: Ie99e24f0697f0950f0fcfa1e5e58b8f4be134018
pull/1627/head
Richard Fuchs 2 years ago
parent 81a0f36f27
commit 19768736c2

@ -217,12 +217,33 @@ static void mix_buffer_src_init_pos(struct mix_buffer *mb, struct mix_buffer_ssr
}
bool mix_buffer_write(struct mix_buffer *mb, uint32_t ssrc, const void *buf, unsigned int samples) {
static void mix_buff_src_shift_delay(struct mix_buffer *mb, struct mix_buffer_ssrc_source *src,
const struct timeval *last, const struct timeval *now)
{
if (!last || !now)
return;
long long diff_us = timeval_diff(now, last);
if (diff_us <= 0)
return;
unsigned int samples = mb->clockrate * diff_us / 1000000;
mix_buffer_src_add_delay(mb, src, samples);
}
// takes the difference between two time stamps into account, scaled to the given clock rate,
// to add an additional write-delay for a newly created source
bool mix_buffer_write_delay(struct mix_buffer *mb, uint32_t ssrc, const void *buf, unsigned int samples,
const struct timeval *last, const struct timeval *now)
{
LOCK(&mb->lock);
AUTO_CLEANUP(struct mix_buffer_ssrc_source *src, mix_ssrc_put) = get_ssrc(ssrc, mb->ssrc_hash);
bool created;
AUTO_CLEANUP(struct mix_buffer_ssrc_source *src, mix_ssrc_put)
= get_ssrc_full(ssrc, mb->ssrc_hash, &created);
if (!src)
return false;
if (created)
mix_buff_src_shift_delay(mb, src, last, now);
// loop twice at the most to re-run logic after a reset
while (true) {

@ -64,7 +64,12 @@ void mix_buffer_destroy(struct mix_buffer *);
void *mix_buffer_read_fast(struct mix_buffer *, unsigned int samples, unsigned int *size);
void mix_buffer_read_slow(struct mix_buffer *, void *outbuf, unsigned int samples);
bool mix_buffer_write(struct mix_buffer *, uint32_t ssrc, const void *buf, unsigned int samples);
bool mix_buffer_write_delay(struct mix_buffer *, uint32_t ssrc, const void *buf, unsigned int samples,
const struct timeval *, const struct timeval *);
INLINE bool mix_buffer_write(struct mix_buffer *mb, uint32_t ssrc, const void *buf, unsigned int samples) {
return mix_buffer_write_delay(mb, ssrc, buf, samples, NULL, NULL);
}
#endif

@ -451,6 +451,56 @@ int main(void) {
assert(size == 20);
assert(memcmp(p, "1122334455" "\0\0\0\0\0\0\0\0\0\0", size) == 0);
// src now fallen behind, catch up with reader
ret = mix_buffer_write(&mb, 0x1234, "xxxxxxxxxx", 5);
assert(ret == true);
p = mix_buffer_read_fast(&mb, 10, &size);
assert(p != NULL);
assert(size == 20);
assert(memcmp(p, "\0\0\0\0\0\0\0\0\0\0" "xxxxxxxxxx", size) == 0);
// mix two sources
ret = mix_buffer_write(&mb, 0x1234, "1122334455", 5);
assert(ret == true);
// add new source
ret = mix_buffer_write(&mb, 0x6543, "9988776655", 5);
assert(ret == true);
ret = mix_buffer_write(&mb, 0x1234, "3344556677", 5);
assert(ret == true);
// output partially mixed, new source delayed
p = mix_buffer_read_fast(&mb, 10, &size);
assert(p == NULL);
assert(size == 20);
mix_buffer_read_slow(&mb, buf, 10);
assert(memcmp(buf, "1122334455llllllllll" , size) == 0);
// caught up now. add new source with extra delay:
// 10 ms constant, 15 ms extra = 25 ms total = 12.5 sampes (12)
struct timeval last = { 100, 200 };
struct timeval now = { 100, 15200 };
ret = mix_buffer_write_delay(&mb, 0x3333, "0011223344", 5, &last, &now);
assert(ret == true);
// mix-in previous source
ret = mix_buffer_write(&mb, 0x6543, "3322114455998866334422339988776655443322", 20);
assert(ret == true);
// read mixed output
p = mix_buffer_read_fast(&mb, 20, &size);
assert(p != NULL);
assert(size == 40);
assert(memcmp(p, "332211445599886633442233iiiiiiiiii443322", size) == 0);
mix_buffer_destroy(&mb);
return 0;

Loading…
Cancel
Save