Bug 1353313 - Add synchronization mechanism to CodecProxy. r=jolin

MozReview-Commit-ID: 3sqW06nIkoJ
This commit is contained in:
Munro Mengjue Chiang 2017-04-14 10:04:24 +08:00
Родитель 874d6c226e
Коммит c805ded682
1 изменённых файлов: 47 добавлений и 31 удалений

Просмотреть файл

@ -57,6 +57,7 @@ public final class CodecProxy {
private class CallbacksForwarder extends ICodecCallbacks.Stub {
private final Callbacks mCallbacks;
private boolean mEndOfInput;
private boolean mCodecProxyReleased;
CallbacksForwarder(Callbacks callbacks) {
mCallbacks = callbacks;
@ -64,25 +65,31 @@ public final class CodecProxy {
@Override
public synchronized void onInputQueued(long timestamp) throws RemoteException {
if (!mEndOfInput) {
if (!mEndOfInput && !mCodecProxyReleased) {
mCallbacks.onInputStatus(timestamp, true /* processed */);
}
}
@Override
public synchronized void onInputPending(long timestamp) throws RemoteException {
if (!mEndOfInput) {
if (!mEndOfInput && !mCodecProxyReleased) {
mCallbacks.onInputStatus(timestamp, false /* processed */);
}
}
@Override
public void onOutputFormatChanged(FormatParam format) throws RemoteException {
mCallbacks.onOutputFormatChanged(format.asFormat());
public synchronized void onOutputFormatChanged(FormatParam format) throws RemoteException {
if (!mCodecProxyReleased) {
mCallbacks.onOutputFormatChanged(format.asFormat());
}
}
@Override
public void onOutput(Sample sample) throws RemoteException {
public synchronized void onOutput(Sample sample) throws RemoteException {
if (mCodecProxyReleased) {
sample.dispose();
return;
}
if (mOutputSurface != null) {
// Don't render to surface just yet. Callback will make that happen when it's time.
mSurfaceOutputs.offer(sample);
@ -100,13 +107,19 @@ public final class CodecProxy {
reportError(fatal);
}
private void reportError(boolean fatal) {
mCallbacks.onError(fatal);
private synchronized void reportError(boolean fatal) {
if (!mCodecProxyReleased) {
mCallbacks.onError(fatal);
}
}
private void setEndOfInput(boolean end) {
mEndOfInput = end;
}
private synchronized void setCodecProxyReleased() {
mCodecProxyReleased = true;
}
}
@WrapForJNI
@ -236,36 +249,39 @@ public final class CodecProxy {
}
@WrapForJNI
public synchronized boolean release() {
if (mRemote == null) {
Log.w(LOGTAG, "codec already ended");
return true;
}
if (DEBUG) { Log.d(LOGTAG, "release " + this); }
public boolean release() {
mCallbacks.setCodecProxyReleased();
synchronized(this) {
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
// should not happen unless caller release codec before processing all buffers.
Log.w(LOGTAG, "release codec when " + mSurfaceOutputs.size() + " output buffers unhandled");
try {
for (Sample s : mSurfaceOutputs) {
mRemote.releaseOutput(s, true);
if (!mSurfaceOutputs.isEmpty()) {
// Flushing output buffers to surface may cause some frames to be skipped and
// should not happen unless caller release codec before processing all buffers.
Log.w(LOGTAG, "release codec when " + mSurfaceOutputs.size() + " output buffers unhandled");
try {
for (Sample s : mSurfaceOutputs) {
mRemote.releaseOutput(s, true);
}
} catch (RemoteException e) {
e.printStackTrace();
}
mSurfaceOutputs.clear();
}
try {
RemoteManager.getInstance().releaseCodec(this);
} catch (DeadObjectException e) {
return false;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
mSurfaceOutputs.clear();
return true;
}
try {
RemoteManager.getInstance().releaseCodec(this);
} catch (DeadObjectException e) {
return false;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
return true;
}
@WrapForJNI