Bug 1346235 - part 4: recycle unpopulated input samples. r=jchen
authorJohn Lin <jolin@mozilla.com>
Fri, 17 Mar 2017 15:06:39 +0800
changeset 348404 c4f7d0039351ec60456a1613ed34b0645bdc292e
parent 348403 0dad897e64bd4ba08d167e4f9d09faea1340de0e
child 348405 37d0954bf1431c13ef29457a124c691201674068
push id39149
push userjolin@mozilla.com
push dateMon, 20 Mar 2017 11:18:00 +0000
treeherderautoland@c4f7d0039351 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen
bugs1346235
milestone55.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 1346235 - part 4: recycle unpopulated input samples. r=jchen 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); }