Bug 1340041 - make callbacks no-op for dying CodecProxy. r?jchen
MozReview-Commit-ID: CJPwRNp78HP
--- a/mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
@@ -35,49 +35,56 @@ public final class CodecProxy {
public interface Callbacks {
void onInputExhausted();
void onOutputFormatChanged(MediaFormat format);
void onOutput(Sample output);
void onError(boolean fatal);
}
+ private static Callbacks sNoOpCallbacks = new Callbacks() {
+ public void onInputExhausted() { }
+ public void onOutputFormatChanged(MediaFormat format) { }
+ public void onOutput(Sample output) { output.dispose(); }
+ public void onError(boolean fatal) { }
+ };
+
@WrapForJNI
public static class NativeCallbacks extends JNIObject implements Callbacks {
public native void onInputExhausted();
public native void onOutputFormatChanged(MediaFormat format);
public native void onOutput(Sample output);
public native void onError(boolean fatal);
@Override // JNIObject
protected native void disposeNative();
}
private class CallbacksForwarder extends ICodecCallbacks.Stub {
- private final Callbacks mCallbacks;
+ private Callbacks mCallbacks;
private boolean mEndOfInput;
CallbacksForwarder(Callbacks callbacks) {
mCallbacks = callbacks;
}
@Override
- public void onInputExhausted() throws RemoteException {
+ public synchronized void onInputExhausted() throws RemoteException {
if (!mEndOfInput) {
mCallbacks.onInputExhausted();
}
}
@Override
- public void onOutputFormatChanged(FormatParam format) throws RemoteException {
+ public synchronized void onOutputFormatChanged(FormatParam format) throws RemoteException {
mCallbacks.onOutputFormatChanged(format.asFormat());
}
@Override
- public void onOutput(Sample sample) throws RemoteException {
+ public synchronized void onOutput(Sample sample) throws RemoteException {
if (mOutputSurface != null) {
// Don't render to surface just yet. Callback will make that happen when it's time.
mSurfaceOutputs.offer(sample);
mCallbacks.onOutput(sample);
} else {
// Non-surface output needs no rendering.
mCallbacks.onOutput(sample);
mRemote.releaseOutput(sample, false);
@@ -85,23 +92,27 @@ public final class CodecProxy {
}
}
@Override
public void onError(boolean fatal) throws RemoteException {
reportError(fatal);
}
- private void reportError(boolean fatal) {
+ private synchronized void reportError(boolean fatal) {
mCallbacks.onError(fatal);
}
private void setEndOfInput(boolean end) {
mEndOfInput = end;
}
+
+ private synchronized void cancel() {
+ mCallbacks = sNoOpCallbacks;
+ }
}
@WrapForJNI
public static CodecProxy create(MediaFormat format,
Surface surface,
Callbacks callbacks,
String drmStubId) {
return RemoteManager.getInstance().createCodec(format, surface, callbacks, drmStubId);
@@ -214,16 +225,18 @@ public final class CodecProxy {
e.printStackTrace();
return false;
}
return true;
}
@WrapForJNI
public synchronized boolean release() {
+ mCallbacks.cancel();
+
if (mRemote == null) {
Log.w(LOGTAG, "codec already ended");
return true;
}
if (DEBUG) { Log.d(LOGTAG, "release " + this); }
if (!mSurfaceOutputs.isEmpty()) {
// Flushing output buffers to surface may cause some frames to be skipped and