Android: Handle SurfaceTextureHelper ctor failure for decoder and capturer

BUG=webrtc:5874
TEST=Manually throw an exception inside the SurfaceTextureHelper ctor and run AppRTCDemo.

Review-Url: https://codereview.webrtc.org/1840193007
Cr-Commit-Position: refs/heads/master@{#12665}
This commit is contained in:
magjed
2016-05-09 08:28:45 -07:00
committed by Commit bot
parent d040480f69
commit 2aa84260d8
6 changed files with 77 additions and 41 deletions

View File

@ -50,7 +50,8 @@ class SurfaceTextureHelper {
/**
* Construct a new SurfaceTextureHelper sharing OpenGL resources with |sharedContext|. A dedicated
* thread and handler is created for handling the SurfaceTexture.
* thread and handler is created for handling the SurfaceTexture. May return null if EGL fails to
* initialize a pixel buffer surface and make it current.
*/
public static SurfaceTextureHelper create(
final String threadName, final EglBase.Context sharedContext) {
@ -65,7 +66,12 @@ class SurfaceTextureHelper {
return ThreadUtils.invokeUninterruptibly(handler, new Callable<SurfaceTextureHelper>() {
@Override
public SurfaceTextureHelper call() {
try {
return new SurfaceTextureHelper(sharedContext, handler);
} catch (RuntimeException e) {
Logging.e(TAG, threadName + " create failure", e);
return null;
}
}
});
}
@ -315,8 +321,16 @@ class SurfaceTextureHelper {
this.handler = handler;
eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_BUFFER);
try {
// Both these statements have been observed to fail on rare occasions, see BUG=webrtc:5682.
eglBase.createDummyPbufferSurface();
eglBase.makeCurrent();
} catch (RuntimeException e) {
// Clean up before rethrowing the exception.
eglBase.release();
handler.getLooper().quit();
throw e;
}
oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
surfaceTexture = new SurfaceTexture(oesTextureId);

View File

@ -369,7 +369,11 @@ public class VideoCapturerAndroid implements
final CapturerObserver frameObserver) {
Logging.d(TAG, "startCapture requested: " + width + "x" + height + "@" + framerate);
if (surfaceTextureHelper == null) {
throw new IllegalArgumentException("surfaceTextureHelper not set.");
frameObserver.onCapturerStarted(false /* success */);
if (eventsHandler != null) {
eventsHandler.onCameraError("No SurfaceTexture created.");
}
return;
}
if (applicationContext == null) {
throw new IllegalArgumentException("applicationContext not set.");

View File

@ -345,8 +345,13 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
ResetVariables();
if (use_surface_) {
surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>(
surface_texture_helper_ = SurfaceTextureHelper::create(
jni, "Decoder SurfaceTextureHelper", render_egl_context_);
if (!surface_texture_helper_) {
ALOGE << "Couldn't create SurfaceTextureHelper - fallback to SW codec";
sw_fallback_required_ = true;
return WEBRTC_VIDEO_CODEC_ERROR;
}
}
jobject j_video_codec_enum = JavaEnumFromIndexAndClassName(

View File

@ -30,18 +30,16 @@ int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni,
return 0;
}
AndroidVideoCapturerJni::AndroidVideoCapturerJni(
JNIEnv* jni,
AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
jobject j_video_capturer,
jobject j_egl_context)
: j_video_capturer_(jni, j_video_capturer),
j_video_capturer_class_(
jni, FindClass(jni, "org/webrtc/VideoCapturer")),
j_video_capturer_class_(jni, FindClass(jni, "org/webrtc/VideoCapturer")),
j_observer_class_(
jni,
FindClass(jni,
"org/webrtc/VideoCapturer$NativeObserver")),
surface_texture_helper_(new rtc::RefCountedObject<SurfaceTextureHelper>(
surface_texture_helper_(SurfaceTextureHelper::create(
jni, "Camera SurfaceTextureHelper", j_egl_context)),
capturer_(nullptr) {
LOG(LS_INFO) << "AndroidVideoCapturerJni ctor";
@ -54,10 +52,12 @@ AndroidVideoCapturerJni::~AndroidVideoCapturerJni() {
*j_video_capturer_,
GetMethodID(jni(), *j_video_capturer_class_, "dispose", "()V"));
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.dispose()";
if (surface_texture_helper_) {
jni()->CallVoidMethod(
surface_texture_helper_->GetJavaSurfaceTextureHelper(),
GetMethodID(jni(), FindClass(jni(), "org/webrtc/SurfaceTextureHelper"),
"dispose", "()V"));
}
CHECK_EXCEPTION(jni()) << "error during SurfaceTextureHelper.dispose()";
}
@ -82,12 +82,12 @@ void AndroidVideoCapturerJni::Start(int width, int height, int framerate,
jni(), *j_video_capturer_class_, "startCapture",
"(IIILorg/webrtc/SurfaceTextureHelper;Landroid/content/Context;"
"Lorg/webrtc/VideoCapturer$CapturerObserver;)V");
jni()->CallVoidMethod(*j_video_capturer_,
m, width, height,
framerate,
surface_texture_helper_->GetJavaSurfaceTextureHelper(),
application_context_,
j_frame_observer);
jni()->CallVoidMethod(
*j_video_capturer_, m, width, height, framerate,
surface_texture_helper_
? surface_texture_helper_->GetJavaSurfaceTextureHelper()
: nullptr,
application_context_, j_frame_observer);
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.startCapture";
}

View File

@ -17,16 +17,28 @@
namespace webrtc_jni {
SurfaceTextureHelper::SurfaceTextureHelper(
JNIEnv* jni, const char* thread_name, jobject j_egl_context)
: j_surface_texture_helper_(jni, jni->CallStaticObjectMethod(
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
GetStaticMethodID(jni,
rtc::scoped_refptr<SurfaceTextureHelper> SurfaceTextureHelper::create(
JNIEnv* jni,
const char* thread_name,
jobject j_egl_context) {
jobject j_surface_texture_helper = jni->CallStaticObjectMethod(
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
GetStaticMethodID(jni, FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
"create",
"(Ljava/lang/String;Lorg/webrtc/EglBase$Context;)"
"Lorg/webrtc/SurfaceTextureHelper;"),
jni->NewStringUTF(thread_name), j_egl_context)),
jni->NewStringUTF(thread_name), j_egl_context);
CHECK_EXCEPTION(jni)
<< "error during initialization of Java SurfaceTextureHelper";
if (IsNull(jni, j_surface_texture_helper))
return nullptr;
return new rtc::RefCountedObject<SurfaceTextureHelper>(
jni, j_surface_texture_helper);
}
SurfaceTextureHelper::SurfaceTextureHelper(JNIEnv* jni,
jobject j_surface_texture_helper)
: j_surface_texture_helper_(jni, j_surface_texture_helper),
j_return_texture_method_(
GetMethodID(jni,
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),

View File

@ -38,9 +38,9 @@ namespace webrtc_jni {
// 4. Call CreateTextureFrame to wrap the Java texture in a VideoFrameBuffer.
class SurfaceTextureHelper : public rtc::RefCountInterface {
public:
SurfaceTextureHelper(JNIEnv* jni,
const char* thread_name,
jobject j_egl_context);
// Might return null if creating the Java SurfaceTextureHelper fails.
static rtc::scoped_refptr<SurfaceTextureHelper> create(
JNIEnv* jni, const char* thread_name, jobject j_egl_context);
jobject GetJavaSurfaceTextureHelper() const;
@ -51,6 +51,7 @@ class SurfaceTextureHelper : public rtc::RefCountInterface {
protected:
~SurfaceTextureHelper();
SurfaceTextureHelper(JNIEnv* jni, jobject j_surface_texture_helper);
private:
// May be called on arbitrary thread.