mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 20:31:29 +02:00
completed code for dynamicly resizing jitter buffer
This commit is contained in:
parent
a5457eb86b
commit
cb6681f6f8
2 changed files with 60 additions and 23 deletions
|
@ -158,7 +158,7 @@ const int16_t& AudioRingBuffer::operator[] (const int index) const {
|
||||||
|
|
||||||
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
||||||
printf("\n mixed. %d samples remaining\n", samplesAvailable());
|
//printf("\nmixed. %d samples remaining\n", samplesAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int AudioRingBuffer::samplesAvailable() const {
|
unsigned int AudioRingBuffer::samplesAvailable() const {
|
||||||
|
|
|
@ -33,8 +33,7 @@ InterframeTimeGapHistory::InterframeTimeGapHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterframeTimeGapHistory::frameReceived() {
|
void InterframeTimeGapHistory::frameReceived() {
|
||||||
|
|
||||||
static QQueue<quint64> gaps;
|
|
||||||
static quint64 gapsSum = 0;
|
static quint64 gapsSum = 0;
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
|
@ -46,6 +45,14 @@ void InterframeTimeGapHistory::frameReceived() {
|
||||||
// update the current interval max
|
// update the current interval max
|
||||||
if (gap > _currentIntervalMaxGap) {
|
if (gap > _currentIntervalMaxGap) {
|
||||||
_currentIntervalMaxGap = gap;
|
_currentIntervalMaxGap = gap;
|
||||||
|
|
||||||
|
// keep the window max gap at least as large as the current interval max
|
||||||
|
// this allows the window max gap to respond immediately to a sudden spike in gap times
|
||||||
|
// also, this prevents the window max gap from staying at 0 until the first interval of samples filled up
|
||||||
|
if (_currentIntervalMaxGap > _windowMaxGap) {
|
||||||
|
_windowMaxGap = _currentIntervalMaxGap;
|
||||||
|
_newWindowMaxGapAvailable = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_numSamplesInCurrentInterval++;
|
_numSamplesInCurrentInterval++;
|
||||||
|
|
||||||
|
@ -116,17 +123,35 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
|
||||||
readBytes += sizeof(int16_t);
|
readBytes += sizeof(int16_t);
|
||||||
|
|
||||||
if (numSilentSamples > 0) {
|
if (numSilentSamples > 0) {
|
||||||
addSilentFrame(numSilentSamples);
|
|
||||||
|
if (_currentJitterBufferFrames > _desiredJitterBufferFrames) {
|
||||||
|
// our current jitter buffer size exceeds its desired value, so ignore some silent
|
||||||
|
// frames to get that size as close to desired as possible
|
||||||
|
int samplesPerFrame = getSamplesPerFrame();
|
||||||
|
int numSilentFrames = numSilentSamples / samplesPerFrame;
|
||||||
|
int numFramesToDropDesired = _currentJitterBufferFrames - _desiredJitterBufferFrames;
|
||||||
|
|
||||||
|
if (numSilentFrames > numFramesToDropDesired) {
|
||||||
|
// we have more than enough frames to drop to get the jitter buffer to its desired length
|
||||||
|
int numSilentFramesToAdd = numSilentFrames - numFramesToDropDesired;
|
||||||
|
addSilentFrame(numSilentFramesToAdd * samplesPerFrame);
|
||||||
|
_currentJitterBufferFrames = _desiredJitterBufferFrames;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// we need to drop all frames to get the jitter buffer close as possible to its desired length
|
||||||
|
_currentJitterBufferFrames -= numSilentFrames;
|
||||||
|
printf("dropped silent packet! jbuffer size is now %d ###############", _currentJitterBufferFrames);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addSilentFrame(numSilentSamples);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("\nparsed silent packet of %d samples\n", numSilentSamples);
|
|
||||||
} else {
|
} else {
|
||||||
// there is audio data to read
|
// there is audio data to read
|
||||||
int dataBytes = writeData(packet.data() + readBytes, packet.size() - readBytes);
|
int dataBytes = writeData(packet.data() + readBytes, packet.size() - readBytes);
|
||||||
readBytes += dataBytes;
|
readBytes += dataBytes;
|
||||||
|
|
||||||
printf("\nparsed packet of %d data bytes\n", dataBytes);
|
|
||||||
}
|
}
|
||||||
printf("%d samples available\n", samplesAvailable());
|
//printf("parsed packet. %d samples available\n", samplesAvailable());
|
||||||
|
|
||||||
return readBytes;
|
return readBytes;
|
||||||
}
|
}
|
||||||
|
@ -174,16 +199,18 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
||||||
|
|
||||||
int samplesPerFrame = getSamplesPerFrame();
|
int samplesPerFrame = getSamplesPerFrame();
|
||||||
int currentJitterBufferSamples = 3 * samplesPerFrame; //_currentJitterBufferFrames * samplesPerFrame;
|
int desiredJitterBufferSamples = _desiredJitterBufferFrames * samplesPerFrame;
|
||||||
|
|
||||||
//printf("\nsamples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
//printf("\nsamples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
||||||
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + currentJitterBufferSamples)) {
|
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + _desiredJitterBufferFrames)) {
|
||||||
|
|
||||||
|
printf("\nMIXING DELAYED! waiting for jitter buffer to fill after being starved\n");
|
||||||
|
printf("samples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
||||||
|
|
||||||
|
// if the buffer was starved, allow it to accrue at least the desired number of
|
||||||
|
// jitter buffer frames before we start taking frames from it for mixing
|
||||||
|
|
||||||
//printf("\nMIXING DELAYED! waiting for jitter buffer to fill after being starved\n");
|
|
||||||
//printf("samples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
|
||||||
// if the buffer was starved and hasn't filled back up all the way, don't mix yet
|
|
||||||
if (_shouldOutputStarveDebug) {
|
if (_shouldOutputStarveDebug) {
|
||||||
_shouldOutputStarveDebug = false;
|
_shouldOutputStarveDebug = false;
|
||||||
}
|
}
|
||||||
|
@ -192,26 +219,34 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
||||||
|
|
||||||
} else if (samplesAvailable() < samplesPerFrame) {
|
} else if (samplesAvailable() < samplesPerFrame) {
|
||||||
|
|
||||||
//printf("\nMIXING DELAYED! jitter buffer is starved!!!\n");
|
printf("\nMIXING DELAYED! jitter buffer is starved!!!\n");
|
||||||
//printf("samples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
printf("samples available: %d frames available: %d\n", samplesAvailable(), samplesAvailable() / samplesPerFrame);
|
||||||
// if the buffer doesn't have a full frame of samples for mixing, it is starved
|
|
||||||
|
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
|
||||||
_isStarved = true;
|
_isStarved = true;
|
||||||
|
|
||||||
|
// set to 0 to indicate the jitter buffer is starved
|
||||||
|
_currentJitterBufferFrames = 0;
|
||||||
|
|
||||||
// reset our _shouldOutputStarveDebug to true so the next is printed
|
// reset our _shouldOutputStarveDebug to true so the next is printed
|
||||||
_shouldOutputStarveDebug = true;
|
_shouldOutputStarveDebug = true;
|
||||||
|
|
||||||
// if buffer was starved, we've effectively increased the jitter buffer by one frame
|
|
||||||
// by "holding back" this ring buffer's contents until the next client frame is prepared.
|
|
||||||
_currentJitterBufferFrames++;
|
|
||||||
//printf("jbuffer size increased: new size: %d\n", _currentJitterBufferFrames);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
//printf("WILL MIX\n");
|
//printf("WILL MIX\n");
|
||||||
|
|
||||||
// good buffer, add this to the mix
|
// good buffer, add this to the mix
|
||||||
_isStarved = false;
|
|
||||||
|
if (_isStarved) {
|
||||||
|
|
||||||
|
// if this buffer was just finished replenishing after being starved, the number of frames in it now
|
||||||
|
// is the length of the jitter buffer
|
||||||
|
_currentJitterBufferFrames = samplesAvailable() / samplesPerFrame;
|
||||||
|
printf("jitter buffer length is now %d; desired: %d --------\n", _currentJitterBufferFrames, _desiredJitterBufferFrames);
|
||||||
|
|
||||||
|
_isStarved = false;
|
||||||
|
}
|
||||||
|
|
||||||
// since we've read data from ring buffer at least once - we've started
|
// since we've read data from ring buffer at least once - we've started
|
||||||
_hasStarted = true;
|
_hasStarted = true;
|
||||||
|
@ -228,5 +263,7 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() {
|
||||||
if (_desiredJitterBufferFrames < 1) {
|
if (_desiredJitterBufferFrames < 1) {
|
||||||
_desiredJitterBufferFrames = 1;
|
_desiredJitterBufferFrames = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf(" desired jbuffer size is now %d --------------------------------\n", _desiredJitterBufferFrames);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue