diff options
author | Kurt Korbatits <kurt.korbatits@nokia.com> | 2009-09-09 22:47:18 (GMT) |
---|---|---|
committer | Kurt Korbatits <kurt.korbatits@nokia.com> | 2009-09-09 22:47:18 (GMT) |
commit | a08aa0b58ecbc59b77fe545898987bbff31fddd0 (patch) | |
tree | 34ffbbf1ae1aa708b53cba48a5883a1d0988a5d3 /src/multimedia/audio | |
parent | 2196db60fa75fc559adb1405c1b43858122ff9e7 (diff) | |
download | Qt-a08aa0b58ecbc59b77fe545898987bbff31fddd0.zip Qt-a08aa0b58ecbc59b77fe545898987bbff31fddd0.tar.gz Qt-a08aa0b58ecbc59b77fe545898987bbff31fddd0.tar.bz2 |
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
Diffstat (limited to 'src/multimedia/audio')
-rw-r--r-- | src/multimedia/audio/qaudioinput_win32_p.cpp | 53 | ||||
-rw-r--r-- | src/multimedia/audio/qaudioinput_win32_p.h | 1 | ||||
-rw-r--r-- | src/multimedia/audio/qaudiooutput_win32_p.cpp | 27 | ||||
-rw-r--r-- | 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<buffer_size/period_size; i++) { @@ -286,18 +305,26 @@ bool QAudioInputPrivate::open() void QAudioInputPrivate::close() { - deviceState = QAudio::StopState; - int delay = (buffer_size-bytesReady())*1000/(settings.frequency() - *settings.channels()*(settings.sampleSize()/8)); + if(deviceState == QAudio::StopState) + return; + waveInReset(hWaveIn); - Sleep(delay+10); + waveInClose(hWaveIn); + deviceState = QAudio::StopState; + + int count = 0; + while(!finished && count < 100) { + count++; + Sleep(10); + } + EnterCriticalSection(&waveInCriticalSection); for(int i=0; i<waveFreeBlockCount; i++) { if(waveBlocks[i].dwFlags & WHDR_PREPARED) waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); } + LeaveCriticalSection(&waveInCriticalSection); freeBlocks(waveBlocks); - waveInClose(hWaveIn); } int QAudioInputPrivate::bytesReady() const @@ -384,6 +411,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) header = 0; p+=l; + EnterCriticalSection(&waveInCriticalSection); if(!pullMode) { if(l+period_size > 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()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT"; + qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this; #endif bytesAvailable = bytesReady(); diff --git a/src/multimedia/audio/qaudioinput_win32_p.h b/src/multimedia/audio/qaudioinput_win32_p.h index da0df24..3363b6a 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.h +++ b/src/multimedia/audio/qaudioinput_win32_p.h @@ -117,6 +117,7 @@ private: HWAVEIN hWaveIn; MMRESULT result; WAVEHDR* waveBlocks; + volatile bool finished; volatile int waveFreeBlockCount; int waveCurrentBlock; diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index de4981d..fae680c 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -72,11 +72,16 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioF deviceState = QAudio::StopState; audioSource = 0; pullMode = true; + finished = false; InitializeCriticalSection(&waveOutCriticalSection); } QAudioOutputPrivate::~QAudioOutputPrivate() { + EnterCriticalSection(&waveOutCriticalSection); + finished = true; + LeaveCriticalSection(&waveOutCriticalSection); + close(); DeleteCriticalSection(&waveOutCriticalSection); } @@ -101,11 +106,15 @@ void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, return; case WOM_DONE: EnterCriticalSection(&waveOutCriticalSection); + if(qAudio->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; |