From a08aa0b58ecbc59b77fe545898987bbff31fddd0 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 10 Sep 2009 08:47:18 +1000 Subject: Crash in audiooutput demo when switching output -waveOut callback was calling into class during destruction. Changed to wait until close of waveOut/waveIn before returning from destructor. -Reduced default buffer on wince implementation. -Added error checking on buffer allocation. Task-number:261049, 261053 Reviewed-by:Bill King --- src/multimedia/audio/qaudioinput_win32_p.cpp | 53 ++++++++++++++++++++++----- src/multimedia/audio/qaudioinput_win32_p.h | 1 + src/multimedia/audio/qaudiooutput_win32_p.cpp | 27 +++++++++++++- src/multimedia/audio/qaudiooutput_win32_p.h | 1 + 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index 4a62c32..315a59b 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -73,6 +73,7 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFor audioSource = 0; pullMode = true; resuming = false; + finished = false; connect(this,SIGNAL(processMore()),SLOT(deviceReady())); @@ -81,7 +82,7 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFor QAudioInputPrivate::~QAudioInputPrivate() { - close(); + stop(); DeleteCriticalSection(&waveInCriticalSection); } @@ -104,10 +105,13 @@ void CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, EnterCriticalSection(&waveInCriticalSection); if(qAudio->waveFreeBlockCount > 0) qAudio->waveFreeBlockCount--; - LeaveCriticalSection(&waveInCriticalSection); qAudio->feedback(); + LeaveCriticalSection(&waveInCriticalSection); break; case WIM_CLOSE: + EnterCriticalSection(&waveInCriticalSection); + qAudio->finished = true; + LeaveCriticalSection(&waveInCriticalSection); break; default: return; @@ -198,8 +202,6 @@ void QAudioInputPrivate::stop() if(deviceState == QAudio::StopState) return; - deviceState = QAudio::StopState; - close(); emit stateChanged(deviceState); } @@ -218,6 +220,11 @@ bool QAudioInputPrivate::open() } else { period_size = buffer_size/5; } +#ifdef Q_OS_WINCE + // For wince reduce size to 40ms for buffer size and 20ms period + buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.04; + period_size = buffer_size/2; +#endif timeStamp.restart(); wfx.nSamplesPerSec = settings.frequency(); wfx.wBitsPerSample = settings.sampleSize(); @@ -256,7 +263,19 @@ bool QAudioInputPrivate::open() return false; } waveBlocks = allocateBlocks(period_size, buffer_size/period_size); + + if(waveBlocks == 0) { + errorState = QAudio::OpenError; + deviceState = QAudio::StopState; + emit stateChanged(deviceState); + qWarning("QAudioInput: failed to allocate blocks. open failed"); + return false; + } + + EnterCriticalSection(&waveInCriticalSection); waveFreeBlockCount = buffer_size/period_size; + LeaveCriticalSection(&waveInCriticalSection); + waveCurrentBlock = 0; for(int i=0; i len && waveFreeBlockCount == buffer_size/period_size) done = true; @@ -391,6 +419,8 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if(waveFreeBlockCount == buffer_size/period_size) done = true; } + LeaveCriticalSection(&waveInCriticalSection); + written+=l; } #ifdef DEBUG_AUDIO @@ -413,7 +443,10 @@ void QAudioInputPrivate::resume() return; } } + EnterCriticalSection(&waveInCriticalSection); waveFreeBlockCount = buffer_size/period_size; + LeaveCriticalSection(&waveInCriticalSection); + waveCurrentBlock = 0; header = 0; resuming = true; @@ -466,7 +499,7 @@ void QAudioInputPrivate::feedback() { #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); - qDebug()<finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) { + LeaveCriticalSection(&waveOutCriticalSection); + return; + } qAudio->waveFreeBlockCount++; if(qAudio->waveFreeBlockCount >= qAudio->buffer_size/qAudio->period_size) qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size; - LeaveCriticalSection(&waveOutCriticalSection); qAudio->feedback(); + LeaveCriticalSection(&waveOutCriticalSection); break; default: return; @@ -201,7 +210,11 @@ bool QAudioOutputPrivate::open() period_size = buffer_size/5; } waveBlocks = allocateBlocks(period_size, buffer_size/period_size); + + EnterCriticalSection(&waveOutCriticalSection); waveFreeBlockCount = buffer_size/period_size; + LeaveCriticalSection(&waveOutCriticalSection); + waveCurrentBlock = 0; if(audioBuffer == 0) @@ -281,6 +294,7 @@ int QAudioOutputPrivate::bytesFree() const { int buf; buf = waveFreeBlockCount*period_size; + return buf; } @@ -326,8 +340,12 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) int remain; current = &waveBlocks[waveCurrentBlock]; while(l > 0) { - if(waveFreeBlockCount==0) + EnterCriticalSection(&waveOutCriticalSection); + if(waveFreeBlockCount==0) { + LeaveCriticalSection(&waveOutCriticalSection); break; + } + LeaveCriticalSection(&waveOutCriticalSection); if(current->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); @@ -348,8 +366,10 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) waveFreeBlockCount--; LeaveCriticalSection(&waveOutCriticalSection); #ifdef DEBUG_AUDIO + EnterCriticalSection(&waveOutCriticalSection); qDebug("write out l=%d, waveFreeBlockCount=%d", current->dwBufferLength,waveFreeBlockCount); + LeaveCriticalSection(&waveOutCriticalSection); #endif totalTimeValue += current->dwBufferLength /(settings.channels()*(settings.sampleSize()/8)) @@ -422,11 +442,14 @@ bool QAudioOutputPrivate::deviceReady() waveOutRestart(hWaveOut); } else if(l == 0) { bytesAvailable = bytesFree(); + + EnterCriticalSection(&waveOutCriticalSection); if(waveFreeBlockCount == buffer_size/period_size) { errorState = QAudio::UnderrunError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } + LeaveCriticalSection(&waveOutCriticalSection); } else if(i < 0) { bytesAvailable = bytesFree(); diff --git a/src/multimedia/audio/qaudiooutput_win32_p.h b/src/multimedia/audio/qaudiooutput_win32_p.h index 16c71dd..68f418e 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.h +++ b/src/multimedia/audio/qaudiooutput_win32_p.h @@ -132,6 +132,7 @@ private: MMRESULT result; WAVEHDR header; WAVEHDR* waveBlocks; + volatile bool finished; volatile int waveFreeBlockCount; int waveCurrentBlock; char* audioBuffer; -- cgit v0.12