- 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}
This commit is contained in:
@ -61,16 +61,13 @@ using webrtc::kVideoCodecVP8;
|
||||
|
||||
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 @@ class MediaCodecVideoDecoder : public webrtc::VideoDecoder,
|
||||
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 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(
|
||||
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 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
||||
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 @@ void MediaCodecVideoDecoder::OnMessage(rtc::Message* msg) {
|
||||
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() {}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user