Index: webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java |
diff --git a/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java b/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java |
index 0c47c38c8aae827c6a1d663d5baeffc8bc7f4f62..b726860e8ec7f6337e5b2bbb55b574328c310863 100644 |
--- a/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java |
+++ b/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java |
@@ -454,6 +454,7 @@ public class MediaCodecVideoEncoder { |
this.type = type; |
if (mediaCodec == null) { |
Logging.e(TAG, "Can not create media encoder"); |
+ release(); |
return false; |
} |
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); |
@@ -471,6 +472,7 @@ public class MediaCodecVideoEncoder { |
} catch (IllegalStateException e) { |
Logging.e(TAG, "initEncode failed", e); |
+ release(); |
return false; |
} |
return true; |
@@ -544,36 +546,47 @@ public class MediaCodecVideoEncoder { |
Logging.d(TAG, "Java releaseEncoder"); |
checkOnMediaCodecThread(); |
- // Run Mediacodec stop() and release() on separate thread since sometime |
- // Mediacodec.stop() may hang. |
- final CountDownLatch releaseDone = new CountDownLatch(1); |
+ class CaughtException { |
+ Exception e; |
+ } |
+ final CaughtException caughtException = new CaughtException(); |
+ boolean stopHung = false; |
+ |
+ if (mediaCodec != null) { |
+ // Run Mediacodec stop() and release() on separate thread since sometime |
+ // Mediacodec.stop() may hang. |
+ final CountDownLatch releaseDone = new CountDownLatch(1); |
- Runnable runMediaCodecRelease = new Runnable() { |
- @Override |
- public void run() { |
- try { |
+ Runnable runMediaCodecRelease = new Runnable() { |
+ @Override |
+ public void run() { |
Logging.d(TAG, "Java releaseEncoder on release thread"); |
- mediaCodec.stop(); |
- mediaCodec.release(); |
+ try { |
+ mediaCodec.stop(); |
+ } catch (Exception e) { |
+ Logging.e(TAG, "Media encoder stop failed", e); |
+ } |
+ try { |
+ mediaCodec.release(); |
+ } catch (Exception e) { |
+ Logging.e(TAG, "Media encoder release failed", e); |
+ caughtException.e = e; |
+ } |
Logging.d(TAG, "Java releaseEncoder on release thread done"); |
- } catch (Exception e) { |
- Logging.e(TAG, "Media encoder release failed", e); |
+ |
+ releaseDone.countDown(); |
} |
- releaseDone.countDown(); |
- } |
- }; |
- new Thread(runMediaCodecRelease).start(); |
+ }; |
+ new Thread(runMediaCodecRelease).start(); |
- if (!ThreadUtils.awaitUninterruptibly(releaseDone, MEDIA_CODEC_RELEASE_TIMEOUT_MS)) { |
- Logging.e(TAG, "Media encoder release timeout"); |
- codecErrors++; |
- if (errorCallback != null) { |
- Logging.e(TAG, "Invoke codec error callback. Errors: " + codecErrors); |
- errorCallback.onMediaCodecVideoEncoderCriticalError(codecErrors); |
+ if (!ThreadUtils.awaitUninterruptibly(releaseDone, MEDIA_CODEC_RELEASE_TIMEOUT_MS)) { |
+ Logging.e(TAG, "Media encoder release timeout"); |
+ stopHung = true; |
} |
+ |
+ mediaCodec = null; |
} |
- mediaCodec = null; |
mediaCodecThread = null; |
if (drawer != null) { |
drawer.release(); |
@@ -588,6 +601,25 @@ public class MediaCodecVideoEncoder { |
inputSurface = null; |
} |
runningInstance = null; |
+ |
+ if (stopHung) { |
+ codecErrors++; |
+ if (errorCallback != null) { |
+ Logging.e(TAG, "Invoke codec error callback. Errors: " + codecErrors); |
+ errorCallback.onMediaCodecVideoEncoderCriticalError(codecErrors); |
+ } |
+ throw new RuntimeException("Media encoder release timeout."); |
+ } |
+ |
+ // Re-throw any runtime exception caught inside the other thread. Since this is an invoke, add |
+ // stack trace for the waiting thread as well. |
+ if (caughtException.e != null) { |
+ final RuntimeException runtimeException = new RuntimeException(caughtException.e); |
+ runtimeException.setStackTrace(ThreadUtils.concatStackTraces( |
+ caughtException.e.getStackTrace(), runtimeException.getStackTrace())); |
+ throw runtimeException; |
+ } |
+ |
Logging.d(TAG, "Java releaseEncoder done"); |
} |