Bug 1264199: P8. Handle potential resampling errors. r=kinetik
The speex resampler can never return an error in its current state. But just in case and to handle any future changes to the speex resampler.
Also ensure that we can never access a stale speex resampler.
MozReview-Commit-ID: CEME0AA9ghK
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -100,20 +100,17 @@ void
}
void
AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn,
size_t aFrames) const
{
MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() == mOut.Channels());
- if (mOut.Layout() == mIn.Layout()) {
- return;
- }
- if (mOut.Channels() == 1) {
+ if (mOut.Channels() == 1 || mOut.Layout() == mIn.Layout()) {
// If channel count is 1, planar and non-planar formats are the same and
// there's nothing to reorder.
if (aOut != aIn) {
memmove(aOut, aIn, FramesOutToBytes(aFrames));
}
return;
}
@@ -248,29 +245,38 @@ size_t
AudioConverter::ResampleAudio(void* aOut, const void* aIn, size_t aFrames)
{
if (!mResampler) {
return 0;
}
uint32_t outframes = ResampleRecipientFrames(aFrames);
uint32_t inframes = aFrames;
+ int error;
if (mOut.Format() == AudioConfig::FORMAT_FLT) {
const float* in = reinterpret_cast<const float*>(aIn);
float* out = reinterpret_cast<float*>(aOut);
- speex_resampler_process_interleaved_float(mResampler, in, &inframes,
- out, &outframes);
+ error =
+ speex_resampler_process_interleaved_float(mResampler, in, &inframes,
+ out, &outframes);
} else if (mOut.Format() == AudioConfig::FORMAT_S16) {
const int16_t* in = reinterpret_cast<const int16_t*>(aIn);
int16_t* out = reinterpret_cast<int16_t*>(aOut);
- speex_resampler_process_interleaved_int(mResampler, in, &inframes,
- out, &outframes);
+ error =
+ speex_resampler_process_interleaved_int(mResampler, in, &inframes,
+ out, &outframes);
} else {
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
}
+ MOZ_ASSERT(error == RESAMPLER_ERR_SUCCESS);
+ if (error != RESAMPLER_ERR_SUCCESS) {
+ speex_resampler_destroy(mResampler);
+ mResampler = nullptr;
+ return 0;
+ }
MOZ_ASSERT(inframes == aFrames, "Some frames will be dropped");
return outframes;
}
void
AudioConverter::RecreateResampler()
{
if (mResampler) {
@@ -293,18 +299,17 @@ AudioConverter::RecreateResampler()
size_t
AudioConverter::DrainResampler(void* aOut)
{
if (!mResampler) {
return 0;
}
int frames = speex_resampler_get_input_latency(mResampler);
- AlignedByteBuffer buffer(FramesOutToSamples(frames) *
- AudioConfig::SampleSize(mOut.Format()));
+ AlignedByteBuffer buffer(FramesOutToBytes(frames));
if (!buffer) {
// OOM
return 0;
}
frames = ResampleAudio(aOut, buffer.Data(), frames);
// Tore down the resampler as it's easier than handling follow-up.
RecreateResampler();
return frames;
@@ -353,16 +358,19 @@ AudioConverter::UpmixAudio(void* aOut, c
}
size_t
AudioConverter::ResampleRecipientFrames(size_t aFrames) const
{
if (!aFrames && mIn.Rate() != mOut.Rate()) {
// The resampler will be drained, account for frames currently buffered
// in the resampler.
+ if (!mResampler) {
+ return 0;
+ }
return speex_resampler_get_output_latency(mResampler);
} else {
return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
}
}
size_t
AudioConverter::FramesOutToSamples(size_t aFrames) const