Bug 620331 - Remote nsAudioStreamRemote::GetMinWriteSamples; r=kinetik
authorPaul ADENOT <paul@paul.cx>
Sun, 15 May 2011 12:53:55 +0200
changeset 69676 f937f55b4a7f8e80b997403ab49a8885408b23da
parent 69675 a466b57361d08afaca52c65ef113cca96d2a6fa0
child 69677 48c0f02f4614fe670a736f6eb8924a4c3c3e60e5
push id99
push usereakhgari@mozilla.com
push dateTue, 24 May 2011 18:03:59 +0000
treeherdermozilla-aurora@26d6981b3d6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs620331
milestone6.0a1
Bug 620331 - Remote nsAudioStreamRemote::GetMinWriteSamples; r=kinetik
content/media/nsAudioStream.cpp
dom/ipc/AudioChild.cpp
dom/ipc/AudioChild.h
dom/ipc/AudioParent.cpp
dom/ipc/AudioParent.h
dom/ipc/PAudio.ipdl
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -221,16 +221,37 @@ class AudioSetVolumeEvent : public nsRun
     mAudioChild->SendSetVolume(mVolume);
     return NS_OK;
   }
   
   nsRefPtr<AudioChild> mAudioChild;
   double mVolume;
 };
 
+
+class AudioMinWriteSampleEvent : public nsRunnable
+{
+ public:
+  AudioMinWriteSampleEvent(AudioChild* aChild)
+  {
+    mAudioChild = aChild;
+  }
+
+  NS_IMETHOD Run()
+  {
+    if (!mAudioChild->IsIPCOpen())
+      return NS_OK;
+
+    mAudioChild->SendMinWriteSample();
+    return NS_OK;
+  }
+
+  nsRefPtr<AudioChild> mAudioChild;
+};
+
 class AudioDrainEvent : public nsRunnable
 {
  public:
   AudioDrainEvent(AudioChild* aChild)
   {
     mAudioChild = aChild;
   }
 
@@ -665,19 +686,21 @@ nsAudioStreamRemote::Write(const void* a
 PRUint32
 nsAudioStreamRemote::Available()
 {
   return FAKE_BUFFER_SIZE;
 }
 
 PRInt32 nsAudioStreamRemote::GetMinWriteSamples()
 {
-  /** TODO: Implement this function for remoting. We could potentially remote
-            to a backend which has a start threshold... */
-  return 1;
+  if (!mAudioChild)
+    return -1;
+  nsCOMPtr<nsIRunnable> event = new AudioMinWriteSampleEvent(mAudioChild);
+  NS_DispatchToMainThread(event);
+  return mAudioChild->WaitForMinWriteSample();
 }
 
 void
 nsAudioStreamRemote::SetVolume(double aVolume)
 {
   if (!mAudioChild)
     return;
   nsCOMPtr<nsIRunnable> event = new AudioSetVolumeEvent(mAudioChild, aVolume);
--- a/dom/ipc/AudioChild.cpp
+++ b/dom/ipc/AudioChild.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set sw=4 ts=8 et tw=80 : */
+/* vim: set sw=2 ts=2 et tw=80 : */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -36,23 +36,23 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/dom/AudioChild.h"
 
 namespace mozilla {
 namespace dom {
-
 NS_IMPL_THREADSAFE_ADDREF(AudioChild);
 NS_IMPL_THREADSAFE_RELEASE(AudioChild);
 
 AudioChild::AudioChild()
   : mLastSampleOffset(-1),
     mLastSampleOffsetTime(0),
+    mMinWriteSample(-2),// Initial value, -2, error on -1
     mAudioReentrantMonitor("AudioChild.mReentrantMonitor"),
     mIPCOpen(PR_TRUE),
     mDrained(PR_FALSE)
 {
   MOZ_COUNT_CTOR(AudioChild);
 }
 
 AudioChild::~AudioChild()
@@ -79,16 +79,35 @@ bool
 AudioChild::RecvDrainDone()
 {
   ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor);
   mDrained = PR_TRUE;
   mAudioReentrantMonitor.NotifyAll();
   return true;
 }
 
+PRInt32
+AudioChild::WaitForMinWriteSample()
+{
+  ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor);
+  // -2 : initial value
+  while (mMinWriteSample == -2 && mIPCOpen)
+    mAudioReentrantMonitor.Wait();
+  return mMinWriteSample;
+}
+
+bool
+AudioChild::RecvMinWriteSampleDone(const PRInt32& minSamples)
+{
+  ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor);
+  mMinWriteSample = minSamples;
+  mAudioReentrantMonitor.NotifyAll();
+  return true;
+}
+
 void
 AudioChild::WaitForDrain()
 {
   ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor);
   while (!mDrained && mIPCOpen) {
     mAudioReentrantMonitor.Wait();
   }
 }
--- a/dom/ipc/AudioChild.h
+++ b/dom/ipc/AudioChild.h
@@ -51,27 +51,30 @@ class AudioChild : public PAudioChild
  public:
     NS_IMETHOD_(nsrefcnt) AddRef();
     NS_IMETHOD_(nsrefcnt) Release();
 
     AudioChild();
     virtual ~AudioChild();
     virtual bool RecvSampleOffsetUpdate(const PRInt64&, const PRInt64&);
     virtual bool RecvDrainDone();
+    virtual PRInt32 WaitForMinWriteSample();
+    virtual bool RecvMinWriteSampleDone(const PRInt32& sampleCount);
     virtual void WaitForDrain();
     virtual void ActorDestroy(ActorDestroyReason);
-    
+
     PRInt64 GetLastKnownSampleOffset();
     PRInt64 GetLastKnownSampleOffsetTime();
 
     PRBool IsIPCOpen() { return mIPCOpen; };
  private:
     nsAutoRefCnt mRefCnt;
     NS_DECL_OWNINGTHREAD
     PRInt64 mLastSampleOffset, mLastSampleOffsetTime;
+    PRInt32 mMinWriteSample;
     mozilla::ReentrantMonitor mAudioReentrantMonitor;
     PRPackedBool mIPCOpen;
     PRPackedBool mDrained;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/ipc/AudioParent.cpp
+++ b/dom/ipc/AudioParent.cpp
@@ -103,16 +103,59 @@ class AudioStreamShutdownEvent : public 
     mOwner->Shutdown();
     return NS_OK;
   }
 
  private:
     nsRefPtr<nsAudioStream> mOwner;
 };
 
+
+class AudioMinWriteSampleDone : public nsRunnable
+{
+ public:
+  AudioMinWriteSampleDone(AudioParent* owner, PRInt32 minSamples)
+  {
+    mOwner = owner;
+    mMinSamples = minSamples;
+  }
+
+  NS_IMETHOD Run()
+  {
+    mOwner->SendMinWriteSampleDone(mMinSamples);
+    return NS_OK;
+  }
+
+ private:
+    nsRefPtr<AudioParent> mOwner;
+    PRInt32 mMinSamples;
+};
+
+class AudioMinWriteSampleEvent : public nsRunnable
+{
+ public:
+  AudioMinWriteSampleEvent(AudioParent* parent, nsAudioStream* owner)
+  {
+    mParent = parent;
+    mOwner = owner;
+  }
+
+  NS_IMETHOD Run()
+  {
+    PRInt32 minSamples = mOwner->GetMinWriteSamples();
+    nsCOMPtr<nsIRunnable> event = new AudioMinWriteSampleDone(mParent, minSamples);
+    NS_DispatchToMainThread(event);
+    return NS_OK;
+  }
+
+ private:
+    nsRefPtr<nsAudioStream> mOwner;
+    nsRefPtr<AudioParent> mParent;
+};
+
 class AudioDrainDoneEvent : public nsRunnable
 {
  public:
   AudioDrainDoneEvent(AudioParent* owner)
   {
     mOwner = owner;
   }
 
@@ -182,16 +225,27 @@ AudioParent::RecvSetVolume(const float& 
 {
   if (!mStream)
       return false;
   mStream->SetVolume(aVolume);
   return true;
 }
 
 bool
+AudioParent::RecvMinWriteSample()
+{
+  if (!mStream)
+    return false;
+  nsCOMPtr<nsIRunnable> event = new AudioMinWriteSampleEvent(this, mStream);
+  nsCOMPtr<nsIThread> thread = mStream->GetThread();
+  thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
+  return true;
+}
+
+bool
 AudioParent::RecvDrain()
 {
   if (!mStream)
     return false;
   nsCOMPtr<nsIRunnable> event = new AudioDrainEvent(this, mStream);
   nsCOMPtr<nsIThread> thread = mStream->GetThread();
   thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
   return true;
@@ -223,16 +277,24 @@ bool
 AudioParent::RecvShutdown()
 {
   Shutdown();
   unused << PAudioParent::Send__delete__(this);
   return true;
 }
 
 bool
+AudioParent::SendMinWriteSampleDone(PRInt32 minSamples)
+{
+  if (mIPCOpen)
+    return PAudioParent::SendMinWriteSampleDone(minSamples);
+  return true;
+}
+
+bool
 AudioParent::SendDrainDone()
 {
   if (mIPCOpen)
     return PAudioParent::SendDrainDone();
   return true;
 }
 
 AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat)
--- a/dom/ipc/AudioParent.h
+++ b/dom/ipc/AudioParent.h
@@ -57,28 +57,34 @@ class AudioParent : public PAudioParent,
     RecvWrite(
             const nsCString& data,
             const PRUint32& count);
 
     virtual bool
     RecvSetVolume(const float& aVolume);
 
     virtual bool
+    RecvMinWriteSample();
+
+    virtual bool
     RecvDrain();
 
     virtual bool
     RecvPause();
 
     virtual bool
     RecvResume();
 
     virtual bool
     RecvShutdown();
 
     virtual bool
+    SendMinWriteSampleDone(PRInt32 minSamples);
+
+    virtual bool
     SendDrainDone();
 
     AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
     virtual ~AudioParent();
     virtual void ActorDestroy(ActorDestroyReason);
 
     nsRefPtr<nsAudioStream> mStream;
     nsCOMPtr<nsITimer> mTimer;
--- a/dom/ipc/PAudio.ipdl
+++ b/dom/ipc/PAudio.ipdl
@@ -47,25 +47,27 @@ protocol PAudio
   manager PContent;
 
 parent:
 
   Write(nsCString data, PRUint32 count);
 
   SetVolume(float aVolume);
 
+  MinWriteSample();
   Drain();
 
   Pause();
   Resume();
   Shutdown();
 
  child:
 
   __delete__();
 
   SampleOffsetUpdate(PRInt64 offset, PRInt64 time);
+  MinWriteSampleDone(PRInt32 sampleCount);
   DrainDone();
 
 };
 
 } // namespace dom
 } // namespace mozilla