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
|
* 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(
|
public static SurfaceTextureHelper create(
|
||||||
final String threadName, final EglBase.Context sharedContext) {
|
final String threadName, final EglBase.Context sharedContext) {
|
||||||
@ -65,7 +66,12 @@ class SurfaceTextureHelper {
|
|||||||
return ThreadUtils.invokeUninterruptibly(handler, new Callable<SurfaceTextureHelper>() {
|
return ThreadUtils.invokeUninterruptibly(handler, new Callable<SurfaceTextureHelper>() {
|
||||||
@Override
|
@Override
|
||||||
public SurfaceTextureHelper call() {
|
public SurfaceTextureHelper call() {
|
||||||
return new SurfaceTextureHelper(sharedContext, handler);
|
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;
|
this.handler = handler;
|
||||||
|
|
||||||
eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_BUFFER);
|
eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_BUFFER);
|
||||||
eglBase.createDummyPbufferSurface();
|
try {
|
||||||
eglBase.makeCurrent();
|
// 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);
|
oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
|
||||||
surfaceTexture = new SurfaceTexture(oesTextureId);
|
surfaceTexture = new SurfaceTexture(oesTextureId);
|
||||||
|
|||||||
@ -369,7 +369,11 @@ public class VideoCapturerAndroid implements
|
|||||||
final CapturerObserver frameObserver) {
|
final CapturerObserver frameObserver) {
|
||||||
Logging.d(TAG, "startCapture requested: " + width + "x" + height + "@" + framerate);
|
Logging.d(TAG, "startCapture requested: " + width + "x" + height + "@" + framerate);
|
||||||
if (surfaceTextureHelper == null) {
|
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) {
|
if (applicationContext == null) {
|
||||||
throw new IllegalArgumentException("applicationContext not set.");
|
throw new IllegalArgumentException("applicationContext not set.");
|
||||||
|
|||||||
@ -345,8 +345,13 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
|||||||
ResetVariables();
|
ResetVariables();
|
||||||
|
|
||||||
if (use_surface_) {
|
if (use_surface_) {
|
||||||
surface_texture_helper_ = new rtc::RefCountedObject<SurfaceTextureHelper>(
|
surface_texture_helper_ = SurfaceTextureHelper::create(
|
||||||
jni, "Decoder SurfaceTextureHelper", render_egl_context_);
|
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(
|
jobject j_video_codec_enum = JavaEnumFromIndexAndClassName(
|
||||||
|
|||||||
@ -30,18 +30,16 @@ int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidVideoCapturerJni::AndroidVideoCapturerJni(
|
AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
|
||||||
JNIEnv* jni,
|
jobject j_video_capturer,
|
||||||
jobject j_video_capturer,
|
jobject j_egl_context)
|
||||||
jobject j_egl_context)
|
|
||||||
: j_video_capturer_(jni, j_video_capturer),
|
: j_video_capturer_(jni, j_video_capturer),
|
||||||
j_video_capturer_class_(
|
j_video_capturer_class_(jni, FindClass(jni, "org/webrtc/VideoCapturer")),
|
||||||
jni, FindClass(jni, "org/webrtc/VideoCapturer")),
|
|
||||||
j_observer_class_(
|
j_observer_class_(
|
||||||
jni,
|
jni,
|
||||||
FindClass(jni,
|
FindClass(jni,
|
||||||
"org/webrtc/VideoCapturer$NativeObserver")),
|
"org/webrtc/VideoCapturer$NativeObserver")),
|
||||||
surface_texture_helper_(new rtc::RefCountedObject<SurfaceTextureHelper>(
|
surface_texture_helper_(SurfaceTextureHelper::create(
|
||||||
jni, "Camera SurfaceTextureHelper", j_egl_context)),
|
jni, "Camera SurfaceTextureHelper", j_egl_context)),
|
||||||
capturer_(nullptr) {
|
capturer_(nullptr) {
|
||||||
LOG(LS_INFO) << "AndroidVideoCapturerJni ctor";
|
LOG(LS_INFO) << "AndroidVideoCapturerJni ctor";
|
||||||
@ -54,10 +52,12 @@ AndroidVideoCapturerJni::~AndroidVideoCapturerJni() {
|
|||||||
*j_video_capturer_,
|
*j_video_capturer_,
|
||||||
GetMethodID(jni(), *j_video_capturer_class_, "dispose", "()V"));
|
GetMethodID(jni(), *j_video_capturer_class_, "dispose", "()V"));
|
||||||
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.dispose()";
|
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.dispose()";
|
||||||
jni()->CallVoidMethod(
|
if (surface_texture_helper_) {
|
||||||
surface_texture_helper_->GetJavaSurfaceTextureHelper(),
|
jni()->CallVoidMethod(
|
||||||
GetMethodID(jni(), FindClass(jni(), "org/webrtc/SurfaceTextureHelper"),
|
surface_texture_helper_->GetJavaSurfaceTextureHelper(),
|
||||||
"dispose", "()V"));
|
GetMethodID(jni(), FindClass(jni(), "org/webrtc/SurfaceTextureHelper"),
|
||||||
|
"dispose", "()V"));
|
||||||
|
}
|
||||||
CHECK_EXCEPTION(jni()) << "error during SurfaceTextureHelper.dispose()";
|
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",
|
jni(), *j_video_capturer_class_, "startCapture",
|
||||||
"(IIILorg/webrtc/SurfaceTextureHelper;Landroid/content/Context;"
|
"(IIILorg/webrtc/SurfaceTextureHelper;Landroid/content/Context;"
|
||||||
"Lorg/webrtc/VideoCapturer$CapturerObserver;)V");
|
"Lorg/webrtc/VideoCapturer$CapturerObserver;)V");
|
||||||
jni()->CallVoidMethod(*j_video_capturer_,
|
jni()->CallVoidMethod(
|
||||||
m, width, height,
|
*j_video_capturer_, m, width, height, framerate,
|
||||||
framerate,
|
surface_texture_helper_
|
||||||
surface_texture_helper_->GetJavaSurfaceTextureHelper(),
|
? surface_texture_helper_->GetJavaSurfaceTextureHelper()
|
||||||
application_context_,
|
: nullptr,
|
||||||
j_frame_observer);
|
application_context_, j_frame_observer);
|
||||||
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.startCapture";
|
CHECK_EXCEPTION(jni()) << "error during VideoCapturer.startCapture";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,21 +17,33 @@
|
|||||||
|
|
||||||
namespace webrtc_jni {
|
namespace webrtc_jni {
|
||||||
|
|
||||||
SurfaceTextureHelper::SurfaceTextureHelper(
|
rtc::scoped_refptr<SurfaceTextureHelper> SurfaceTextureHelper::create(
|
||||||
JNIEnv* jni, const char* thread_name, jobject j_egl_context)
|
JNIEnv* jni,
|
||||||
: j_surface_texture_helper_(jni, jni->CallStaticObjectMethod(
|
const char* thread_name,
|
||||||
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
|
jobject j_egl_context) {
|
||||||
GetStaticMethodID(jni,
|
jobject j_surface_texture_helper = jni->CallStaticObjectMethod(
|
||||||
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
|
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
|
||||||
"create",
|
GetStaticMethodID(jni, FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
|
||||||
"(Ljava/lang/String;Lorg/webrtc/EglBase$Context;)"
|
"create",
|
||||||
"Lorg/webrtc/SurfaceTextureHelper;"),
|
"(Ljava/lang/String;Lorg/webrtc/EglBase$Context;)"
|
||||||
jni->NewStringUTF(thread_name), j_egl_context)),
|
"Lorg/webrtc/SurfaceTextureHelper;"),
|
||||||
j_return_texture_method_(
|
jni->NewStringUTF(thread_name), j_egl_context);
|
||||||
GetMethodID(jni,
|
CHECK_EXCEPTION(jni)
|
||||||
FindClass(jni, "org/webrtc/SurfaceTextureHelper"),
|
<< "error during initialization of Java SurfaceTextureHelper";
|
||||||
"returnTextureFrame",
|
if (IsNull(jni, j_surface_texture_helper))
|
||||||
"()V")) {
|
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"),
|
||||||
|
"returnTextureFrame",
|
||||||
|
"()V")) {
|
||||||
CHECK_EXCEPTION(jni) << "error during initialization of SurfaceTextureHelper";
|
CHECK_EXCEPTION(jni) << "error during initialization of SurfaceTextureHelper";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,9 +38,9 @@ namespace webrtc_jni {
|
|||||||
// 4. Call CreateTextureFrame to wrap the Java texture in a VideoFrameBuffer.
|
// 4. Call CreateTextureFrame to wrap the Java texture in a VideoFrameBuffer.
|
||||||
class SurfaceTextureHelper : public rtc::RefCountInterface {
|
class SurfaceTextureHelper : public rtc::RefCountInterface {
|
||||||
public:
|
public:
|
||||||
SurfaceTextureHelper(JNIEnv* jni,
|
// Might return null if creating the Java SurfaceTextureHelper fails.
|
||||||
const char* thread_name,
|
static rtc::scoped_refptr<SurfaceTextureHelper> create(
|
||||||
jobject j_egl_context);
|
JNIEnv* jni, const char* thread_name, jobject j_egl_context);
|
||||||
|
|
||||||
jobject GetJavaSurfaceTextureHelper() const;
|
jobject GetJavaSurfaceTextureHelper() const;
|
||||||
|
|
||||||
@ -51,6 +51,7 @@ class SurfaceTextureHelper : public rtc::RefCountInterface {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
~SurfaceTextureHelper();
|
~SurfaceTextureHelper();
|
||||||
|
SurfaceTextureHelper(JNIEnv* jni, jobject j_surface_texture_helper);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// May be called on arbitrary thread.
|
// May be called on arbitrary thread.
|
||||||
|
|||||||
Reference in New Issue
Block a user