diff options
author | Kurt Korbatits <kurt.korbatits@nokia.com> | 2010-04-26 22:56:25 (GMT) |
---|---|---|
committer | Kurt Korbatits <kurt.korbatits@nokia.com> | 2010-04-26 22:56:25 (GMT) |
commit | e340e68d7ee2c0e7cbf2e1bd2f79b15418141016 (patch) | |
tree | e84e854441d9c75b7e19826ad51b1d1ee4950704 /src/multimedia | |
parent | 4fedbbded38d7a978c16b41d66439e00e586dfb1 (diff) | |
download | Qt-e340e68d7ee2c0e7cbf2e1bd2f79b15418141016.zip Qt-e340e68d7ee2c0e7cbf2e1bd2f79b15418141016.tar.gz Qt-e340e68d7ee2c0e7cbf2e1bd2f79b15418141016.tar.bz2 |
win32 backend for low-level audio fixes
- fix deadlock with QAudioInput (win32) backend
- changed win32 backend to use QMutex lock
- setNotifyInterval(0) to disable notify() signal
Reviewed-by:Derick Hawcroft
Diffstat (limited to 'src/multimedia')
-rw-r--r-- | src/multimedia/audio/qaudioinput_win32_p.cpp | 68 | ||||
-rw-r--r-- | src/multimedia/audio/qaudioinput_win32_p.h | 3 | ||||
-rw-r--r-- | src/multimedia/audio/qaudiooutput_win32_p.cpp | 71 | ||||
-rw-r--r-- | src/multimedia/audio/qaudiooutput_win32_p.h | 3 |
4 files changed, 67 insertions, 78 deletions
diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index 5152d9a..8240047 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -57,8 +57,6 @@ QT_BEGIN_NAMESPACE //#define DEBUG_AUDIO 1 -static const int minimumIntervalTime = 50; - QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -74,16 +72,11 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFor pullMode = true; resuming = false; finished = false; - - connect(this,SIGNAL(processMore()),SLOT(deviceReady())); - - InitializeCriticalSection(&waveInCriticalSection); } QAudioInputPrivate::~QAudioInputPrivate() { stop(); - DeleteCriticalSection(&waveInCriticalSection); } void CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, @@ -98,20 +91,18 @@ void CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, if(!qAudio) return; + QMutexLocker(&qAudio->mutex); + switch(uMsg) { case WIM_OPEN: break; case WIM_DATA: - EnterCriticalSection(&qAudio->waveInCriticalSection); if(qAudio->waveFreeBlockCount > 0) qAudio->waveFreeBlockCount--; qAudio->feedback(); - LeaveCriticalSection(&qAudio->waveInCriticalSection); break; case WIM_CLOSE: - EnterCriticalSection(&qAudio->waveInCriticalSection); qAudio->finished = true; - LeaveCriticalSection(&qAudio->waveInCriticalSection); break; default: return; @@ -156,8 +147,7 @@ void QAudioInputPrivate::freeBlocks(WAVEHDR* blockArray) int count = buffer_size/period_size; for(int i = 0; i < count; i++) { - if (blocks->dwFlags & WHDR_PREPARED) - waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR)); + waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR)); blocks+=sizeof(WAVEHDR); } HeapFree(GetProcessHeap(), 0, blockArray); @@ -279,9 +269,9 @@ bool QAudioInputPrivate::open() return false; } - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; @@ -325,13 +315,11 @@ void QAudioInputPrivate::close() 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); + mutex.lock(); + for(int i=0; i<waveFreeBlockCount; i++) + waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); freeBlocks(waveBlocks); + mutex.unlock(); } int QAudioInputPrivate::bytesReady() const @@ -402,9 +390,10 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); waveFreeBlockCount++; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + waveBlocks[header].dwBytesRecorded=0; waveBlocks[header].dwFlags = 0L; result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); @@ -412,18 +401,22 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result); errorState = QAudio::IOError; - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + return 0; } result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { qWarning("QAudioInput: failed to setup block %d,err=%d",header,result); errorState = QAudio::IOError; - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + return 0; } header++; @@ -431,7 +424,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) header = 0; p+=l; - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); if(!pullMode) { if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size) done = true; @@ -439,7 +432,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if(waveFreeBlockCount == buffer_size/period_size) done = true; } - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); written+=l; } @@ -463,9 +456,10 @@ void QAudioInputPrivate::resume() return; } } - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; header = 0; @@ -493,10 +487,7 @@ int QAudioInputPrivate::periodSize() const void QAudioInputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioInputPrivate::notifyInterval() const @@ -530,14 +521,13 @@ void QAudioInputPrivate::feedback() QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this; #endif - bytesAvailable = bytesReady(); - if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) - emit processMore(); + QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection); } bool QAudioInputPrivate::deviceReady() { + bytesAvailable = bytesReady(); #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT"; @@ -554,7 +544,7 @@ bool QAudioInputPrivate::deviceReady() a->trigger(); } - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/audio/qaudioinput_win32_p.h b/src/multimedia/audio/qaudioinput_win32_p.h index a12c75e..1737bb1 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.h +++ b/src/multimedia/audio/qaudioinput_win32_p.h @@ -62,6 +62,7 @@ #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> #include <QtCore/qdatetime.h> +#include <QtCore/qmutex.h> #include <QtMultimedia/qaudio.h> #include <QtMultimedia/qaudiodeviceinfo.h> @@ -122,7 +123,7 @@ private: volatile int waveFreeBlockCount; int waveCurrentBlock; - CRITICAL_SECTION waveInCriticalSection; + QMutex mutex; static void CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index b92565d..533583a 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -56,8 +56,6 @@ QT_BEGIN_NAMESPACE -static const int minimumIntervalTime = 50; - QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -73,17 +71,15 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioF audioSource = 0; pullMode = true; finished = false; - InitializeCriticalSection(&waveOutCriticalSection); } QAudioOutputPrivate::~QAudioOutputPrivate() { - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); finished = true; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); close(); - DeleteCriticalSection(&waveOutCriticalSection); } void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, @@ -98,6 +94,8 @@ void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, if(!qAudio) return; + QMutexLocker(&qAudio->mutex); + switch(uMsg) { case WOM_OPEN: qAudio->feedback(); @@ -105,16 +103,13 @@ void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, case WOM_CLOSE: return; case WOM_DONE: - EnterCriticalSection(&qAudio->waveOutCriticalSection); if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) { - LeaveCriticalSection(&qAudio->waveOutCriticalSection); return; } qAudio->waveFreeBlockCount++; if(qAudio->waveFreeBlockCount >= qAudio->buffer_size/qAudio->period_size) qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size; qAudio->feedback(); - LeaveCriticalSection(&qAudio->waveOutCriticalSection); break; default: return; @@ -150,8 +145,7 @@ void QAudioOutputPrivate::freeBlocks(WAVEHDR* blockArray) int count = buffer_size/period_size; for(int i = 0; i < count; i++) { - if (blocks->dwFlags & WHDR_PREPARED) - waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR)); + waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR)); blocks+=sizeof(WAVEHDR); } HeapFree(GetProcessHeap(), 0, blockArray); @@ -226,9 +220,9 @@ bool QAudioOutputPrivate::open() } waveBlocks = allocateBlocks(period_size, buffer_size/period_size); - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; @@ -334,10 +328,7 @@ int QAudioOutputPrivate::bufferSize() const void QAudioOutputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioOutputPrivate::notifyInterval() const @@ -369,12 +360,12 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) int remain; current = &waveBlocks[waveCurrentBlock]; while(l > 0) { - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); if(waveFreeBlockCount==0) { - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); break; } - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); if(current->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); @@ -391,15 +382,13 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveOutCriticalSection); #ifdef DEBUG_AUDIO - EnterCriticalSection(&waveOutCriticalSection); qDebug("write out l=%d, waveFreeBlockCount=%d", current->dwBufferLength,waveFreeBlockCount); - LeaveCriticalSection(&waveOutCriticalSection); #endif + mutex.unlock(); totalTimeValue += current->dwBufferLength; waveCurrentBlock++; waveCurrentBlock %= buffer_size/period_size; @@ -454,7 +443,7 @@ void QAudioOutputPrivate::feedback() bool QAudioOutputPrivate::deviceReady() { - if(deviceState == QAudio::StoppedState) + if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState) return false; if(pullMode) { @@ -468,14 +457,16 @@ bool QAudioOutputPrivate::deviceReady() startup = true; bool full=false; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); if(waveFreeBlockCount==0) full = true; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); + if (full){ #ifdef DEBUG_AUDIO qDebug() << "Skipping data as unable to write"; #endif - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); @@ -505,12 +496,14 @@ bool QAudioOutputPrivate::deviceReady() bytesAvailable = bytesFree(); int check = 0; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); check = waveFreeBlockCount; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); + if(check == buffer_size/period_size) { - errorState = QAudio::UnderrunError; if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } @@ -522,19 +515,23 @@ bool QAudioOutputPrivate::deviceReady() } } else { int buffered; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); buffered = waveFreeBlockCount; - LeaveCriticalSection(&waveOutCriticalSection); - errorState = QAudio::UnderrunError; + mutex.unlock(); + if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); + if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } } if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return true; - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/audio/qaudiooutput_win32_p.h b/src/multimedia/audio/qaudiooutput_win32_p.h index a7a0b07..aab1064 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.h +++ b/src/multimedia/audio/qaudiooutput_win32_p.h @@ -61,6 +61,7 @@ #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> #include <QtCore/qdatetime.h> +#include <QtCore/qmutex.h> #include <QtMultimedia/qaudio.h> #include <QtMultimedia/qaudiodeviceinfo.h> @@ -119,7 +120,7 @@ private: static void CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); - CRITICAL_SECTION waveOutCriticalSection; + QMutex mutex; WAVEHDR* allocateBlocks(int size, int count); void freeBlocks(WAVEHDR* blockArray); |