Bug 717026 - Ensure libsydneyaudio windows block size is an even multiple of channels*frame_size. r=kinetik

This commit is contained in:
Chris Pearce 2012-01-19 14:11:51 +13:00
Родитель bdf9362d41
Коммит 3333e53c6b
2 изменённых файлов: 16 добавлений и 10 удалений

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

@ -631,7 +631,6 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
LOG(PR_LOG_DEBUG, ("%p Begun audio thread/loop", mDecoder.get())); LOG(PR_LOG_DEBUG, ("%p Begun audio thread/loop", mDecoder.get()));
PRInt64 audioDuration = 0; PRInt64 audioDuration = 0;
PRInt64 audioStartTime = -1; PRInt64 audioStartTime = -1;
PRInt64 framesWritten = 0;
PRUint32 channels, rate; PRUint32 channels, rate;
double volume = -1; double volume = -1;
bool setVolume; bool setVolume;
@ -746,6 +745,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
break; break;
} }
PRInt64 framesWritten = 0;
if (missingFrames > 0) { if (missingFrames > 0) {
// The next audio chunk begins some time after the end of the last chunk // The next audio chunk begins some time after the end of the last chunk
// we pushed to the audio hardware. We must push silence into the audio // we pushed to the audio hardware. We must push silence into the audio
@ -780,18 +780,22 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
bool seeking = false; bool seeking = false;
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (framesWritten < minWriteFrames) { PRInt64 unplayedFrames = audioDuration % minWriteFrames;
// We've not written minWriteFrames in the last write, the audio if (minWriteFrames > 1 && unplayedFrames > 0) {
// may not start playing. Write silence to ensure we've got enough // Sound is written by libsydneyaudio to the hardware in blocks of
// written to start playback. // frames of size minWriteFrames. So if the number of frames we've
PRInt64 minToWrite = minWriteFrames - framesWritten; // written isn't an exact multiple of minWriteFrames, we'll have
if (minToWrite < PR_UINT32_MAX / channels) { // left over audio data which hasn't yet been written to the hardware,
// and so that audio will not start playing. Write silence to ensure
// the last block gets pushed to hardware, so that playback starts.
PRInt64 framesToWrite = minWriteFrames - unplayedFrames;
if (framesToWrite < PR_UINT32_MAX / channels) {
// Write silence manually rather than using PlaySilence(), so that // Write silence manually rather than using PlaySilence(), so that
// the AudioAPI doesn't get a copy of the audio frames. // the AudioAPI doesn't get a copy of the audio frames.
PRUint32 numSamples = minToWrite * channels; PRUint32 numSamples = framesToWrite * channels;
nsAutoArrayPtr<AudioDataValue> buf(new AudioDataValue[numSamples]); nsAutoArrayPtr<AudioDataValue> buf(new AudioDataValue[numSamples]);
memset(buf.get(), 0, numSamples * sizeof(AudioDataValue)); memset(buf.get(), 0, numSamples * sizeof(AudioDataValue));
mAudioStream->Write(buf, minToWrite); mAudioStream->Write(buf, framesToWrite);
} }
} }

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

@ -169,10 +169,12 @@ int sa_stream_create_pcm(sa_stream_t **s,
_s->deviceName = DEFAULT_DEVICE_NAME; _s->deviceName = DEFAULT_DEVICE_NAME;
_s->device = DEFAULT_DEVICE; _s->device = DEFAULT_DEVICE;
_s->playing = 0; _s->playing = 0;
_s->blockSize = BYTES_PER_SAMPLE * ((rate * nchannels * BLOCK_DURATION_MS) / 1000); _s->blockSize = BYTES_PER_SAMPLE * nchannels * ((rate * BLOCK_DURATION_MS) / 1000);
/* Other parts of the code assumes that the block size is evenly /* Other parts of the code assumes that the block size is evenly
divisible by 2. */ divisible by 2. */
assert((_s->blockSize & 1) != 1); assert((_s->blockSize & 1) != 1);
assert((_s->blockSize % BYTES_PER_SAMPLE) == 0);
assert(((_s->blockSize / BYTES_PER_SAMPLE) % nchannels) == 0);
*s = _s; *s = _s;
return SA_SUCCESS; return SA_SUCCESS;
} }