changed Audio.cpp to not overflow _audioOutput buffer, and 2 other things

added _consecutiveNotMixedCount to prevent premature injector stream
deletion;  made silent-frame drop only occur in dynamic jitter buffer
mode
This commit is contained in:
wangyix 2014-07-08 11:16:39 -07:00
parent e34f592a83
commit 2e73ac8bc1
4 changed files with 25 additions and 16 deletions

View file

@ -138,11 +138,14 @@ void AudioMixerClientData::pushBuffersAfterFrameSend() {
// this was a used buffer, push the output pointer forwards // this was a used buffer, push the output pointer forwards
PositionalAudioRingBuffer* audioBuffer = *i; PositionalAudioRingBuffer* audioBuffer = *i;
const int INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD = 100;
if (audioBuffer->willBeAddedToMix()) { if (audioBuffer->willBeAddedToMix()) {
audioBuffer->shiftReadPosition(audioBuffer->getSamplesPerFrame()); audioBuffer->shiftReadPosition(audioBuffer->getSamplesPerFrame());
audioBuffer->setWillBeAddedToMix(false); audioBuffer->setWillBeAddedToMix(false);
} else if (audioBuffer->getType() == PositionalAudioRingBuffer::Injector } else if (audioBuffer->getType() == PositionalAudioRingBuffer::Injector
&& audioBuffer->hasStarted() && audioBuffer->isStarved()) { && audioBuffer->hasStarted() && audioBuffer->isStarved()
&& audioBuffer->getConsecutiveNotMixedCount() > INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD) {
// this is an empty audio buffer that has starved, safe to delete // this is an empty audio buffer that has starved, safe to delete
// also delete its sequence number stats // also delete its sequence number stats
QUuid streamIdentifier = ((InjectedAudioRingBuffer*)audioBuffer)->getStreamIdentifier(); QUuid streamIdentifier = ((InjectedAudioRingBuffer*)audioBuffer)->getStreamIdentifier();

View file

@ -67,7 +67,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_proceduralAudioOutput(NULL), _proceduralAudioOutput(NULL),
_proceduralOutputDevice(NULL), _proceduralOutputDevice(NULL),
_inputRingBuffer(0), _inputRingBuffer(0),
_ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO), _ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, false, 100),
_isStereoInput(false), _isStereoInput(false),
_averagedLatency(0.0), _averagedLatency(0.0),
_measuredJitter(0), _measuredJitter(0),
@ -869,14 +869,11 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
_numFramesDisplayStarve = 10; _numFramesDisplayStarve = 10;
} }
// if there is anything in the ring buffer, decide what to do int numSamplesAudioOutputRoomFor = _audioOutput->bytesFree() / sizeof(int16_t);
if (_ringBuffer.samplesAvailable() > 0) { int numNetworkOutputSamples = std::min(_ringBuffer.samplesAvailable(), (int)(numSamplesAudioOutputRoomFor * networkOutputToOutputRatio));
int numNetworkOutputSamples = _ringBuffer.samplesAvailable(); // if there is data in the ring buffer and room in the audio output, decide what to do
int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio; if (numNetworkOutputSamples > 0) {
QByteArray outputBuffer;
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
int numSamplesNeededToStartPlayback = std::min(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (_jitterBufferSamples * 2), int numSamplesNeededToStartPlayback = std::min(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (_jitterBufferSamples * 2),
_ringBuffer.getSampleCapacity()); _ringBuffer.getSampleCapacity());
@ -885,6 +882,11 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
// We are still waiting for enough samples to begin playback // We are still waiting for enough samples to begin playback
// qDebug() << numNetworkOutputSamples << " samples so far, waiting for " << numSamplesNeededToStartPlayback; // qDebug() << numNetworkOutputSamples << " samples so far, waiting for " << numSamplesNeededToStartPlayback;
} else { } else {
int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio;
QByteArray outputBuffer;
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
// We are either already playing back, or we have enough audio to start playing back. // We are either already playing back, or we have enough audio to start playing back.
//qDebug() << "pushing " << numNetworkOutputSamples; //qDebug() << "pushing " << numNetworkOutputSamples;
_ringBuffer.setIsStarved(false); _ringBuffer.setIsStarved(false);

View file

@ -99,7 +99,8 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::
_listenerUnattenuatedZone(NULL), _listenerUnattenuatedZone(NULL),
_desiredJitterBufferFrames(1), _desiredJitterBufferFrames(1),
_currentJitterBufferFrames(-1), _currentJitterBufferFrames(-1),
_dynamicJitterBuffers(dynamicJitterBuffers) _dynamicJitterBuffers(dynamicJitterBuffers),
_consecutiveNotMixedCount(0)
{ {
} }
@ -129,7 +130,7 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
numSilentSamples = getSamplesPerFrame(); numSilentSamples = getSamplesPerFrame();
if (numSilentSamples > 0) { if (numSilentSamples > 0) {
if (_currentJitterBufferFrames > _desiredJitterBufferFrames) { if (_dynamicJitterBuffers && _currentJitterBufferFrames > _desiredJitterBufferFrames) {
// our current jitter buffer size exceeds its desired value, so ignore some silent // our current jitter buffer size exceeds its desired value, so ignore some silent
// frames to get that size as close to desired as possible // frames to get that size as close to desired as possible
int samplesPerFrame = getSamplesPerFrame(); int samplesPerFrame = getSamplesPerFrame();
@ -206,11 +207,12 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) { if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) {
// if the buffer was starved, allow it to accrue at least the desired number of // 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 // jitter buffer frames before we start taking frames from it for mixing
if (_shouldOutputStarveDebug) { if (_shouldOutputStarveDebug) {
_shouldOutputStarveDebug = false; _shouldOutputStarveDebug = false;
} }
_consecutiveNotMixedCount++;
return false; return false;
} else if (samplesAvailable() < samplesPerFrame) { } else if (samplesAvailable() < samplesPerFrame) {
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved // if the buffer doesn't have a full frame of samples to take for mixing, it is starved
@ -222,6 +224,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// reset our _shouldOutputStarveDebug to true so the next is printed // reset our _shouldOutputStarveDebug to true so the next is printed
_shouldOutputStarveDebug = true; _shouldOutputStarveDebug = true;
_consecutiveNotMixedCount++;
return false; return false;
} }
@ -231,6 +234,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// minus one (since a frame will be read immediately after this) is the length of the jitter buffer // minus one (since a frame will be read immediately after this) is the length of the jitter buffer
_currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1; _currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1;
_isStarved = false; _isStarved = false;
_consecutiveNotMixedCount = 0;
} }
// 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

View file

@ -83,6 +83,8 @@ public:
int getDesiredJitterBufferFrames() const { return _desiredJitterBufferFrames; } int getDesiredJitterBufferFrames() const { return _desiredJitterBufferFrames; }
int getCurrentJitterBufferFrames() const { return _currentJitterBufferFrames; } int getCurrentJitterBufferFrames() const { return _currentJitterBufferFrames; }
int getConsecutiveNotMixedCount() const { return _consecutiveNotMixedCount; }
protected: protected:
// disallow copying of PositionalAudioRingBuffer objects // disallow copying of PositionalAudioRingBuffer objects
PositionalAudioRingBuffer(const PositionalAudioRingBuffer&); PositionalAudioRingBuffer(const PositionalAudioRingBuffer&);
@ -107,9 +109,7 @@ protected:
bool _dynamicJitterBuffers; bool _dynamicJitterBuffers;
// extra stats // extra stats
int _starveCount; int _consecutiveNotMixedCount;
int _silentFramesDropped;
}; };
#endif // hifi_PositionalAudioRingBuffer_h #endif // hifi_PositionalAudioRingBuffer_h