From 63564ecf7c49c7b025e5379db451ef8d535dcff1 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 16 Jul 2013 11:00:36 +0200 Subject: [PATCH] Bug 891986 - Keep the source ArrayBuffer to a decodeAudioData call alive until the decoding is complete. r=mccr8,ehsan --- content/media/webaudio/AudioContext.cpp | 13 ++++++------ content/media/webaudio/AudioContext.h | 2 +- content/media/webaudio/MediaBufferDecoder.cpp | 30 +++++++++++++++++++++++++++ content/media/webaudio/MediaBufferDecoder.h | 8 ++++++- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index c18acfdbc1ca..44abf6d05dea 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -176,12 +176,13 @@ AudioContext::CreateBuffer(JSContext* aJSContext, ArrayBuffer& aBuffer, aBuffer.Data(), aBuffer.Length(), contentType); - WebAudioDecodeJob job(contentType, this); + nsRefPtr job = + new WebAudioDecodeJob(contentType, this, aBuffer); if (mDecoder.SyncDecodeMedia(contentType.get(), - aBuffer.Data(), aBuffer.Length(), job) && - job.mOutput) { - nsRefPtr buffer = job.mOutput.forget(); + aBuffer.Data(), aBuffer.Length(), *job) && + job->mOutput) { + nsRefPtr buffer = job->mOutput.forget(); if (aMixToMono) { buffer->MixToMono(aJSContext); } @@ -374,8 +375,8 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer, if (aFailureCallback.WasPassed()) { failureCallback = &aFailureCallback.Value(); } - nsAutoPtr job( - new WebAudioDecodeJob(contentType, this, + nsRefPtr job( + new WebAudioDecodeJob(contentType, this, aBuffer, &aSuccessCallback, failureCallback)); mDecoder.AsyncDecodeMedia(contentType.get(), aBuffer.Data(), aBuffer.Length(), *job); diff --git a/content/media/webaudio/AudioContext.h b/content/media/webaudio/AudioContext.h index be96a2dcc681..794004c1e9ec 100644 --- a/content/media/webaudio/AudioContext.h +++ b/content/media/webaudio/AudioContext.h @@ -227,7 +227,7 @@ private: nsRefPtr mDestination; nsRefPtr mListener; MediaBufferDecoder mDecoder; - nsTArray > mDecodeJobs; + nsTArray > mDecodeJobs; // Two hashsets containing all the PannerNodes and AudioBufferSourceNodes, // to compute the doppler shift, and also to stop AudioBufferSourceNodes. // These are all weak pointers. diff --git a/content/media/webaudio/MediaBufferDecoder.cpp b/content/media/webaudio/MediaBufferDecoder.cpp index 1d5fcddc5ab1..c02f75b6f828 100644 --- a/content/media/webaudio/MediaBufferDecoder.cpp +++ b/content/media/webaudio/MediaBufferDecoder.cpp @@ -25,6 +25,29 @@ namespace mozilla { +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutput) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuccessCallback) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mFailureCallback) + tmp->mArrayBuffer = nullptr; +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebAudioDecodeJob) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutput) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuccessCallback) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFailureCallback) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebAudioDecodeJob) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mArrayBuffer) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebAudioDecodeJob, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebAudioDecodeJob, Release) + using namespace dom; #ifdef PR_LOGGING @@ -793,6 +816,7 @@ MediaBufferDecoder::Shutdown() { WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType, AudioContext* aContext, + const ArrayBuffer& aBuffer, DecodeSuccessCallback* aSuccessCallback, DecodeErrorCallback* aFailureCallback) : mContentType(aContentType) @@ -805,15 +829,21 @@ WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType, MOZ_ASSERT(NS_IsMainThread()); MOZ_COUNT_CTOR(WebAudioDecodeJob); + mArrayBuffer = aBuffer.Obj(); + MOZ_ASSERT(aSuccessCallback || (!aSuccessCallback && !aFailureCallback), "If a success callback is not passed, no failure callback should be passed either"); + + nsContentUtils::HoldJSObjects(this, NS_CYCLE_COLLECTION_PARTICIPANT(WebAudioDecodeJob)); } WebAudioDecodeJob::~WebAudioDecodeJob() { MOZ_ASSERT(NS_IsMainThread()); MOZ_COUNT_DTOR(WebAudioDecodeJob); + mArrayBuffer = nullptr; + nsContentUtils::DropJSObjects(this); } void diff --git a/content/media/webaudio/MediaBufferDecoder.h b/content/media/webaudio/MediaBufferDecoder.h index 564c95f10664..0aa4d01a8a11 100644 --- a/content/media/webaudio/MediaBufferDecoder.h +++ b/content/media/webaudio/MediaBufferDecoder.h @@ -26,16 +26,20 @@ class DecodeErrorCallback; class DecodeSuccessCallback; } -struct WebAudioDecodeJob +struct WebAudioDecodeJob MOZ_FINAL { // You may omit both the success and failure callback, or you must pass both. // The callbacks are only necessary for asynchronous operation. WebAudioDecodeJob(const nsACString& aContentType, dom::AudioContext* aContext, + const dom::ArrayBuffer& aBuffer, dom::DecodeSuccessCallback* aSuccessCallback = nullptr, dom::DecodeErrorCallback* aFailureCallback = nullptr); ~WebAudioDecodeJob(); + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebAudioDecodeJob) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebAudioDecodeJob) + enum ErrorCode { NoError, UnknownContent, @@ -52,6 +56,8 @@ struct WebAudioDecodeJob bool AllocateBuffer(); + + JS::Heap mArrayBuffer; nsCString mContentType; uint32_t mWriteIndex; nsRefPtr mContext; -- 2.11.4.GIT