2013-07-10 00:45:36 +00:00
|
|
|
/*
|
2016-02-10 07:54:43 -08:00
|
|
|
* Copyright 2013 The WebRTC project authors. All Rights Reserved.
|
2013-07-10 00:45:36 +00:00
|
|
|
*
|
2016-02-10 07:54:43 -08:00
|
|
|
* 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.
|
2013-07-10 00:45:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Hints for future visitors:
|
|
|
|
|
// This entire file is an implementation detail of the org.webrtc Java package,
|
|
|
|
|
// the most interesting bits of which are org.webrtc.PeerConnection{,Factory}.
|
|
|
|
|
// The layout of this file is roughly:
|
|
|
|
|
// - various helper C++ functions & classes that wrap Java counterparts and
|
|
|
|
|
// expose a C++ interface that can be passed to the C++ PeerConnection APIs
|
|
|
|
|
// - implementations of methods declared "static" in the Java package (named
|
|
|
|
|
// things like Java_org_webrtc_OMG_Can_This_Name_Be_Any_Longer, prescribed by
|
|
|
|
|
// the JNI spec).
|
|
|
|
|
//
|
|
|
|
|
// Lifecycle notes: objects are owned where they will be called; in other words
|
|
|
|
|
// FooObservers are owned by C++-land, and user-callable objects (e.g.
|
|
|
|
|
// PeerConnection and VideoTrack) are owned by Java-land.
|
|
|
|
|
// When this file allocates C++ RefCountInterfaces it AddRef()s an artificial
|
|
|
|
|
// ref simulating the jlong held in Java-land, and then Release()s the ref in
|
|
|
|
|
// the respective free call. Sometimes this AddRef is implicit in the
|
|
|
|
|
// construction of a scoped_refptr<> which is then .release()d.
|
|
|
|
|
// Any persistent (non-local) references from C++ to Java must be global or weak
|
|
|
|
|
// (in which case they must be checked before use)!
|
|
|
|
|
//
|
|
|
|
|
// Exception notes: pretty much all JNI calls can throw Java exceptions, so each
|
|
|
|
|
// call through a JNIEnv* pointer needs to be followed by an ExceptionCheck()
|
|
|
|
|
// call. In this file this is done in CHECK_EXCEPTION, making for much easier
|
|
|
|
|
// debugging in case of failure (the alternative is to wait for control to
|
|
|
|
|
// return to the Java frame that called code in this file, at which point it's
|
|
|
|
|
// impossible to tell which JNI call broke).
|
|
|
|
|
|
|
|
|
|
#include <jni.h>
|
|
|
|
|
#undef JNIEXPORT
|
|
|
|
|
#define JNIEXPORT __attribute__((visibility("default")))
|
|
|
|
|
|
2014-08-13 17:26:08 +00:00
|
|
|
#include <limits>
|
2016-04-26 03:13:22 -07:00
|
|
|
#include <memory>
|
2015-12-17 03:04:15 -08:00
|
|
|
#include <utility>
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2016-02-10 10:53:12 +01:00
|
|
|
#include "webrtc/api/androidvideocapturer.h"
|
|
|
|
|
#include "webrtc/api/dtlsidentitystore.h"
|
|
|
|
|
#include "webrtc/api/java/jni/androidmediadecoder_jni.h"
|
|
|
|
|
#include "webrtc/api/java/jni/androidmediaencoder_jni.h"
|
|
|
|
|
#include "webrtc/api/java/jni/androidnetworkmonitor_jni.h"
|
|
|
|
|
#include "webrtc/api/java/jni/androidvideocapturer_jni.h"
|
|
|
|
|
#include "webrtc/api/java/jni/classreferenceholder.h"
|
|
|
|
|
#include "webrtc/api/java/jni/jni_helpers.h"
|
|
|
|
|
#include "webrtc/api/java/jni/native_handle_impl.h"
|
|
|
|
|
#include "webrtc/api/mediaconstraintsinterface.h"
|
|
|
|
|
#include "webrtc/api/peerconnectioninterface.h"
|
|
|
|
|
#include "webrtc/api/rtpreceiverinterface.h"
|
|
|
|
|
#include "webrtc/api/rtpsenderinterface.h"
|
2016-03-14 11:59:18 -07:00
|
|
|
#include "webrtc/api/webrtcsdp.h"
|
2014-08-13 17:26:08 +00:00
|
|
|
#include "webrtc/base/bind.h"
|
2014-09-09 11:45:44 +00:00
|
|
|
#include "webrtc/base/checks.h"
|
2015-12-07 23:17:15 +01:00
|
|
|
#include "webrtc/base/event_tracer.h"
|
2014-08-13 17:26:08 +00:00
|
|
|
#include "webrtc/base/logging.h"
|
2015-09-01 16:11:18 -07:00
|
|
|
#include "webrtc/base/logsinks.h"
|
2014-08-13 17:26:08 +00:00
|
|
|
#include "webrtc/base/messagequeue.h"
|
2015-12-07 23:17:15 +01:00
|
|
|
#include "webrtc/base/networkmonitor.h"
|
2014-08-13 17:26:08 +00:00
|
|
|
#include "webrtc/base/ssladapter.h"
|
2015-02-09 23:25:58 +00:00
|
|
|
#include "webrtc/base/stringutils.h"
|
Move talk/media to webrtc/media
I removed the 'libjingle' target in talk/libjingle.gyp and replaced
all users of it with base/base.gyp:rtc_base. It seems the jsoncpp
and expat dependencies were not used by it's previous references.
The files in talk/media/testdata were uploaded to Google Storage and
added .sha1 files in resources/media instead of simply moving them.
The previously disabled warnings that were inherited from
talk/build/common.gypi are now replaced by target-specific disabling
of only the failing warnings. Additional disabling was needed since the stricter
compilation warnings that applies to code in webrtc/.
License headers will be updated in a follow-up CL in order to not
break Git history.
Other modifications:
* Updated the header guards.
* Sorted the includes using chromium/src/tools/sort-headers.py
except for these files:
talk/app/webrtc/peerconnectionendtoend_unittest.cc
talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
webrtc/media/devices/win32devicemanager.cc.
* Unused GYP reference to libjingle_tests_additional_deps was removed.
* Removed duplicated GYP entries of
webrtc/base/testutils.cc
webrtc/base/testutils.h
The HAVE_WEBRTC_VIDEO and HAVE_WEBRTC_VOICE defines were used by only talk/media,
so they were moved to the media.gyp.
I also checked that none of
EXPAT_RELATIVE_PATH,
FEATURE_ENABLE_VOICEMAIL,
GTEST_RELATIVE_PATH,
JSONCPP_RELATIVE_PATH,
LOGGING=1,
SRTP_RELATIVE_PATH,
FEATURE_ENABLE_SSL,
FEATURE_ENABLE_VOICEMAIL,
FEATURE_ENABLE_PSTN,
HAVE_SCTP,
HAVE_SRTP,
are used by the talk/media code.
For Chromium, the following changes will need to be applied to the roll CL that updates the
DEPS for WebRTC and libjingle: https://codereview.chromium.org/1604303002/
BUG=webrtc:5420
NOPRESUBMIT=True
TBR=tommi@webrtc.org
Review URL: https://codereview.webrtc.org/1587193006
Cr-Commit-Position: refs/heads/master@{#11495}
2016-02-04 23:52:28 -08:00
|
|
|
#include "webrtc/media/base/videocapturer.h"
|
|
|
|
|
#include "webrtc/media/devices/videorendererfactory.h"
|
2016-02-12 06:39:40 +01:00
|
|
|
#include "webrtc/media/engine/webrtcvideodecoderfactory.h"
|
|
|
|
|
#include "webrtc/media/engine/webrtcvideoencoderfactory.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/field_trial_default.h"
|
2016-02-08 01:07:19 -08:00
|
|
|
#include "webrtc/system_wrappers/include/logcat_trace_context.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/trace.h"
|
2013-07-17 14:42:53 +00:00
|
|
|
#include "webrtc/voice_engine/include/voe_base.h"
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-09-01 15:04:13 -07:00
|
|
|
using cricket::WebRtcVideoDecoderFactory;
|
|
|
|
|
using cricket::WebRtcVideoEncoderFactory;
|
2014-07-29 17:36:52 +00:00
|
|
|
using rtc::Bind;
|
|
|
|
|
using rtc::Thread;
|
|
|
|
|
using rtc::ThreadManager;
|
2013-07-10 00:45:36 +00:00
|
|
|
using webrtc::AudioSourceInterface;
|
|
|
|
|
using webrtc::AudioTrackInterface;
|
|
|
|
|
using webrtc::AudioTrackVector;
|
|
|
|
|
using webrtc::CreateSessionDescriptionObserver;
|
2013-07-12 16:04:50 +00:00
|
|
|
using webrtc::DataBuffer;
|
|
|
|
|
using webrtc::DataChannelInit;
|
|
|
|
|
using webrtc::DataChannelInterface;
|
|
|
|
|
using webrtc::DataChannelObserver;
|
2013-07-10 00:45:36 +00:00
|
|
|
using webrtc::IceCandidateInterface;
|
2016-02-08 01:07:19 -08:00
|
|
|
using webrtc::LogcatTraceContext;
|
2013-07-10 00:45:36 +00:00
|
|
|
using webrtc::MediaConstraintsInterface;
|
|
|
|
|
using webrtc::MediaSourceInterface;
|
|
|
|
|
using webrtc::MediaStreamInterface;
|
|
|
|
|
using webrtc::MediaStreamTrackInterface;
|
|
|
|
|
using webrtc::PeerConnectionFactoryInterface;
|
|
|
|
|
using webrtc::PeerConnectionInterface;
|
|
|
|
|
using webrtc::PeerConnectionObserver;
|
2015-10-06 12:29:25 -07:00
|
|
|
using webrtc::RtpReceiverInterface;
|
|
|
|
|
using webrtc::RtpSenderInterface;
|
2013-07-10 00:45:36 +00:00
|
|
|
using webrtc::SessionDescriptionInterface;
|
|
|
|
|
using webrtc::SetSessionDescriptionObserver;
|
|
|
|
|
using webrtc::StatsObserver;
|
|
|
|
|
using webrtc::StatsReport;
|
2014-12-15 13:22:54 +00:00
|
|
|
using webrtc::StatsReports;
|
2016-03-08 01:27:48 +01:00
|
|
|
using webrtc::VideoTrackSourceInterface;
|
2013-07-10 00:45:36 +00:00
|
|
|
using webrtc::VideoTrackInterface;
|
|
|
|
|
using webrtc::VideoTrackVector;
|
2014-02-13 03:56:14 +00:00
|
|
|
using webrtc::kVideoCodecVP8;
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-02-13 12:46:51 +00:00
|
|
|
namespace webrtc_jni {
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-02-09 23:25:58 +00:00
|
|
|
// Field trials initialization string
|
|
|
|
|
static char *field_trials_init_string = NULL;
|
|
|
|
|
|
2014-09-15 17:52:42 +00:00
|
|
|
// Set in PeerConnectionFactory_initializeAndroidGlobals().
|
|
|
|
|
static bool factory_static_initialized = false;
|
2015-09-01 15:04:13 -07:00
|
|
|
static bool video_hw_acceleration_enabled = true;
|
2014-09-15 17:52:42 +00:00
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// Return the (singleton) Java Enum object corresponding to |index|;
|
|
|
|
|
// |state_class_fragment| is something like "MediaSource$State".
|
2015-02-23 17:44:27 +00:00
|
|
|
static jobject JavaEnumFromIndex(
|
2013-07-10 00:45:36 +00:00
|
|
|
JNIEnv* jni, const std::string& state_class_fragment, int index) {
|
2015-02-13 12:46:51 +00:00
|
|
|
const std::string state_class = "org/webrtc/" + state_class_fragment;
|
|
|
|
|
return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
|
|
|
|
|
state_class, index);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
static DataChannelInit JavaDataChannelInitToNative(
|
|
|
|
|
JNIEnv* jni, jobject j_init) {
|
|
|
|
|
DataChannelInit init;
|
|
|
|
|
|
|
|
|
|
jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init");
|
|
|
|
|
jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z");
|
|
|
|
|
jfieldID max_retransmit_time_id =
|
|
|
|
|
GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I");
|
|
|
|
|
jfieldID max_retransmits_id =
|
|
|
|
|
GetFieldID(jni, j_init_class, "maxRetransmits", "I");
|
|
|
|
|
jfieldID protocol_id =
|
|
|
|
|
GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;");
|
|
|
|
|
jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z");
|
|
|
|
|
jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I");
|
|
|
|
|
|
|
|
|
|
init.ordered = GetBooleanField(jni, j_init, ordered_id);
|
|
|
|
|
init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id);
|
|
|
|
|
init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id);
|
|
|
|
|
init.protocol = JavaToStdString(
|
|
|
|
|
jni, GetStringField(jni, j_init, protocol_id));
|
|
|
|
|
init.negotiated = GetBooleanField(jni, j_init, negotiated_id);
|
|
|
|
|
init.id = GetIntField(jni, j_init, id_id);
|
|
|
|
|
|
|
|
|
|
return init;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
class ConstraintsWrapper;
|
|
|
|
|
|
|
|
|
|
// Adapter between the C++ PeerConnectionObserver interface and the Java
|
|
|
|
|
// PeerConnection.Observer interface. Wraps an instance of the Java interface
|
|
|
|
|
// and dispatches C++ callbacks to Java.
|
|
|
|
|
class PCOJava : public PeerConnectionObserver {
|
|
|
|
|
public:
|
|
|
|
|
PCOJava(JNIEnv* jni, jobject j_observer)
|
|
|
|
|
: j_observer_global_(jni, j_observer),
|
2013-07-12 16:04:50 +00:00
|
|
|
j_observer_class_(jni, GetObjectClass(jni, *j_observer_global_)),
|
|
|
|
|
j_media_stream_class_(jni, FindClass(jni, "org/webrtc/MediaStream")),
|
|
|
|
|
j_media_stream_ctor_(GetMethodID(
|
|
|
|
|
jni, *j_media_stream_class_, "<init>", "(J)V")),
|
|
|
|
|
j_audio_track_class_(jni, FindClass(jni, "org/webrtc/AudioTrack")),
|
2013-07-10 00:45:36 +00:00
|
|
|
j_audio_track_ctor_(GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni, *j_audio_track_class_, "<init>", "(J)V")),
|
|
|
|
|
j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")),
|
|
|
|
|
j_video_track_ctor_(GetMethodID(
|
|
|
|
|
jni, *j_video_track_class_, "<init>", "(J)V")),
|
|
|
|
|
j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")),
|
|
|
|
|
j_data_channel_ctor_(GetMethodID(
|
|
|
|
|
jni, *j_data_channel_class_, "<init>", "(J)V")) {
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-27 13:39:58 +02:00
|
|
|
virtual ~PCOJava() {
|
|
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
while (!remote_streams_.empty())
|
|
|
|
|
DisposeRemoteStream(remote_streams_.begin());
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnIceCandidate(const IceCandidateInterface* candidate) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
std::string sdp;
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(candidate->ToString(&sdp)) << "got so far: " << sdp;
|
2013-07-10 00:45:36 +00:00
|
|
|
jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
|
|
|
|
|
jmethodID ctor = GetMethodID(jni(), candidate_class,
|
|
|
|
|
"<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
|
|
|
|
|
jstring j_sdp = JavaStringFromStdString(jni(), sdp);
|
2016-03-14 11:59:18 -07:00
|
|
|
jobject j_candidate = jni()->NewObject(candidate_class, ctor, j_mid,
|
|
|
|
|
candidate->sdp_mline_index(), j_sdp);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during NewObject";
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_,
|
2013-07-10 00:45:36 +00:00
|
|
|
"onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
void OnIceCandidatesRemoved(
|
2016-04-29 06:09:15 -07:00
|
|
|
const std::vector<cricket::Candidate>& candidates) override {
|
2016-03-14 11:59:18 -07:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jobjectArray candidates_array = ToJavaCandidateArray(jni(), candidates);
|
|
|
|
|
jmethodID m =
|
|
|
|
|
GetMethodID(jni(), *j_observer_class_, "onIceCandidatesRemoved",
|
|
|
|
|
"([Lorg/webrtc/IceCandidate;)V");
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, candidates_array);
|
|
|
|
|
CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnSignalingChange(
|
|
|
|
|
PeerConnectionInterface::SignalingState new_state) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID m = GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni(), *j_observer_class_, "onSignalingChange",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Lorg/webrtc/PeerConnection$SignalingState;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject new_state_enum =
|
|
|
|
|
JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnIceConnectionChange(
|
|
|
|
|
PeerConnectionInterface::IceConnectionState new_state) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID m = GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni(), *j_observer_class_, "onIceConnectionChange",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject new_state_enum = JavaEnumFromIndex(
|
|
|
|
|
jni(), "PeerConnection$IceConnectionState", new_state);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-08 11:08:35 -07:00
|
|
|
void OnIceConnectionReceivingChange(bool receiving) override {
|
|
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jmethodID m = GetMethodID(
|
|
|
|
|
jni(), *j_observer_class_, "onIceConnectionReceivingChange", "(Z)V");
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, receiving);
|
|
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnIceGatheringChange(
|
|
|
|
|
PeerConnectionInterface::IceGatheringState new_state) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID m = GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni(), *j_observer_class_, "onIceGatheringChange",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject new_state_enum = JavaEnumFromIndex(
|
|
|
|
|
jni(), "PeerConnection$IceGatheringState", new_state);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnAddStream(MediaStreamInterface* stream) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2015-08-27 13:39:58 +02:00
|
|
|
// Java MediaStream holds one reference. Corresponding Release() is in
|
|
|
|
|
// MediaStream_free, triggered by MediaStream.dispose().
|
|
|
|
|
stream->AddRef();
|
|
|
|
|
jobject j_stream =
|
|
|
|
|
jni()->NewObject(*j_media_stream_class_, j_media_stream_ctor_,
|
|
|
|
|
reinterpret_cast<jlong>(stream));
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during NewObject";
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-08-27 13:39:58 +02:00
|
|
|
for (const auto& track : stream->GetAudioTracks()) {
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring id = JavaStringFromStdString(jni(), track->id());
|
2015-08-27 13:39:58 +02:00
|
|
|
// Java AudioTrack holds one reference. Corresponding Release() is in
|
|
|
|
|
// MediaStreamTrack_free, triggered by AudioTrack.dispose().
|
|
|
|
|
track->AddRef();
|
|
|
|
|
jobject j_track =
|
|
|
|
|
jni()->NewObject(*j_audio_track_class_, j_audio_track_ctor_,
|
|
|
|
|
reinterpret_cast<jlong>(track.get()), id);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during NewObject";
|
2013-08-12 23:26:21 +00:00
|
|
|
jfieldID audio_tracks_id = GetFieldID(jni(),
|
|
|
|
|
*j_media_stream_class_,
|
|
|
|
|
"audioTracks",
|
|
|
|
|
"Ljava/util/LinkedList;");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID add = GetMethodID(jni(),
|
2014-01-09 00:31:17 +00:00
|
|
|
GetObjectClass(jni(), audio_tracks),
|
|
|
|
|
"add",
|
|
|
|
|
"(Ljava/lang/Object;)Z");
|
|
|
|
|
jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(added);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-27 13:39:58 +02:00
|
|
|
for (const auto& track : stream->GetVideoTracks()) {
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring id = JavaStringFromStdString(jni(), track->id());
|
2015-08-27 13:39:58 +02:00
|
|
|
// Java VideoTrack holds one reference. Corresponding Release() is in
|
|
|
|
|
// MediaStreamTrack_free, triggered by VideoTrack.dispose().
|
|
|
|
|
track->AddRef();
|
|
|
|
|
jobject j_track =
|
|
|
|
|
jni()->NewObject(*j_video_track_class_, j_video_track_ctor_,
|
|
|
|
|
reinterpret_cast<jlong>(track.get()), id);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during NewObject";
|
2013-08-12 23:26:21 +00:00
|
|
|
jfieldID video_tracks_id = GetFieldID(jni(),
|
|
|
|
|
*j_media_stream_class_,
|
|
|
|
|
"videoTracks",
|
|
|
|
|
"Ljava/util/LinkedList;");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID add = GetMethodID(jni(),
|
2014-01-09 00:31:17 +00:00
|
|
|
GetObjectClass(jni(), video_tracks),
|
|
|
|
|
"add",
|
|
|
|
|
"(Ljava/lang/Object;)Z");
|
|
|
|
|
jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallBooleanMethod";
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(added);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
2015-08-27 13:39:58 +02:00
|
|
|
remote_streams_[stream] = NewGlobalRef(jni(), j_stream);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
|
|
|
|
|
"(Lorg/webrtc/MediaStream;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnRemoveStream(MediaStreamInterface* stream) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2015-08-27 13:39:58 +02:00
|
|
|
NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(it != remote_streams_.end()) << "unexpected stream: " << std::hex
|
|
|
|
|
<< stream;
|
2015-08-27 13:39:58 +02:00
|
|
|
jobject j_stream = it->second;
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onRemoveStream",
|
|
|
|
|
"(Lorg/webrtc/MediaStream;)V");
|
2015-08-27 13:39:58 +02:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2015-08-27 13:39:58 +02:00
|
|
|
DisposeRemoteStream(it);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnDataChannel(DataChannelInterface* channel) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jobject j_channel = jni()->NewObject(
|
|
|
|
|
*j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during NewObject";
|
2013-07-12 16:04:50 +00:00
|
|
|
|
|
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
|
|
|
|
|
"(Lorg/webrtc/DataChannel;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
|
2013-08-12 23:26:21 +00:00
|
|
|
|
|
|
|
|
// Channel is now owned by Java object, and will be freed from
|
|
|
|
|
// DataChannel.dispose(). Important that this be done _after_ the
|
|
|
|
|
// CallVoidMethod above as Java code might call back into native code and be
|
|
|
|
|
// surprised to see a refcount of 2.
|
|
|
|
|
int bumped_count = channel->AddRef();
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(bumped_count == 2) << "Unexpected refcount OnDataChannel";
|
2013-08-12 23:26:21 +00:00
|
|
|
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnRenegotiationNeeded() override {
|
2014-01-13 22:04:12 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jmethodID m =
|
|
|
|
|
GetMethodID(jni(), *j_observer_class_, "onRenegotiationNeeded", "()V");
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2014-01-13 22:04:12 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
void SetConstraints(ConstraintsWrapper* constraints) {
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(!constraints_.get()) << "constraints already set!";
|
2013-07-10 00:45:36 +00:00
|
|
|
constraints_.reset(constraints);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ConstraintsWrapper* constraints() { return constraints_.get(); }
|
|
|
|
|
|
|
|
|
|
private:
|
2015-08-27 13:39:58 +02:00
|
|
|
typedef std::map<MediaStreamInterface*, jobject> NativeToJavaStreamsMap;
|
|
|
|
|
|
|
|
|
|
void DisposeRemoteStream(const NativeToJavaStreamsMap::iterator& it) {
|
|
|
|
|
jobject j_stream = it->second;
|
|
|
|
|
remote_streams_.erase(it);
|
|
|
|
|
jni()->CallVoidMethod(
|
|
|
|
|
j_stream, GetMethodID(jni(), *j_media_stream_class_, "dispose", "()V"));
|
|
|
|
|
CHECK_EXCEPTION(jni()) << "error during MediaStream.dispose()";
|
|
|
|
|
DeleteGlobalRef(jni(), j_stream);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
jobject ToJavaCandidate(JNIEnv* jni,
|
|
|
|
|
jclass* candidate_class,
|
|
|
|
|
const cricket::Candidate& candidate) {
|
|
|
|
|
std::string sdp = webrtc::SdpSerializeCandidate(candidate);
|
|
|
|
|
RTC_CHECK(!sdp.empty()) << "got an empty ICE candidate";
|
|
|
|
|
jmethodID ctor = GetMethodID(jni, *candidate_class, "<init>",
|
|
|
|
|
"(Ljava/lang/String;ILjava/lang/String;)V");
|
|
|
|
|
jstring j_mid = JavaStringFromStdString(jni, candidate.transport_name());
|
|
|
|
|
jstring j_sdp = JavaStringFromStdString(jni, sdp);
|
|
|
|
|
// sdp_mline_index is not used, pass an invalid value -1.
|
|
|
|
|
jobject j_candidate =
|
|
|
|
|
jni->NewObject(*candidate_class, ctor, j_mid, -1, j_sdp);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during Java Candidate NewObject";
|
|
|
|
|
return j_candidate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jobjectArray ToJavaCandidateArray(
|
|
|
|
|
JNIEnv* jni,
|
|
|
|
|
const std::vector<cricket::Candidate>& candidates) {
|
|
|
|
|
jclass candidate_class = FindClass(jni, "org/webrtc/IceCandidate");
|
|
|
|
|
jobjectArray java_candidates =
|
|
|
|
|
jni->NewObjectArray(candidates.size(), candidate_class, NULL);
|
|
|
|
|
int i = 0;
|
|
|
|
|
for (const cricket::Candidate& candidate : candidates) {
|
|
|
|
|
jobject j_candidate = ToJavaCandidate(jni, &candidate_class, candidate);
|
|
|
|
|
jni->SetObjectArrayElement(java_candidates, i++, j_candidate);
|
|
|
|
|
}
|
|
|
|
|
return java_candidates;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JNIEnv* jni() {
|
|
|
|
|
return AttachCurrentThreadIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jobject> j_observer_global_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_observer_class_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_media_stream_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
const jmethodID j_media_stream_ctor_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jclass> j_audio_track_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
const jmethodID j_audio_track_ctor_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jclass> j_video_track_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
const jmethodID j_video_track_ctor_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jclass> j_data_channel_class_;
|
|
|
|
|
const jmethodID j_data_channel_ctor_;
|
2015-08-27 13:39:58 +02:00
|
|
|
// C++ -> Java remote streams. The stored jobects are global refs and must be
|
|
|
|
|
// manually deleted upon removal. Use DisposeRemoteStream().
|
|
|
|
|
NativeToJavaStreamsMap remote_streams_;
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<ConstraintsWrapper> constraints_;
|
2013-07-10 00:45:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Wrapper for a Java MediaConstraints object. Copies all needed data so when
|
|
|
|
|
// the constructor returns the Java object is no longer needed.
|
|
|
|
|
class ConstraintsWrapper : public MediaConstraintsInterface {
|
|
|
|
|
public:
|
|
|
|
|
ConstraintsWrapper(JNIEnv* jni, jobject j_constraints) {
|
|
|
|
|
PopulateConstraintsFromJavaPairList(
|
|
|
|
|
jni, j_constraints, "mandatory", &mandatory_);
|
|
|
|
|
PopulateConstraintsFromJavaPairList(
|
|
|
|
|
jni, j_constraints, "optional", &optional_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ~ConstraintsWrapper() {}
|
|
|
|
|
|
|
|
|
|
// MediaConstraintsInterface.
|
2015-03-04 12:58:35 +00:00
|
|
|
const Constraints& GetMandatory() const override { return mandatory_; }
|
2013-07-12 16:04:50 +00:00
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
const Constraints& GetOptional() const override { return optional_; }
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Helper for translating a List<Pair<String, String>> to a Constraints.
|
|
|
|
|
static void PopulateConstraintsFromJavaPairList(
|
|
|
|
|
JNIEnv* jni, jobject j_constraints,
|
|
|
|
|
const char* field_name, Constraints* field) {
|
|
|
|
|
jfieldID j_id = GetFieldID(jni,
|
|
|
|
|
GetObjectClass(jni, j_constraints), field_name, "Ljava/util/List;");
|
|
|
|
|
jobject j_list = GetObjectField(jni, j_constraints, j_id);
|
2016-03-24 19:36:46 -07:00
|
|
|
for (jobject entry : Iterable(jni, j_list)) {
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID get_key = GetMethodID(jni,
|
|
|
|
|
GetObjectClass(jni, entry), "getKey", "()Ljava/lang/String;");
|
|
|
|
|
jstring j_key = reinterpret_cast<jstring>(
|
|
|
|
|
jni->CallObjectMethod(entry, get_key));
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID get_value = GetMethodID(jni,
|
|
|
|
|
GetObjectClass(jni, entry), "getValue", "()Ljava/lang/String;");
|
|
|
|
|
jstring j_value = reinterpret_cast<jstring>(
|
|
|
|
|
jni->CallObjectMethod(entry, get_value));
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
field->push_back(Constraint(JavaToStdString(jni, j_key),
|
|
|
|
|
JavaToStdString(jni, j_value)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Constraints mandatory_;
|
|
|
|
|
Constraints optional_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static jobject JavaSdpFromNativeSdp(
|
|
|
|
|
JNIEnv* jni, const SessionDescriptionInterface* desc) {
|
|
|
|
|
std::string sdp;
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(desc->ToString(&sdp)) << "got so far: " << sdp;
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring j_description = JavaStringFromStdString(jni, sdp);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
jclass j_type_class = FindClass(
|
|
|
|
|
jni, "org/webrtc/SessionDescription$Type");
|
|
|
|
|
jmethodID j_type_from_canonical = GetStaticMethodID(
|
|
|
|
|
jni, j_type_class, "fromCanonicalForm",
|
|
|
|
|
"(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring j_type_string = JavaStringFromStdString(jni, desc->type());
|
2013-07-10 00:45:36 +00:00
|
|
|
jobject j_type = jni->CallStaticObjectMethod(
|
2014-01-09 00:31:17 +00:00
|
|
|
j_type_class, j_type_from_canonical, j_type_string);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
|
|
|
|
|
jmethodID j_sdp_ctor = GetMethodID(
|
|
|
|
|
jni, j_sdp_class, "<init>",
|
|
|
|
|
"(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
|
|
|
|
|
jobject j_sdp = jni->NewObject(
|
2014-01-09 00:31:17 +00:00
|
|
|
j_sdp_class, j_sdp_ctor, j_type, j_description);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
2013-07-10 00:45:36 +00:00
|
|
|
return j_sdp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class T> // T is one of {Create,Set}SessionDescriptionObserver.
|
|
|
|
|
class SdpObserverWrapper : public T {
|
|
|
|
|
public:
|
|
|
|
|
SdpObserverWrapper(JNIEnv* jni, jobject j_observer,
|
|
|
|
|
ConstraintsWrapper* constraints)
|
|
|
|
|
: constraints_(constraints),
|
2013-07-12 16:04:50 +00:00
|
|
|
j_observer_global_(jni, j_observer),
|
|
|
|
|
j_observer_class_(jni, GetObjectClass(jni, j_observer)) {
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
virtual ~SdpObserverWrapper() {}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
// Can't mark override because of templating.
|
2013-07-10 00:45:36 +00:00
|
|
|
virtual void OnSuccess() {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
// Can't mark override because of templating.
|
2013-07-10 00:45:36 +00:00
|
|
|
virtual void OnSuccess(SessionDescriptionInterface* desc) {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID m = GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni(), *j_observer_class_, "onCreateSuccess",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Lorg/webrtc/SessionDescription;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// Common implementation for failure of Set & Create types, distinguished by
|
|
|
|
|
// |op| being "Set" or "Create".
|
2016-01-08 00:43:07 -08:00
|
|
|
void DoOnFailure(const std::string& op, const std::string& error) {
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
|
|
|
|
|
"(Ljava/lang/String;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jstring j_error_string = JavaStringFromStdString(jni(), error);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JNIEnv* jni() {
|
|
|
|
|
return AttachCurrentThreadIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-09 00:31:17 +00:00
|
|
|
private:
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<ConstraintsWrapper> constraints_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jobject> j_observer_global_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_observer_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CreateSdpObserverWrapper
|
|
|
|
|
: public SdpObserverWrapper<CreateSessionDescriptionObserver> {
|
|
|
|
|
public:
|
|
|
|
|
CreateSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
|
|
|
|
|
ConstraintsWrapper* constraints)
|
|
|
|
|
: SdpObserverWrapper(jni, j_observer, constraints) {}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnFailure(const std::string& error) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2016-01-08 00:43:07 -08:00
|
|
|
SdpObserverWrapper::DoOnFailure(std::string("Create"), error);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SetSdpObserverWrapper
|
|
|
|
|
: public SdpObserverWrapper<SetSessionDescriptionObserver> {
|
|
|
|
|
public:
|
|
|
|
|
SetSdpObserverWrapper(JNIEnv* jni, jobject j_observer,
|
|
|
|
|
ConstraintsWrapper* constraints)
|
|
|
|
|
: SdpObserverWrapper(jni, j_observer, constraints) {}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnFailure(const std::string& error) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2016-01-08 00:43:07 -08:00
|
|
|
SdpObserverWrapper::DoOnFailure(std::string("Set"), error);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
|
|
|
|
|
// and dispatching the callback from C++ back to Java.
|
|
|
|
|
class DataChannelObserverWrapper : public DataChannelObserver {
|
|
|
|
|
public:
|
|
|
|
|
DataChannelObserverWrapper(JNIEnv* jni, jobject j_observer)
|
|
|
|
|
: j_observer_global_(jni, j_observer),
|
|
|
|
|
j_observer_class_(jni, GetObjectClass(jni, j_observer)),
|
2014-08-26 11:08:06 +00:00
|
|
|
j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")),
|
2015-07-01 13:34:33 -07:00
|
|
|
j_on_buffered_amount_change_mid_(GetMethodID(
|
|
|
|
|
jni, *j_observer_class_, "onBufferedAmountChange", "(J)V")),
|
|
|
|
|
j_on_state_change_mid_(
|
|
|
|
|
GetMethodID(jni, *j_observer_class_, "onStateChange", "()V")),
|
2013-07-12 16:04:50 +00:00
|
|
|
j_on_message_mid_(GetMethodID(jni, *j_observer_class_, "onMessage",
|
|
|
|
|
"(Lorg/webrtc/DataChannel$Buffer;)V")),
|
2015-07-01 13:34:33 -07:00
|
|
|
j_buffer_ctor_(GetMethodID(jni, *j_buffer_class_, "<init>",
|
|
|
|
|
"(Ljava/nio/ByteBuffer;Z)V")) {}
|
2013-07-12 16:04:50 +00:00
|
|
|
|
|
|
|
|
virtual ~DataChannelObserverWrapper() {}
|
|
|
|
|
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
void OnBufferedAmountChange(uint64_t previous_amount) override {
|
2015-07-01 13:34:33 -07:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, j_on_buffered_amount_change_mid_,
|
|
|
|
|
previous_amount);
|
|
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnStateChange() override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2013-07-12 16:04:50 +00:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnMessage(const DataBuffer& buffer) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2015-03-24 09:19:06 +00:00
|
|
|
jobject byte_buffer = jni()->NewDirectByteBuffer(
|
rtc::Buffer improvements
1. Constructors, SetData(), and AppendData() now accept uint8_t*,
int8_t*, and char*. Previously, they accepted void*, meaning that
any kind of pointer was accepted. I think requiring an explicit
cast in cases where the input array isn't already of a byte-sized
type is a better compromise between convenience and safety.
2. data() can now return a uint8_t* instead of a char*, which seems
more appropriate for a byte array, and is harder to mix up with
zero-terminated C strings. data<int8_t>() is also available so
that callers that want that type instead won't have to cast, as
is data<char>() (which remains the default until all existing
callers have been fixed).
3. Constructors, SetData(), and AppendData() now accept arrays
natively, not just decayed to pointers. The advantage of this is
that callers don't have to pass the size separately.
4. There are new constructors that allow setting size and capacity
without initializing the array. Previously, this had to be done
separately after construction.
5. Instead of TransferTo(), Buffer now supports swap(), and move
construction and assignment, and has a Pass() method that works
just like std::move(). (The Pass method is modeled after
scoped_ptr::Pass().)
R=jmarusic@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/42989004
Cr-Commit-Position: refs/heads/master@{#9033}
2015-04-20 14:03:07 +02:00
|
|
|
const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
|
2013-07-12 16:04:50 +00:00
|
|
|
jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_,
|
|
|
|
|
byte_buffer, buffer.binary);
|
|
|
|
|
jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
JNIEnv* jni() {
|
|
|
|
|
return AttachCurrentThreadIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ScopedGlobalRef<jobject> j_observer_global_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_observer_class_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_buffer_class_;
|
2015-07-01 13:34:33 -07:00
|
|
|
const jmethodID j_on_buffered_amount_change_mid_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const jmethodID j_on_state_change_mid_;
|
|
|
|
|
const jmethodID j_on_message_mid_;
|
|
|
|
|
const jmethodID j_buffer_ctor_;
|
|
|
|
|
};
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// Adapter for a Java StatsObserver presenting a C++ StatsObserver and
|
|
|
|
|
// dispatching the callback from C++ back to Java.
|
|
|
|
|
class StatsObserverWrapper : public StatsObserver {
|
|
|
|
|
public:
|
|
|
|
|
StatsObserverWrapper(JNIEnv* jni, jobject j_observer)
|
2013-07-12 16:04:50 +00:00
|
|
|
: j_observer_global_(jni, j_observer),
|
|
|
|
|
j_observer_class_(jni, GetObjectClass(jni, j_observer)),
|
|
|
|
|
j_stats_report_class_(jni, FindClass(jni, "org/webrtc/StatsReport")),
|
2013-07-10 00:45:36 +00:00
|
|
|
j_stats_report_ctor_(GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni, *j_stats_report_class_, "<init>",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Ljava/lang/String;Ljava/lang/String;D"
|
|
|
|
|
"[Lorg/webrtc/StatsReport$Value;)V")),
|
2013-07-12 16:04:50 +00:00
|
|
|
j_value_class_(jni, FindClass(
|
2013-07-10 00:45:36 +00:00
|
|
|
jni, "org/webrtc/StatsReport$Value")),
|
|
|
|
|
j_value_ctor_(GetMethodID(
|
2013-07-12 16:04:50 +00:00
|
|
|
jni, *j_value_class_, "<init>",
|
2013-07-10 00:45:36 +00:00
|
|
|
"(Ljava/lang/String;Ljava/lang/String;)V")) {
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
virtual ~StatsObserverWrapper() {}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void OnComplete(const StatsReports& reports) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
|
|
|
|
jobjectArray j_reports = ReportsToJava(jni(), reports);
|
2013-07-12 16:04:50 +00:00
|
|
|
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
|
|
|
|
|
"([Lorg/webrtc/StatsReport;)V");
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
jobjectArray ReportsToJava(
|
2014-12-15 13:22:54 +00:00
|
|
|
JNIEnv* jni, const StatsReports& reports) {
|
2013-07-10 00:45:36 +00:00
|
|
|
jobjectArray reports_array = jni->NewObjectArray(
|
2013-07-12 16:04:50 +00:00
|
|
|
reports.size(), *j_stats_report_class_, NULL);
|
2014-12-15 13:22:54 +00:00
|
|
|
int i = 0;
|
|
|
|
|
for (const auto* report : reports) {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni);
|
2015-03-12 16:35:55 +00:00
|
|
|
jstring j_id = JavaStringFromStdString(jni, report->id()->ToString());
|
2015-01-19 20:41:26 +00:00
|
|
|
jstring j_type = JavaStringFromStdString(jni, report->TypeToString());
|
|
|
|
|
jobjectArray j_values = ValuesToJava(jni, report->values());
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject j_report = jni->NewObject(*j_stats_report_class_,
|
|
|
|
|
j_stats_report_ctor_,
|
|
|
|
|
j_id,
|
|
|
|
|
j_type,
|
2015-01-19 20:41:26 +00:00
|
|
|
report->timestamp(),
|
2014-01-09 00:31:17 +00:00
|
|
|
j_values);
|
2014-12-15 13:22:54 +00:00
|
|
|
jni->SetObjectArrayElement(reports_array, i++, j_report);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
return reports_array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jobjectArray ValuesToJava(JNIEnv* jni, const StatsReport::Values& values) {
|
|
|
|
|
jobjectArray j_values = jni->NewObjectArray(
|
2013-07-12 16:04:50 +00:00
|
|
|
values.size(), *j_value_class_, NULL);
|
2015-03-04 15:25:19 +00:00
|
|
|
int i = 0;
|
|
|
|
|
for (const auto& it : values) {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni);
|
2014-12-12 17:41:28 +00:00
|
|
|
// Should we use the '.name' enum value here instead of converting the
|
|
|
|
|
// name to a string?
|
2015-03-04 15:25:19 +00:00
|
|
|
jstring j_name = JavaStringFromStdString(jni, it.second->display_name());
|
|
|
|
|
jstring j_value = JavaStringFromStdString(jni, it.second->ToString());
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject j_element_value =
|
|
|
|
|
jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
|
2015-03-04 15:25:19 +00:00
|
|
|
jni->SetObjectArrayElement(j_values, i++, j_element_value);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
return j_values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JNIEnv* jni() {
|
|
|
|
|
return AttachCurrentThreadIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jobject> j_observer_global_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_observer_class_;
|
|
|
|
|
const ScopedGlobalRef<jclass> j_stats_report_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
const jmethodID j_stats_report_ctor_;
|
2013-07-12 16:04:50 +00:00
|
|
|
const ScopedGlobalRef<jclass> j_value_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
const jmethodID j_value_ctor_;
|
|
|
|
|
};
|
|
|
|
|
|
2016-03-23 10:33:07 +01:00
|
|
|
// Wrapper dispatching rtc::VideoSinkInterface to a Java VideoRenderer
|
2013-07-10 00:45:36 +00:00
|
|
|
// instance.
|
2016-03-23 10:33:07 +01:00
|
|
|
class JavaVideoRendererWrapper
|
|
|
|
|
: public rtc::VideoSinkInterface<cricket::VideoFrame> {
|
2013-07-10 00:45:36 +00:00
|
|
|
public:
|
|
|
|
|
JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
|
2013-07-12 16:04:50 +00:00
|
|
|
: j_callbacks_(jni, j_callbacks),
|
|
|
|
|
j_render_frame_id_(GetMethodID(
|
|
|
|
|
jni, GetObjectClass(jni, j_callbacks), "renderFrame",
|
|
|
|
|
"(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
|
|
|
|
|
j_frame_class_(jni,
|
|
|
|
|
FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
|
2014-09-15 17:52:42 +00:00
|
|
|
j_i420_frame_ctor_id_(GetMethodID(
|
2015-08-29 15:57:43 +02:00
|
|
|
jni, *j_frame_class_, "<init>", "(III[I[Ljava/nio/ByteBuffer;J)V")),
|
2014-09-15 17:52:42 +00:00
|
|
|
j_texture_frame_ctor_id_(GetMethodID(
|
|
|
|
|
jni, *j_frame_class_, "<init>",
|
2015-11-19 10:43:36 +01:00
|
|
|
"(IIII[FJ)V")),
|
2015-08-25 09:32:06 +02:00
|
|
|
j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) {
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
virtual ~JavaVideoRendererWrapper() {}
|
|
|
|
|
|
2016-03-23 10:33:07 +01:00
|
|
|
void OnFrame(const cricket::VideoFrame& video_frame) override {
|
2014-01-09 00:31:17 +00:00
|
|
|
ScopedLocalRefFrame local_ref_frame(jni());
|
2016-03-23 10:33:07 +01:00
|
|
|
jobject j_frame = (video_frame.GetNativeHandle() != nullptr)
|
|
|
|
|
? CricketToJavaTextureFrame(&video_frame)
|
|
|
|
|
: CricketToJavaI420Frame(&video_frame);
|
2015-09-29 16:33:16 +02:00
|
|
|
// |j_callbacks_| is responsible for releasing |j_frame| with
|
|
|
|
|
// VideoRenderer.renderFrameDone().
|
2015-08-25 09:32:06 +02:00
|
|
|
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
|
|
|
|
|
CHECK_EXCEPTION(jni());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2015-09-29 16:33:16 +02:00
|
|
|
// Make a shallow copy of |frame| to be used with Java. The callee has
|
|
|
|
|
// ownership of the frame, and the frame should be released with
|
|
|
|
|
// VideoRenderer.releaseNativeFrame().
|
|
|
|
|
static jlong javaShallowCopy(const cricket::VideoFrame* frame) {
|
|
|
|
|
return jlongFromPointer(frame->Copy());
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// Return a VideoRenderer.I420Frame referring to the data in |frame|.
|
2014-09-15 17:52:42 +00:00
|
|
|
jobject CricketToJavaI420Frame(const cricket::VideoFrame* frame) {
|
2014-01-09 00:31:17 +00:00
|
|
|
jintArray strides = jni()->NewIntArray(3);
|
|
|
|
|
jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
|
Reland of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #1 id:1 of https://codereview.webrtc.org/1921493004/ )
Reason for revert:
Chrome has been updated, cl https://codereview.chromium.org/1919283005/
Original issue's description:
> Revert of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #5 id:80001 of https://codereview.webrtc.org/1901973002/ )
>
> Reason for revert:
> GetYPlane, GetYPitch etc is used by Chromium.
>
> Original issue's description:
> > Delete cricket::VideoFrame methods GetYPlane and GetYPitch.
> >
> > (And similarly for U and V). Also change video_frame_buffer method to
> > return a const ref to a scoped_ref_ptr.
> >
> > This cl is analogous to https://codereview.webrtc.org/1900673002/,
> > which delete corresponding methods in webrtc::VideoFrame.
> >
> > BUG=webrtc:5682
> >
> > Committed: https://crrev.com/1c27c6bf4cf0476dd2f09425509afaae4cdfe599
> > Cr-Commit-Position: refs/heads/master@{#12492}
>
> TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,nisse@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:5682
>
> Committed: https://crrev.com/b05f994bb6f3055c852891c8acb531aee916a668
> Cr-Commit-Position: refs/heads/master@{#12494}
TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,terelius@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:5682
Review-Url: https://codereview.webrtc.org/1923903002
Cr-Commit-Position: refs/heads/master@{#12559}
2016-04-29 02:56:00 -07:00
|
|
|
strides_array[0] = frame->video_frame_buffer()->StrideY();
|
|
|
|
|
strides_array[1] = frame->video_frame_buffer()->StrideU();
|
|
|
|
|
strides_array[2] = frame->video_frame_buffer()->StrideV();
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->ReleaseIntArrayElements(strides, strides_array, 0);
|
|
|
|
|
jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
|
Reland of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #1 id:1 of https://codereview.webrtc.org/1921493004/ )
Reason for revert:
Chrome has been updated, cl https://codereview.chromium.org/1919283005/
Original issue's description:
> Revert of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #5 id:80001 of https://codereview.webrtc.org/1901973002/ )
>
> Reason for revert:
> GetYPlane, GetYPitch etc is used by Chromium.
>
> Original issue's description:
> > Delete cricket::VideoFrame methods GetYPlane and GetYPitch.
> >
> > (And similarly for U and V). Also change video_frame_buffer method to
> > return a const ref to a scoped_ref_ptr.
> >
> > This cl is analogous to https://codereview.webrtc.org/1900673002/,
> > which delete corresponding methods in webrtc::VideoFrame.
> >
> > BUG=webrtc:5682
> >
> > Committed: https://crrev.com/1c27c6bf4cf0476dd2f09425509afaae4cdfe599
> > Cr-Commit-Position: refs/heads/master@{#12492}
>
> TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,nisse@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:5682
>
> Committed: https://crrev.com/b05f994bb6f3055c852891c8acb531aee916a668
> Cr-Commit-Position: refs/heads/master@{#12494}
TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,terelius@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:5682
Review-Url: https://codereview.webrtc.org/1923903002
Cr-Commit-Position: refs/heads/master@{#12559}
2016-04-29 02:56:00 -07:00
|
|
|
jobject y_buffer = jni()->NewDirectByteBuffer(
|
|
|
|
|
const_cast<uint8_t*>(frame->video_frame_buffer()->DataY()),
|
|
|
|
|
frame->video_frame_buffer()->StrideY() *
|
|
|
|
|
frame->video_frame_buffer()->height());
|
2016-04-04 00:57:29 -07:00
|
|
|
size_t chroma_size =
|
|
|
|
|
((frame->width() + 1) / 2) * ((frame->height() + 1) / 2);
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject u_buffer = jni()->NewDirectByteBuffer(
|
Reland of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #1 id:1 of https://codereview.webrtc.org/1921493004/ )
Reason for revert:
Chrome has been updated, cl https://codereview.chromium.org/1919283005/
Original issue's description:
> Revert of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #5 id:80001 of https://codereview.webrtc.org/1901973002/ )
>
> Reason for revert:
> GetYPlane, GetYPitch etc is used by Chromium.
>
> Original issue's description:
> > Delete cricket::VideoFrame methods GetYPlane and GetYPitch.
> >
> > (And similarly for U and V). Also change video_frame_buffer method to
> > return a const ref to a scoped_ref_ptr.
> >
> > This cl is analogous to https://codereview.webrtc.org/1900673002/,
> > which delete corresponding methods in webrtc::VideoFrame.
> >
> > BUG=webrtc:5682
> >
> > Committed: https://crrev.com/1c27c6bf4cf0476dd2f09425509afaae4cdfe599
> > Cr-Commit-Position: refs/heads/master@{#12492}
>
> TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,nisse@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:5682
>
> Committed: https://crrev.com/b05f994bb6f3055c852891c8acb531aee916a668
> Cr-Commit-Position: refs/heads/master@{#12494}
TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,terelius@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:5682
Review-Url: https://codereview.webrtc.org/1923903002
Cr-Commit-Position: refs/heads/master@{#12559}
2016-04-29 02:56:00 -07:00
|
|
|
const_cast<uint8_t*>(frame->video_frame_buffer()->DataU()),
|
|
|
|
|
chroma_size);
|
2014-01-09 00:31:17 +00:00
|
|
|
jobject v_buffer = jni()->NewDirectByteBuffer(
|
Reland of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #1 id:1 of https://codereview.webrtc.org/1921493004/ )
Reason for revert:
Chrome has been updated, cl https://codereview.chromium.org/1919283005/
Original issue's description:
> Revert of Delete cricket::VideoFrame methods GetYPlane and GetYPitch. (patchset #5 id:80001 of https://codereview.webrtc.org/1901973002/ )
>
> Reason for revert:
> GetYPlane, GetYPitch etc is used by Chromium.
>
> Original issue's description:
> > Delete cricket::VideoFrame methods GetYPlane and GetYPitch.
> >
> > (And similarly for U and V). Also change video_frame_buffer method to
> > return a const ref to a scoped_ref_ptr.
> >
> > This cl is analogous to https://codereview.webrtc.org/1900673002/,
> > which delete corresponding methods in webrtc::VideoFrame.
> >
> > BUG=webrtc:5682
> >
> > Committed: https://crrev.com/1c27c6bf4cf0476dd2f09425509afaae4cdfe599
> > Cr-Commit-Position: refs/heads/master@{#12492}
>
> TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,nisse@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:5682
>
> Committed: https://crrev.com/b05f994bb6f3055c852891c8acb531aee916a668
> Cr-Commit-Position: refs/heads/master@{#12494}
TBR=magjed@webrtc.org,perkj@webrtc.org,pbos@webrtc.org,pthatcher@webrtc.org,terelius@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:5682
Review-Url: https://codereview.webrtc.org/1923903002
Cr-Commit-Position: refs/heads/master@{#12559}
2016-04-29 02:56:00 -07:00
|
|
|
const_cast<uint8_t*>(frame->video_frame_buffer()->DataV()),
|
|
|
|
|
chroma_size);
|
2014-01-09 00:31:17 +00:00
|
|
|
jni()->SetObjectArrayElement(planes, 0, y_buffer);
|
|
|
|
|
jni()->SetObjectArrayElement(planes, 1, u_buffer);
|
|
|
|
|
jni()->SetObjectArrayElement(planes, 2, v_buffer);
|
2013-07-10 00:45:36 +00:00
|
|
|
return jni()->NewObject(
|
2014-09-15 17:52:42 +00:00
|
|
|
*j_frame_class_, j_i420_frame_ctor_id_,
|
2016-04-04 00:57:29 -07:00
|
|
|
frame->width(), frame->height(),
|
2016-04-13 03:29:16 -07:00
|
|
|
static_cast<int>(frame->rotation()),
|
2015-09-29 16:33:16 +02:00
|
|
|
strides, planes, javaShallowCopy(frame));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-15 17:52:42 +00:00
|
|
|
// Return a VideoRenderer.I420Frame referring texture object in |frame|.
|
|
|
|
|
jobject CricketToJavaTextureFrame(const cricket::VideoFrame* frame) {
|
|
|
|
|
NativeHandleImpl* handle =
|
|
|
|
|
reinterpret_cast<NativeHandleImpl*>(frame->GetNativeHandle());
|
2015-11-19 10:43:36 +01:00
|
|
|
jfloatArray sampling_matrix = jni()->NewFloatArray(16);
|
|
|
|
|
jni()->SetFloatArrayRegion(sampling_matrix, 0, 16, handle->sampling_matrix);
|
2014-09-15 17:52:42 +00:00
|
|
|
return jni()->NewObject(
|
|
|
|
|
*j_frame_class_, j_texture_frame_ctor_id_,
|
2016-04-04 00:57:29 -07:00
|
|
|
frame->width(), frame->height(),
|
2016-04-13 03:29:16 -07:00
|
|
|
static_cast<int>(frame->rotation()),
|
2015-11-19 10:43:36 +01:00
|
|
|
handle->oes_texture_id, sampling_matrix, javaShallowCopy(frame));
|
2014-09-15 17:52:42 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JNIEnv* jni() {
|
|
|
|
|
return AttachCurrentThreadIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
ScopedGlobalRef<jobject> j_callbacks_;
|
2013-07-10 00:45:36 +00:00
|
|
|
jmethodID j_render_frame_id_;
|
2013-07-12 16:04:50 +00:00
|
|
|
ScopedGlobalRef<jclass> j_frame_class_;
|
2014-09-15 17:52:42 +00:00
|
|
|
jmethodID j_i420_frame_ctor_id_;
|
|
|
|
|
jmethodID j_texture_frame_ctor_id_;
|
2013-07-12 16:04:50 +00:00
|
|
|
ScopedGlobalRef<jclass> j_byte_buffer_class_;
|
2013-07-10 00:45:36 +00:00
|
|
|
};
|
|
|
|
|
|
2015-02-11 11:26:56 +00:00
|
|
|
|
2013-08-12 23:26:21 +00:00
|
|
|
static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
|
2013-07-12 16:04:50 +00:00
|
|
|
jfieldID native_dc_id = GetFieldID(jni,
|
|
|
|
|
GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
|
|
|
|
|
jlong j_d = GetLongField(jni, j_dc, native_dc_id);
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<DataChannelInterface*>(j_d);
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, DataChannel_registerObserverNative)(
|
|
|
|
|
JNIEnv* jni, jobject j_dc, jobject j_observer) {
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<DataChannelObserverWrapper> observer(
|
2013-07-12 16:04:50 +00:00
|
|
|
new DataChannelObserverWrapper(jni, j_observer));
|
|
|
|
|
ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
|
2013-12-11 21:07:18 +00:00
|
|
|
return jlongFromPointer(observer.release());
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, DataChannel_unregisterObserverNative)(
|
|
|
|
|
JNIEnv* jni, jobject j_dc, jlong native_observer) {
|
|
|
|
|
ExtractNativeDC(jni, j_dc)->UnregisterObserver();
|
|
|
|
|
delete reinterpret_cast<DataChannelObserverWrapper*>(native_observer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jstring, DataChannel_label)(JNIEnv* jni, jobject j_dc) {
|
|
|
|
|
return JavaStringFromStdString(jni, ExtractNativeDC(jni, j_dc)->label());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, DataChannel_state)(JNIEnv* jni, jobject j_dc) {
|
|
|
|
|
return JavaEnumFromIndex(
|
|
|
|
|
jni, "DataChannel$State", ExtractNativeDC(jni, j_dc)->state());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, DataChannel_bufferedAmount)(JNIEnv* jni, jobject j_dc) {
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint64_t buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
|
|
|
|
|
RTC_CHECK_LE(buffered_amount, std::numeric_limits<int64_t>::max())
|
2014-09-09 11:45:44 +00:00
|
|
|
<< "buffered_amount overflowed jlong!";
|
2013-07-12 16:04:50 +00:00
|
|
|
return static_cast<jlong>(buffered_amount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, DataChannel_close)(JNIEnv* jni, jobject j_dc) {
|
|
|
|
|
ExtractNativeDC(jni, j_dc)->Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, DataChannel_sendNative)(JNIEnv* jni, jobject j_dc,
|
|
|
|
|
jbyteArray data, jboolean binary) {
|
|
|
|
|
jbyte* bytes = jni->GetByteArrayElements(data, NULL);
|
|
|
|
|
bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
|
2016-03-20 06:15:43 -07:00
|
|
|
rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data)),
|
2013-07-12 16:04:50 +00:00
|
|
|
binary));
|
|
|
|
|
jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, DataChannel_dispose)(JNIEnv* jni, jobject j_dc) {
|
2013-08-12 23:26:21 +00:00
|
|
|
CHECK_RELEASE(ExtractNativeDC(jni, j_dc));
|
2013-07-12 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-08-06 19:00:53 +00:00
|
|
|
JOW(void, Logging_nativeEnableTracing)(
|
|
|
|
|
JNIEnv* jni, jclass, jstring j_path, jint nativeLevels,
|
|
|
|
|
jint nativeSeverity) {
|
|
|
|
|
std::string path = JavaToStdString(jni, j_path);
|
|
|
|
|
if (nativeLevels != webrtc::kTraceNone) {
|
2013-09-05 16:40:43 +00:00
|
|
|
webrtc::Trace::set_level_filter(nativeLevels);
|
2013-10-01 02:40:43 +00:00
|
|
|
if (path != "logcat:") {
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK_EQ(0, webrtc::Trace::SetTraceFile(path.c_str(), false))
|
2014-09-09 11:45:44 +00:00
|
|
|
<< "SetTraceFile failed";
|
2013-10-01 02:40:43 +00:00
|
|
|
} else {
|
|
|
|
|
// Intentionally leak this to avoid needing to reason about its lifecycle.
|
|
|
|
|
// It keeps no state and functions only as a dispatch point.
|
|
|
|
|
static LogcatTraceContext* g_trace_callback = new LogcatTraceContext();
|
|
|
|
|
}
|
2013-08-06 19:00:53 +00:00
|
|
|
}
|
2015-05-23 09:54:07 +02:00
|
|
|
if (nativeSeverity >= rtc::LS_SENSITIVE && nativeSeverity <= rtc::LS_ERROR) {
|
|
|
|
|
rtc::LogMessage::LogToDebug(
|
|
|
|
|
static_cast<rtc::LoggingSeverity>(nativeSeverity));
|
|
|
|
|
}
|
2013-08-06 19:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2015-09-01 16:11:18 -07:00
|
|
|
JOW(void, Logging_nativeEnableLogThreads)(JNIEnv* jni, jclass) {
|
|
|
|
|
rtc::LogMessage::LogThreads(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, Logging_nativeEnableLogTimeStamps)(JNIEnv* jni, jclass) {
|
|
|
|
|
rtc::LogMessage::LogTimestamps(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, Logging_nativeLog)(
|
2015-09-14 15:06:39 -07:00
|
|
|
JNIEnv* jni, jclass, jint j_severity, jstring j_tag, jstring j_message) {
|
2015-09-01 16:11:18 -07:00
|
|
|
std::string message = JavaToStdString(jni, j_message);
|
2015-09-14 15:06:39 -07:00
|
|
|
std::string tag = JavaToStdString(jni, j_tag);
|
|
|
|
|
LOG_TAG(static_cast<rtc::LoggingSeverity>(j_severity), tag) << message;
|
2015-09-01 16:11:18 -07:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(void, PeerConnection_freePeerConnection)(JNIEnv*, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
CHECK_RELEASE(reinterpret_cast<PeerConnectionInterface*>(j_p));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_freeObserver)(JNIEnv*, jclass, jlong j_p) {
|
|
|
|
|
PCOJava* p = reinterpret_cast<PCOJava*>(j_p);
|
|
|
|
|
delete p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, MediaSource_free)(JNIEnv*, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
CHECK_RELEASE(reinterpret_cast<MediaSourceInterface*>(j_p));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-17 03:26:59 +00:00
|
|
|
JOW(void, VideoRenderer_freeWrappedVideoRenderer)(JNIEnv*, jclass, jlong j_p) {
|
|
|
|
|
delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-29 15:57:43 +02:00
|
|
|
JOW(void, VideoRenderer_releaseNativeFrame)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_frame_ptr) {
|
|
|
|
|
delete reinterpret_cast<const cricket::VideoFrame*>(j_frame_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(void, MediaStreamTrack_free)(JNIEnv*, jclass, jlong j_p) {
|
2015-10-06 12:29:25 -07:00
|
|
|
reinterpret_cast<MediaStreamTrackInterface*>(j_p)->Release();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStream_nativeAddAudioTrack)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamInterface*>(pointer)->AddTrack(
|
2013-07-10 00:45:36 +00:00
|
|
|
reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStream_nativeAddVideoTrack)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamInterface*>(pointer)
|
|
|
|
|
->AddTrack(reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStream_nativeRemoveAudioTrack)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong pointer, jlong j_audio_track_pointer) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
|
2013-07-10 00:45:36 +00:00
|
|
|
reinterpret_cast<AudioTrackInterface*>(j_audio_track_pointer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStream_nativeRemoveVideoTrack)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong pointer, jlong j_video_track_pointer) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamInterface*>(pointer)->RemoveTrack(
|
2013-07-10 00:45:36 +00:00
|
|
|
reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jstring, MediaStream_nativeLabel)(JNIEnv* jni, jclass, jlong j_p) {
|
|
|
|
|
return JavaStringFromStdString(
|
|
|
|
|
jni, reinterpret_cast<MediaStreamInterface*>(j_p)->label());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, MediaStream_free)(JNIEnv*, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
|
|
|
|
|
JNIEnv * jni, jclass, jobject j_observer) {
|
|
|
|
|
return (jlong)new PCOJava(jni, j_observer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, PeerConnectionFactory_initializeAndroidGlobals)(
|
2014-05-14 22:00:50 +00:00
|
|
|
JNIEnv* jni, jclass, jobject context,
|
2014-09-15 17:52:42 +00:00
|
|
|
jboolean initialize_audio, jboolean initialize_video,
|
2015-09-01 15:04:13 -07:00
|
|
|
jboolean video_hw_acceleration) {
|
2013-07-10 00:45:36 +00:00
|
|
|
bool failure = false;
|
2015-09-01 15:04:13 -07:00
|
|
|
video_hw_acceleration_enabled = video_hw_acceleration;
|
2015-10-19 09:39:32 -07:00
|
|
|
AndroidNetworkMonitor::SetAndroidContext(jni, context);
|
2014-09-15 17:52:42 +00:00
|
|
|
if (!factory_static_initialized) {
|
2014-09-17 11:44:51 +00:00
|
|
|
if (initialize_video) {
|
2015-02-11 11:26:56 +00:00
|
|
|
failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
|
2014-09-17 11:44:51 +00:00
|
|
|
}
|
2014-09-15 17:52:42 +00:00
|
|
|
if (initialize_audio)
|
2015-03-09 12:39:53 +00:00
|
|
|
failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), context);
|
2014-09-15 17:52:42 +00:00
|
|
|
factory_static_initialized = true;
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
return !failure;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-09 23:25:58 +00:00
|
|
|
JOW(void, PeerConnectionFactory_initializeFieldTrials)(
|
|
|
|
|
JNIEnv* jni, jclass, jstring j_trials_init_string) {
|
|
|
|
|
field_trials_init_string = NULL;
|
|
|
|
|
if (j_trials_init_string != NULL) {
|
|
|
|
|
const char* init_string =
|
|
|
|
|
jni->GetStringUTFChars(j_trials_init_string, NULL);
|
|
|
|
|
int init_string_length = jni->GetStringUTFLength(j_trials_init_string);
|
|
|
|
|
field_trials_init_string = new char[init_string_length + 1];
|
|
|
|
|
rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
|
|
|
|
|
jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
|
2015-02-13 12:46:51 +00:00
|
|
|
LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
|
2015-02-09 23:25:58 +00:00
|
|
|
}
|
|
|
|
|
webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 23:17:15 +01:00
|
|
|
JOW(void, PeerConnectionFactory_initializeInternalTracer)(JNIEnv* jni, jclass) {
|
|
|
|
|
rtc::tracing::SetupInternalTracer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, PeerConnectionFactory_startInternalTracingCapture)(
|
|
|
|
|
JNIEnv* jni, jclass, jstring j_event_tracing_filename) {
|
|
|
|
|
if (!j_event_tracing_filename)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const char* init_string =
|
|
|
|
|
jni->GetStringUTFChars(j_event_tracing_filename, NULL);
|
|
|
|
|
LOG(LS_INFO) << "Starting internal tracing to: " << init_string;
|
|
|
|
|
bool ret = rtc::tracing::StartInternalCapture(init_string);
|
|
|
|
|
jni->ReleaseStringUTFChars(j_event_tracing_filename, init_string);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnectionFactory_stopInternalTracingCapture)(
|
|
|
|
|
JNIEnv* jni, jclass) {
|
|
|
|
|
rtc::tracing::StopInternalCapture();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnectionFactory_shutdownInternalTracer)(JNIEnv* jni, jclass) {
|
|
|
|
|
rtc::tracing::ShutdownInternalTracer();
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-13 03:56:14 +00:00
|
|
|
// Helper struct for working around the fact that CreatePeerConnectionFactory()
|
|
|
|
|
// comes in two flavors: either entirely automagical (constructing its own
|
|
|
|
|
// threads and deleting them on teardown, but no external codec factory support)
|
|
|
|
|
// or entirely manual (requires caller to delete threads after factory
|
|
|
|
|
// teardown). This struct takes ownership of its ctor's arguments to present a
|
|
|
|
|
// single thing for Java to hold and eventually free.
|
|
|
|
|
class OwnedFactoryAndThreads {
|
|
|
|
|
public:
|
|
|
|
|
OwnedFactoryAndThreads(Thread* worker_thread,
|
|
|
|
|
Thread* signaling_thread,
|
2015-09-01 15:04:13 -07:00
|
|
|
WebRtcVideoEncoderFactory* encoder_factory,
|
|
|
|
|
WebRtcVideoDecoderFactory* decoder_factory,
|
2015-10-19 09:39:32 -07:00
|
|
|
rtc::NetworkMonitorFactory* network_monitor_factory,
|
2014-02-13 03:56:14 +00:00
|
|
|
PeerConnectionFactoryInterface* factory)
|
|
|
|
|
: worker_thread_(worker_thread),
|
|
|
|
|
signaling_thread_(signaling_thread),
|
2015-09-01 15:04:13 -07:00
|
|
|
encoder_factory_(encoder_factory),
|
|
|
|
|
decoder_factory_(decoder_factory),
|
2015-10-19 09:39:32 -07:00
|
|
|
network_monitor_factory_(network_monitor_factory),
|
2014-02-13 03:56:14 +00:00
|
|
|
factory_(factory) {}
|
|
|
|
|
|
2015-10-19 09:39:32 -07:00
|
|
|
~OwnedFactoryAndThreads() {
|
|
|
|
|
CHECK_RELEASE(factory_);
|
|
|
|
|
if (network_monitor_factory_ != nullptr) {
|
|
|
|
|
rtc::NetworkMonitorFactory::ReleaseFactory(network_monitor_factory_);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-02-13 03:56:14 +00:00
|
|
|
|
|
|
|
|
PeerConnectionFactoryInterface* factory() { return factory_; }
|
2015-09-01 15:04:13 -07:00
|
|
|
WebRtcVideoEncoderFactory* encoder_factory() { return encoder_factory_; }
|
|
|
|
|
WebRtcVideoDecoderFactory* decoder_factory() { return decoder_factory_; }
|
2015-10-19 09:39:32 -07:00
|
|
|
rtc::NetworkMonitorFactory* network_monitor_factory() {
|
|
|
|
|
return network_monitor_factory_;
|
|
|
|
|
}
|
|
|
|
|
void clear_network_monitor_factory() { network_monitor_factory_ = nullptr; }
|
2015-10-07 14:50:13 -07:00
|
|
|
void InvokeJavaCallbacksOnFactoryThreads();
|
2014-02-13 03:56:14 +00:00
|
|
|
|
|
|
|
|
private:
|
2015-10-07 14:50:13 -07:00
|
|
|
void JavaCallbackOnFactoryThreads();
|
|
|
|
|
|
2016-04-27 06:47:29 -07:00
|
|
|
const std::unique_ptr<Thread> worker_thread_;
|
|
|
|
|
const std::unique_ptr<Thread> signaling_thread_;
|
2015-09-01 15:04:13 -07:00
|
|
|
WebRtcVideoEncoderFactory* encoder_factory_;
|
|
|
|
|
WebRtcVideoDecoderFactory* decoder_factory_;
|
2015-10-19 09:39:32 -07:00
|
|
|
rtc::NetworkMonitorFactory* network_monitor_factory_;
|
2014-02-13 03:56:14 +00:00
|
|
|
PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
|
|
|
|
|
};
|
|
|
|
|
|
2015-10-07 14:50:13 -07:00
|
|
|
void OwnedFactoryAndThreads::JavaCallbackOnFactoryThreads() {
|
|
|
|
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
|
|
|
ScopedLocalRefFrame local_ref_frame(jni);
|
|
|
|
|
jclass j_factory_class = FindClass(jni, "org/webrtc/PeerConnectionFactory");
|
|
|
|
|
jmethodID m = nullptr;
|
2016-03-29 10:17:42 -07:00
|
|
|
if (Thread::Current() == worker_thread_.get()) {
|
2015-10-07 14:50:13 -07:00
|
|
|
LOG(LS_INFO) << "Worker thread JavaCallback";
|
|
|
|
|
m = GetStaticMethodID(jni, j_factory_class, "onWorkerThreadReady", "()V");
|
|
|
|
|
}
|
2016-03-29 10:17:42 -07:00
|
|
|
if (Thread::Current() == signaling_thread_.get()) {
|
2015-10-07 14:50:13 -07:00
|
|
|
LOG(LS_INFO) << "Signaling thread JavaCallback";
|
|
|
|
|
m = GetStaticMethodID(
|
|
|
|
|
jni, j_factory_class, "onSignalingThreadReady", "()V");
|
|
|
|
|
}
|
|
|
|
|
if (m != nullptr) {
|
|
|
|
|
jni->CallStaticVoidMethod(j_factory_class, m);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during JavaCallback::CallStaticVoidMethod";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OwnedFactoryAndThreads::InvokeJavaCallbacksOnFactoryThreads() {
|
|
|
|
|
LOG(LS_INFO) << "InvokeJavaCallbacksOnFactoryThreads.";
|
|
|
|
|
worker_thread_->Invoke<void>(
|
|
|
|
|
Bind(&OwnedFactoryAndThreads::JavaCallbackOnFactoryThreads, this));
|
|
|
|
|
signaling_thread_->Invoke<void>(
|
|
|
|
|
Bind(&OwnedFactoryAndThreads::JavaCallbackOnFactoryThreads, this));
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-14 14:45:38 -08:00
|
|
|
PeerConnectionFactoryInterface::Options ParseOptionsFromJava(JNIEnv* jni,
|
|
|
|
|
jobject options) {
|
|
|
|
|
jclass options_class = jni->GetObjectClass(options);
|
|
|
|
|
jfieldID network_ignore_mask_field =
|
|
|
|
|
jni->GetFieldID(options_class, "networkIgnoreMask", "I");
|
|
|
|
|
int network_ignore_mask =
|
|
|
|
|
jni->GetIntField(options, network_ignore_mask_field);
|
|
|
|
|
|
|
|
|
|
jfieldID disable_encryption_field =
|
|
|
|
|
jni->GetFieldID(options_class, "disableEncryption", "Z");
|
|
|
|
|
bool disable_encryption =
|
|
|
|
|
jni->GetBooleanField(options, disable_encryption_field);
|
|
|
|
|
|
|
|
|
|
jfieldID disable_network_monitor_field =
|
|
|
|
|
jni->GetFieldID(options_class, "disableNetworkMonitor", "Z");
|
|
|
|
|
bool disable_network_monitor =
|
|
|
|
|
jni->GetBooleanField(options, disable_network_monitor_field);
|
|
|
|
|
|
|
|
|
|
PeerConnectionFactoryInterface::Options native_options;
|
|
|
|
|
|
|
|
|
|
// This doesn't necessarily match the c++ version of this struct; feel free
|
|
|
|
|
// to add more parameters as necessary.
|
|
|
|
|
native_options.network_ignore_mask = network_ignore_mask;
|
|
|
|
|
native_options.disable_encryption = disable_encryption;
|
|
|
|
|
native_options.disable_network_monitor = disable_network_monitor;
|
|
|
|
|
return native_options;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
|
2016-01-14 14:45:38 -08:00
|
|
|
JNIEnv* jni, jclass, jobject joptions) {
|
2014-05-14 17:33:32 +00:00
|
|
|
// talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
|
|
|
|
|
// ThreadManager only WrapCurrentThread()s the thread where it is first
|
|
|
|
|
// created. Since the semantics around when auto-wrapping happens in
|
2014-07-29 17:36:52 +00:00
|
|
|
// webrtc/base/ are convoluted, we simply wrap here to avoid having to think
|
2014-05-14 17:33:32 +00:00
|
|
|
// about ramifications of auto-wrapping there.
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::ThreadManager::Instance()->WrapCurrentThread();
|
2013-08-12 23:26:21 +00:00
|
|
|
webrtc::Trace::CreateTrace();
|
2014-02-13 03:56:14 +00:00
|
|
|
Thread* worker_thread = new Thread();
|
|
|
|
|
worker_thread->SetName("worker_thread", NULL);
|
|
|
|
|
Thread* signaling_thread = new Thread();
|
|
|
|
|
signaling_thread->SetName("signaling_thread", NULL);
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(worker_thread->Start() && signaling_thread->Start())
|
2014-09-09 11:45:44 +00:00
|
|
|
<< "Failed to start threads";
|
2015-09-01 15:04:13 -07:00
|
|
|
WebRtcVideoEncoderFactory* encoder_factory = nullptr;
|
|
|
|
|
WebRtcVideoDecoderFactory* decoder_factory = nullptr;
|
2015-10-19 09:39:32 -07:00
|
|
|
rtc::NetworkMonitorFactory* network_monitor_factory = nullptr;
|
|
|
|
|
|
2016-01-14 14:45:38 -08:00
|
|
|
PeerConnectionFactoryInterface::Options options;
|
|
|
|
|
bool has_options = joptions != NULL;
|
|
|
|
|
if (has_options) {
|
|
|
|
|
options = ParseOptionsFromJava(jni, joptions);
|
|
|
|
|
}
|
2016-02-08 01:07:19 -08:00
|
|
|
|
2015-09-01 15:04:13 -07:00
|
|
|
if (video_hw_acceleration_enabled) {
|
|
|
|
|
encoder_factory = new MediaCodecVideoEncoderFactory();
|
|
|
|
|
decoder_factory = new MediaCodecVideoDecoderFactory();
|
2014-12-01 20:02:13 +00:00
|
|
|
}
|
2016-01-14 14:45:38 -08:00
|
|
|
// 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)) {
|
|
|
|
|
network_monitor_factory = new AndroidNetworkMonitorFactory();
|
|
|
|
|
rtc::NetworkMonitorFactory::SetFactory(network_monitor_factory);
|
|
|
|
|
}
|
2016-02-08 01:07:19 -08:00
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 03:56:14 +00:00
|
|
|
webrtc::CreatePeerConnectionFactory(worker_thread,
|
|
|
|
|
signaling_thread,
|
|
|
|
|
NULL,
|
2015-09-01 15:04:13 -07:00
|
|
|
encoder_factory,
|
|
|
|
|
decoder_factory));
|
2015-09-17 17:20:38 +02:00
|
|
|
RTC_CHECK(factory) << "Failed to create the peer connection factory; "
|
|
|
|
|
<< "WebRTC/libjingle init likely failed on this device";
|
2016-01-14 14:45:38 -08:00
|
|
|
// TODO(honghaiz): Maybe put the options as the argument of
|
|
|
|
|
// CreatePeerConnectionFactory.
|
|
|
|
|
if (has_options) {
|
|
|
|
|
factory->SetOptions(options);
|
|
|
|
|
}
|
2014-02-13 03:56:14 +00:00
|
|
|
OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
|
2015-09-01 15:04:13 -07:00
|
|
|
worker_thread, signaling_thread,
|
|
|
|
|
encoder_factory, decoder_factory,
|
2015-10-19 09:39:32 -07:00
|
|
|
network_monitor_factory, factory.release());
|
2015-10-07 14:50:13 -07:00
|
|
|
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
|
2014-02-13 03:56:14 +00:00
|
|
|
return jlongFromPointer(owned_factory);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-07 14:50:13 -07:00
|
|
|
JOW(void, PeerConnectionFactory_nativeFreeFactory)(JNIEnv*, jclass, jlong j_p) {
|
2014-02-13 03:56:14 +00:00
|
|
|
delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
|
2015-02-09 23:25:58 +00:00
|
|
|
if (field_trials_init_string) {
|
|
|
|
|
webrtc::field_trial::InitFieldTrialsFromString(NULL);
|
|
|
|
|
delete field_trials_init_string;
|
|
|
|
|
field_trials_init_string = NULL;
|
|
|
|
|
}
|
2013-08-12 23:26:21 +00:00
|
|
|
webrtc::Trace::ReturnTrace();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-02-13 03:56:14 +00:00
|
|
|
static PeerConnectionFactoryInterface* factoryFromJava(jlong j_p) {
|
|
|
|
|
return reinterpret_cast<OwnedFactoryAndThreads*>(j_p)->factory();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 14:50:13 -07:00
|
|
|
JOW(void, PeerConnectionFactory_nativeThreadsCallbacks)(
|
|
|
|
|
JNIEnv*, jclass, jlong j_p) {
|
|
|
|
|
OwnedFactoryAndThreads *factory =
|
|
|
|
|
reinterpret_cast<OwnedFactoryAndThreads*>(j_p);
|
|
|
|
|
factory->InvokeJavaCallbacksOnFactoryThreads();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jstring label) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 03:56:14 +00:00
|
|
|
factoryFromJava(native_factory));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<MediaStreamInterface> stream(
|
2013-07-10 00:45:36 +00:00
|
|
|
factory->CreateLocalMediaStream(JavaToStdString(jni, label)));
|
|
|
|
|
return (jlong)stream.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateVideoSource)(
|
2016-03-14 03:59:38 -07:00
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jobject j_egl_context,
|
|
|
|
|
jobject j_video_capturer, jobject j_constraints) {
|
2016-02-12 17:05:29 +01:00
|
|
|
// Create a cricket::VideoCapturer from |j_video_capturer|.
|
|
|
|
|
rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate =
|
|
|
|
|
new rtc::RefCountedObject<AndroidVideoCapturerJni>(
|
2016-03-14 03:59:38 -07:00
|
|
|
jni, j_video_capturer, j_egl_context);
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<cricket::VideoCapturer> capturer(
|
2016-02-12 17:05:29 +01:00
|
|
|
new webrtc::AndroidVideoCapturer(delegate));
|
2016-03-08 01:27:48 +01:00
|
|
|
// Create a webrtc::VideoTrackSourceInterface from the cricket::VideoCapturer,
|
2016-02-12 17:05:29 +01:00
|
|
|
// native factory and constraints.
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<ConstraintsWrapper> constraints(
|
2013-07-10 00:45:36 +00:00
|
|
|
new ConstraintsWrapper(jni, j_constraints));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 03:56:14 +00:00
|
|
|
factoryFromJava(native_factory));
|
2016-03-08 01:27:48 +01:00
|
|
|
rtc::scoped_refptr<VideoTrackSourceInterface> source(
|
2016-02-12 17:05:29 +01:00
|
|
|
factory->CreateVideoSource(capturer.release(), constraints.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
return (jlong)source.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateVideoTrack)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jstring id,
|
|
|
|
|
jlong native_source) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 03:56:14 +00:00
|
|
|
factoryFromJava(native_factory));
|
2016-03-08 01:27:48 +01:00
|
|
|
rtc::scoped_refptr<VideoTrackInterface> track(factory->CreateVideoTrack(
|
|
|
|
|
JavaToStdString(jni, id),
|
|
|
|
|
reinterpret_cast<VideoTrackSourceInterface*>(native_source)));
|
2013-07-10 00:45:36 +00:00
|
|
|
return (jlong)track.release();
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-13 04:01:04 +00:00
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) {
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<ConstraintsWrapper> constraints(
|
2014-02-13 04:01:04 +00:00
|
|
|
new ConstraintsWrapper(jni, j_constraints));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 04:01:04 +00:00
|
|
|
factoryFromJava(native_factory));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<AudioSourceInterface> source(
|
2014-02-13 04:01:04 +00:00
|
|
|
factory->CreateAudioSource(constraints.get()));
|
|
|
|
|
return (jlong)source.release();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack)(
|
2014-02-13 04:01:04 +00:00
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jstring id,
|
|
|
|
|
jlong native_source) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
2014-02-13 03:56:14 +00:00
|
|
|
factoryFromJava(native_factory));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<AudioTrackInterface> track(factory->CreateAudioTrack(
|
2014-02-13 04:01:04 +00:00
|
|
|
JavaToStdString(jni, id),
|
|
|
|
|
reinterpret_cast<AudioSourceInterface*>(native_source)));
|
2013-07-10 00:45:36 +00:00
|
|
|
return (jlong)track.release();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-24 09:00:36 -08:00
|
|
|
JOW(jboolean, PeerConnectionFactory_nativeStartAecDump)(
|
2016-01-15 03:06:36 -08:00
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jint file,
|
|
|
|
|
jint filesize_limit_bytes) {
|
2015-11-24 09:00:36 -08:00
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
|
|
|
|
factoryFromJava(native_factory));
|
2016-01-15 03:06:36 -08:00
|
|
|
return factory->StartAecDump(file, filesize_limit_bytes);
|
2015-11-24 09:00:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnectionFactory_nativeStopAecDump)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory) {
|
|
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
|
|
|
|
factoryFromJava(native_factory));
|
|
|
|
|
factory->StopAecDump();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, PeerConnectionFactory_nativeStartRtcEventLog)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jint file) {
|
|
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
|
|
|
|
factoryFromJava(native_factory));
|
|
|
|
|
return factory->StartRtcEventLog(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnectionFactory_nativeStopRtcEventLog)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory) {
|
|
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
|
|
|
|
factoryFromJava(native_factory));
|
|
|
|
|
factory->StopRtcEventLog();
|
|
|
|
|
}
|
|
|
|
|
|
Makes libjingle_peerconnection_android_unittest run on networkless devices.
PeerConnectionTest.java currently works, but only on a device with
network interfaces up. This is not a problem for desktop, but it is a
problem when running on Android devices since the devices in the lab
generally don't have network (due to the chaotic radio environment in
the device labs, devices are simply kept in flight mode).
The test does work if one modifies this line in the file
webrtc/base/network.cc:
bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) ||
IsIgnoredNetwork(*network));
If we remove the IFF_LOOPBACK clause, the test starts working on
an Android device in flight mode. This is nice - we're running the
call and packets interact with the OS network stack, which is good
for this end-to-end test. We can't just remove the clause though since
having loopback is undesirable for everyone except the test (right)?
so we need to make this behavior configurable.
This CL takes a stab at a complete solution where we pass a boolean
all the way through the Java PeerConnectionFactory down to the
BasicNetworkManager. This comes as a heavy price in interface
changes though. It's pretty out of proportion, but fundamentally we
need some way of telling the network manager that it is on Android
and in test mode. Passing the boolean all the way through is one way.
Another way might be to put the loopback filter behind an ifdef and
link a custom libjingle_peerconnection.so with the test. That is hacky
but doesn't pollute the interfaces. Not sure how to solve that in GYP
but it could mean some duplication between the production and
test .so files.
It would have been perfect to use flags here, but then we need to
hook up gflags parsing to some main() somewhere to make sure the
flag gets parsed, and make sure to pass that flag in our tests.
I'm not sure how that can be done.
Making the loopback filtering conditional is exactly how we solved the
equivalent problem in content_browsertests in Chrome, and it worked
great.
That's all I could think of.
BUG=4181
R=perkj@webrtc.org, pthatcher@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/36769004
Cr-Commit-Position: refs/heads/master@{#8344}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8344 4adac7df-926f-26a2-2b94-8c16560cd09d
2015-02-12 09:23:59 +00:00
|
|
|
JOW(void, PeerConnectionFactory_nativeSetOptions)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jobject options) {
|
|
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
|
|
|
|
|
factoryFromJava(native_factory));
|
2016-01-14 14:45:38 -08:00
|
|
|
PeerConnectionFactoryInterface::Options options_to_set =
|
|
|
|
|
ParseOptionsFromJava(jni, options);
|
Makes libjingle_peerconnection_android_unittest run on networkless devices.
PeerConnectionTest.java currently works, but only on a device with
network interfaces up. This is not a problem for desktop, but it is a
problem when running on Android devices since the devices in the lab
generally don't have network (due to the chaotic radio environment in
the device labs, devices are simply kept in flight mode).
The test does work if one modifies this line in the file
webrtc/base/network.cc:
bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) ||
IsIgnoredNetwork(*network));
If we remove the IFF_LOOPBACK clause, the test starts working on
an Android device in flight mode. This is nice - we're running the
call and packets interact with the OS network stack, which is good
for this end-to-end test. We can't just remove the clause though since
having loopback is undesirable for everyone except the test (right)?
so we need to make this behavior configurable.
This CL takes a stab at a complete solution where we pass a boolean
all the way through the Java PeerConnectionFactory down to the
BasicNetworkManager. This comes as a heavy price in interface
changes though. It's pretty out of proportion, but fundamentally we
need some way of telling the network manager that it is on Android
and in test mode. Passing the boolean all the way through is one way.
Another way might be to put the loopback filter behind an ifdef and
link a custom libjingle_peerconnection.so with the test. That is hacky
but doesn't pollute the interfaces. Not sure how to solve that in GYP
but it could mean some duplication between the production and
test .so files.
It would have been perfect to use flags here, but then we need to
hook up gflags parsing to some main() somewhere to make sure the
flag gets parsed, and make sure to pass that flag in our tests.
I'm not sure how that can be done.
Making the loopback filtering conditional is exactly how we solved the
equivalent problem in content_browsertests in Chrome, and it worked
great.
That's all I could think of.
BUG=4181
R=perkj@webrtc.org, pthatcher@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/36769004
Cr-Commit-Position: refs/heads/master@{#8344}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8344 4adac7df-926f-26a2-2b94-8c16560cd09d
2015-02-12 09:23:59 +00:00
|
|
|
factory->SetOptions(options_to_set);
|
2016-01-14 15:56:26 -08:00
|
|
|
|
|
|
|
|
if (options_to_set.disable_network_monitor) {
|
|
|
|
|
OwnedFactoryAndThreads* owner =
|
|
|
|
|
reinterpret_cast<OwnedFactoryAndThreads*>(native_factory);
|
|
|
|
|
if (owner->network_monitor_factory()) {
|
|
|
|
|
rtc::NetworkMonitorFactory::ReleaseFactory(
|
|
|
|
|
owner->network_monitor_factory());
|
|
|
|
|
owner->clear_network_monitor_factory();
|
|
|
|
|
}
|
|
|
|
|
}
|
Makes libjingle_peerconnection_android_unittest run on networkless devices.
PeerConnectionTest.java currently works, but only on a device with
network interfaces up. This is not a problem for desktop, but it is a
problem when running on Android devices since the devices in the lab
generally don't have network (due to the chaotic radio environment in
the device labs, devices are simply kept in flight mode).
The test does work if one modifies this line in the file
webrtc/base/network.cc:
bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) ||
IsIgnoredNetwork(*network));
If we remove the IFF_LOOPBACK clause, the test starts working on
an Android device in flight mode. This is nice - we're running the
call and packets interact with the OS network stack, which is good
for this end-to-end test. We can't just remove the clause though since
having loopback is undesirable for everyone except the test (right)?
so we need to make this behavior configurable.
This CL takes a stab at a complete solution where we pass a boolean
all the way through the Java PeerConnectionFactory down to the
BasicNetworkManager. This comes as a heavy price in interface
changes though. It's pretty out of proportion, but fundamentally we
need some way of telling the network manager that it is on Android
and in test mode. Passing the boolean all the way through is one way.
Another way might be to put the loopback filter behind an ifdef and
link a custom libjingle_peerconnection.so with the test. That is hacky
but doesn't pollute the interfaces. Not sure how to solve that in GYP
but it could mean some duplication between the production and
test .so files.
It would have been perfect to use flags here, but then we need to
hook up gflags parsing to some main() somewhere to make sure the
flag gets parsed, and make sure to pass that flag in our tests.
I'm not sure how that can be done.
Making the loopback filtering conditional is exactly how we solved the
equivalent problem in content_browsertests in Chrome, and it worked
great.
That's all I could think of.
BUG=4181
R=perkj@webrtc.org, pthatcher@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/36769004
Cr-Commit-Position: refs/heads/master@{#8344}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8344 4adac7df-926f-26a2-2b94-8c16560cd09d
2015-02-12 09:23:59 +00:00
|
|
|
}
|
|
|
|
|
|
2015-09-01 15:04:13 -07:00
|
|
|
JOW(void, PeerConnectionFactory_nativeSetVideoHwAccelerationOptions)(
|
2015-11-20 01:31:25 -08:00
|
|
|
JNIEnv* jni, jclass, jlong native_factory, jobject local_egl_context,
|
|
|
|
|
jobject remote_egl_context) {
|
2015-09-01 15:04:13 -07:00
|
|
|
OwnedFactoryAndThreads* owned_factory =
|
|
|
|
|
reinterpret_cast<OwnedFactoryAndThreads*>(native_factory);
|
2015-11-20 01:31:25 -08:00
|
|
|
|
2015-12-18 00:34:37 -08:00
|
|
|
jclass j_eglbase14_context_class =
|
|
|
|
|
FindClass(jni, "org/webrtc/EglBase14$Context");
|
|
|
|
|
|
2015-11-20 01:31:25 -08:00
|
|
|
MediaCodecVideoEncoderFactory* encoder_factory =
|
|
|
|
|
static_cast<MediaCodecVideoEncoderFactory*>
|
|
|
|
|
(owned_factory->encoder_factory());
|
2015-12-18 00:34:37 -08:00
|
|
|
if (encoder_factory &&
|
|
|
|
|
jni->IsInstanceOf(local_egl_context, j_eglbase14_context_class)) {
|
2015-11-20 01:31:25 -08:00
|
|
|
LOG(LS_INFO) << "Set EGL context for HW encoding.";
|
2015-12-15 02:48:07 -08:00
|
|
|
encoder_factory->SetEGLContext(jni, local_egl_context);
|
2015-11-20 01:31:25 -08:00
|
|
|
}
|
|
|
|
|
|
2015-09-01 15:04:13 -07:00
|
|
|
MediaCodecVideoDecoderFactory* decoder_factory =
|
|
|
|
|
static_cast<MediaCodecVideoDecoderFactory*>
|
|
|
|
|
(owned_factory->decoder_factory());
|
2016-03-29 05:13:21 -07:00
|
|
|
if (decoder_factory) {
|
2015-11-20 01:31:25 -08:00
|
|
|
LOG(LS_INFO) << "Set EGL context for HW decoding.";
|
2015-12-15 02:48:07 -08:00
|
|
|
decoder_factory->SetEGLContext(jni, remote_egl_context);
|
2015-09-01 15:04:13 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-30 12:35:24 -07:00
|
|
|
static PeerConnectionInterface::IceTransportsType
|
|
|
|
|
JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$IceTransportsType",
|
|
|
|
|
j_ice_transports_type);
|
|
|
|
|
|
|
|
|
|
if (enum_name == "ALL")
|
|
|
|
|
return PeerConnectionInterface::kAll;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "RELAY")
|
|
|
|
|
return PeerConnectionInterface::kRelay;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "NOHOST")
|
|
|
|
|
return PeerConnectionInterface::kNoHost;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "NONE")
|
|
|
|
|
return PeerConnectionInterface::kNone;
|
|
|
|
|
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(false) << "Unexpected IceTransportsType enum_name " << enum_name;
|
2015-04-30 12:35:24 -07:00
|
|
|
return PeerConnectionInterface::kAll;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PeerConnectionInterface::BundlePolicy
|
|
|
|
|
JavaBundlePolicyToNativeType(JNIEnv* jni, jobject j_bundle_policy) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$BundlePolicy",
|
|
|
|
|
j_bundle_policy);
|
|
|
|
|
|
|
|
|
|
if (enum_name == "BALANCED")
|
|
|
|
|
return PeerConnectionInterface::kBundlePolicyBalanced;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "MAXBUNDLE")
|
|
|
|
|
return PeerConnectionInterface::kBundlePolicyMaxBundle;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "MAXCOMPAT")
|
|
|
|
|
return PeerConnectionInterface::kBundlePolicyMaxCompat;
|
|
|
|
|
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(false) << "Unexpected BundlePolicy enum_name " << enum_name;
|
2015-04-30 12:35:24 -07:00
|
|
|
return PeerConnectionInterface::kBundlePolicyBalanced;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 07:48:41 -07:00
|
|
|
static PeerConnectionInterface::RtcpMuxPolicy
|
|
|
|
|
JavaRtcpMuxPolicyToNativeType(JNIEnv* jni, jobject j_rtcp_mux_policy) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$RtcpMuxPolicy",
|
|
|
|
|
j_rtcp_mux_policy);
|
|
|
|
|
|
|
|
|
|
if (enum_name == "NEGOTIATE")
|
|
|
|
|
return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "REQUIRE")
|
|
|
|
|
return PeerConnectionInterface::kRtcpMuxPolicyRequire;
|
|
|
|
|
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(false) << "Unexpected RtcpMuxPolicy enum_name " << enum_name;
|
2015-05-21 07:48:41 -07:00
|
|
|
return PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-30 12:35:24 -07:00
|
|
|
static PeerConnectionInterface::TcpCandidatePolicy
|
|
|
|
|
JavaTcpCandidatePolicyToNativeType(
|
|
|
|
|
JNIEnv* jni, jobject j_tcp_candidate_policy) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$TcpCandidatePolicy",
|
|
|
|
|
j_tcp_candidate_policy);
|
|
|
|
|
|
|
|
|
|
if (enum_name == "ENABLED")
|
|
|
|
|
return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "DISABLED")
|
|
|
|
|
return PeerConnectionInterface::kTcpCandidatePolicyDisabled;
|
|
|
|
|
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(false) << "Unexpected TcpCandidatePolicy enum_name " << enum_name;
|
2015-04-30 12:35:24 -07:00
|
|
|
return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-01 11:31:27 -07:00
|
|
|
static rtc::KeyType JavaKeyTypeToNativeType(JNIEnv* jni, jobject j_key_type) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$KeyType", j_key_type);
|
|
|
|
|
|
|
|
|
|
if (enum_name == "RSA")
|
|
|
|
|
return rtc::KT_RSA;
|
|
|
|
|
if (enum_name == "ECDSA")
|
|
|
|
|
return rtc::KT_ECDSA;
|
|
|
|
|
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(false) << "Unexpected KeyType enum_name " << enum_name;
|
2015-09-01 11:31:27 -07:00
|
|
|
return rtc::KT_ECDSA;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-28 07:57:34 -07:00
|
|
|
static PeerConnectionInterface::ContinualGatheringPolicy
|
|
|
|
|
JavaContinualGatheringPolicyToNativeType(
|
|
|
|
|
JNIEnv* jni, jobject j_gathering_policy) {
|
|
|
|
|
std::string enum_name = GetJavaEnumName(
|
|
|
|
|
jni, "org/webrtc/PeerConnection$ContinualGatheringPolicy",
|
|
|
|
|
j_gathering_policy);
|
|
|
|
|
if (enum_name == "GATHER_ONCE")
|
|
|
|
|
return PeerConnectionInterface::GATHER_ONCE;
|
|
|
|
|
|
|
|
|
|
if (enum_name == "GATHER_CONTINUALLY")
|
|
|
|
|
return PeerConnectionInterface::GATHER_CONTINUALLY;
|
|
|
|
|
|
|
|
|
|
RTC_CHECK(false) << "Unexpected ContinualGatheringPolicy enum name "
|
|
|
|
|
<< enum_name;
|
|
|
|
|
return PeerConnectionInterface::GATHER_ONCE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
static void JavaIceServersToJsepIceServers(
|
|
|
|
|
JNIEnv* jni, jobject j_ice_servers,
|
|
|
|
|
PeerConnectionInterface::IceServers* ice_servers) {
|
2016-03-24 19:36:46 -07:00
|
|
|
for (jobject j_ice_server : Iterable(jni, j_ice_servers)) {
|
2013-07-10 00:45:36 +00:00
|
|
|
jclass j_ice_server_class = GetObjectClass(jni, j_ice_server);
|
|
|
|
|
jfieldID j_ice_server_uri_id =
|
|
|
|
|
GetFieldID(jni, j_ice_server_class, "uri", "Ljava/lang/String;");
|
|
|
|
|
jfieldID j_ice_server_username_id =
|
|
|
|
|
GetFieldID(jni, j_ice_server_class, "username", "Ljava/lang/String;");
|
|
|
|
|
jfieldID j_ice_server_password_id =
|
|
|
|
|
GetFieldID(jni, j_ice_server_class, "password", "Ljava/lang/String;");
|
|
|
|
|
jstring uri = reinterpret_cast<jstring>(
|
|
|
|
|
GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
|
|
|
|
|
jstring username = reinterpret_cast<jstring>(
|
|
|
|
|
GetObjectField(jni, j_ice_server, j_ice_server_username_id));
|
|
|
|
|
jstring password = reinterpret_cast<jstring>(
|
|
|
|
|
GetObjectField(jni, j_ice_server, j_ice_server_password_id));
|
|
|
|
|
PeerConnectionInterface::IceServer server;
|
|
|
|
|
server.uri = JavaToStdString(jni, uri);
|
|
|
|
|
server.username = JavaToStdString(jni, username);
|
|
|
|
|
server.password = JavaToStdString(jni, password);
|
|
|
|
|
ice_servers->push_back(server);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-29 11:56:26 -07:00
|
|
|
static void JavaRTCConfigurationToJsepRTCConfiguration(
|
|
|
|
|
JNIEnv* jni,
|
|
|
|
|
jobject j_rtc_config,
|
|
|
|
|
PeerConnectionInterface::RTCConfiguration* rtc_config) {
|
2015-04-30 12:35:24 -07:00
|
|
|
jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
|
|
|
|
|
|
|
|
|
|
jfieldID j_ice_transports_type_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "iceTransportsType",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$IceTransportsType;");
|
|
|
|
|
jobject j_ice_transports_type = GetObjectField(
|
|
|
|
|
jni, j_rtc_config, j_ice_transports_type_id);
|
|
|
|
|
|
|
|
|
|
jfieldID j_bundle_policy_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "bundlePolicy",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$BundlePolicy;");
|
|
|
|
|
jobject j_bundle_policy = GetObjectField(
|
|
|
|
|
jni, j_rtc_config, j_bundle_policy_id);
|
|
|
|
|
|
2015-05-21 07:48:41 -07:00
|
|
|
jfieldID j_rtcp_mux_policy_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "rtcpMuxPolicy",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$RtcpMuxPolicy;");
|
|
|
|
|
jobject j_rtcp_mux_policy = GetObjectField(
|
|
|
|
|
jni, j_rtc_config, j_rtcp_mux_policy_id);
|
|
|
|
|
|
2015-04-30 12:35:24 -07:00
|
|
|
jfieldID j_tcp_candidate_policy_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "tcpCandidatePolicy",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$TcpCandidatePolicy;");
|
|
|
|
|
jobject j_tcp_candidate_policy = GetObjectField(
|
|
|
|
|
jni, j_rtc_config, j_tcp_candidate_policy_id);
|
|
|
|
|
|
|
|
|
|
jfieldID j_ice_servers_id = GetFieldID(
|
2015-09-01 11:31:27 -07:00
|
|
|
jni, j_rtc_config_class, "iceServers", "Ljava/util/List;");
|
2015-04-30 12:35:24 -07:00
|
|
|
jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id);
|
|
|
|
|
|
2015-09-01 09:53:56 -07:00
|
|
|
jfieldID j_audio_jitter_buffer_max_packets_id =
|
|
|
|
|
GetFieldID(jni, j_rtc_config_class, "audioJitterBufferMaxPackets", "I");
|
2015-06-01 10:29:41 +02:00
|
|
|
jfieldID j_audio_jitter_buffer_fast_accelerate_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "audioJitterBufferFastAccelerate", "Z");
|
2015-04-30 12:35:24 -07:00
|
|
|
|
2015-09-01 09:53:56 -07:00
|
|
|
jfieldID j_ice_connection_receiving_timeout_id =
|
|
|
|
|
GetFieldID(jni, j_rtc_config_class, "iceConnectionReceivingTimeout", "I");
|
|
|
|
|
|
2015-12-04 12:24:03 -08:00
|
|
|
jfieldID j_ice_backup_candidate_pair_ping_interval_id = GetFieldID(
|
|
|
|
|
jni, j_rtc_config_class, "iceBackupCandidatePairPingInterval", "I");
|
|
|
|
|
|
2015-09-28 07:57:34 -07:00
|
|
|
jfieldID j_continual_gathering_policy_id =
|
|
|
|
|
GetFieldID(jni, j_rtc_config_class, "continualGatheringPolicy",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$ContinualGatheringPolicy;");
|
|
|
|
|
jobject j_continual_gathering_policy =
|
|
|
|
|
GetObjectField(jni, j_rtc_config, j_continual_gathering_policy_id);
|
|
|
|
|
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->type =
|
2015-04-30 12:35:24 -07:00
|
|
|
JavaIceTransportsTypeToNativeType(jni, j_ice_transports_type);
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->bundle_policy =
|
|
|
|
|
JavaBundlePolicyToNativeType(jni, j_bundle_policy);
|
|
|
|
|
rtc_config->rtcp_mux_policy =
|
2015-05-21 07:48:41 -07:00
|
|
|
JavaRtcpMuxPolicyToNativeType(jni, j_rtcp_mux_policy);
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->tcp_candidate_policy =
|
2015-04-30 12:35:24 -07:00
|
|
|
JavaTcpCandidatePolicyToNativeType(jni, j_tcp_candidate_policy);
|
2015-09-29 11:56:26 -07:00
|
|
|
JavaIceServersToJsepIceServers(jni, j_ice_servers, &rtc_config->servers);
|
|
|
|
|
rtc_config->audio_jitter_buffer_max_packets =
|
2015-05-11 12:44:23 +02:00
|
|
|
GetIntField(jni, j_rtc_config, j_audio_jitter_buffer_max_packets_id);
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->audio_jitter_buffer_fast_accelerate = GetBooleanField(
|
2015-06-01 10:29:41 +02:00
|
|
|
jni, j_rtc_config, j_audio_jitter_buffer_fast_accelerate_id);
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->ice_connection_receiving_timeout =
|
2015-09-01 09:53:56 -07:00
|
|
|
GetIntField(jni, j_rtc_config, j_ice_connection_receiving_timeout_id);
|
2015-12-04 12:24:03 -08:00
|
|
|
rtc_config->ice_backup_candidate_pair_ping_interval = GetIntField(
|
|
|
|
|
jni, j_rtc_config, j_ice_backup_candidate_pair_ping_interval_id);
|
2015-09-29 11:56:26 -07:00
|
|
|
rtc_config->continual_gathering_policy =
|
2015-09-28 07:57:34 -07:00
|
|
|
JavaContinualGatheringPolicyToNativeType(
|
|
|
|
|
jni, j_continual_gathering_policy);
|
2015-09-29 11:56:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
|
|
|
|
|
JNIEnv *jni, jclass, jlong factory, jobject j_rtc_config,
|
|
|
|
|
jobject j_constraints, jlong observer_p) {
|
|
|
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
|
|
|
|
|
reinterpret_cast<PeerConnectionFactoryInterface*>(
|
|
|
|
|
factoryFromJava(factory)));
|
|
|
|
|
|
|
|
|
|
PeerConnectionInterface::RTCConfiguration rtc_config;
|
|
|
|
|
JavaRTCConfigurationToJsepRTCConfiguration(jni, j_rtc_config, &rtc_config);
|
|
|
|
|
|
|
|
|
|
jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
|
|
|
|
|
jfieldID j_key_type_id = GetFieldID(jni, j_rtc_config_class, "keyType",
|
|
|
|
|
"Lorg/webrtc/PeerConnection$KeyType;");
|
|
|
|
|
jobject j_key_type = GetObjectField(jni, j_rtc_config, j_key_type_id);
|
2015-04-30 12:35:24 -07:00
|
|
|
|
2015-09-01 11:31:27 -07:00
|
|
|
// Create ECDSA certificate.
|
|
|
|
|
if (JavaKeyTypeToNativeType(jni, j_key_type) == rtc::KT_ECDSA) {
|
2016-04-26 03:13:22 -07:00
|
|
|
std::unique_ptr<rtc::SSLIdentity> ssl_identity(
|
2015-09-01 11:31:27 -07:00
|
|
|
rtc::SSLIdentity::Generate(webrtc::kIdentityName, rtc::KT_ECDSA));
|
|
|
|
|
if (ssl_identity.get()) {
|
|
|
|
|
rtc_config.certificates.push_back(
|
2015-12-17 03:04:15 -08:00
|
|
|
rtc::RTCCertificate::Create(std::move(ssl_identity)));
|
2015-09-01 11:31:27 -07:00
|
|
|
LOG(LS_INFO) << "ECDSA certificate created.";
|
|
|
|
|
} else {
|
|
|
|
|
// Failing to create certificate should not abort peer connection
|
|
|
|
|
// creation. Instead default encryption (currently RSA) will be used.
|
|
|
|
|
LOG(LS_WARNING) <<
|
|
|
|
|
"Failed to generate SSLIdentity. Default encryption will be used.";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
|
|
|
|
|
observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
|
2015-04-30 12:35:24 -07:00
|
|
|
rtc_config, observer->constraints(), NULL, NULL, observer));
|
2013-07-10 00:45:36 +00:00
|
|
|
return (jlong)pc.release();
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
static rtc::scoped_refptr<PeerConnectionInterface> ExtractNativePC(
|
2013-07-10 00:45:36 +00:00
|
|
|
JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
jfieldID native_pc_id = GetFieldID(jni,
|
|
|
|
|
GetObjectClass(jni, j_pc), "nativePeerConnection", "J");
|
|
|
|
|
jlong j_p = GetLongField(jni, j_pc, native_pc_id);
|
2014-07-29 17:36:52 +00:00
|
|
|
return rtc::scoped_refptr<PeerConnectionInterface>(
|
2013-07-10 00:45:36 +00:00
|
|
|
reinterpret_cast<PeerConnectionInterface*>(j_p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, PeerConnection_getLocalDescription)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
const SessionDescriptionInterface* sdp =
|
|
|
|
|
ExtractNativePC(jni, j_pc)->local_description();
|
|
|
|
|
return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, PeerConnection_getRemoteDescription)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
const SessionDescriptionInterface* sdp =
|
|
|
|
|
ExtractNativePC(jni, j_pc)->remote_description();
|
|
|
|
|
return sdp ? JavaSdpFromNativeSdp(jni, sdp) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:04:50 +00:00
|
|
|
JOW(jobject, PeerConnection_createDataChannel)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jstring j_label, jobject j_init) {
|
|
|
|
|
DataChannelInit init = JavaDataChannelInitToNative(jni, j_init);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<DataChannelInterface> channel(
|
2013-07-12 16:04:50 +00:00
|
|
|
ExtractNativePC(jni, j_pc)->CreateDataChannel(
|
|
|
|
|
JavaToStdString(jni, j_label), &init));
|
2013-09-03 18:58:12 +00:00
|
|
|
// Mustn't pass channel.get() directly through NewObject to avoid reading its
|
|
|
|
|
// vararg parameter as 64-bit and reading memory that doesn't belong to the
|
|
|
|
|
// 32-bit parameter.
|
|
|
|
|
jlong nativeChannelPtr = jlongFromPointer(channel.get());
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(nativeChannelPtr) << "Failed to create DataChannel";
|
2013-07-12 16:04:50 +00:00
|
|
|
jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
|
|
|
|
|
jmethodID j_data_channel_ctor = GetMethodID(
|
|
|
|
|
jni, j_data_channel_class, "<init>", "(J)V");
|
|
|
|
|
jobject j_channel = jni->NewObject(
|
2013-09-03 18:58:12 +00:00
|
|
|
j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
2013-07-12 16:04:50 +00:00
|
|
|
// Channel is now owned by Java object, and will be freed from there.
|
2013-08-12 23:26:21 +00:00
|
|
|
int bumped_count = channel->AddRef();
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(bumped_count == 2) << "Unexpected refcount";
|
2013-07-12 16:04:50 +00:00
|
|
|
return j_channel;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(void, PeerConnection_createOffer)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
|
|
|
|
|
ConstraintsWrapper* constraints =
|
|
|
|
|
new ConstraintsWrapper(jni, j_constraints);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
|
|
|
|
|
new rtc::RefCountedObject<CreateSdpObserverWrapper>(
|
2013-07-10 00:45:36 +00:00
|
|
|
jni, j_observer, constraints));
|
|
|
|
|
ExtractNativePC(jni, j_pc)->CreateOffer(observer, constraints);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_createAnswer)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jobject j_observer, jobject j_constraints) {
|
|
|
|
|
ConstraintsWrapper* constraints =
|
|
|
|
|
new ConstraintsWrapper(jni, j_constraints);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<CreateSdpObserverWrapper> observer(
|
|
|
|
|
new rtc::RefCountedObject<CreateSdpObserverWrapper>(
|
2013-07-10 00:45:36 +00:00
|
|
|
jni, j_observer, constraints));
|
|
|
|
|
ExtractNativePC(jni, j_pc)->CreateAnswer(observer, constraints);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper to create a SessionDescriptionInterface from a SessionDescription.
|
|
|
|
|
static SessionDescriptionInterface* JavaSdpToNativeSdp(
|
|
|
|
|
JNIEnv* jni, jobject j_sdp) {
|
|
|
|
|
jfieldID j_type_id = GetFieldID(
|
|
|
|
|
jni, GetObjectClass(jni, j_sdp), "type",
|
|
|
|
|
"Lorg/webrtc/SessionDescription$Type;");
|
|
|
|
|
jobject j_type = GetObjectField(jni, j_sdp, j_type_id);
|
|
|
|
|
jmethodID j_canonical_form_id = GetMethodID(
|
|
|
|
|
jni, GetObjectClass(jni, j_type), "canonicalForm",
|
|
|
|
|
"()Ljava/lang/String;");
|
|
|
|
|
jstring j_type_string = (jstring)jni->CallObjectMethod(
|
|
|
|
|
j_type, j_canonical_form_id);
|
2014-09-09 11:45:44 +00:00
|
|
|
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
|
2013-07-10 00:45:36 +00:00
|
|
|
std::string std_type = JavaToStdString(jni, j_type_string);
|
|
|
|
|
|
|
|
|
|
jfieldID j_description_id = GetFieldID(
|
|
|
|
|
jni, GetObjectClass(jni, j_sdp), "description", "Ljava/lang/String;");
|
|
|
|
|
jstring j_description = (jstring)GetObjectField(jni, j_sdp, j_description_id);
|
|
|
|
|
std::string std_description = JavaToStdString(jni, j_description);
|
|
|
|
|
|
|
|
|
|
return webrtc::CreateSessionDescription(
|
|
|
|
|
std_type, std_description, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_setLocalDescription)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc,
|
|
|
|
|
jobject j_observer, jobject j_sdp) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<SetSdpObserverWrapper> observer(
|
|
|
|
|
new rtc::RefCountedObject<SetSdpObserverWrapper>(
|
2013-07-10 00:45:36 +00:00
|
|
|
jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
|
|
|
|
|
ExtractNativePC(jni, j_pc)->SetLocalDescription(
|
|
|
|
|
observer, JavaSdpToNativeSdp(jni, j_sdp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_setRemoteDescription)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc,
|
|
|
|
|
jobject j_observer, jobject j_sdp) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<SetSdpObserverWrapper> observer(
|
|
|
|
|
new rtc::RefCountedObject<SetSdpObserverWrapper>(
|
2013-07-10 00:45:36 +00:00
|
|
|
jni, j_observer, reinterpret_cast<ConstraintsWrapper*>(NULL)));
|
|
|
|
|
ExtractNativePC(jni, j_pc)->SetRemoteDescription(
|
|
|
|
|
observer, JavaSdpToNativeSdp(jni, j_sdp));
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-29 11:56:26 -07:00
|
|
|
JOW(jboolean, PeerConnection_setConfiguration)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jobject j_rtc_config) {
|
|
|
|
|
PeerConnectionInterface::RTCConfiguration rtc_config;
|
|
|
|
|
JavaRTCConfigurationToJsepRTCConfiguration(jni, j_rtc_config, &rtc_config);
|
|
|
|
|
return ExtractNativePC(jni, j_pc)->SetConfiguration(rtc_config);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, PeerConnection_nativeAddIceCandidate)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jstring j_sdp_mid,
|
|
|
|
|
jint j_sdp_mline_index, jstring j_candidate_sdp) {
|
|
|
|
|
std::string sdp_mid = JavaToStdString(jni, j_sdp_mid);
|
|
|
|
|
std::string sdp = JavaToStdString(jni, j_candidate_sdp);
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<IceCandidateInterface> candidate(
|
2013-07-10 00:45:36 +00:00
|
|
|
webrtc::CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, NULL));
|
|
|
|
|
return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
static cricket::Candidate GetCandidateFromJava(JNIEnv* jni,
|
|
|
|
|
jobject j_candidate) {
|
|
|
|
|
jclass j_candidate_class = GetObjectClass(jni, j_candidate);
|
|
|
|
|
jfieldID j_sdp_mid_id =
|
|
|
|
|
GetFieldID(jni, j_candidate_class, "sdpMid", "Ljava/lang/String;");
|
|
|
|
|
std::string sdp_mid =
|
|
|
|
|
JavaToStdString(jni, GetStringField(jni, j_candidate, j_sdp_mid_id));
|
|
|
|
|
jfieldID j_sdp_id =
|
|
|
|
|
GetFieldID(jni, j_candidate_class, "sdp", "Ljava/lang/String;");
|
|
|
|
|
std::string sdp =
|
|
|
|
|
JavaToStdString(jni, GetStringField(jni, j_candidate, j_sdp_id));
|
|
|
|
|
cricket::Candidate candidate;
|
|
|
|
|
if (!webrtc::SdpDeserializeCandidate(sdp_mid, sdp, &candidate, NULL)) {
|
|
|
|
|
LOG(LS_ERROR) << "SdpDescrializeCandidate failed with sdp " << sdp;
|
|
|
|
|
}
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, PeerConnection_nativeRemoveIceCandidates)
|
|
|
|
|
(JNIEnv* jni, jobject j_pc, jobjectArray j_candidates) {
|
|
|
|
|
std::vector<cricket::Candidate> candidates;
|
|
|
|
|
size_t num_candidates = jni->GetArrayLength(j_candidates);
|
|
|
|
|
for (size_t i = 0; i < num_candidates; ++i) {
|
|
|
|
|
jobject j_candidate = jni->GetObjectArrayElement(j_candidates, i);
|
|
|
|
|
candidates.push_back(GetCandidateFromJava(jni, j_candidate));
|
|
|
|
|
}
|
|
|
|
|
return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates);
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(jboolean, PeerConnection_nativeAddLocalStream)(
|
2014-11-04 11:31:29 +00:00
|
|
|
JNIEnv* jni, jobject j_pc, jlong native_stream) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return ExtractNativePC(jni, j_pc)->AddStream(
|
2014-11-04 11:31:29 +00:00
|
|
|
reinterpret_cast<MediaStreamInterface*>(native_stream));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_nativeRemoveLocalStream)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jlong native_stream) {
|
|
|
|
|
ExtractNativePC(jni, j_pc)->RemoveStream(
|
|
|
|
|
reinterpret_cast<MediaStreamInterface*>(native_stream));
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-02 11:27:40 -08:00
|
|
|
JOW(jobject, PeerConnection_nativeCreateSender)(
|
2015-12-18 16:58:44 -08:00
|
|
|
JNIEnv* jni, jobject j_pc, jstring j_kind, jstring j_stream_id) {
|
2015-12-02 11:27:40 -08:00
|
|
|
jclass j_rtp_sender_class = FindClass(jni, "org/webrtc/RtpSender");
|
|
|
|
|
jmethodID j_rtp_sender_ctor =
|
|
|
|
|
GetMethodID(jni, j_rtp_sender_class, "<init>", "(J)V");
|
|
|
|
|
|
|
|
|
|
std::string kind = JavaToStdString(jni, j_kind);
|
2015-12-18 16:58:44 -08:00
|
|
|
std::string stream_id = JavaToStdString(jni, j_stream_id);
|
2015-12-02 11:27:40 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderInterface> sender =
|
2015-12-18 16:58:44 -08:00
|
|
|
ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id);
|
2015-12-02 11:27:40 -08:00
|
|
|
if (!sender.get()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
jlong nativeSenderPtr = jlongFromPointer(sender.get());
|
|
|
|
|
jobject j_sender =
|
|
|
|
|
jni->NewObject(j_rtp_sender_class, j_rtp_sender_ctor, nativeSenderPtr);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
// Sender is now owned by the Java object, and will be freed from
|
|
|
|
|
// RtpSender.dispose(), called by PeerConnection.dispose() or getSenders().
|
|
|
|
|
sender->AddRef();
|
|
|
|
|
return j_sender;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 12:29:25 -07:00
|
|
|
JOW(jobject, PeerConnection_nativeGetSenders)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
jclass j_array_list_class = FindClass(jni, "java/util/ArrayList");
|
|
|
|
|
jmethodID j_array_list_ctor =
|
|
|
|
|
GetMethodID(jni, j_array_list_class, "<init>", "()V");
|
|
|
|
|
jmethodID j_array_list_add =
|
|
|
|
|
GetMethodID(jni, j_array_list_class, "add", "(Ljava/lang/Object;)Z");
|
|
|
|
|
jobject j_senders = jni->NewObject(j_array_list_class, j_array_list_ctor);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
|
|
|
|
|
jclass j_rtp_sender_class = FindClass(jni, "org/webrtc/RtpSender");
|
|
|
|
|
jmethodID j_rtp_sender_ctor =
|
|
|
|
|
GetMethodID(jni, j_rtp_sender_class, "<init>", "(J)V");
|
|
|
|
|
|
|
|
|
|
auto senders = ExtractNativePC(jni, j_pc)->GetSenders();
|
|
|
|
|
for (const auto& sender : senders) {
|
|
|
|
|
jlong nativeSenderPtr = jlongFromPointer(sender.get());
|
|
|
|
|
jobject j_sender =
|
|
|
|
|
jni->NewObject(j_rtp_sender_class, j_rtp_sender_ctor, nativeSenderPtr);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
2015-12-02 11:27:40 -08:00
|
|
|
// Sender is now owned by the Java object, and will be freed from
|
|
|
|
|
// RtpSender.dispose(), called by PeerConnection.dispose() or getSenders().
|
2015-10-06 12:29:25 -07:00
|
|
|
sender->AddRef();
|
|
|
|
|
jni->CallBooleanMethod(j_senders, j_array_list_add, j_sender);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
|
|
|
|
|
}
|
|
|
|
|
return j_senders;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, PeerConnection_nativeGetReceivers)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
jclass j_array_list_class = FindClass(jni, "java/util/ArrayList");
|
|
|
|
|
jmethodID j_array_list_ctor =
|
|
|
|
|
GetMethodID(jni, j_array_list_class, "<init>", "()V");
|
|
|
|
|
jmethodID j_array_list_add =
|
|
|
|
|
GetMethodID(jni, j_array_list_class, "add", "(Ljava/lang/Object;)Z");
|
|
|
|
|
jobject j_receivers = jni->NewObject(j_array_list_class, j_array_list_ctor);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
|
|
|
|
|
jclass j_rtp_receiver_class = FindClass(jni, "org/webrtc/RtpReceiver");
|
|
|
|
|
jmethodID j_rtp_receiver_ctor =
|
|
|
|
|
GetMethodID(jni, j_rtp_receiver_class, "<init>", "(J)V");
|
|
|
|
|
|
|
|
|
|
auto receivers = ExtractNativePC(jni, j_pc)->GetReceivers();
|
|
|
|
|
for (const auto& receiver : receivers) {
|
|
|
|
|
jlong nativeReceiverPtr = jlongFromPointer(receiver.get());
|
|
|
|
|
jobject j_receiver = jni->NewObject(j_rtp_receiver_class,
|
|
|
|
|
j_rtp_receiver_ctor, nativeReceiverPtr);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
// Receiver is now owned by Java object, and will be freed from there.
|
|
|
|
|
receiver->AddRef();
|
|
|
|
|
jni->CallBooleanMethod(j_receivers, j_array_list_add, j_receiver);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
|
|
|
|
|
}
|
|
|
|
|
return j_receivers;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(bool, PeerConnection_nativeGetStats)(
|
|
|
|
|
JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<StatsObserverWrapper> observer(
|
|
|
|
|
new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
|
2013-07-10 00:45:36 +00:00
|
|
|
return ExtractNativePC(jni, j_pc)->GetStats(
|
2014-03-03 21:30:06 +00:00
|
|
|
observer,
|
|
|
|
|
reinterpret_cast<MediaStreamTrackInterface*>(native_track),
|
|
|
|
|
PeerConnectionInterface::kStatsOutputLevelStandard);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, PeerConnection_signalingState)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
PeerConnectionInterface::SignalingState state =
|
|
|
|
|
ExtractNativePC(jni, j_pc)->signaling_state();
|
|
|
|
|
return JavaEnumFromIndex(jni, "PeerConnection$SignalingState", state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, PeerConnection_iceConnectionState)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
PeerConnectionInterface::IceConnectionState state =
|
|
|
|
|
ExtractNativePC(jni, j_pc)->ice_connection_state();
|
|
|
|
|
return JavaEnumFromIndex(jni, "PeerConnection$IceConnectionState", state);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 07:57:06 +00:00
|
|
|
JOW(jobject, PeerConnection_iceGatheringState)(JNIEnv* jni, jobject j_pc) {
|
2013-07-10 00:45:36 +00:00
|
|
|
PeerConnectionInterface::IceGatheringState state =
|
|
|
|
|
ExtractNativePC(jni, j_pc)->ice_gathering_state();
|
2015-01-21 07:57:06 +00:00
|
|
|
return JavaEnumFromIndex(jni, "PeerConnection$IceGatheringState", state);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, PeerConnection_close)(JNIEnv* jni, jobject j_pc) {
|
|
|
|
|
ExtractNativePC(jni, j_pc)->Close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, MediaSource_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<MediaSourceInterface> p(
|
2013-07-10 00:45:36 +00:00
|
|
|
reinterpret_cast<MediaSourceInterface*>(j_p));
|
|
|
|
|
return JavaEnumFromIndex(jni, "MediaSource$State", p->state());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, VideoRenderer_nativeWrapVideoRenderer)(
|
|
|
|
|
JNIEnv* jni, jclass, jobject j_callbacks) {
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<JavaVideoRendererWrapper> renderer(
|
2013-07-10 00:45:36 +00:00
|
|
|
new JavaVideoRendererWrapper(jni, j_callbacks));
|
|
|
|
|
return (jlong)renderer.release();
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-05 17:29:59 +00:00
|
|
|
JOW(void, VideoRenderer_nativeCopyPlane)(
|
|
|
|
|
JNIEnv *jni, jclass, jobject j_src_buffer, jint width, jint height,
|
|
|
|
|
jint src_stride, jobject j_dst_buffer, jint dst_stride) {
|
|
|
|
|
size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
|
|
|
|
|
size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
|
|
|
|
|
RTC_CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
|
|
|
|
|
RTC_CHECK(src_size >= src_stride * height)
|
2015-02-05 17:29:59 +00:00
|
|
|
<< "Insufficient source buffer capacity " << src_size;
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK(dst_size >= dst_stride * height)
|
2015-02-05 17:29:59 +00:00
|
|
|
<< "Isufficient destination buffer capacity " << dst_size;
|
|
|
|
|
uint8_t *src =
|
|
|
|
|
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
|
|
|
|
|
uint8_t *dst =
|
|
|
|
|
reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
|
|
|
|
|
if (src_stride == dst_stride) {
|
|
|
|
|
memcpy(dst, src, src_stride * height);
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < height; i++) {
|
|
|
|
|
memcpy(dst, src, width);
|
|
|
|
|
src += src_stride;
|
|
|
|
|
dst += dst_stride;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 13:53:56 +00:00
|
|
|
JOW(void, VideoSource_stop)(JNIEnv* jni, jclass, jlong j_p) {
|
2016-03-08 01:27:48 +01:00
|
|
|
reinterpret_cast<VideoTrackSourceInterface*>(j_p)->Stop();
|
2013-10-03 18:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, VideoSource_restart)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_p_source, jlong j_p_format) {
|
2016-03-08 01:27:48 +01:00
|
|
|
reinterpret_cast<VideoTrackSourceInterface*>(j_p_source)->Restart();
|
2013-10-03 18:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
JOW(jstring, MediaStreamTrack_nativeId)(JNIEnv* jni, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return JavaStringFromStdString(
|
|
|
|
|
jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->id());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jstring, MediaStreamTrack_nativeKind)(JNIEnv* jni, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return JavaStringFromStdString(
|
|
|
|
|
jni, reinterpret_cast<MediaStreamTrackInterface*>(j_p)->kind());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStreamTrack_nativeEnabled)(JNIEnv* jni, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamTrackInterface*>(j_p)->enabled();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, MediaStreamTrack_nativeState)(JNIEnv* jni, jclass, jlong j_p) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return JavaEnumFromIndex(
|
|
|
|
|
jni,
|
|
|
|
|
"MediaStreamTrack$State",
|
|
|
|
|
reinterpret_cast<MediaStreamTrackInterface*>(j_p)->state());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jboolean, MediaStreamTrack_nativeSetEnabled)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_p, jboolean enabled) {
|
2013-08-12 23:26:21 +00:00
|
|
|
return reinterpret_cast<MediaStreamTrackInterface*>(j_p)
|
|
|
|
|
->set_enabled(enabled);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, VideoTrack_nativeAddRenderer)(
|
|
|
|
|
JNIEnv* jni, jclass,
|
|
|
|
|
jlong j_video_track_pointer, jlong j_renderer_pointer) {
|
2016-03-23 10:33:07 +01:00
|
|
|
reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)
|
|
|
|
|
->AddOrUpdateSink(
|
|
|
|
|
reinterpret_cast<rtc::VideoSinkInterface<cricket::VideoFrame>*>(
|
|
|
|
|
j_renderer_pointer),
|
|
|
|
|
rtc::VideoSinkWants());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, VideoTrack_nativeRemoveRenderer)(
|
|
|
|
|
JNIEnv* jni, jclass,
|
|
|
|
|
jlong j_video_track_pointer, jlong j_renderer_pointer) {
|
2016-03-23 10:33:07 +01:00
|
|
|
reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)
|
|
|
|
|
->RemoveSink(
|
|
|
|
|
reinterpret_cast<rtc::VideoSinkInterface<cricket::VideoFrame>*>(
|
|
|
|
|
j_renderer_pointer));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
2015-02-13 12:46:51 +00:00
|
|
|
|
2015-09-01 16:11:18 -07:00
|
|
|
JOW(jlong, CallSessionFileRotatingLogSink_nativeAddSink)(
|
|
|
|
|
JNIEnv* jni, jclass,
|
|
|
|
|
jstring j_dirPath, jint j_maxFileSize, jint j_severity) {
|
|
|
|
|
std::string dir_path = JavaToStdString(jni, j_dirPath);
|
|
|
|
|
rtc::CallSessionFileRotatingLogSink* sink =
|
|
|
|
|
new rtc::CallSessionFileRotatingLogSink(dir_path, j_maxFileSize);
|
|
|
|
|
if (!sink->Init()) {
|
|
|
|
|
LOG_V(rtc::LoggingSeverity::LS_WARNING) <<
|
|
|
|
|
"Failed to init CallSessionFileRotatingLogSink for path " << dir_path;
|
|
|
|
|
delete sink;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
rtc::LogMessage::AddLogToStream(
|
|
|
|
|
sink, static_cast<rtc::LoggingSeverity>(j_severity));
|
|
|
|
|
return (jlong) sink;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, CallSessionFileRotatingLogSink_nativeDeleteSink)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_sink) {
|
|
|
|
|
rtc::CallSessionFileRotatingLogSink* sink =
|
|
|
|
|
reinterpret_cast<rtc::CallSessionFileRotatingLogSink*>(j_sink);
|
|
|
|
|
rtc::LogMessage::RemoveLogToStream(sink);
|
|
|
|
|
delete sink;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jbyteArray, CallSessionFileRotatingLogSink_nativeGetLogData)(
|
|
|
|
|
JNIEnv* jni, jclass, jstring j_dirPath) {
|
|
|
|
|
std::string dir_path = JavaToStdString(jni, j_dirPath);
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<rtc::CallSessionFileRotatingStream> stream(
|
2015-09-01 16:11:18 -07:00
|
|
|
new rtc::CallSessionFileRotatingStream(dir_path));
|
|
|
|
|
if (!stream->Open()) {
|
|
|
|
|
LOG_V(rtc::LoggingSeverity::LS_WARNING) <<
|
|
|
|
|
"Failed to open CallSessionFileRotatingStream for path " << dir_path;
|
|
|
|
|
return jni->NewByteArray(0);
|
|
|
|
|
}
|
|
|
|
|
size_t log_size = 0;
|
|
|
|
|
if (!stream->GetSize(&log_size) || log_size == 0) {
|
|
|
|
|
LOG_V(rtc::LoggingSeverity::LS_WARNING) <<
|
|
|
|
|
"CallSessionFileRotatingStream returns 0 size for path " << dir_path;
|
|
|
|
|
return jni->NewByteArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t read = 0;
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<jbyte> buffer(static_cast<jbyte*>(malloc(log_size)));
|
2015-09-01 16:11:18 -07:00
|
|
|
stream->ReadAll(buffer.get(), log_size, &read, nullptr);
|
|
|
|
|
|
|
|
|
|
jbyteArray result = jni->NewByteArray(read);
|
|
|
|
|
jni->SetByteArrayRegion(result, 0, read, buffer.get());
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 15:11:25 -08:00
|
|
|
JOW(jboolean, RtpSender_nativeSetTrack)(JNIEnv* jni,
|
2015-10-06 12:29:25 -07:00
|
|
|
jclass,
|
|
|
|
|
jlong j_rtp_sender_pointer,
|
|
|
|
|
jlong j_track_pointer) {
|
2016-01-07 15:11:25 -08:00
|
|
|
return reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
2015-10-06 12:29:25 -07:00
|
|
|
->SetTrack(reinterpret_cast<MediaStreamTrackInterface*>(j_track_pointer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, RtpSender_nativeGetTrack)(JNIEnv* jni,
|
|
|
|
|
jclass,
|
|
|
|
|
jlong j_rtp_sender_pointer,
|
|
|
|
|
jlong j_track_pointer) {
|
|
|
|
|
return jlongFromPointer(
|
|
|
|
|
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
|
|
|
|
->track()
|
|
|
|
|
.release());
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 19:36:46 -07:00
|
|
|
static bool JavaEncodingToJsepRtpEncodingParameters(
|
|
|
|
|
JNIEnv* jni,
|
|
|
|
|
jobject j_encodings,
|
|
|
|
|
std::vector<webrtc::RtpEncodingParameters>* encodings) {
|
|
|
|
|
const int kBitrateUnlimited = -1;
|
|
|
|
|
jclass j_encoding_parameters_class =
|
|
|
|
|
jni->FindClass("org/webrtc/RtpParameters$Encoding");
|
2016-03-29 17:21:29 -07:00
|
|
|
jfieldID active_id =
|
|
|
|
|
GetFieldID(jni, j_encoding_parameters_class, "active", "Z");
|
2016-03-24 19:36:46 -07:00
|
|
|
jfieldID bitrate_id = GetFieldID(jni, j_encoding_parameters_class,
|
|
|
|
|
"maxBitrateBps", "Ljava/lang/Integer;");
|
|
|
|
|
jclass j_integer_class = jni->FindClass("java/lang/Integer");
|
|
|
|
|
jmethodID int_value_id = GetMethodID(jni, j_integer_class, "intValue", "()I");
|
|
|
|
|
|
|
|
|
|
for (jobject j_encoding_parameters : Iterable(jni, j_encodings)) {
|
|
|
|
|
webrtc::RtpEncodingParameters encoding;
|
2016-03-29 17:21:29 -07:00
|
|
|
encoding.active = GetBooleanField(jni, j_encoding_parameters, active_id);
|
2016-04-04 10:21:02 -07:00
|
|
|
jobject j_bitrate =
|
|
|
|
|
GetNullableObjectField(jni, j_encoding_parameters, bitrate_id);
|
2016-03-24 19:36:46 -07:00
|
|
|
if (!IsNull(jni, j_bitrate)) {
|
|
|
|
|
int bitrate_value = jni->CallIntMethod(j_bitrate, int_value_id);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during CallIntMethod";
|
|
|
|
|
encoding.max_bitrate_bps = bitrate_value;
|
|
|
|
|
} else {
|
|
|
|
|
encoding.max_bitrate_bps = kBitrateUnlimited;
|
|
|
|
|
}
|
|
|
|
|
encodings->push_back(encoding);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-20 16:23:10 -07:00
|
|
|
static bool JavaCodecToJsepRtpCodecParameters(
|
|
|
|
|
JNIEnv* jni,
|
|
|
|
|
jobject j_codecs,
|
|
|
|
|
std::vector<webrtc::RtpCodecParameters>* codecs) {
|
|
|
|
|
jclass codec_class = jni->FindClass("org/webrtc/RtpParameters$Codec");
|
|
|
|
|
jfieldID payload_type_id = GetFieldID(jni, codec_class, "payloadType", "I");
|
|
|
|
|
jfieldID mime_type_id =
|
|
|
|
|
GetFieldID(jni, codec_class, "mimeType", "Ljava/lang/String;");
|
|
|
|
|
jfieldID clock_rate_id = GetFieldID(jni, codec_class, "clockRate", "I");
|
|
|
|
|
jfieldID channels_id = GetFieldID(jni, codec_class, "channels", "I");
|
|
|
|
|
|
|
|
|
|
for (jobject j_codec : Iterable(jni, j_codecs)) {
|
|
|
|
|
webrtc::RtpCodecParameters codec;
|
|
|
|
|
codec.payload_type = GetIntField(jni, j_codec, payload_type_id);
|
|
|
|
|
codec.mime_type =
|
|
|
|
|
JavaToStdString(jni, GetStringField(jni, j_codec, mime_type_id));
|
|
|
|
|
codec.clock_rate = GetIntField(jni, j_codec, clock_rate_id);
|
|
|
|
|
codec.channels = GetIntField(jni, j_codec, channels_id);
|
|
|
|
|
codecs->push_back(codec);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 19:36:46 -07:00
|
|
|
JOW(jboolean, RtpSender_nativeSetParameters)
|
|
|
|
|
(JNIEnv* jni, jclass, jlong j_rtp_sender_pointer, jobject j_parameters) {
|
|
|
|
|
if (IsNull(jni, j_parameters)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
jclass parameters_class = jni->FindClass("org/webrtc/RtpParameters");
|
|
|
|
|
jclass encoding_class = jni->FindClass("org/webrtc/RtpParameters$Encoding");
|
|
|
|
|
jfieldID encodings_id =
|
|
|
|
|
GetFieldID(jni, parameters_class, "encodings", "Ljava/util/LinkedList;");
|
2016-04-20 16:23:10 -07:00
|
|
|
jfieldID codecs_id =
|
|
|
|
|
GetFieldID(jni, parameters_class, "codecs", "Ljava/util/LinkedList;");
|
2016-03-24 19:36:46 -07:00
|
|
|
|
|
|
|
|
jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id);
|
2016-04-20 16:23:10 -07:00
|
|
|
jobject j_codecs = GetObjectField(jni, j_parameters, codecs_id);
|
2016-03-24 19:36:46 -07:00
|
|
|
webrtc::RtpParameters parameters;
|
|
|
|
|
JavaEncodingToJsepRtpEncodingParameters(jni, j_encodings,
|
|
|
|
|
¶meters.encodings);
|
2016-04-20 16:23:10 -07:00
|
|
|
JavaCodecToJsepRtpCodecParameters(jni, j_codecs, ¶meters.codecs);
|
2016-03-24 19:36:46 -07:00
|
|
|
return reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
|
|
|
|
->SetParameters(parameters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jobject, RtpSender_nativeGetParameters)
|
|
|
|
|
(JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) {
|
|
|
|
|
webrtc::RtpParameters parameters =
|
|
|
|
|
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)
|
|
|
|
|
->GetParameters();
|
|
|
|
|
|
|
|
|
|
jclass parameters_class = jni->FindClass("org/webrtc/RtpParameters");
|
|
|
|
|
jmethodID parameters_ctor =
|
|
|
|
|
GetMethodID(jni, parameters_class, "<init>", "()V");
|
|
|
|
|
jobject j_parameters = jni->NewObject(parameters_class, parameters_ctor);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
|
|
|
|
|
jclass encoding_class = jni->FindClass("org/webrtc/RtpParameters$Encoding");
|
|
|
|
|
jmethodID encoding_ctor = GetMethodID(jni, encoding_class, "<init>", "()V");
|
|
|
|
|
jfieldID encodings_id =
|
|
|
|
|
GetFieldID(jni, parameters_class, "encodings", "Ljava/util/LinkedList;");
|
|
|
|
|
jobject j_encodings = GetObjectField(jni, j_parameters, encodings_id);
|
2016-04-20 16:23:10 -07:00
|
|
|
jmethodID encodings_add = GetMethodID(jni, GetObjectClass(jni, j_encodings),
|
|
|
|
|
"add", "(Ljava/lang/Object;)Z");
|
2016-03-29 17:21:29 -07:00
|
|
|
jfieldID active_id =
|
|
|
|
|
GetFieldID(jni, encoding_class, "active", "Z");
|
2016-03-24 19:36:46 -07:00
|
|
|
jfieldID bitrate_id =
|
|
|
|
|
GetFieldID(jni, encoding_class, "maxBitrateBps", "Ljava/lang/Integer;");
|
|
|
|
|
|
|
|
|
|
jclass integer_class = jni->FindClass("java/lang/Integer");
|
|
|
|
|
jmethodID integer_ctor = GetMethodID(jni, integer_class, "<init>", "(I)V");
|
|
|
|
|
|
2016-03-29 17:21:29 -07:00
|
|
|
for (const webrtc::RtpEncodingParameters& encoding : parameters.encodings) {
|
2016-03-24 19:36:46 -07:00
|
|
|
jobject j_encoding_parameters =
|
|
|
|
|
jni->NewObject(encoding_class, encoding_ctor);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
2016-03-29 17:21:29 -07:00
|
|
|
jni->SetBooleanField(j_encoding_parameters, active_id, encoding.active);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetBooleanField";
|
2016-03-24 19:36:46 -07:00
|
|
|
if (encoding.max_bitrate_bps > 0) {
|
|
|
|
|
jobject j_bitrate_value =
|
|
|
|
|
jni->NewObject(integer_class, integer_ctor, encoding.max_bitrate_bps);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
jni->SetObjectField(j_encoding_parameters, bitrate_id, j_bitrate_value);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetObjectField";
|
|
|
|
|
}
|
2016-04-20 16:23:10 -07:00
|
|
|
jboolean added = jni->CallBooleanMethod(j_encodings, encodings_add,
|
|
|
|
|
j_encoding_parameters);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
|
|
|
|
|
RTC_CHECK(added);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jclass codec_class = jni->FindClass("org/webrtc/RtpParameters$Codec");
|
|
|
|
|
jmethodID codec_ctor = GetMethodID(jni, codec_class, "<init>", "()V");
|
|
|
|
|
jfieldID codecs_id =
|
|
|
|
|
GetFieldID(jni, parameters_class, "codecs", "Ljava/util/LinkedList;");
|
|
|
|
|
jobject j_codecs = GetObjectField(jni, j_parameters, codecs_id);
|
|
|
|
|
jmethodID codecs_add = GetMethodID(jni, GetObjectClass(jni, j_codecs),
|
|
|
|
|
"add", "(Ljava/lang/Object;)Z");
|
|
|
|
|
jfieldID payload_type_id = GetFieldID(jni, codec_class, "payloadType", "I");
|
|
|
|
|
jfieldID mime_type_id =
|
|
|
|
|
GetFieldID(jni, codec_class, "mimeType", "Ljava/lang/String;");
|
|
|
|
|
jfieldID clock_rate_id = GetFieldID(jni, codec_class, "clockRate", "I");
|
|
|
|
|
jfieldID channels_id = GetFieldID(jni, codec_class, "channels", "I");
|
|
|
|
|
|
|
|
|
|
for (const webrtc::RtpCodecParameters& codec : parameters.codecs) {
|
|
|
|
|
jobject j_codec = jni->NewObject(codec_class, codec_ctor);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during NewObject";
|
|
|
|
|
jni->SetIntField(j_codec, payload_type_id, codec.payload_type);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetIntField";
|
|
|
|
|
jni->SetObjectField(j_codec, mime_type_id,
|
|
|
|
|
JavaStringFromStdString(jni, codec.mime_type));
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetObjectField";
|
|
|
|
|
jni->SetIntField(j_codec, clock_rate_id, codec.clock_rate);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetIntField";
|
|
|
|
|
jni->SetIntField(j_codec, channels_id, codec.channels);
|
|
|
|
|
CHECK_EXCEPTION(jni) << "error during SetIntField";
|
|
|
|
|
jboolean added = jni->CallBooleanMethod(j_codecs, codecs_add, j_codec);
|
2016-03-24 19:36:46 -07:00
|
|
|
CHECK_EXCEPTION(jni) << "error during CallBooleanMethod";
|
2016-04-20 16:23:10 -07:00
|
|
|
RTC_CHECK(added);
|
2016-03-24 19:36:46 -07:00
|
|
|
}
|
2016-04-20 16:23:10 -07:00
|
|
|
|
2016-03-24 19:36:46 -07:00
|
|
|
return j_parameters;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 12:29:25 -07:00
|
|
|
JOW(jstring, RtpSender_nativeId)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) {
|
|
|
|
|
return JavaStringFromStdString(
|
|
|
|
|
jni, reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)->id());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, RtpSender_free)(JNIEnv* jni, jclass, jlong j_rtp_sender_pointer) {
|
|
|
|
|
reinterpret_cast<RtpSenderInterface*>(j_rtp_sender_pointer)->Release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jlong, RtpReceiver_nativeGetTrack)(JNIEnv* jni,
|
|
|
|
|
jclass,
|
|
|
|
|
jlong j_rtp_receiver_pointer,
|
|
|
|
|
jlong j_track_pointer) {
|
|
|
|
|
return jlongFromPointer(
|
|
|
|
|
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)
|
|
|
|
|
->track()
|
|
|
|
|
.release());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(jstring, RtpReceiver_nativeId)(
|
|
|
|
|
JNIEnv* jni, jclass, jlong j_rtp_receiver_pointer) {
|
|
|
|
|
return JavaStringFromStdString(
|
|
|
|
|
jni,
|
|
|
|
|
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)->id());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JOW(void, RtpReceiver_free)(JNIEnv* jni, jclass, jlong j_rtp_receiver_pointer) {
|
|
|
|
|
reinterpret_cast<RtpReceiverInterface*>(j_rtp_receiver_pointer)->Release();
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 12:46:51 +00:00
|
|
|
} // namespace webrtc_jni
|