- Make shared EGL context used for HW video decoding member
of decoder factory class.
- Add new Peer connection factory method to initialize shared
EGL context.
This provides an option to use single peer connection factory
in the application and create peer connections from the same
factory and reinitialize shared EGL context for video
decoding HW acceleration.
R=wzh@webrtc.org
Review URL: https://codereview.webrtc.org/1304063011 .
Cr-Commit-Position: refs/heads/master@{#9838}
diff --git a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
index 5322177..6fb06d0 100644
--- a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
@@ -61,16 +61,13 @@
namespace webrtc_jni {
-jobject MediaCodecVideoDecoderFactory::render_egl_context_ = NULL;
-
class MediaCodecVideoDecoder : public webrtc::VideoDecoder,
public rtc::MessageHandler {
public:
- explicit MediaCodecVideoDecoder(JNIEnv* jni, VideoCodecType codecType);
+ explicit MediaCodecVideoDecoder(
+ JNIEnv* jni, VideoCodecType codecType, jobject render_egl_context);
virtual ~MediaCodecVideoDecoder();
- static int SetAndroidObjects(JNIEnv* jni, jobject render_egl_context);
-
int32_t InitDecode(const VideoCodec* codecSettings, int32_t numberOfCores)
override;
@@ -158,11 +155,16 @@
std::vector<jobject> input_buffers_;
jobject surface_texture_;
jobject previous_surface_texture_;
+
+ // Render EGL context - owned by factory, should not be allocated/destroyed
+ // by VideoDecoder.
+ jobject render_egl_context_;
};
MediaCodecVideoDecoder::MediaCodecVideoDecoder(
- JNIEnv* jni, VideoCodecType codecType) :
+ JNIEnv* jni, VideoCodecType codecType, jobject render_egl_context) :
codecType_(codecType),
+ render_egl_context_(render_egl_context),
key_frame_required_(true),
inited_(false),
sw_fallback_required_(false),
@@ -233,10 +235,8 @@
jni, j_decoder_output_buffer_info_class, "presentationTimestampUs", "J");
CHECK_EXCEPTION(jni) << "MediaCodecVideoDecoder ctor failed";
- use_surface_ = true;
- if (MediaCodecVideoDecoderFactory::render_egl_context_ == NULL) {
- use_surface_ = false;
- }
+ use_surface_ = (render_egl_context_ != NULL) ? true : false;
+ ALOGD("MediaCodecVideoDecoder ctor. Use surface: %d", use_surface_);
memset(&codec_, 0, sizeof(codec_));
AllowBlockingCalls();
}
@@ -310,7 +310,7 @@
codec_.width,
codec_.height,
use_surface_,
- MediaCodecVideoDecoderFactory::render_egl_context_);
+ render_egl_context_);
if (CheckException(jni) || !success) {
ALOGE("Codec initialization error - fallback to SW codec.");
sw_fallback_required_ = true;
@@ -745,35 +745,9 @@
codec_thread_->PostDelayed(kMediaCodecPollMs, this);
}
-int MediaCodecVideoDecoderFactory::SetAndroidObjects(JNIEnv* jni,
- jobject render_egl_context) {
- ALOGD("SetAndroidObjects for surface decoding.");
- if (render_egl_context_) {
- jni->DeleteGlobalRef(render_egl_context_);
- }
- if (IsNull(jni, render_egl_context)) {
- render_egl_context_ = NULL;
- } else {
- render_egl_context_ = jni->NewGlobalRef(render_egl_context);
- if (CheckException(jni)) {
- ALOGE("error calling NewGlobalRef for EGL Context.");
- render_egl_context_ = NULL;
- } else {
- jclass j_egl_context_class = FindClass(jni, "android/opengl/EGLContext");
- if (!jni->IsInstanceOf(render_egl_context_, j_egl_context_class)) {
- ALOGE("Wrong EGL Context.");
- jni->DeleteGlobalRef(render_egl_context_);
- render_egl_context_ = NULL;
- }
- }
- }
- if (render_egl_context_ == NULL) {
- ALOGD("NULL VideoDecoder EGL context - HW surface decoding is disabled.");
- }
- return 0;
-}
-
-MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() {
+MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() :
+ render_egl_context_(NULL) {
+ ALOGD("MediaCodecVideoDecoderFactory ctor");
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jclass j_decoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoDecoder");
@@ -802,21 +776,55 @@
}
}
-MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {}
+MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {
+ ALOGD("MediaCodecVideoDecoderFactory dtor");
+ if (render_egl_context_) {
+ JNIEnv* jni = AttachCurrentThreadIfNeeded();
+ jni->DeleteGlobalRef(render_egl_context_);
+ render_egl_context_ = NULL;
+ }
+}
+
+void MediaCodecVideoDecoderFactory::SetEGLContext(
+ JNIEnv* jni, jobject render_egl_context) {
+ ALOGD("MediaCodecVideoDecoderFactory::SetEGLContext");
+ if (render_egl_context_) {
+ jni->DeleteGlobalRef(render_egl_context_);
+ render_egl_context_ = NULL;
+ }
+ if (!IsNull(jni, render_egl_context)) {
+ render_egl_context_ = jni->NewGlobalRef(render_egl_context);
+ if (CheckException(jni)) {
+ ALOGE("error calling NewGlobalRef for EGL Context.");
+ render_egl_context_ = NULL;
+ } else {
+ jclass j_egl_context_class = FindClass(jni, "android/opengl/EGLContext");
+ if (!jni->IsInstanceOf(render_egl_context_, j_egl_context_class)) {
+ ALOGE("Wrong EGL Context.");
+ jni->DeleteGlobalRef(render_egl_context_);
+ render_egl_context_ = NULL;
+ }
+ }
+ }
+ if (render_egl_context_ == NULL) {
+ ALOGW("NULL VideoDecoder EGL context - HW surface decoding is disabled.");
+ }
+}
webrtc::VideoDecoder* MediaCodecVideoDecoderFactory::CreateVideoDecoder(
VideoCodecType type) {
if (supported_codec_types_.empty()) {
+ ALOGE("No HW video decoder for type %d.", (int)type);
return NULL;
}
- for (std::vector<VideoCodecType>::const_iterator it =
- supported_codec_types_.begin(); it != supported_codec_types_.end();
- ++it) {
- if (*it == type) {
+ for (VideoCodecType codec_type : supported_codec_types_) {
+ if (codec_type == type) {
ALOGD("Create HW video decoder for type %d.", (int)type);
- return new MediaCodecVideoDecoder(AttachCurrentThreadIfNeeded(), type);
+ return new MediaCodecVideoDecoder(
+ AttachCurrentThreadIfNeeded(), type, render_egl_context_);
}
}
+ ALOGE("Can not find HW video decoder for type %d.", (int)type);
return NULL;
}