Bug 1365205 - part 1: check for buffer validness before processing it. r?esawin
flush() invalidates all buffers so buffer callbacks emitted earlier than that should not proceed when they're executed after.
MozReview-Commit-ID: 3KjCmW2VwTy
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
@@ -106,17 +106,17 @@ import org.mozilla.gecko.gfx.GeckoSurfac
try {
feedSampleToBuffer();
} catch (Exception e) {
reportError(Error.FATAL, e);
}
}
private synchronized void onBuffer(int index) {
- if (mStopped) {
+ if (mStopped || !isValidBuffer(index)) {
return;
}
if (!mHasInputCapacitySet) {
int capacity = mCodec.getInputBuffer(index).capacity();
if (capacity > 0) {
mSamplePool.setInputBufferSize(capacity);
mHasInputCapacitySet = true;
@@ -126,16 +126,25 @@ import org.mozilla.gecko.gfx.GeckoSurfac
if (mAvailableInputBuffers.offer(index)) {
feedSampleToBuffer();
} else {
reportError(Error.FATAL, new Exception("FAIL: input buffer queue is full"));
}
}
+ private boolean isValidBuffer(final int index) {
+ try {
+ return mCodec.getInputBuffer(index) != null;
+ } catch (IllegalStateException e) {
+ if (DEBUG) { Log.d(LOGTAG, "invalid input buffer#" + index, e); }
+ return false;
+ }
+ }
+
private void feedSampleToBuffer() {
while (!mAvailableInputBuffers.isEmpty() && !mInputSamples.isEmpty()) {
int index = mAvailableInputBuffers.poll();
int len = 0;
final Sample sample = mInputSamples.poll().sample;
long pts = sample.info.presentationTimeUs;
int flags = sample.info.flags;
MediaCodec.CryptoInfo cryptoInfo = sample.cryptoInfo;
@@ -229,17 +238,17 @@ import org.mozilla.gecko.gfx.GeckoSurfac
private Queue<Output> mSentOutputs = new LinkedList<>();
private boolean mStopped;
private OutputProcessor(boolean renderToSurface) {
mRenderToSurface = renderToSurface;
}
private synchronized void onBuffer(int index, MediaCodec.BufferInfo info) {
- if (mStopped) {
+ if (mStopped || !isValidBuffer(index)) {
return;
}
try {
Sample output = obtainOutputSample(index, info);
mSentOutputs.add(new Output(output, index));
mCallbacks.onOutput(output);
} catch (Exception e) {
@@ -248,16 +257,25 @@ import org.mozilla.gecko.gfx.GeckoSurfac
}
boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
if (DEBUG && eos) {
Log.d(LOGTAG, "output EOS");
}
}
+ private boolean isValidBuffer(final int index) {
+ try {
+ return mCodec.getOutputBuffer(index) != null;
+ } catch (IllegalStateException e) {
+ if (DEBUG) { Log.e(LOGTAG, "invalid buffer#" + index, e); }
+ return false;
+ }
+ }
+
private Sample obtainOutputSample(int index, MediaCodec.BufferInfo info) {
Sample sample = mSamplePool.obtainOutput(info);
if (mRenderToSurface) {
return sample;
}
ByteBuffer output = mCodec.getOutputBuffer(index);