bug 1391482 delay conversion of output of decodeAudioData() from int16_t to float until necessary r?padenot
On platforms with MOZ_SAMPLE_TYPE_S16, decode and resampling was already
performed in 16-bit arithmetic. Keeping the potentially large buffer in
16-bit format halves the memory usage.
This patch does not affect other platforms.
MozReview-Commit-ID: DWZdiPNasie
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -342,82 +342,100 @@ MediaDecodeTask::FinishDecode()
resampler = speex_resampler_init(channelCount,
sampleRate,
destSampleRate,
SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr);
speex_resampler_skip_zeros(resampler);
resampledFrames += speex_resampler_get_output_latency(resampler);
}
- // Allocate the channel buffers. Note that if we end up resampling, we may
- // write fewer bytes than mResampledFrames to the output buffer, in which
- // case writeIndex will tell us how many valid samples we have.
+ // Allocate contiguous channel buffers. Note that if we end up resampling,
+ // we may write fewer bytes than mResampledFrames to the output buffer, in
+ // which case writeIndex will tell us how many valid samples we have.
+ mDecodeJob.mBuffer.mChannelData.SetLength(channelCount);
+#if AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_FLOAT32
+ // This buffer has separate channel arrays that could be transferred to
+ // JS_NewArrayBufferWithContents(), but AudioBuffer::RestoreJSChannelData()
+ // does not yet take advantage of this.
RefPtr<ThreadSharedFloatArrayBufferList> buffer =
ThreadSharedFloatArrayBufferList::
Create(channelCount, resampledFrames, fallible);
if (!buffer) {
ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError);
return;
}
- mDecodeJob.mBuffer.mChannelData.SetLength(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
mDecodeJob.mBuffer.mChannelData[i] = buffer->GetData(i);
}
+#else
+ RefPtr<SharedBuffer> buffer =
+ SharedBuffer::Create(sizeof(AudioDataValue) *
+ resampledFrames * channelCount);
+ if (!buffer) {
+ ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError);
+ return;
+ }
+ auto data = static_cast<AudioDataValue*>(floatBuffer->Data());
+ for (uint32_t i = 0; i < channelCount; ++i) {
+ mDecodeJob.mBuffer.mChannelData[i] = data;
+ data += resampledFrames;
+ }
+#endif
mDecodeJob.mBuffer.mBuffer = buffer.forget();
mDecodeJob.mBuffer.mVolume = 1.0f;
- mDecodeJob.mBuffer.mBufferFormat = AUDIO_FORMAT_FLOAT32;
+ mDecodeJob.mBuffer.mBufferFormat = AUDIO_OUTPUT_FORMAT;
uint32_t writeIndex = 0;
RefPtr<AudioData> audioData;
while ((audioData = mAudioQueue.PopFront())) {
audioData->EnsureAudioBuffer(); // could lead to a copy :(
- AudioDataValue* bufferData = static_cast<AudioDataValue*>
+ const AudioDataValue* bufferData = static_cast<AudioDataValue*>
(audioData->mAudioBuffer->Data());
if (sampleRate != destSampleRate) {
const uint32_t maxOutSamples = resampledFrames - writeIndex;
for (uint32_t i = 0; i < audioData->mChannels; ++i) {
uint32_t inSamples = audioData->mFrames;
uint32_t outSamples = maxOutSamples;
- float* outData =
- mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
+ AudioDataValue* outData = mDecodeJob.mBuffer.
+ ChannelDataForWrite<AudioDataValue>(i) + writeIndex;
WebAudioUtils::SpeexResamplerProcess(
resampler, i, &bufferData[i * audioData->mFrames], &inSamples,
outData, &outSamples);
if (i == audioData->mChannels - 1) {
writeIndex += outSamples;
MOZ_ASSERT(writeIndex <= resampledFrames);
MOZ_ASSERT(inSamples == audioData->mFrames);
}
}
} else {
for (uint32_t i = 0; i < audioData->mChannels; ++i) {
- float* outData =
- mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
- ConvertAudioSamples(&bufferData[i * audioData->mFrames],
- outData, audioData->mFrames);
+ AudioDataValue* outData = mDecodeJob.mBuffer.
+ ChannelDataForWrite<AudioDataValue>(i) + writeIndex;
+ PodCopy(outData, &bufferData[i * audioData->mFrames],
+ audioData->mFrames);
if (i == audioData->mChannels - 1) {
writeIndex += audioData->mFrames;
}
}
}
}
if (sampleRate != destSampleRate) {
uint32_t inputLatency = speex_resampler_get_input_latency(resampler);
const uint32_t maxOutSamples = resampledFrames - writeIndex;
for (uint32_t i = 0; i < channelCount; ++i) {
uint32_t inSamples = inputLatency;
uint32_t outSamples = maxOutSamples;
- float* outData =
- mDecodeJob.mBuffer.ChannelDataForWrite<float>(i) + writeIndex;
+ AudioDataValue* outData =
+ mDecodeJob.mBuffer.ChannelDataForWrite<AudioDataValue>(i) + writeIndex;
WebAudioUtils::SpeexResamplerProcess(
resampler, i, (AudioDataValue*)nullptr, &inSamples,
outData, &outSamples);
if (i == channelCount - 1) {
writeIndex += outSamples;
MOZ_ASSERT(writeIndex <= resampledFrames);