tweaked starve behavior of InboundAudioStream

This commit is contained in:
wangyix 2014-08-05 11:57:34 -07:00
parent 77dad6fe65
commit 84c517c073
3 changed files with 29 additions and 47 deletions

View file

@ -1747,18 +1747,12 @@ float Audio::getInputRingBufferMsecsAvailable() const {
} }
qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) { qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
MixedProcessedAudioStream& receivedAUdioStream = _parent._receivedAudioStream; MixedProcessedAudioStream& receivedAUdioStream = _parent._receivedAudioStream;
const QAudioOutput* audioOutput = _parent._audioOutput;
if (audioOutput->bytesFree() == audioOutput->bufferSize()) {
receivedAUdioStream.setToStarved();
}
int samplesRequested = maxSize / sizeof(int16_t); int samplesRequested = maxSize / sizeof(int16_t);
int samplesPopped; int samplesPopped;
int bytesWritten; int bytesWritten;
if ((samplesPopped = receivedAUdioStream.popSamples(samplesRequested, false, false)) > 0) { if ((samplesPopped = receivedAUdioStream.popSamples(samplesRequested, false)) > 0) {
AudioRingBuffer::ConstIterator lastPopOutput = receivedAUdioStream.getLastPopOutput(); AudioRingBuffer::ConstIterator lastPopOutput = receivedAUdioStream.getLastPopOutput();
lastPopOutput.readSamples((int16_t*)data, samplesPopped); lastPopOutput.readSamples((int16_t*)data, samplesPopped);
bytesWritten = samplesPopped * sizeof(int16_t); bytesWritten = samplesPopped * sizeof(int16_t);

View file

@ -137,7 +137,7 @@ int InboundAudioStream::parseData(const QByteArray& packet) {
return readBytes; return readBytes;
} }
int InboundAudioStream::popSamples(int maxSamples, bool allOrNothing, bool starveOnFail) { int InboundAudioStream::popSamples(int maxSamples, bool allOrNothing, bool starveIfNoSamplesPopped) {
int samplesPopped = 0; int samplesPopped = 0;
int samplesAvailable = _ringBuffer.samplesAvailable(); int samplesAvailable = _ringBuffer.samplesAvailable();
if (_isStarved) { if (_isStarved) {
@ -146,30 +146,27 @@ int InboundAudioStream::popSamples(int maxSamples, bool allOrNothing, bool starv
_lastPopSucceeded = false; _lastPopSucceeded = false;
} else { } else {
if (samplesAvailable >= maxSamples) { if (samplesAvailable >= maxSamples) {
// we have enough samples to pop, so we're good to mix // we have enough samples to pop, so we're good to pop
popSamplesNoCheck(maxSamples); popSamplesNoCheck(maxSamples);
samplesPopped = maxSamples; samplesPopped = maxSamples;
} else if (!allOrNothing && samplesAvailable > 0) {
} else { // we don't have the requested number of samples, but we do have some
// we don't have enough frames, so set this stream to starve // samples available, so pop all those (except in all-or-nothing mode)
// if starveOnFail is true
if (starveOnFail) {
starved();
_consecutiveNotMixedCount++;
}
if (!allOrNothing && samplesAvailable > 0) {
popSamplesNoCheck(samplesAvailable); popSamplesNoCheck(samplesAvailable);
samplesPopped = samplesAvailable; samplesPopped = samplesAvailable;
} else { } else {
_lastPopSucceeded = false; // we can't pop any samples. set this stream to starved if needed
if (starveIfNoSamplesPopped) {
setToStarved();
_consecutiveNotMixedCount++;
} }
_lastPopSucceeded = false;
} }
} }
return samplesPopped; return samplesPopped;
} }
int InboundAudioStream::popFrames(int maxFrames, bool allOrNothing, bool starveOnFail) { int InboundAudioStream::popFrames(int maxFrames, bool allOrNothing, bool starveIfNoFramesPopped) {
int framesPopped = 0; int framesPopped = 0;
int framesAvailable = _ringBuffer.framesAvailable(); int framesAvailable = _ringBuffer.framesAvailable();
if (_isStarved) { if (_isStarved) {
@ -178,24 +175,21 @@ int InboundAudioStream::popFrames(int maxFrames, bool allOrNothing, bool starveO
_lastPopSucceeded = false; _lastPopSucceeded = false;
} else { } else {
if (framesAvailable >= maxFrames) { if (framesAvailable >= maxFrames) {
// we have enough samples to pop, so we're good to mix // we have enough frames to pop, so we're good to pop
popSamplesNoCheck(maxFrames * _ringBuffer.getNumFrameSamples()); popSamplesNoCheck(maxFrames * _ringBuffer.getNumFrameSamples());
framesPopped = maxFrames; framesPopped = maxFrames;
} else if (!allOrNothing && framesAvailable > 0) {
} else { // we don't have the requested number of frames, but we do have some
// we don't have enough frames, so set this stream to starve // frames available, so pop all those (except in all-or-nothing mode)
// if starveOnFail is true
if (starveOnFail) {
starved();
_consecutiveNotMixedCount++;
}
if (!allOrNothing && framesAvailable > 0) {
popSamplesNoCheck(framesAvailable * _ringBuffer.getNumFrameSamples()); popSamplesNoCheck(framesAvailable * _ringBuffer.getNumFrameSamples());
framesPopped = framesAvailable; framesPopped = framesAvailable;
} else { } else {
_lastPopSucceeded = false; // we can't pop any frames. set this stream to starved if needed
if (starveIfNoFramesPopped) {
setToStarved();
_consecutiveNotMixedCount = 1;
} }
_lastPopSucceeded = false;
} }
} }
return framesPopped; return framesPopped;
@ -220,16 +214,12 @@ void InboundAudioStream::framesAvailableChanged() {
} }
void InboundAudioStream::setToStarved() { void InboundAudioStream::setToStarved() {
starved();
if (_ringBuffer.framesAvailable() >= _desiredJitterBufferFrames) {
_isStarved = false;
}
}
void InboundAudioStream::starved() {
_isStarved = true; _isStarved = true;
_consecutiveNotMixedCount = 0; _consecutiveNotMixedCount = 0;
_starveCount++; _starveCount++;
// if we have more than the desired frames when setToStarved() is called, then we'll immediately
// be considered refilled. in that case, there's no need to set _isStarved to true.
_isStarved = (_ringBuffer.framesAvailable() < _desiredJitterBufferFrames);
} }
void InboundAudioStream::setDynamicJitterBuffers(bool dynamicJitterBuffers) { void InboundAudioStream::setDynamicJitterBuffers(bool dynamicJitterBuffers) {

View file

@ -63,8 +63,8 @@ public:
virtual int parseData(const QByteArray& packet); virtual int parseData(const QByteArray& packet);
int popFrames(int maxFrames, bool allOrNothing, bool starveOnFail = true); int popFrames(int maxFrames, bool allOrNothing, bool starveIfNoFramesPopped = true);
int popSamples(int maxSamples, bool allOrNothing, bool starveOnFail = true); int popSamples(int maxSamples, bool allOrNothing, bool starveIfNoSamplesPopped = true);
bool lastPopSucceeded() const { return _lastPopSucceeded; }; bool lastPopSucceeded() const { return _lastPopSucceeded; };
const AudioRingBuffer::ConstIterator& getLastPopOutput() const { return _lastPopOutput; } const AudioRingBuffer::ConstIterator& getLastPopOutput() const { return _lastPopOutput; }
@ -111,8 +111,6 @@ public:
int getPacketsReceived() const { return _incomingSequenceNumberStats.getReceived(); } int getPacketsReceived() const { return _incomingSequenceNumberStats.getReceived(); }
private: private:
void starved();
void frameReceivedUpdateTimingStats(); void frameReceivedUpdateTimingStats();
int clampDesiredJitterBufferFramesValue(int desired) const; int clampDesiredJitterBufferFramesValue(int desired) const;