Bug 1508434 - p4: release audio output buffers after processing on task queue. r=jya
authorJohn Lin <jolin@mozilla.com>
Fri, 11 Jan 2019 17:08:11 +0000
changeset 453507 b6a0a003d609b4d67490367ef717a66fa48dfada
parent 453506 d568d717aa5bb4b4dedd696a5e5b0a127fdf7a1a
child 453508 fd2b5b6a3048f5e7680508b4dc2900f4d3e56480
push id35357
push usernerli@mozilla.com
push dateFri, 11 Jan 2019 21:54:07 +0000
treeherdermozilla-central@0ce024c91511 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1508434
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1508434 - p4: release audio output buffers after processing on task queue. r=jya Differential Revision: https://phabricator.services.mozilla.com/D15985
dom/media/platforms/android/RemoteDataDecoder.cpp
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -27,42 +27,50 @@
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::java;
 using namespace mozilla::java::sdk;
 using media::TimeUnit;
 
 namespace mozilla {
 
-class RemoteVideoDecoder : public RemoteDataDecoder {
+// Hold a reference to the output buffer until we're ready to release it back to
+// the Java codec (for rendering or not).
+class RenderOrReleaseOutput {
  public:
-  // Hold an output buffer and render it to the surface when the frame is sent
-  // to compositor, or release it if not presented.
-  class RenderOrReleaseOutput : public VideoData::Listener {
-   public:
-    RenderOrReleaseOutput(CodecProxy::Param aCodec, Sample::Param aSample)
-        : mCodec(aCodec), mSample(aSample) {}
+  RenderOrReleaseOutput(CodecProxy::Param aCodec, Sample::Param aSample)
+      : mCodec(aCodec), mSample(aSample) {}
+
+  virtual ~RenderOrReleaseOutput() { ReleaseOutput(false); }
 
-    ~RenderOrReleaseOutput() { ReleaseOutput(false); }
-
-    void OnSentToCompositor() override {
-      ReleaseOutput(true);
+ protected:
+  void ReleaseOutput(bool aToRender) {
+    if (mCodec && mSample) {
+      mCodec->ReleaseOutput(mSample, aToRender);
       mCodec = nullptr;
       mSample = nullptr;
     }
+  }
 
-   private:
-    void ReleaseOutput(bool aToRender) {
-      if (mCodec && mSample) {
-        mCodec->ReleaseOutput(mSample, aToRender);
-      }
-    }
+ private:
+  CodecProxy::GlobalRef mCodec;
+  Sample::GlobalRef mSample;
+};
 
-    CodecProxy::GlobalRef mCodec;
-    Sample::GlobalRef mSample;
+class RemoteVideoDecoder : public RemoteDataDecoder {
+ public:
+  // Render the output to the surface when the frame is sent
+  // to compositor, or release it if not presented.
+  class CompositeListener : private RenderOrReleaseOutput,
+                            public VideoData::Listener {
+   public:
+    CompositeListener(CodecProxy::Param aCodec, Sample::Param aSample)
+        : RenderOrReleaseOutput(aCodec, aSample) {}
+
+    void OnSentToCompositor() override { ReleaseOutput(true); }
   };
 
   class InputInfo {
    public:
     InputInfo() {}
 
     InputInfo(const int64_t aDurationUs, const gfx::IntSize& aImageSize,
               const gfx::IntSize& aDisplaySize)
@@ -219,19 +227,20 @@ class RemoteVideoDecoder : public Remote
       MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
       Unused << rv;
       return;
     }
 
     AssertOnTaskQueue();
 
     UniquePtr<VideoData::Listener> releaseSample(
-        new RenderOrReleaseOutput(mJavaDecoder, aSample));
+        new CompositeListener(mJavaDecoder, aSample));
 
     BufferInfo::LocalRef info = aSample->Info();
+    MOZ_ASSERT(info);
 
     int32_t flags;
     bool ok = NS_SUCCEEDED(info->Flags(&flags));
 
     int32_t offset;
     ok &= NS_SUCCEEDED(info->Offset(&offset));
 
     int32_t size;
@@ -381,17 +390,20 @@ class RemoteAudioDecoder : public Remote
           &RemoteAudioDecoder::ProcessOutput, std::move(aSample)));
       MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
       Unused << rv;
       return;
     }
 
     AssertOnTaskQueue();
 
+    RenderOrReleaseOutput autoRelease(mJavaDecoder, aSample);
+
     BufferInfo::LocalRef info = aSample->Info();
+    MOZ_ASSERT(info);
 
     int32_t flags;
     bool ok = NS_SUCCEEDED(info->Flags(&flags));
 
     int32_t offset;
     ok &= NS_SUCCEEDED(info->Offset(&offset));
 
     int64_t presentationTimeUs;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java
@@ -89,27 +89,18 @@ public final class CodecProxy {
         public synchronized void onOutput(Sample sample) throws RemoteException {
             if (mCodecProxyReleased) {
                 sample.dispose();
                 return;
             }
             if (mOutputSurface != null) {
                 // Don't render to surface just yet. Callback will make that happen when it's time.
                 mSurfaceOutputs.offer(sample);
-                mCallbacks.onOutput(sample);
-            } else {
-                // Non-surface output needs no rendering.
-                try {
-                    mCallbacks.onOutput(sample);
-                    mRemote.releaseOutput(sample, false);
-                    sample.dispose();
-                } catch (Exception e) {
-                    reportError(true);
-                }
             }
+            mCallbacks.onOutput(sample);
         }
 
         @Override
         public void onError(boolean fatal) throws RemoteException {
             reportError(fatal);
         }
 
         private synchronized void reportError(boolean fatal) {
@@ -342,33 +333,37 @@ public final class CodecProxy {
             Log.e(LOGTAG, "remote fail to set rates:" + newBitRate);
             e.printStackTrace();
         }
         return true;
     }
 
     @WrapForJNI
     public synchronized boolean releaseOutput(Sample sample, boolean render) {
-        if (!mSurfaceOutputs.remove(sample)) {
-            if (mRemote != null) Log.w(LOGTAG, "already released: " + sample);
-            return true;
+        if (mOutputSurface != null) {
+            if (!mSurfaceOutputs.remove(sample)) {
+                if (mRemote != null) Log.w(LOGTAG, "already released: " + sample);
+                return true;
+            }
+
+            if (DEBUG && !render) {
+                Log.d(LOGTAG, "drop output:" + sample.info.presentationTimeUs);
+            }
         }
 
         if (mRemote == null) {
             Log.w(LOGTAG, "codec already ended");
             sample.dispose();
             return true;
         }
 
-        if (DEBUG && !render) { Log.d(LOGTAG, "drop output:" + sample.info.presentationTimeUs); }
-
         try {
             mRemote.releaseOutput(sample, render);
         } catch (RemoteException e) {
-            Log.e(LOGTAG, "remote fail to render output:" + sample.info.presentationTimeUs);
+            Log.e(LOGTAG, "remote fail to release output:" + sample.info.presentationTimeUs);
             e.printStackTrace();
         }
         sample.dispose();
 
         return true;
     }
 
     /* package */ void reportError(boolean fatal) {