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:
@ -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);
|
||||
|
||||
@ -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.");
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
|
||||
@ -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"),
|
||||
|
||||
@ -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.
|
||||
|
||||
Reference in New Issue
Block a user