Bug 589071 - Avoid shutting down nsAudioStream when another thread may be using it. r=doublec a=roc

This commit is contained in:
Matthew Gregan 2010-08-24 14:06:14 +12:00
Родитель 5e71ea141c
Коммит 1088a92d61
2 изменённых файлов: 22 добавлений и 12 удалений

Просмотреть файл

@ -76,7 +76,8 @@ nsAudioStream::nsAudioStream() :
mRate(0), mRate(0),
mChannels(0), mChannels(0),
mFormat(FORMAT_S16_LE), mFormat(FORMAT_S16_LE),
mPaused(PR_FALSE) mPaused(PR_FALSE),
mInError(PR_FALSE)
{ {
} }
@ -97,6 +98,7 @@ void nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aForm
aRate, aRate,
aNumChannels) != SA_SUCCESS) { aNumChannels) != SA_SUCCESS) {
mAudioHandle = nsnull; mAudioHandle = nsnull;
mInError = PR_TRUE;
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_create_pcm error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_create_pcm error"));
return; return;
} }
@ -104,9 +106,11 @@ void nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aForm
if (sa_stream_open(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) { if (sa_stream_open(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) {
sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle)); sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
mAudioHandle = nsnull; mAudioHandle = nsnull;
mInError = PR_TRUE;
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_open error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_open error"));
return; return;
} }
mInError = PR_FALSE;
} }
void nsAudioStream::Shutdown() void nsAudioStream::Shutdown()
@ -116,6 +120,7 @@ void nsAudioStream::Shutdown()
sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle)); sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
mAudioHandle = nsnull; mAudioHandle = nsnull;
mInError = PR_TRUE;
} }
void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking)
@ -124,12 +129,12 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking)
"Buffer size must be divisible by channel count"); "Buffer size must be divisible by channel count");
NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block"); NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block");
if (mInError)
return;
PRUint32 offset = mBufferOverflow.Length(); PRUint32 offset = mBufferOverflow.Length();
PRUint32 count = aCount + offset; PRUint32 count = aCount + offset;
if (!mAudioHandle)
return;
nsAutoArrayPtr<short> s_data(new short[count]); nsAutoArrayPtr<short> s_data(new short[count]);
if (s_data) { if (s_data) {
@ -193,7 +198,7 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking)
count * sizeof(short)) != SA_SUCCESS) count * sizeof(short)) != SA_SUCCESS)
{ {
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
Shutdown(); mInError = PR_TRUE;
} }
} }
} }
@ -202,7 +207,7 @@ PRUint32 nsAudioStream::Available()
{ {
// If the audio backend failed to open, lie and say we'll accept some // If the audio backend failed to open, lie and say we'll accept some
// data. // data.
if (!mAudioHandle) if (mInError)
return FAKE_BUFFER_SIZE; return FAKE_BUFFER_SIZE;
size_t s = 0; size_t s = 0;
@ -218,7 +223,7 @@ void nsAudioStream::SetVolume(float aVolume)
#if defined(SA_PER_STREAM_VOLUME) #if defined(SA_PER_STREAM_VOLUME)
if (sa_stream_set_volume_abs(static_cast<sa_stream_t*>(mAudioHandle), aVolume) != SA_SUCCESS) { if (sa_stream_set_volume_abs(static_cast<sa_stream_t*>(mAudioHandle), aVolume) != SA_SUCCESS) {
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_set_volume_abs error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_set_volume_abs error"));
Shutdown(); mInError = PR_TRUE;
} }
#else #else
mVolume = aVolume; mVolume = aVolume;
@ -227,7 +232,7 @@ void nsAudioStream::SetVolume(float aVolume)
void nsAudioStream::Drain() void nsAudioStream::Drain()
{ {
if (!mAudioHandle) if (mInError)
return; return;
// Write any remaining unwritten sound data in the overflow buffer // Write any remaining unwritten sound data in the overflow buffer
@ -235,19 +240,21 @@ void nsAudioStream::Drain()
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle), if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
mBufferOverflow.Elements(), mBufferOverflow.Elements(),
mBufferOverflow.Length() * sizeof(short)) != SA_SUCCESS) mBufferOverflow.Length() * sizeof(short)) != SA_SUCCESS)
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
mInError = PR_TRUE;
return; return;
} }
int r = sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle)); int r = sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle));
if (r != SA_SUCCESS && r != SA_ERROR_INVALID) { if (r != SA_SUCCESS && r != SA_ERROR_INVALID) {
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_drain error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_drain error"));
Shutdown(); mInError = PR_TRUE;
} }
} }
void nsAudioStream::Pause() void nsAudioStream::Pause()
{ {
if (!mAudioHandle) if (mInError)
return; return;
mPaused = PR_TRUE; mPaused = PR_TRUE;
sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle)); sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle));
@ -255,7 +262,7 @@ void nsAudioStream::Pause()
void nsAudioStream::Resume() void nsAudioStream::Resume()
{ {
if (!mAudioHandle) if (mInError)
return; return;
mPaused = PR_FALSE; mPaused = PR_FALSE;
sa_stream_resume(static_cast<sa_stream_t*>(mAudioHandle)); sa_stream_resume(static_cast<sa_stream_t*>(mAudioHandle));
@ -263,7 +270,7 @@ void nsAudioStream::Resume()
PRInt64 nsAudioStream::GetPosition() PRInt64 nsAudioStream::GetPosition()
{ {
if (!mAudioHandle) if (mInError)
return -1; return -1;
sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE; sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE;

Просмотреть файл

@ -121,5 +121,8 @@ class nsAudioStream
// PR_TRUE if this audio stream is paused. // PR_TRUE if this audio stream is paused.
PRPackedBool mPaused; PRPackedBool mPaused;
// PR_TRUE if this stream has encountered an error.
PRPackedBool mInError;
}; };
#endif #endif