Bug 1346235 - Part 4: Recycle unpopulated input samples. r=jchen, a=gchang
authorJohn Lin <jolin@mozilla.com>
Fri, 17 Mar 2017 15:06:39 +0800
changeset 395865 8130607e5dbfb8931684fe758f0453c8e727d006
parent 395864 6e00d34c16e72c7a3a5adfc6ae037c62a90c68df
child 395866 fc16131f93233db6253a19ed010d9c5ab6a31303
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen, gchang
bugs1346235
milestone54.0a2
Bug 1346235 - Part 4: Recycle unpopulated input samples. r=jchen, a=gchang MozReview-Commit-ID: Lr0aSQ0OfRg
mobile/android/base/java/org/mozilla/gecko/media/Codec.java
mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
--- a/mobile/android/base/java/org/mozilla/gecko/media/Codec.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/Codec.java
@@ -61,28 +61,36 @@ import java.util.concurrent.ConcurrentLi
         private synchronized Sample onAllocate(int size) {
             Sample sample = mSamplePool.obtainInput(size);
             mDequeuedSamples.add(sample);
             return sample;
         }
 
         private synchronized void onSample(Sample sample) {
             if (sample == null) {
-                Log.w(LOGTAG, "WARN: null input sample");
+                // Ignore empty input.
+                mSamplePool.recycleInput(mDequeuedSamples.remove());
+                Log.w(LOGTAG, "WARN: empty input sample");
                 return;
             }
 
-            if (!sample.isEOS()) {
-                Sample temp = sample;
-                sample = mDequeuedSamples.remove();
-                sample.info = temp.info;
-                sample.cryptoInfo = temp.cryptoInfo;
-                temp.dispose();
+            if (sample.isEOS()) {
+                queueSample(sample);
+                return;
             }
 
+            Sample dequeued = mDequeuedSamples.remove();
+            dequeued.info = sample.info;
+            dequeued.cryptoInfo = sample.cryptoInfo;
+            queueSample(dequeued);
+
+            sample.dispose();
+        }
+
+        private void queueSample(Sample sample) {
             if (!mInputSamples.offer(sample)) {
                 reportError(Error.FATAL, new Exception("FAIL: input sample queue is full"));
                 return;
             }
 
             try {
                 feedSampleToBuffer();
             } catch (Exception e) {
--- a/mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
@@ -165,44 +165,50 @@ public final class CodecProxy {
     }
 
     @WrapForJNI
     public synchronized boolean input(ByteBuffer bytes, BufferInfo info, CryptoInfo cryptoInfo) {
         if (mRemote == null) {
             Log.e(LOGTAG, "cannot send input to an ended codec");
             return false;
         }
+
+        boolean eos = info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+        mCallbacks.setEndOfInput(eos);
+
+        if (eos) {
+            return sendInput(Sample.EOS);
+        }
+
         try {
-            Sample sample = processInput(bytes, info, cryptoInfo);
-            if (sample == null) {
-                return false;
-            }
+            return sendInput(mRemote.dequeueInput(info.size).set(bytes, info, cryptoInfo));
+        } catch (RemoteException e) {
+            Log.e(LOGTAG, "fail to dequeue input buffer", e);
+            return false;
+        } catch (IOException e) {
+            Log.e(LOGTAG, "fail to copy input data.", e);
+            // Balance dequeue/queue.
+            return sendInput(null);
+        }
+    }
+
+    private boolean sendInput(Sample sample) {
+        try {
             mRemote.queueInput(sample);
-            sample.dispose();
+            if (sample != null) {
+                sample.dispose();
+            }
         } catch (Exception e) {
-            Log.e(LOGTAG, "fail to input sample: size=" + info.size +
-                    ", pts=" + info.presentationTimeUs +
-                    ", flags=" + Integer.toHexString(info.flags), e);
+            Log.e(LOGTAG, "fail to queue input:" + sample, e);
             return false;
         }
 
         return true;
     }
 
-    private Sample processInput(ByteBuffer bytes, BufferInfo info, CryptoInfo cryptoInfo)
-            throws RemoteException, IOException {
-        if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
-            mCallbacks.setEndOfInput(true);
-            return Sample.EOS;
-        } else {
-            mCallbacks.setEndOfInput(false);
-            return mRemote.dequeueInput(info.size).set(bytes, info, cryptoInfo);
-        }
-    }
-
     @WrapForJNI
     public synchronized boolean flush() {
         if (mRemote == null) {
             Log.e(LOGTAG, "cannot flush an ended codec");
             return false;
         }
         try {
             if (DEBUG) { Log.d(LOGTAG, "flush " + this); }