From 547b6a570dbad844e79b4ba5eb934f043bab6318 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 8 May 2024 10:36:38 -0400 Subject: codecs: Update libspeex from 1.2beta3 to 1.2rc1 This is a relatively minor bump, but it's the first step towards bringing this current. Change-Id: Iab6c9b0c77f0ba705280434ea74b513364719499 --- lib/rbcodec/codecs/libspeex/jitter.c | 192 ++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 95 deletions(-) (limited to 'lib/rbcodec/codecs/libspeex/jitter.c') diff --git a/lib/rbcodec/codecs/libspeex/jitter.c b/lib/rbcodec/codecs/libspeex/jitter.c index d9f6c67b86..f4e3bc2be1 100644 --- a/lib/rbcodec/codecs/libspeex/jitter.c +++ b/lib/rbcodec/codecs/libspeex/jitter.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: speex_jitter.h Adaptive jitter buffer for Speex @@ -6,18 +6,18 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -73,17 +73,17 @@ TODO: #define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) #define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) -#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) +#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) -#define MAX_TIMINGS 20 +#define MAX_TIMINGS 40 #define MAX_BUFFERS 3 -#define TOP_DELAY 20 +#define TOP_DELAY 40 /** Buffer that keeps the time of arrival of the latest packets */ struct TimingBuffer { int filled; /**< Number of entries occupied in "timing" and "counts"*/ int curr_count; /**< Number of packet timings we got (including those we discarded) */ - spx_int16_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ + spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */ }; @@ -103,7 +103,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing) tb->curr_count++; return; } - + /* Find where the timing info goes in the sorted list */ pos = 0; /* FIXME: Do bisection instead of linear search */ @@ -111,9 +111,9 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing) { pos++; } - + speex_assert(pos <= tb->filled && pos < MAX_TIMINGS); - + /* Shift everything so we can perform the insertion */ if (pos < tb->filled) { @@ -126,7 +126,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing) /* Insert */ tb->timing[pos] = timing; tb->counts[pos] = tb->curr_count; - + tb->curr_count++; if (tb->filledfilled++; @@ -139,12 +139,12 @@ struct JitterBuffer_ { spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */ spx_uint32_t next_stop; /**< Estimated time the next get() will be called */ - + spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/ - + JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */ spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */ - + void (*destroy) (void *); /**< Callback for destroying a packet */ spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */ @@ -154,7 +154,7 @@ struct JitterBuffer_ { int late_cutoff; /**< How late must a packet be for it not to be considered at all */ int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ int auto_adjust; /**< Whether to automatically adjust the delay at any time */ - + struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */ struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */ int window_size; /**< Total window over which the late frames are counted */ @@ -162,15 +162,15 @@ struct JitterBuffer_ { int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */ int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */ int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */ - + int lost_count; /**< Number of consecutive lost packets */ }; -/** Based on available data, this computes the optimal delay for the jitter buffer. +/** Based on available data, this computes the optimal delay for the jitter buffer. The optimised function is in timestamp units and is: cost = delay + late_factor*[number of frames that would be late if we used that delay] @param tb Array of buffers - @param late_factor Equivalent cost of a late frame (in timestamp units) + @param late_factor Equivalent cost of a late frame (in timestamp units) */ static spx_int16_t compute_opt_delay(JitterBuffer *jitter) { @@ -186,27 +186,27 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter) int worst = 0; spx_int32_t deltaT; struct TimingBuffer *tb; - + tb = jitter->_tb; - + /* Number of packet timings we have received (including those we didn't keep) */ tot_count = 0; for (i=0;ilatency_tradeoff != 0) late_factor = jitter->latency_tradeoff * 100.0f / tot_count; else late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count; - + /*fprintf(stderr, "late_factor = %f\n", late_factor);*/ for (i=0;idelay_step); pos[next]++; - + /* Actual cost function that tells us how bad using this delay would be */ cost = -latest + late_factor*late; /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/ @@ -243,24 +243,24 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter) } else { break; } - + /* For the next timing we will consider, there will be one more late packet to count */ late++; /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */ if (latest >= 0 && !penalty_taken) { penalty_taken = 1; - late+=2; + late+=4; } } - + deltaT = best-worst; /* This is a default "automatic latency tradeoff" when none is provided */ jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY; /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/ - + /* FIXME: Compute a short-term estimate too and combine with the long-term one */ - + /* Prevents reducing the buffer size when we haven't really had much data */ if (tot_count < TOP_DELAY && opt > 0) return 0; @@ -269,7 +269,7 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter) /** Initialise jitter buffer */ -JitterBuffer *jitter_buffer_init(int step_size) +EXPORT JitterBuffer *jitter_buffer_init(int step_size) { JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); if (jitter) @@ -294,7 +294,7 @@ JitterBuffer *jitter_buffer_init(int step_size) } /** Reset jitter buffer */ -void jitter_buffer_reset(JitterBuffer *jitter) +EXPORT void jitter_buffer_reset(JitterBuffer *jitter) { int i; for (i=0;ilost_count = 0; jitter->buffered = 0; jitter->auto_tradeoff = 32000; - + for (i=0;i_tb[i]); @@ -325,7 +325,7 @@ void jitter_buffer_reset(JitterBuffer *jitter) } /** Destroy jitter buffer */ -void jitter_buffer_destroy(JitterBuffer *jitter) +EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) { jitter_buffer_reset(jitter); speex_free(jitter); @@ -365,12 +365,12 @@ static void shift_timings(JitterBuffer *jitter, spx_int16_t amount) /** Put one packet into the jitter buffer */ -void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) +EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) { int i,j; int late; /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ - + /* Cleanup buffer (remove old packets that weren't played) */ if (!jitter->reset_state) { @@ -388,7 +388,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) } } } - + /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/ /* Check if packet is late (could still be useful though) */ if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) @@ -398,7 +398,14 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) } else { late = 0; } - + + /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is + * used to resync. */ + if (jitter->lost_count>20) + { + jitter_buffer_reset(jitter); + } + /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp)) { @@ -409,7 +416,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) if (jitter->packets[i].data==NULL) break; } - + /*No place left in the buffer, need to make room for it by discarding the oldest packet */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { @@ -428,13 +435,9 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) else speex_free(jitter->packets[i].data); jitter->packets[i].data=NULL; - if (jitter->lost_count>20) - { - jitter_buffer_reset(jitter); - } - /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ + /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ } - + /* Copy packet in buffer */ if (jitter->destroy) { @@ -454,18 +457,18 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) else jitter->arrival[i] = jitter->next_stop; } - - + + } /** Get one packet from the jitter buffer */ -int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) +EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) { int i; unsigned int j; int incomplete = 0; spx_int16_t opt; - + if (start_offset != NULL) *start_offset = 0; @@ -485,7 +488,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 } if (found) { - jitter->reset_state=0; + jitter->reset_state=0; jitter->pointer_timestamp = oldest; jitter->next_stop = oldest; } else { @@ -494,36 +497,36 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 return JITTER_BUFFER_MISSING; } } - + jitter->last_returned_timestamp = jitter->pointer_timestamp; - + if (jitter->interp_requested != 0) { packet->timestamp = jitter->pointer_timestamp; packet->span = jitter->interp_requested; - + /* Increment the pointer because it got decremented in the delay update */ jitter->pointer_timestamp += jitter->interp_requested; packet->len = 0; /*fprintf (stderr, "Deferred interpolate\n");*/ - + jitter->interp_requested = 0; - + jitter->buffered = packet->span - desired_span; return JITTER_BUFFER_INSERTION; } - + /* Searching for the packet that fits best */ - + /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ for (i=0;ipackets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) break; } - + /* If no match, try for an "older" packet that still spans (fully) the current chunk */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { @@ -533,7 +536,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 break; } } - + /* If still no match, try for an "older" packet that spans part of the current chunk */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { @@ -543,7 +546,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 break; } } - + /* If still no match, try for earliest packet possible */ if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) { @@ -577,17 +580,17 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) { spx_int32_t offset; - + /* We (obviously) haven't lost this packet */ jitter->lost_count = 0; - + /* In this case, 0 isn't as a valid timestamp */ if (jitter->arrival[i] != 0) { update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin); } - - + + if (jitter->packets[i].len > packet->len) { speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); @@ -611,10 +614,10 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 *start_offset = offset; else if (offset != 0) speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset); - + packet->timestamp = jitter->packets[i].timestamp; jitter->last_returned_timestamp = packet->timestamp; - + packet->span = jitter->packets[i].span; packet->sequence = jitter->packets[i].sequence; packet->user_data = jitter->packets[i].user_data; @@ -622,36 +625,36 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span; jitter->buffered = packet->span - desired_span; - + if (start_offset != NULL) jitter->buffered += *start_offset; - + return JITTER_BUFFER_OK; } - - + + /* If we haven't found anything worth returning */ - + /*fprintf (stderr, "not found\n");*/ jitter->lost_count++; /*fprintf (stderr, "m");*/ /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/ - + opt = compute_opt_delay(jitter); - - /* Should we force an increase in the buffer or just do normal interpolation? */ + + /* Should we force an increase in the buffer or just do normal interpolation? */ if (opt < 0) { /* Need to increase buffering */ - + /* Shift histogram to compensate */ shift_timings(jitter, -opt); - + packet->timestamp = jitter->pointer_timestamp; packet->span = -opt; /* Don't move the pointer_timestamp forward */ packet->len = 0; - + jitter->buffered = packet->span - desired_span; return JITTER_BUFFER_INSERTION; /*jitter->pointer_timestamp -= jitter->delay_step;*/ @@ -659,12 +662,12 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 } else { /* Normal packet loss */ packet->timestamp = jitter->pointer_timestamp; - + desired_span = ROUND_DOWN(desired_span, jitter->concealment_size); packet->span = desired_span; jitter->pointer_timestamp += desired_span; packet->len = 0; - + jitter->buffered = packet->span - desired_span; return JITTER_BUFFER_MISSING; /*fprintf (stderr, "Normal loss\n");*/ @@ -673,7 +676,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3 } -int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) +EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) { int i, j; for (i=0;ipointer_timestamp += opt; jitter->interp_requested = -opt; /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/ @@ -727,14 +730,14 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket jitter->pointer_timestamp += opt; /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/ } - + return opt; } /* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ -int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) +EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) { - /* If the programmer calls jitter_buffer_update_delay() directly, + /* If the programmer calls jitter_buffer_update_delay() directly, automatically disable auto-adjustment */ jitter->auto_adjust = 0; @@ -742,17 +745,17 @@ int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, } /** Get pointer timestamp of jitter buffer */ -int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) +EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) { return jitter->pointer_timestamp; } -void jitter_buffer_tick(JitterBuffer *jitter) +EXPORT void jitter_buffer_tick(JitterBuffer *jitter) { /* Automatically-adjust the buffering delay if requested */ if (jitter->auto_adjust) _jitter_buffer_update_delay(jitter, NULL, NULL); - + if (jitter->buffered >= 0) { jitter->next_stop = jitter->pointer_timestamp - jitter->buffered; @@ -763,12 +766,12 @@ void jitter_buffer_tick(JitterBuffer *jitter) jitter->buffered = 0; } -void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) +EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) { /* Automatically-adjust the buffering delay if requested */ if (jitter->auto_adjust) _jitter_buffer_update_delay(jitter, NULL, NULL); - + if (jitter->buffered < 0) speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); jitter->next_stop = jitter->pointer_timestamp - rem; @@ -776,7 +779,7 @@ void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) /* Used like the ioctl function to control the jitter buffer parameters */ -int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) +EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) { int count, i; switch(request) @@ -836,4 +839,3 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) } return 0; } - -- cgit v1.2.3