mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=991533 limit AudioBuffers from decodeAudioData to the same sample rates as createBuffer r=ehsan
The numberOfChannels array on AudioBuffer is now an infallible array, as this is considerably smaller than infallible channel data array allocations in AllocateAudioBlock and similar to channel data pointer array allocations in AudioChunk. --HG-- extra : transplant_source : C%29_%13%9C%9C%A1%E1%A3%E8%C9_%93%11%85lM%FC%7E%BC
This commit is contained in:
parent
651d766fc4
commit
63192b0276
@ -41,12 +41,13 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioBuffer, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioBuffer, Release)
|
||||
|
||||
AudioBuffer::AudioBuffer(AudioContext* aContext, uint32_t aLength,
|
||||
float aSampleRate)
|
||||
AudioBuffer::AudioBuffer(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate)
|
||||
: mContext(aContext),
|
||||
mLength(aLength),
|
||||
mSampleRate(aSampleRate)
|
||||
{
|
||||
mJSChannels.SetCapacity(aNumberOfChannels);
|
||||
SetIsDOMBinding();
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
@ -63,22 +64,35 @@ AudioBuffer::ClearJSChannels()
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
bool
|
||||
AudioBuffer::InitializeBuffers(uint32_t aNumberOfChannels, JSContext* aJSContext)
|
||||
/* static */ already_AddRefed<AudioBuffer>
|
||||
AudioBuffer::Create(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate,
|
||||
JSContext* aJSContext, ErrorResult& aRv)
|
||||
{
|
||||
if (!mJSChannels.SetCapacity(aNumberOfChannels)) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < aNumberOfChannels; ++i) {
|
||||
JS::Rooted<JSObject*> array(aJSContext,
|
||||
JS_NewFloat32Array(aJSContext, mLength));
|
||||
if (!array) {
|
||||
return false;
|
||||
}
|
||||
mJSChannels.AppendElement(array.get());
|
||||
// Note that a buffer with zero channels is permitted here for the sake of
|
||||
// AudioProcessingEvent, where channel counts must match parameters passed
|
||||
// to createScriptProcessor(), one of which may be zero.
|
||||
if (aSampleRate < WebAudioUtils::MinSampleRate ||
|
||||
aSampleRate > WebAudioUtils::MaxSampleRate ||
|
||||
!aLength || aLength > INT32_MAX) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
nsRefPtr<AudioBuffer> buffer =
|
||||
new AudioBuffer(aContext, aNumberOfChannels, aLength, aSampleRate);
|
||||
|
||||
for (uint32_t i = 0; i < aNumberOfChannels; ++i) {
|
||||
JS::Rooted<JSObject*> array(aJSContext,
|
||||
JS_NewFloat32Array(aJSContext, aLength));
|
||||
if (!array) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
buffer->mJSChannels.AppendElement(array.get());
|
||||
}
|
||||
|
||||
return buffer.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -33,17 +33,13 @@ class AudioContext;
|
||||
class AudioBuffer MOZ_FINAL : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
AudioBuffer(AudioContext* aContext, uint32_t aLength,
|
||||
float aSampleRate);
|
||||
~AudioBuffer();
|
||||
static already_AddRefed<AudioBuffer>
|
||||
Create(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate,
|
||||
JSContext* aJSContext, ErrorResult& aRv);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
// This function needs to be called in order to allocate
|
||||
// all of the channels. It is fallible!
|
||||
bool InitializeBuffers(uint32_t aNumberOfChannels,
|
||||
JSContext* aJSContext);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioBuffer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioBuffer)
|
||||
|
||||
@ -100,12 +96,16 @@ public:
|
||||
void SetRawChannelContents(uint32_t aChannel, float* aContents);
|
||||
|
||||
protected:
|
||||
AudioBuffer(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate);
|
||||
~AudioBuffer();
|
||||
|
||||
bool RestoreJSChannelData(JSContext* aJSContext);
|
||||
void ClearJSChannels();
|
||||
|
||||
nsRefPtr<AudioContext> mContext;
|
||||
// Float32Arrays
|
||||
AutoFallibleTArray<JS::Heap<JSObject*>, 2> mJSChannels;
|
||||
nsAutoTArray<JS::Heap<JSObject*>, 2> mJSChannels;
|
||||
|
||||
// mSharedChannels aggregates the data from mJSChannels. This is non-null
|
||||
// if and only if the mJSChannels are neutered.
|
||||
|
@ -204,26 +204,13 @@ AudioContext::CreateBuffer(JSContext* aJSContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aSampleRate < WebAudioUtils::MinSampleRate ||
|
||||
aSampleRate > WebAudioUtils::MaxSampleRate ||
|
||||
!aLength || !aNumberOfChannels) {
|
||||
if (!aNumberOfChannels) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aLength > INT32_MAX) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<AudioBuffer> buffer =
|
||||
new AudioBuffer(this, int32_t(aLength), aSampleRate);
|
||||
if (!buffer->InitializeBuffers(aNumberOfChannels, aJSContext)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return buffer.forget();
|
||||
return AudioBuffer::Create(this, aNumberOfChannels, aLength,
|
||||
aSampleRate, aJSContext, aRv);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -137,10 +137,11 @@ public:
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
// Create the input buffer
|
||||
nsRefPtr<AudioBuffer> renderedBuffer = new AudioBuffer(context,
|
||||
mLength,
|
||||
mSampleRate);
|
||||
if (!renderedBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
|
||||
ErrorResult rv;
|
||||
nsRefPtr<AudioBuffer> renderedBuffer =
|
||||
AudioBuffer::Create(context, mInputChannels.Length(),
|
||||
mLength, mSampleRate, cx, rv);
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
|
||||
|
@ -53,13 +53,10 @@ AudioProcessingEvent::LazilyCreateBuffer(uint32_t aNumberOfChannels,
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
nsRefPtr<AudioBuffer> buffer =
|
||||
new AudioBuffer(mNode->Context(), mNode->BufferSize(),
|
||||
mNode->Context()->SampleRate());
|
||||
if (!buffer->InitializeBuffers(aNumberOfChannels, cx)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioBuffer::Create(mNode->Context(), aNumberOfChannels,
|
||||
mNode->BufferSize(),
|
||||
mNode->Context()->SampleRate(), cx, aRv);
|
||||
MOZ_ASSERT(buffer || aRv.ErrorCode() == NS_ERROR_OUT_OF_MEMORY);
|
||||
return buffer.forget();
|
||||
}
|
||||
|
||||
|
@ -413,8 +413,10 @@ WebAudioDecodeJob::AllocateBuffer()
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
// Now create the AudioBuffer
|
||||
mOutput = new AudioBuffer(mContext, mWriteIndex, mContext->SampleRate());
|
||||
if (!mOutput->InitializeBuffers(mChannelBuffers.Length(), cx)) {
|
||||
ErrorResult rv;
|
||||
mOutput = AudioBuffer::Create(mContext, mChannelBuffers.Length(),
|
||||
mWriteIndex, mContext->SampleRate(), cx, rv);
|
||||
if (rv.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -415,10 +415,12 @@ private:
|
||||
// Create the input buffer
|
||||
nsRefPtr<AudioBuffer> inputBuffer;
|
||||
if (!mNullInput) {
|
||||
inputBuffer = new AudioBuffer(node->Context(),
|
||||
node->BufferSize(),
|
||||
node->Context()->SampleRate());
|
||||
if (!inputBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
|
||||
ErrorResult rv;
|
||||
inputBuffer =
|
||||
AudioBuffer::Create(node->Context(), mInputChannels.Length(),
|
||||
node->BufferSize(),
|
||||
node->Context()->SampleRate(), cx, rv);
|
||||
if (rv.Failed()) {
|
||||
return NS_OK;
|
||||
}
|
||||
// Put the channel data inside it
|
||||
|
Loading…
Reference in New Issue
Block a user