Injectable software codecs for Android.

This is similar to https://webrtc-review.googlesource.com/c/src/+/3620
for iOS.

Using the new WebRtcMediaEngineFactory::Create API, the built-in
software video codecs are no longer appended to the injected codecs.

To be able to use the software codecs, they are exposed as Java
classes through SoftwareVideoEncoderFactory etc.

There is also a new DefaultVideoEncoderFactory used by AppRTCMobile.
This factory tries to use hardware implementations where available,
but falls back to using the injected software codecs.

The HardwareVideoEncoderFactory is temporarily also falling back on
the software codecs in its default configuration in order to
maintain backwards compatibility.

Bug: webrtc:7925
Change-Id: I3e8c5ed492ccd160aca968986ad217d7978a951c
Reviewed-on: https://webrtc-review.googlesource.com/17480
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Commit-Queue: Anders Carlsson <andersc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20647}
This commit is contained in:
Anders Carlsson
2017-11-10 13:15:04 +01:00
committed by Commit Bot
parent 45bbc8ac19
commit dc1b9f179a
39 changed files with 1171 additions and 170 deletions

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
class VP8Decoder extends WrappedNativeVideoDecoder {
VP8Decoder() {
super(createNativeDecoder());
}
private static native long createNativeDecoder();
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
class VP8Encoder extends WrappedNativeVideoEncoder {
VP8Encoder() {
super(createNativeEncoder());
}
private static native long createNativeEncoder();
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
class VP9Decoder extends WrappedNativeVideoDecoder {
VP9Decoder() {
super(createNativeDecoder());
}
private static native long createNativeDecoder();
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
class VP9Encoder extends WrappedNativeVideoEncoder {
VP9Encoder() {
super(createNativeEncoder());
}
private static native long createNativeEncoder();
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
/**
* Wraps a native webrtc::VideoDecoder.
*/
class WrappedNativeVideoDecoder implements VideoDecoder {
private final long nativeDecoder;
WrappedNativeVideoDecoder(long nativeDecoder) {
this.nativeDecoder = nativeDecoder;
}
@CalledByNative
public long getNativeDecoder() {
return this.nativeDecoder;
}
@Override
public VideoCodecStatus initDecode(Settings settings, Callback decodeCallback) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus release() {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus decode(EncodedImage frame, DecodeInfo info) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public boolean getPrefersLateDecoding() {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public String getImplementationName() {
throw new UnsupportedOperationException("Not implemented.");
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
/**
* Wraps a native webrtc::VideoEncoder.
*/
class WrappedNativeVideoEncoder implements VideoEncoder {
private final long nativeEncoder;
WrappedNativeVideoEncoder(long nativeEncoder) {
this.nativeEncoder = nativeEncoder;
}
@CalledByNative
public long getNativeEncoder() {
return this.nativeEncoder;
}
@Override
public VideoCodecStatus initEncode(Settings settings, Callback encodeCallback) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus release() {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus encode(VideoFrame frame, EncodeInfo info) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus setChannelParameters(short packetLoss, long roundTripTimeMs) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public VideoCodecStatus setRateAllocation(BitrateAllocation allocation, int framerate) {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public ScalingSettings getScalingSettings() {
throw new UnsupportedOperationException("Not implemented.");
}
@Override
public String getImplementationName() {
throw new UnsupportedOperationException("Not implemented.");
}
}

View File

@ -5,6 +5,7 @@ include_rules = [
"+logging/rtc_event_log/rtc_event_log_factory_interface.h",
"+media/base",
"+media/engine",
"+modules/audio_device/include/audio_device.h",
"+modules/audio_processing/include/audio_processing.h",
"+modules/include",
"+modules/utility/include/jvm_android.h",

View File

@ -0,0 +1,54 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <jni.h>
#include "media/base/codec.h"
#include "media/base/h264_profile_level_id.h"
#include "media/base/mediaconstants.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/videocodecinfo.h"
namespace webrtc {
namespace jni {
static bool IsSameH264Profile(const cricket::CodecParameterMap& params1,
const cricket::CodecParameterMap& params2) {
const rtc::Optional<H264::ProfileLevelId> profile_level_id =
H264::ParseSdpProfileLevelId(params1);
const rtc::Optional<H264::ProfileLevelId> other_profile_level_id =
H264::ParseSdpProfileLevelId(params2);
// Compare H264 profiles, but not levels.
return profile_level_id && other_profile_level_id &&
profile_level_id->profile == other_profile_level_id->profile;
}
JNI_FUNCTION_DECLARATION(jboolean,
DefaultVideoEncoderFactory_isSameCodec,
JNIEnv* jni,
jclass,
jobject info1,
jobject info2) {
cricket::VideoCodec codec1 =
cricket::VideoCodec(VideoCodecInfoToSdpVideoFormat(jni, info1));
cricket::VideoCodec codec2 =
cricket::VideoCodec(VideoCodecInfoToSdpVideoFormat(jni, info2));
if (!cricket::CodecNamesEq(codec1.name, codec2.name))
return false;
if (cricket::CodecNamesEq(codec1.name.c_str(), cricket::kH264CodecName) &&
!IsSameH264Profile(codec1.params, codec2.params)) {
return false;
}
return true;
}
} // namespace jni
} // namespace webrtc

View File

@ -9,9 +9,12 @@
*/
#include "sdk/android/src/jni/pc/media_jni.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "call/callfactoryinterface.h"
#include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
#include "media/engine/webrtcmediaengine.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_processing/include/audio_processing.h"
namespace webrtc {
@ -38,5 +41,20 @@ cricket::MediaEngineInterface* CreateMediaEngine(
video_decoder_factory, audio_mixer, audio_processor);
}
cricket::MediaEngineInterface* CreateMediaEngine(
rtc::scoped_refptr<AudioDeviceModule> adm,
rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
rtc::scoped_refptr<AudioMixer> audio_mixer,
rtc::scoped_refptr<AudioProcessing> audio_processor) {
return cricket::WebRtcMediaEngineFactory::Create(
adm, audio_encoder_factory, audio_decoder_factory,
std::move(video_encoder_factory), std::move(video_decoder_factory),
audio_mixer, audio_processor)
.release();
}
} // namespace jni
} // namespace webrtc

View File

@ -21,6 +21,8 @@ class AudioDecoderFactory;
class RtcEventLogFactoryInterface;
class AudioMixer;
class AudioProcessing;
class VideoEncoderFactory;
class VideoDecoderFactory;
} // namespace webrtc
namespace cricket {
@ -44,6 +46,15 @@ cricket::MediaEngineInterface* CreateMediaEngine(
rtc::scoped_refptr<AudioMixer> audio_mixer,
rtc::scoped_refptr<AudioProcessing> audio_processor);
cricket::MediaEngineInterface* CreateMediaEngine(
rtc::scoped_refptr<AudioDeviceModule> adm,
rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
rtc::scoped_refptr<AudioMixer> audio_mixer,
rtc::scoped_refptr<AudioProcessing> audio_processor);
} // namespace jni
} // namespace webrtc

View File

@ -32,5 +32,16 @@ cricket::MediaEngineInterface* CreateMediaEngine(
return nullptr;
}
cricket::MediaEngineInterface* CreateMediaEngine(
rtc::scoped_refptr<AudioDeviceModule> adm,
rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
rtc::scoped_refptr<AudioMixer> audio_mixer,
rtc::scoped_refptr<AudioProcessing> audio_processor) {
return nullptr;
}
} // namespace jni
} // namespace webrtc

View File

@ -13,15 +13,31 @@
namespace webrtc {
namespace jni {
cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
JNIEnv* jni,
jobject j_encoder_factory) {
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
jobject j_encoder_factory) {
return nullptr;
}
cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
JNIEnv* jni,
jobject j_decoder_factory) {
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
jobject j_decoder_factory) {
return nullptr;
}
cricket::WebRtcVideoEncoderFactory* CreateLegacyVideoEncoderFactory() {
return nullptr;
}
cricket::WebRtcVideoDecoderFactory* CreateLegacyVideoDecoderFactory() {
return nullptr;
}
VideoEncoderFactory* WrapLegacyVideoEncoderFactory(
cricket::WebRtcVideoEncoderFactory* legacy_encoder_factory) {
return nullptr;
}
VideoDecoderFactory* WrapLegacyVideoDecoderFactory(
cricket::WebRtcVideoDecoderFactory* legacy_decoder_factory) {
return nullptr;
}

View File

@ -38,15 +38,15 @@ class OwnedFactoryAndThreads {
OwnedFactoryAndThreads(std::unique_ptr<Thread> network_thread,
std::unique_ptr<Thread> worker_thread,
std::unique_ptr<Thread> signaling_thread,
WebRtcVideoEncoderFactory* encoder_factory,
WebRtcVideoDecoderFactory* decoder_factory,
WebRtcVideoEncoderFactory* legacy_encoder_factory,
WebRtcVideoDecoderFactory* legacy_decoder_factory,
rtc::NetworkMonitorFactory* network_monitor_factory,
PeerConnectionFactoryInterface* factory)
: network_thread_(std::move(network_thread)),
worker_thread_(std::move(worker_thread)),
signaling_thread_(std::move(signaling_thread)),
encoder_factory_(encoder_factory),
decoder_factory_(decoder_factory),
legacy_encoder_factory_(legacy_encoder_factory),
legacy_decoder_factory_(legacy_decoder_factory),
network_monitor_factory_(network_monitor_factory),
factory_(factory) {}
@ -55,8 +55,12 @@ class OwnedFactoryAndThreads {
PeerConnectionFactoryInterface* factory() { return factory_; }
Thread* signaling_thread() { return signaling_thread_.get(); }
Thread* worker_thread() { return worker_thread_.get(); }
WebRtcVideoEncoderFactory* encoder_factory() { return encoder_factory_; }
WebRtcVideoDecoderFactory* decoder_factory() { return decoder_factory_; }
WebRtcVideoEncoderFactory* legacy_encoder_factory() {
return legacy_encoder_factory_;
}
WebRtcVideoDecoderFactory* legacy_decoder_factory() {
return legacy_decoder_factory_;
}
rtc::NetworkMonitorFactory* network_monitor_factory() {
return network_monitor_factory_;
}
@ -69,8 +73,8 @@ class OwnedFactoryAndThreads {
const std::unique_ptr<Thread> network_thread_;
const std::unique_ptr<Thread> worker_thread_;
const std::unique_ptr<Thread> signaling_thread_;
WebRtcVideoEncoderFactory* encoder_factory_;
WebRtcVideoDecoderFactory* decoder_factory_;
WebRtcVideoEncoderFactory* legacy_encoder_factory_;
WebRtcVideoDecoderFactory* legacy_decoder_factory_;
rtc::NetworkMonitorFactory* network_monitor_factory_;
PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
};

View File

@ -12,7 +12,10 @@
#include <utility>
#include "api/peerconnectioninterface.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "media/base/mediaengine.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/utility/include/jvm_android.h"
// We don't depend on the audio processing module implementation.
// The user may pass in a nullptr.
@ -161,8 +164,6 @@ jlong CreatePeerConnectionFactoryForJava(
signaling_thread->SetName("signaling_thread", NULL);
RTC_CHECK(signaling_thread->Start()) << "Failed to start thread";
cricket::WebRtcVideoEncoderFactory* video_encoder_factory = nullptr;
cricket::WebRtcVideoDecoderFactory* video_decoder_factory = nullptr;
rtc::NetworkMonitorFactory* network_monitor_factory = nullptr;
auto audio_encoder_factory = CreateAudioEncoderFactory();
auto audio_decoder_factory = CreateAudioDecoderFactory();
@ -173,10 +174,6 @@ jlong CreatePeerConnectionFactoryForJava(
options = JavaToNativePeerConnectionFactoryOptions(jni, joptions);
}
if (video_hw_acceleration_enabled) {
video_encoder_factory = CreateVideoEncoderFactory(jni, jencoder_factory);
video_decoder_factory = CreateVideoDecoderFactory(jni, jdecoder_factory);
}
// Do not create network_monitor_factory only if the options are
// provided and disable_network_monitor therein is set to true.
if (!(has_options && options.disable_network_monitor)) {
@ -189,9 +186,49 @@ jlong CreatePeerConnectionFactoryForJava(
std::unique_ptr<CallFactoryInterface> call_factory(CreateCallFactory());
std::unique_ptr<RtcEventLogFactoryInterface> rtc_event_log_factory(
CreateRtcEventLogFactory());
std::unique_ptr<cricket::MediaEngineInterface> media_engine(CreateMediaEngine(
adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
video_decoder_factory, audio_mixer, audio_processor));
cricket::WebRtcVideoEncoderFactory* legacy_video_encoder_factory = nullptr;
cricket::WebRtcVideoDecoderFactory* legacy_video_decoder_factory = nullptr;
std::unique_ptr<cricket::MediaEngineInterface> media_engine;
if (jencoder_factory == nullptr && jdecoder_factory == nullptr) {
// This uses the legacy API, which automatically uses the internal SW
// codecs in WebRTC.
if (video_hw_acceleration_enabled) {
legacy_video_encoder_factory = CreateLegacyVideoEncoderFactory();
legacy_video_decoder_factory = CreateLegacyVideoDecoderFactory();
}
media_engine.reset(CreateMediaEngine(
adm, audio_encoder_factory, audio_decoder_factory,
legacy_video_encoder_factory, legacy_video_decoder_factory, audio_mixer,
audio_processor));
} else {
// This uses the new API, does not automatically include software codecs.
std::unique_ptr<VideoEncoderFactory> video_encoder_factory = nullptr;
if (jencoder_factory == nullptr) {
legacy_video_encoder_factory = CreateLegacyVideoEncoderFactory();
video_encoder_factory = std::unique_ptr<VideoEncoderFactory>(
WrapLegacyVideoEncoderFactory(legacy_video_encoder_factory));
} else {
video_encoder_factory = std::unique_ptr<VideoEncoderFactory>(
CreateVideoEncoderFactory(jni, jencoder_factory));
}
std::unique_ptr<VideoDecoderFactory> video_decoder_factory = nullptr;
if (jdecoder_factory == nullptr) {
legacy_video_decoder_factory = CreateLegacyVideoDecoderFactory();
video_decoder_factory = std::unique_ptr<VideoDecoderFactory>(
WrapLegacyVideoDecoderFactory(legacy_video_decoder_factory));
} else {
video_decoder_factory = std::unique_ptr<VideoDecoderFactory>(
CreateVideoDecoderFactory(jni, jdecoder_factory));
}
rtc::scoped_refptr<AudioDeviceModule> adm_scoped = nullptr;
media_engine.reset(CreateMediaEngine(
adm_scoped, audio_encoder_factory, audio_decoder_factory,
std::move(video_encoder_factory), std::move(video_decoder_factory),
audio_mixer, audio_processor));
}
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
CreateModularPeerConnectionFactory(
@ -207,8 +244,8 @@ jlong CreatePeerConnectionFactoryForJava(
}
OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
std::move(network_thread), std::move(worker_thread),
std::move(signaling_thread), video_encoder_factory, video_decoder_factory,
network_monitor_factory, factory.release());
std::move(signaling_thread), legacy_video_encoder_factory,
legacy_video_decoder_factory, network_monitor_factory, factory.release());
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
return jlongFromPointer(owned_factory);
}

View File

@ -10,7 +10,10 @@
#include <jni.h>
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "api/videosourceproxy.h"
#include "media/engine/convert_legacy_video_factory.h"
#include "media/engine/webrtcvideodecoderfactory.h"
#include "media/engine/webrtcvideoencoderfactory.h"
#include "rtc_base/logging.h"
@ -26,35 +29,38 @@
namespace webrtc {
namespace jni {
// TODO(sakal): Remove this once MediaCodecVideoDecoder/Encoder are no longer
// used and all applications inject their own codecs.
// This is semi broken if someone wants to create multiple peerconnection
// factories.
static bool use_media_codec_encoder_factory;
static bool use_media_codec_decoder_factory;
cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
JNIEnv* jni,
jobject j_encoder_factory) {
use_media_codec_encoder_factory = j_encoder_factory == nullptr;
if (use_media_codec_encoder_factory) {
return new MediaCodecVideoEncoderFactory();
} else {
return new VideoEncoderFactoryWrapper(jni, j_encoder_factory);
}
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
jobject j_encoder_factory) {
return new VideoEncoderFactoryWrapper(jni, j_encoder_factory);
}
cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
JNIEnv* jni,
jobject j_decoder_factory) {
use_media_codec_decoder_factory = j_decoder_factory == nullptr;
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
jobject j_decoder_factory) {
return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
}
if (use_media_codec_decoder_factory) {
return new MediaCodecVideoDecoderFactory();
} else {
return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
}
cricket::WebRtcVideoEncoderFactory* CreateLegacyVideoEncoderFactory() {
return new MediaCodecVideoEncoderFactory();
}
cricket::WebRtcVideoDecoderFactory* CreateLegacyVideoDecoderFactory() {
return new MediaCodecVideoDecoderFactory();
}
VideoEncoderFactory* WrapLegacyVideoEncoderFactory(
cricket::WebRtcVideoEncoderFactory* legacy_encoder_factory) {
return ConvertVideoEncoderFactory(
std::unique_ptr<cricket::WebRtcVideoEncoderFactory>(
legacy_encoder_factory))
.release();
}
VideoDecoderFactory* WrapLegacyVideoDecoderFactory(
cricket::WebRtcVideoDecoderFactory* legacy_decoder_factory) {
return ConvertVideoDecoderFactory(
std::unique_ptr<cricket::WebRtcVideoDecoderFactory>(
legacy_decoder_factory))
.release();
}
jobject GetJavaSurfaceTextureHelper(
@ -114,21 +120,25 @@ JNI_FUNCTION_DECLARATION(
jclass j_eglbase14_context_class =
FindClass(jni, "org/webrtc/EglBase14$Context");
MediaCodecVideoEncoderFactory* encoder_factory =
static_cast<MediaCodecVideoEncoderFactory*>(
owned_factory->encoder_factory());
if (use_media_codec_encoder_factory && encoder_factory &&
jni->IsInstanceOf(local_egl_context, j_eglbase14_context_class)) {
RTC_LOG(LS_INFO) << "Set EGL context for HW encoding.";
encoder_factory->SetEGLContext(jni, local_egl_context);
if (owned_factory->legacy_encoder_factory()) {
MediaCodecVideoEncoderFactory* encoder_factory =
static_cast<MediaCodecVideoEncoderFactory*>(
owned_factory->legacy_encoder_factory());
if (encoder_factory &&
jni->IsInstanceOf(local_egl_context, j_eglbase14_context_class)) {
RTC_LOG(LS_INFO) << "Set EGL context for HW encoding.";
encoder_factory->SetEGLContext(jni, local_egl_context);
}
}
MediaCodecVideoDecoderFactory* decoder_factory =
static_cast<MediaCodecVideoDecoderFactory*>(
owned_factory->decoder_factory());
if (use_media_codec_decoder_factory && decoder_factory) {
RTC_LOG(LS_INFO) << "Set EGL context for HW decoding.";
decoder_factory->SetEGLContext(jni, remote_egl_context);
if (owned_factory->legacy_decoder_factory()) {
MediaCodecVideoDecoderFactory* decoder_factory =
static_cast<MediaCodecVideoDecoderFactory*>(
owned_factory->legacy_decoder_factory());
if (decoder_factory) {
RTC_LOG(LS_INFO) << "Set EGL context for HW decoding.";
decoder_factory->SetEGLContext(jni, remote_egl_context);
}
}
}

View File

@ -20,18 +20,29 @@ class WebRtcVideoEncoderFactory;
class WebRtcVideoDecoderFactory;
} // namespace cricket
namespace webrtc {
class VideoEncoderFactory;
class VideoDecoderFactory;
} // namespace webrtc
namespace webrtc {
namespace jni {
class SurfaceTextureHelper;
cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
JNIEnv* jni,
jobject j_encoder_factory);
VideoEncoderFactory* CreateVideoEncoderFactory(JNIEnv* jni,
jobject j_encoder_factory);
cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
JNIEnv* jni,
jobject j_decoder_factory);
VideoDecoderFactory* CreateVideoDecoderFactory(JNIEnv* jni,
jobject j_decoder_factory);
cricket::WebRtcVideoEncoderFactory* CreateLegacyVideoEncoderFactory();
cricket::WebRtcVideoDecoderFactory* CreateLegacyVideoDecoderFactory();
VideoEncoderFactory* WrapLegacyVideoEncoderFactory(
cricket::WebRtcVideoEncoderFactory* legacy_encoder_factory);
VideoDecoderFactory* WrapLegacyVideoDecoderFactory(
cricket::WebRtcVideoDecoderFactory* legacy_decoder_factory);
jobject GetJavaSurfaceTextureHelper(
const rtc::scoped_refptr<SurfaceTextureHelper>& surface_texture_helper);

View File

@ -0,0 +1,57 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sdk/android/src/jni/videocodecinfo.h"
#include "sdk/android/src/jni/classreferenceholder.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni, jobject j_info) {
jclass video_codec_info_class = FindClass(jni, "org/webrtc/VideoCodecInfo");
jfieldID name_field =
GetFieldID(jni, video_codec_info_class, "name", "Ljava/lang/String;");
jfieldID params_field =
GetFieldID(jni, video_codec_info_class, "params", "Ljava/util/Map;");
jobject j_params = jni->GetObjectField(j_info, params_field);
jstring j_name =
static_cast<jstring>(jni->GetObjectField(j_info, name_field));
return SdpVideoFormat(JavaToStdString(jni, j_name),
JavaToStdMapStrings(jni, j_params));
}
jobject SdpVideoFormatToVideoCodecInfo(JNIEnv* jni,
const SdpVideoFormat& format) {
jclass hash_map_class = jni->FindClass("java/util/HashMap");
jmethodID hash_map_constructor =
jni->GetMethodID(hash_map_class, "<init>", "()V");
jmethodID put_method = jni->GetMethodID(
hash_map_class, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jclass video_codec_info_class = FindClass(jni, "org/webrtc/VideoCodecInfo");
jmethodID video_codec_info_constructor = jni->GetMethodID(
video_codec_info_class, "<init>", "(Ljava/lang/String;Ljava/util/Map;)V");
jobject j_params = jni->NewObject(hash_map_class, hash_map_constructor);
for (auto const& param : format.parameters) {
jni->CallObjectMethod(j_params, put_method,
JavaStringFromStdString(jni, param.first),
JavaStringFromStdString(jni, param.second));
}
return jni->NewObject(video_codec_info_class, video_codec_info_constructor,
JavaStringFromStdString(jni, format.name), j_params);
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,28 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_ANDROID_SRC_JNI_VIDEOCODECINFO_H_
#define SDK_ANDROID_SRC_JNI_VIDEOCODECINFO_H_
#include <jni.h>
#include "api/video_codecs/sdp_video_format.h"
namespace webrtc {
namespace jni {
SdpVideoFormat VideoCodecInfoToSdpVideoFormat(JNIEnv* jni, jobject info);
jobject SdpVideoFormatToVideoCodecInfo(JNIEnv* jni,
const SdpVideoFormat& format);
} // namespace jni
} // namespace webrtc
#endif // SDK_ANDROID_SRC_JNI_VIDEOCODECINFO_H_

View File

@ -10,10 +10,11 @@
#include "sdk/android/src/jni/videodecoderfactorywrapper.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h"
#include "common_types.h" // NOLINT(build/include)
#include "rtc_base/logging.h"
#include "sdk/android/src/jni/videodecoderwrapper.h"
#include "sdk/android/src/jni/wrappednativecodec.h"
namespace webrtc {
namespace jni {
@ -27,19 +28,20 @@ VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper(JNIEnv* jni,
"(Ljava/lang/String;)Lorg/webrtc/VideoDecoder;");
}
VideoDecoder* VideoDecoderFactoryWrapper::CreateVideoDecoderWithParams(
const cricket::VideoCodec& codec,
cricket::VideoDecoderParams params) {
std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::CreateVideoDecoder(
const SdpVideoFormat& format) {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jstring name = JavaStringFromStdString(jni, codec.name);
jstring name = JavaStringFromStdString(jni, format.name);
jobject decoder =
jni->CallObjectMethod(*decoder_factory_, create_decoder_method_, name);
return decoder != nullptr ? new VideoDecoderWrapper(jni, decoder) : nullptr;
return decoder != nullptr ? WrapOrUnwrapVideoDecoder(jni, decoder) : nullptr;
}
void VideoDecoderFactoryWrapper::DestroyVideoDecoder(VideoDecoder* decoder) {
delete decoder;
std::vector<SdpVideoFormat> VideoDecoderFactoryWrapper::GetSupportedFormats()
const {
// TODO(andersc): VideoDecoderFactory.java does not have this method.
return std::vector<SdpVideoFormat>();
}
} // namespace jni

View File

@ -13,7 +13,7 @@
#include <jni.h>
#include "media/engine/webrtcvideodecoderfactory.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
@ -21,16 +21,13 @@ namespace jni {
// Wrapper for Java VideoDecoderFactory class. Delegates method calls through
// JNI and wraps the decoder inside VideoDecoderWrapper.
class VideoDecoderFactoryWrapper : public cricket::WebRtcVideoDecoderFactory {
class VideoDecoderFactoryWrapper : public VideoDecoderFactory {
public:
VideoDecoderFactoryWrapper(JNIEnv* jni, jobject decoder_factory);
// Caller takes the ownership of the returned object and it should be released
// by calling DestroyVideoDecoder().
VideoDecoder* CreateVideoDecoderWithParams(
const cricket::VideoCodec& codec,
cricket::VideoDecoderParams params) override;
void DestroyVideoDecoder(VideoDecoder* decoder) override;
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
const SdpVideoFormat& format) override;
private:
const ScopedGlobalRef<jobject> decoder_factory_;

View File

@ -0,0 +1,39 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <jni.h>
#include "media/engine/videodecodersoftwarefallbackwrapper.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/wrappednativecodec.h"
namespace webrtc {
namespace jni {
JNI_FUNCTION_DECLARATION(jlong,
VideoDecoderFallback_createNativeDecoder,
JNIEnv* jni,
jclass,
jobject j_fallback_decoder,
jobject j_primary_decoder) {
std::unique_ptr<VideoDecoder> fallback_decoder =
WrapOrUnwrapVideoDecoder(jni, j_fallback_decoder);
std::unique_ptr<VideoDecoder> primary_decoder =
WrapOrUnwrapVideoDecoder(jni, j_primary_decoder);
VideoDecoderSoftwareFallbackWrapper* nativeWrapper =
new VideoDecoderSoftwareFallbackWrapper(std::move(fallback_decoder),
std::move(primary_decoder));
return jlongFromPointer(nativeWrapper);
}
} // namespace jni
} // namespace webrtc

View File

@ -13,17 +13,16 @@
#include "api/video_codecs/video_encoder.h"
#include "common_types.h" // NOLINT(build/include)
#include "rtc_base/logging.h"
#include "sdk/android/src/jni/classreferenceholder.h"
#include "sdk/android/src/jni/videoencoderwrapper.h"
#include "sdk/android/src/jni/class_loader.h"
#include "sdk/android/src/jni/videocodecinfo.h"
#include "sdk/android/src/jni/wrappednativecodec.h"
namespace webrtc {
namespace jni {
VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni,
jobject encoder_factory)
: video_codec_info_class_(jni, FindClass(jni, "org/webrtc/VideoCodecInfo")),
hash_map_class_(jni, jni->FindClass("java/util/HashMap")),
encoder_factory_(jni, encoder_factory) {
: encoder_factory_(jni, encoder_factory) {
jclass encoder_factory_class = jni->GetObjectClass(*encoder_factory_);
create_encoder_method_ = jni->GetMethodID(
encoder_factory_class, "createEncoder",
@ -32,71 +31,53 @@ VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper(JNIEnv* jni,
jni->GetMethodID(encoder_factory_class, "getSupportedCodecs",
"()[Lorg/webrtc/VideoCodecInfo;");
video_codec_info_constructor_ =
jni->GetMethodID(*video_codec_info_class_, "<init>",
"(ILjava/lang/String;Ljava/util/Map;)V");
payload_field_ = jni->GetFieldID(*video_codec_info_class_, "payload", "I");
name_field_ =
jni->GetFieldID(*video_codec_info_class_, "name", "Ljava/lang/String;");
params_field_ =
jni->GetFieldID(*video_codec_info_class_, "params", "Ljava/util/Map;");
hash_map_constructor_ = jni->GetMethodID(*hash_map_class_, "<init>", "()V");
put_method_ = jni->GetMethodID(
*hash_map_class_, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
supported_codecs_ = GetSupportedCodecs(jni);
supported_formats_ = GetSupportedFormats(jni);
}
VideoEncoder* VideoEncoderFactoryWrapper::CreateVideoEncoder(
const cricket::VideoCodec& codec) {
std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder(
const SdpVideoFormat& format) {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jobject j_codec_info = ToJavaCodecInfo(jni, codec);
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
jobject encoder = jni->CallObjectMethod(*encoder_factory_,
create_encoder_method_, j_codec_info);
return encoder != nullptr ? new VideoEncoderWrapper(jni, encoder) : nullptr;
return encoder != nullptr ? WrapOrUnwrapVideoEncoder(jni, encoder) : nullptr;
}
jobject VideoEncoderFactoryWrapper::ToJavaCodecInfo(
JNIEnv* jni,
const cricket::VideoCodec& codec) {
jobject j_params = jni->NewObject(*hash_map_class_, hash_map_constructor_);
for (auto const& param : codec.params) {
jni->CallObjectMethod(j_params, put_method_,
JavaStringFromStdString(jni, param.first),
JavaStringFromStdString(jni, param.second));
}
return jni->NewObject(*video_codec_info_class_, video_codec_info_constructor_,
codec.id, JavaStringFromStdString(jni, codec.name),
j_params);
VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder(
const SdpVideoFormat& format) const {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jobject j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format);
jobject encoder = jni->CallObjectMethod(*encoder_factory_,
create_encoder_method_, j_codec_info);
jclass wrapped_native_encoder_class =
GetClass(jni, "org/webrtc/WrappedNativeVideoEncoder");
CodecInfo codec_info;
// Check if this is a wrapped native software encoder implementation.
codec_info.is_hardware_accelerated =
!jni->IsInstanceOf(encoder, wrapped_native_encoder_class);
codec_info.has_internal_source = false;
return codec_info;
}
std::vector<cricket::VideoCodec> VideoEncoderFactoryWrapper::GetSupportedCodecs(
std::vector<SdpVideoFormat> VideoEncoderFactoryWrapper::GetSupportedFormats(
JNIEnv* jni) const {
const jobjectArray j_supported_codecs = static_cast<jobjectArray>(
jni->CallObjectMethod(*encoder_factory_, get_supported_codecs_method_));
const jsize supported_codecs_count = jni->GetArrayLength(j_supported_codecs);
std::vector<cricket::VideoCodec> supported_codecs;
supported_codecs.resize(supported_codecs_count);
std::vector<SdpVideoFormat> supported_formats;
for (jsize i = 0; i < supported_codecs_count; i++) {
jobject j_supported_codec =
jni->GetObjectArrayElement(j_supported_codecs, i);
int payload = jni->GetIntField(j_supported_codec, payload_field_);
jobject j_params = jni->GetObjectField(j_supported_codec, params_field_);
jstring j_name = static_cast<jstring>(
jni->GetObjectField(j_supported_codec, name_field_));
supported_codecs[i] =
cricket::VideoCodec(payload, JavaToStdString(jni, j_name));
supported_codecs[i].params = JavaToStdMapStrings(jni, j_params);
supported_formats.push_back(
VideoCodecInfoToSdpVideoFormat(jni, j_supported_codec));
}
return supported_codecs;
}
void VideoEncoderFactoryWrapper::DestroyVideoEncoder(VideoEncoder* encoder) {
delete encoder;
return supported_formats;
}
} // namespace jni

View File

@ -14,7 +14,8 @@
#include <jni.h>
#include <vector>
#include "media/engine/webrtcvideoencoderfactory.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
@ -22,41 +23,29 @@ namespace jni {
// Wrapper for Java VideoEncoderFactory class. Delegates method calls through
// JNI and wraps the encoder inside VideoEncoderWrapper.
class VideoEncoderFactoryWrapper : public cricket::WebRtcVideoEncoderFactory {
class VideoEncoderFactoryWrapper : public VideoEncoderFactory {
public:
VideoEncoderFactoryWrapper(JNIEnv* jni, jobject encoder_factory);
// Caller takes the ownership of the returned object and it should be released
// by calling DestroyVideoEncoder().
VideoEncoder* CreateVideoEncoder(const cricket::VideoCodec& codec) override;
std::unique_ptr<VideoEncoder> CreateVideoEncoder(
const SdpVideoFormat& format) override;
// Returns a list of supported codecs in order of preference.
const std::vector<cricket::VideoCodec>& supported_codecs() const override {
return supported_codecs_;
std::vector<SdpVideoFormat> GetSupportedFormats() const override {
return supported_formats_;
}
void DestroyVideoEncoder(VideoEncoder* encoder) override;
CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
private:
std::vector<cricket::VideoCodec> GetSupportedCodecs(JNIEnv* jni) const;
jobject ToJavaCodecInfo(JNIEnv* jni, const cricket::VideoCodec& codec);
std::vector<SdpVideoFormat> GetSupportedFormats(JNIEnv* jni) const;
const ScopedGlobalRef<jclass> video_codec_info_class_;
const ScopedGlobalRef<jclass> hash_map_class_;
const ScopedGlobalRef<jobject> encoder_factory_;
jmethodID create_encoder_method_;
jmethodID get_supported_codecs_method_;
jmethodID video_codec_info_constructor_;
jfieldID payload_field_;
jfieldID name_field_;
jfieldID params_field_;
jmethodID hash_map_constructor_;
jmethodID put_method_;
std::vector<cricket::VideoCodec> supported_codecs_;
std::vector<SdpVideoFormat> supported_formats_;
};
} // namespace jni

View File

@ -0,0 +1,34 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <jni.h>
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
JNI_FUNCTION_DECLARATION(jlong,
VP8Encoder_createNativeEncoder,
JNIEnv* jni,
jclass) {
return jlongFromPointer(VP8Encoder::Create());
}
JNI_FUNCTION_DECLARATION(jlong,
VP8Decoder_createNativeDecoder,
JNIEnv* jni,
jclass) {
return jlongFromPointer(VP8Decoder::Create());
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,34 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <jni.h>
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
JNI_FUNCTION_DECLARATION(jlong,
VP9Encoder_createNativeEncoder,
JNIEnv* jni,
jclass) {
return jlongFromPointer(VP9Encoder::Create());
}
JNI_FUNCTION_DECLARATION(jlong,
VP9Decoder_createNativeDecoder,
JNIEnv* jni,
jclass) {
return jlongFromPointer(VP9Decoder::Create());
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,58 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sdk/android/src/jni/wrappednativecodec.h"
#include "sdk/android/generated_video_jni/jni/WrappedNativeVideoDecoder_jni.h"
#include "sdk/android/generated_video_jni/jni/WrappedNativeVideoEncoder_jni.h"
#include "sdk/android/src/jni/class_loader.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/videodecoderwrapper.h"
#include "sdk/android/src/jni/videoencoderwrapper.h"
namespace webrtc {
namespace jni {
std::unique_ptr<VideoDecoder> WrapOrUnwrapVideoDecoder(JNIEnv* jni,
jobject j_decoder) {
jclass wrapped_native_decoder_class =
GetClass(jni, "org/webrtc/WrappedNativeVideoDecoder");
VideoDecoder* decoder;
if (jni->IsInstanceOf(j_decoder, wrapped_native_decoder_class)) {
jlong native_decoder =
Java_WrappedNativeVideoDecoder_getNativeDecoder(jni, j_decoder);
decoder = reinterpret_cast<VideoDecoder*>(native_decoder);
} else {
decoder = new VideoDecoderWrapper(jni, j_decoder);
}
return std::unique_ptr<VideoDecoder>(decoder);
}
std::unique_ptr<VideoEncoder> WrapOrUnwrapVideoEncoder(JNIEnv* jni,
jobject j_encoder) {
jclass wrapped_native_encoder_class =
GetClass(jni, "org/webrtc/WrappedNativeVideoEncoder");
VideoEncoder* encoder;
if (jni->IsInstanceOf(j_encoder, wrapped_native_encoder_class)) {
jlong native_encoder =
Java_WrappedNativeVideoEncoder_getNativeEncoder(jni, j_encoder);
encoder = reinterpret_cast<VideoEncoder*>(native_encoder);
} else {
encoder = new VideoEncoderWrapper(jni, j_encoder);
}
return std::unique_ptr<VideoEncoder>(encoder);
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,38 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_ANDROID_SRC_JNI_WRAPPEDNATIVECODEC_H_
#define SDK_ANDROID_SRC_JNI_WRAPPEDNATIVECODEC_H_
#include <jni.h>
#include <memory>
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_encoder.h"
namespace webrtc {
namespace jni {
/* If the j_decoder is a wrapped native decoder, unwrap it. If it is not,
* wrap it in a VideoDecoderWrapper.
*/
std::unique_ptr<VideoDecoder> WrapOrUnwrapVideoDecoder(JNIEnv* jni,
jobject j_decoder);
/* If the j_encoder is a wrapped native encoder, unwrap it. If it is not,
* wrap it in a VideoEncoderWrapper.
*/
std::unique_ptr<VideoEncoder> WrapOrUnwrapVideoEncoder(JNIEnv* jni,
jobject j_encoder);
} // namespace jni
} // namespace webrtc
#endif // SDK_ANDROID_SRC_JNI_WRAPPEDNATIVECODEC_H_