mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 614160 - Fix remote audio ownership and avoid sending IPCs when actor is being destroyed. r=dougt a=blocking-fennec
--HG-- extra : rebase_source : 0fe7883f97fb4f014b9f39ced902bc96b0eebc31
This commit is contained in:
parent
35d2ba11b4
commit
d96f71fdba
@ -138,7 +138,7 @@ class nsAudioStreamRemote : public nsAudioStream
|
||||
PRInt64 GetSampleOffset();
|
||||
PRBool IsPaused();
|
||||
|
||||
AudioChild* mAudioChild;
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
|
||||
SampleFormat mFormat;
|
||||
int mRate;
|
||||
@ -149,12 +149,6 @@ class nsAudioStreamRemote : public nsAudioStream
|
||||
PRInt32 mBytesPerSample;
|
||||
|
||||
friend class AudioInitEvent;
|
||||
friend class AudioShutdownEvent;
|
||||
friend class AudioWriteEvent;
|
||||
friend class AudioSetVolumeEvent;
|
||||
friend class AudioPauseEvent;
|
||||
friend class AudioDrainEvent;
|
||||
friend class AudioGetSampleEvent;
|
||||
};
|
||||
|
||||
class AudioInitEvent : public nsRunnable
|
||||
@ -181,27 +175,27 @@ class AudioInitEvent : public nsRunnable
|
||||
class AudioWriteEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioWriteEvent(nsAudioStreamRemote* owner,
|
||||
AudioWriteEvent(AudioChild* aChild,
|
||||
const void* aBuf,
|
||||
PRUint32 aNumberOfSamples,
|
||||
PRUint32 aBytesPerSample)
|
||||
{
|
||||
mOwner = owner;
|
||||
mAudioChild = aChild;
|
||||
mBytesPerSample = aBytesPerSample;
|
||||
mBuffer.Assign((const char*)aBuf, aNumberOfSamples*aBytesPerSample);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mOwner->mAudioChild)
|
||||
if (!mAudioChild->IsIPCOpen())
|
||||
return NS_OK;
|
||||
|
||||
mOwner->mAudioChild->SendWrite(mBuffer,
|
||||
mBuffer.Length() / mBytesPerSample);
|
||||
mAudioChild->SendWrite(mBuffer,
|
||||
mBuffer.Length() / mBytesPerSample);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsAudioStreamRemote> mOwner;
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
nsCString mBuffer;
|
||||
PRUint32 mBytesPerSample;
|
||||
};
|
||||
@ -209,73 +203,90 @@ class AudioWriteEvent : public nsRunnable
|
||||
class AudioSetVolumeEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioSetVolumeEvent(nsAudioStreamRemote* owner, float volume)
|
||||
AudioSetVolumeEvent(AudioChild* aChild, float volume)
|
||||
{
|
||||
mOwner = owner;
|
||||
mAudioChild = aChild;
|
||||
mVolume = volume;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mOwner->mAudioChild)
|
||||
if (!mAudioChild->IsIPCOpen())
|
||||
return NS_OK;
|
||||
|
||||
mOwner->mAudioChild->SendSetVolume(mVolume);
|
||||
mAudioChild->SendSetVolume(mVolume);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsAudioStreamRemote> mOwner;
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
float mVolume;
|
||||
};
|
||||
|
||||
class AudioDrainEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioDrainEvent(nsAudioStreamRemote* owner)
|
||||
AudioDrainEvent(AudioChild* aChild)
|
||||
{
|
||||
mOwner = owner;
|
||||
mAudioChild = aChild;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mOwner->mAudioChild)
|
||||
if (!mAudioChild->IsIPCOpen())
|
||||
return NS_OK;
|
||||
|
||||
mOwner->mAudioChild->SendDrain();
|
||||
mAudioChild->SendDrain();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsAudioStreamRemote> mOwner;
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
};
|
||||
|
||||
|
||||
class AudioPauseEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioPauseEvent(nsAudioStreamRemote* owner, PRBool pause)
|
||||
AudioPauseEvent(AudioChild* aChild, PRBool pause)
|
||||
{
|
||||
mOwner = owner;
|
||||
mAudioChild = aChild;
|
||||
mPause = pause;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mOwner->mAudioChild)
|
||||
if (!mAudioChild->IsIPCOpen())
|
||||
return NS_OK;
|
||||
|
||||
if (mPause)
|
||||
mOwner->mAudioChild->SendPause();
|
||||
mAudioChild->SendPause();
|
||||
else
|
||||
mOwner->mAudioChild->SendResume();
|
||||
mAudioChild->SendResume();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsAudioStreamRemote> mOwner;
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
PRBool mPause;
|
||||
};
|
||||
|
||||
|
||||
class AudioShutdownEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioShutdownEvent(AudioChild* aChild)
|
||||
{
|
||||
mAudioChild = aChild;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (mAudioChild->IsIPCOpen())
|
||||
PAudioChild::Send__delete__(mAudioChild);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<AudioChild> mAudioChild;
|
||||
};
|
||||
#endif // MOZ_IPC
|
||||
|
||||
|
||||
@ -602,14 +613,17 @@ nsAudioStreamRemote::Init(PRInt32 aNumChannels,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new AudioInitEvent(this);
|
||||
NS_DispatchToMainThread(event);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsAudioStreamRemote::Shutdown()
|
||||
{
|
||||
PAudioChild::Send__delete__(mAudioChild);
|
||||
if (!mAudioChild)
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioShutdownEvent(mAudioChild);
|
||||
NS_DispatchToMainThread(event);
|
||||
mAudioChild = nsnull;
|
||||
}
|
||||
|
||||
@ -618,7 +632,9 @@ nsAudioStreamRemote::Write(const void* aBuf,
|
||||
PRUint32 aCount,
|
||||
PRBool aBlocking)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event = new AudioWriteEvent(this,
|
||||
if (!mAudioChild)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioWriteEvent(mAudioChild,
|
||||
aBuf,
|
||||
aCount,
|
||||
mBytesPerSample);
|
||||
@ -635,14 +651,18 @@ nsAudioStreamRemote::Available()
|
||||
void
|
||||
nsAudioStreamRemote::SetVolume(float aVolume)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event = new AudioSetVolumeEvent(this, aVolume);
|
||||
if (!mAudioChild)
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioSetVolumeEvent(mAudioChild, aVolume);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
void
|
||||
nsAudioStreamRemote::Drain()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event = new AudioDrainEvent(this);
|
||||
if (!mAudioChild)
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioDrainEvent(mAudioChild);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
@ -650,7 +670,9 @@ void
|
||||
nsAudioStreamRemote::Pause()
|
||||
{
|
||||
mPaused = PR_TRUE;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(this, PR_TRUE);
|
||||
if (!mAudioChild)
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mAudioChild, PR_TRUE);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
@ -658,7 +680,9 @@ void
|
||||
nsAudioStreamRemote::Resume()
|
||||
{
|
||||
mPaused = PR_FALSE;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(this, PR_FALSE);
|
||||
if (!mAudioChild)
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mAudioChild, PR_FALSE);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,13 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(AudioChild);
|
||||
NS_IMPL_THREADSAFE_RELEASE(AudioChild);
|
||||
|
||||
AudioChild::AudioChild()
|
||||
: mLastSampleOffset(-1),
|
||||
mLastSampleOffsetTime(0)
|
||||
mLastSampleOffsetTime(0),
|
||||
mIPCOpen(PR_TRUE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AudioChild);
|
||||
}
|
||||
@ -54,6 +58,12 @@ AudioChild::~AudioChild()
|
||||
MOZ_COUNT_DTOR(AudioChild);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIPCOpen = PR_FALSE;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChild::RecvSampleOffsetUpdate(const PRInt64& offset,
|
||||
const PRInt64& time)
|
||||
|
@ -48,14 +48,23 @@ namespace dom {
|
||||
class AudioChild : public PAudioChild
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
AudioChild();
|
||||
virtual ~AudioChild();
|
||||
virtual bool RecvSampleOffsetUpdate(const PRInt64&, const PRInt64&);
|
||||
virtual void ActorDestroy(ActorDestroyReason);
|
||||
|
||||
PRInt64 GetLastKnownSampleOffset();
|
||||
PRInt64 GetLastKnownSampleOffsetTime();
|
||||
|
||||
PRBool IsIPCOpen() { return mIPCOpen; };
|
||||
private:
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
PRInt64 mLastSampleOffset, mLastSampleOffsetTime;
|
||||
PRPackedBool mIPCOpen;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -66,12 +66,35 @@ class AudioWriteEvent : public nsRunnable
|
||||
PRUint32 mCount;
|
||||
};
|
||||
|
||||
class AudioPauseEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AudioPauseEvent(nsAudioStream* owner, PRBool aPause)
|
||||
{
|
||||
mOwner = owner;
|
||||
mPause = aPause;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (mPause)
|
||||
mOwner->Pause();
|
||||
else
|
||||
mOwner->Resume();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsAudioStream> mOwner;
|
||||
PRBool mPause;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(AudioParent, nsITimerCallback)
|
||||
|
||||
nsresult
|
||||
AudioParent::Notify(nsITimer* timer)
|
||||
{
|
||||
if (!mStream) {
|
||||
if (!mIPCOpen || !mStream) {
|
||||
timer->Cancel();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -110,16 +133,18 @@ AudioParent::RecvDrain()
|
||||
bool
|
||||
AudioParent::RecvPause()
|
||||
{
|
||||
if (mStream)
|
||||
mStream->Pause();
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mStream, PR_TRUE);
|
||||
nsCOMPtr<nsIThread> thread = nsAudioStream::GetGlobalThread();
|
||||
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioParent::RecvResume()
|
||||
{
|
||||
if (mStream)
|
||||
mStream->Resume();
|
||||
nsCOMPtr<nsIRunnable> event = new AudioPauseEvent(mStream, PR_FALSE);
|
||||
nsCOMPtr<nsIThread> thread = nsAudioStream::GetGlobalThread();
|
||||
thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -139,6 +164,7 @@ AudioParent::Recv__delete__()
|
||||
}
|
||||
|
||||
AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat)
|
||||
: mIPCOpen(PR_TRUE)
|
||||
{
|
||||
mStream = nsAudioStream::AllocateStream();
|
||||
if (mStream)
|
||||
@ -156,5 +182,11 @@ AudioParent::~AudioParent()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AudioParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIPCOpen = PR_FALSE;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -75,10 +75,13 @@ class AudioParent : public PAudioParent, public nsITimerCallback
|
||||
|
||||
AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
|
||||
virtual ~AudioParent();
|
||||
virtual void ActorDestroy(ActorDestroyReason);
|
||||
|
||||
nsRefPtr<nsAudioStream> mStream;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
private:
|
||||
PRPackedBool mIPCOpen;
|
||||
};
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -333,14 +333,16 @@ ContentChild::AllocPAudio(const PRInt32& numChannels,
|
||||
const PRInt32& rate,
|
||||
const PRInt32& format)
|
||||
{
|
||||
PAudioChild *child = new AudioChild();
|
||||
AudioChild *child = new AudioChild();
|
||||
NS_ADDREF(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPAudio(PAudioChild* doomed)
|
||||
{
|
||||
delete doomed;
|
||||
AudioChild *child = static_cast<AudioChild*>(doomed);
|
||||
NS_RELEASE(child);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -427,7 +427,7 @@ ContentParent::AllocPAudio(const PRInt32& numChannels,
|
||||
const PRInt32& format)
|
||||
{
|
||||
AudioParent *parent = new AudioParent(numChannels, rate, format);
|
||||
parent->AddRef();
|
||||
NS_ADDREF(parent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user