Bug 1346235 - part 4: recycle unpopulated input samples. r?jchen draft
authorJohn Lin <jolin@mozilla.com>
Fri, 17 Mar 2017 15:06:39 +0800
changeset 501431 7d6e79fc676fbd831e302e29737991e58a81bcbb
parent 501430 2d966b1b5f19692739da24ceb6b790279c27b7c4
child 549881 07ce5b0e556d4b3c59681d8a4d97533e3149aba5
push id49982
push userbmo:jolin@mozilla.com
push dateMon, 20 Mar 2017 09:23:03 +0000
reviewersjchen
bugs1346235
milestone55.0a1
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); }