summaryrefslogtreecommitdiffstats
path: root/src/multimedia/audio
diff options
context:
space:
mode:
authorKurt Korbatits <kurt.korbatits@nokia.com>2009-09-09 22:47:18 (GMT)
committerKurt Korbatits <kurt.korbatits@nokia.com>2009-09-09 22:47:18 (GMT)
commita08aa0b58ecbc59b77fe545898987bbff31fddd0 (patch)
tree34ffbbf1ae1aa708b53cba48a5883a1d0988a5d3 /src/multimedia/audio
parent2196db60fa75fc559adb1405c1b43858122ff9e7 (diff)
downloadQt-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.cpp53
-rw-r--r--src/multimedia/audio/qaudioinput_win32_p.h1
-rw-r--r--src/multimedia/audio/qaudiooutput_win32_p.cpp27
-rw-r--r--src/multimedia/audio/qaudiooutput_win32_p.h1
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;