Bug 1346235 - part 4: recycle unpopulated input samples. r?jchen
MozReview-Commit-ID: Lr0aSQ0OfRg
--- 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); }