OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <memory> | |
12 #include <utility> | |
13 | |
14 #include "webrtc/api/peerconnectioninterface.h" | |
15 #include "webrtc/media/base/mediaengine.h" | |
16 #include "webrtc/modules/utility/include/jvm_android.h" | |
17 #include "webrtc/rtc_base/event_tracer.h" | |
18 #include "webrtc/rtc_base/stringutils.h" | |
19 #include "webrtc/rtc_base/thread.h" | |
20 #include "webrtc/sdk/android/src/jni/jni_helpers.h" | |
21 #include "webrtc/sdk/android/src/jni/pc/androidnetworkmonitor_jni.h" | |
22 #include "webrtc/sdk/android/src/jni/pc/audio_jni.h" | |
23 #include "webrtc/sdk/android/src/jni/pc/java_native_conversion.h" | |
24 #include "webrtc/sdk/android/src/jni/pc/media_jni.h" | |
25 #include "webrtc/sdk/android/src/jni/pc/ownedfactoryandthreads.h" | |
26 #include "webrtc/sdk/android/src/jni/pc/peerconnectionobserver_jni.h" | |
27 #include "webrtc/sdk/android/src/jni/pc/video_jni.h" | |
28 #include "webrtc/system_wrappers/include/field_trial.h" | |
29 // Adding 'nogncheck' to disable the gn include headers check. | |
30 // We don't want to depend on 'system_wrappers:field_trial_default' because | |
31 // clients should be able to provide their own implementation. | |
32 #include "webrtc/system_wrappers/include/field_trial_default.h" // nogncheck | |
33 #include "webrtc/system_wrappers/include/trace.h" | |
34 | |
35 namespace webrtc_jni { | |
36 | |
37 // Note: Some of the video-specific PeerConnectionFactory methods are | |
38 // implemented in "video_jni.cc". This is done so that if an application | |
39 // doesn't need video support, it can just link with "null_video_jni.cc" | |
40 // instead of "video_jni.cc", which doesn't bring in the video-specific | |
41 // dependencies. | |
42 | |
43 // Field trials initialization string | |
44 static char* field_trials_init_string = nullptr; | |
45 | |
46 // Set in PeerConnectionFactory_initializeAndroidGlobals(). | |
47 static bool factory_static_initialized = false; | |
48 static bool video_hw_acceleration_enabled = true; | |
49 | |
50 JOW(jlong, PeerConnectionFactory_nativeCreateObserver) | |
51 (JNIEnv* jni, jclass, jobject j_observer) { | |
52 return (jlong) new PeerConnectionObserverJni(jni, j_observer); | |
53 } | |
54 | |
55 JOW(void, PeerConnectionFactory_nativeInitializeAndroidGlobals) | |
56 (JNIEnv* jni, jclass, jobject context, jboolean video_hw_acceleration) { | |
57 video_hw_acceleration_enabled = video_hw_acceleration; | |
58 if (!factory_static_initialized) { | |
59 webrtc::JVM::Initialize(GetJVM()); | |
60 factory_static_initialized = true; | |
61 } | |
62 } | |
63 | |
64 JOW(void, PeerConnectionFactory_initializeFieldTrials) | |
65 (JNIEnv* jni, jclass, jstring j_trials_init_string) { | |
66 field_trials_init_string = NULL; | |
67 if (j_trials_init_string != NULL) { | |
68 const char* init_string = | |
69 jni->GetStringUTFChars(j_trials_init_string, NULL); | |
70 int init_string_length = jni->GetStringUTFLength(j_trials_init_string); | |
71 field_trials_init_string = new char[init_string_length + 1]; | |
72 rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string); | |
73 jni->ReleaseStringUTFChars(j_trials_init_string, init_string); | |
74 LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string; | |
75 } | |
76 webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string); | |
77 } | |
78 | |
79 JOW(void, PeerConnectionFactory_initializeInternalTracer)(JNIEnv* jni, jclass) { | |
80 rtc::tracing::SetupInternalTracer(); | |
81 } | |
82 | |
83 JOW(jstring, PeerConnectionFactory_nativeFieldTrialsFindFullName) | |
84 (JNIEnv* jni, jclass, jstring j_name) { | |
85 return JavaStringFromStdString( | |
86 jni, webrtc::field_trial::FindFullName(JavaToStdString(jni, j_name))); | |
87 } | |
88 | |
89 JOW(jboolean, PeerConnectionFactory_startInternalTracingCapture) | |
90 (JNIEnv* jni, jclass, jstring j_event_tracing_filename) { | |
91 if (!j_event_tracing_filename) | |
92 return false; | |
93 | |
94 const char* init_string = | |
95 jni->GetStringUTFChars(j_event_tracing_filename, NULL); | |
96 LOG(LS_INFO) << "Starting internal tracing to: " << init_string; | |
97 bool ret = rtc::tracing::StartInternalCapture(init_string); | |
98 jni->ReleaseStringUTFChars(j_event_tracing_filename, init_string); | |
99 return ret; | |
100 } | |
101 | |
102 JOW(void, PeerConnectionFactory_stopInternalTracingCapture) | |
103 (JNIEnv* jni, jclass) { | |
104 rtc::tracing::StopInternalCapture(); | |
105 } | |
106 | |
107 JOW(void, PeerConnectionFactory_shutdownInternalTracer)(JNIEnv* jni, jclass) { | |
108 rtc::tracing::ShutdownInternalTracer(); | |
109 } | |
110 | |
111 JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory) | |
112 (JNIEnv* jni, | |
113 jclass, | |
114 jobject joptions, | |
115 jobject jencoder_factory, | |
116 jobject jdecoder_factory) { | |
117 // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but | |
118 // ThreadManager only WrapCurrentThread()s the thread where it is first | |
119 // created. Since the semantics around when auto-wrapping happens in | |
120 // webrtc/rtc_base/ are convoluted, we simply wrap here to avoid having to | |
121 // think about ramifications of auto-wrapping there. | |
122 rtc::ThreadManager::Instance()->WrapCurrentThread(); | |
123 webrtc::Trace::CreateTrace(); | |
124 | |
125 std::unique_ptr<rtc::Thread> network_thread = | |
126 rtc::Thread::CreateWithSocketServer(); | |
127 network_thread->SetName("network_thread", nullptr); | |
128 RTC_CHECK(network_thread->Start()) << "Failed to start thread"; | |
129 | |
130 std::unique_ptr<rtc::Thread> worker_thread = rtc::Thread::Create(); | |
131 worker_thread->SetName("worker_thread", nullptr); | |
132 RTC_CHECK(worker_thread->Start()) << "Failed to start thread"; | |
133 | |
134 std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create(); | |
135 signaling_thread->SetName("signaling_thread", NULL); | |
136 RTC_CHECK(signaling_thread->Start()) << "Failed to start thread"; | |
137 | |
138 cricket::WebRtcVideoEncoderFactory* video_encoder_factory = nullptr; | |
139 cricket::WebRtcVideoDecoderFactory* video_decoder_factory = nullptr; | |
140 rtc::NetworkMonitorFactory* network_monitor_factory = nullptr; | |
141 auto audio_encoder_factory = CreateAudioEncoderFactory(); | |
142 auto audio_decoder_factory = CreateAudioDecoderFactory(); | |
143 | |
144 webrtc::PeerConnectionFactoryInterface::Options options; | |
145 bool has_options = joptions != NULL; | |
146 if (has_options) { | |
147 options = JavaToNativePeerConnectionFactoryOptions(jni, joptions); | |
148 } | |
149 | |
150 if (video_hw_acceleration_enabled) { | |
151 video_encoder_factory = CreateVideoEncoderFactory(jni, jencoder_factory); | |
152 video_decoder_factory = CreateVideoDecoderFactory(jni, jdecoder_factory); | |
153 } | |
154 // Do not create network_monitor_factory only if the options are | |
155 // provided and disable_network_monitor therein is set to true. | |
156 if (!(has_options && options.disable_network_monitor)) { | |
157 network_monitor_factory = new AndroidNetworkMonitorFactory(); | |
158 rtc::NetworkMonitorFactory::SetFactory(network_monitor_factory); | |
159 } | |
160 | |
161 webrtc::AudioDeviceModule* adm = nullptr; | |
162 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer = nullptr; | |
163 std::unique_ptr<webrtc::CallFactoryInterface> call_factory( | |
164 CreateCallFactory()); | |
165 std::unique_ptr<webrtc::RtcEventLogFactoryInterface> rtc_event_log_factory( | |
166 CreateRtcEventLogFactory()); | |
167 std::unique_ptr<cricket::MediaEngineInterface> media_engine(CreateMediaEngine( | |
168 adm, audio_encoder_factory, audio_decoder_factory, video_encoder_factory, | |
169 video_decoder_factory, audio_mixer)); | |
170 | |
171 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
172 CreateModularPeerConnectionFactory( | |
173 network_thread.get(), worker_thread.get(), signaling_thread.get(), | |
174 adm, audio_encoder_factory, audio_decoder_factory, | |
175 video_encoder_factory, video_decoder_factory, audio_mixer, | |
176 std::move(media_engine), std::move(call_factory), | |
177 std::move(rtc_event_log_factory))); | |
178 RTC_CHECK(factory) << "Failed to create the peer connection factory; " | |
179 << "WebRTC/libjingle init likely failed on this device"; | |
180 // TODO(honghaiz): Maybe put the options as the argument of | |
181 // CreatePeerConnectionFactory. | |
182 if (has_options) { | |
183 factory->SetOptions(options); | |
184 } | |
185 OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads( | |
186 std::move(network_thread), std::move(worker_thread), | |
187 std::move(signaling_thread), video_encoder_factory, video_decoder_factory, | |
188 network_monitor_factory, factory.release()); | |
189 owned_factory->InvokeJavaCallbacksOnFactoryThreads(); | |
190 return jlongFromPointer(owned_factory); | |
191 } | |
192 | |
193 JOW(void, PeerConnectionFactory_nativeFreeFactory)(JNIEnv*, jclass, jlong j_p) { | |
194 delete reinterpret_cast<OwnedFactoryAndThreads*>(j_p); | |
195 if (field_trials_init_string) { | |
196 webrtc::field_trial::InitFieldTrialsFromString(NULL); | |
197 delete field_trials_init_string; | |
198 field_trials_init_string = NULL; | |
199 } | |
200 webrtc::Trace::ReturnTrace(); | |
201 } | |
202 | |
203 JOW(void, PeerConnectionFactory_nativeThreadsCallbacks) | |
204 (JNIEnv*, jclass, jlong j_p) { | |
205 OwnedFactoryAndThreads* factory = | |
206 reinterpret_cast<OwnedFactoryAndThreads*>(j_p); | |
207 factory->InvokeJavaCallbacksOnFactoryThreads(); | |
208 } | |
209 | |
210 JOW(jlong, PeerConnectionFactory_nativeCreateLocalMediaStream) | |
211 (JNIEnv* jni, jclass, jlong native_factory, jstring label) { | |
212 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
213 factoryFromJava(native_factory)); | |
214 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream( | |
215 factory->CreateLocalMediaStream(JavaToStdString(jni, label))); | |
216 return (jlong)stream.release(); | |
217 } | |
218 | |
219 JOW(jlong, PeerConnectionFactory_nativeCreateAudioSource) | |
220 (JNIEnv* jni, jclass, jlong native_factory, jobject j_constraints) { | |
221 std::unique_ptr<MediaConstraintsJni> constraints( | |
222 new MediaConstraintsJni(jni, j_constraints)); | |
223 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
224 factoryFromJava(native_factory)); | |
225 cricket::AudioOptions options; | |
226 CopyConstraintsIntoAudioOptions(constraints.get(), &options); | |
227 rtc::scoped_refptr<webrtc::AudioSourceInterface> source( | |
228 factory->CreateAudioSource(options)); | |
229 return (jlong)source.release(); | |
230 } | |
231 | |
232 JOW(jlong, PeerConnectionFactory_nativeCreateAudioTrack) | |
233 (JNIEnv* jni, jclass, jlong native_factory, jstring id, jlong native_source) { | |
234 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
235 factoryFromJava(native_factory)); | |
236 rtc::scoped_refptr<webrtc::AudioTrackInterface> track( | |
237 factory->CreateAudioTrack( | |
238 JavaToStdString(jni, id), | |
239 reinterpret_cast<webrtc::AudioSourceInterface*>(native_source))); | |
240 return (jlong)track.release(); | |
241 } | |
242 | |
243 JOW(jboolean, PeerConnectionFactory_nativeStartAecDump) | |
244 (JNIEnv* jni, | |
245 jclass, | |
246 jlong native_factory, | |
247 jint file, | |
248 jint filesize_limit_bytes) { | |
249 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
250 factoryFromJava(native_factory)); | |
251 return factory->StartAecDump(file, filesize_limit_bytes); | |
252 } | |
253 | |
254 JOW(void, PeerConnectionFactory_nativeStopAecDump) | |
255 (JNIEnv* jni, jclass, jlong native_factory) { | |
256 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
257 factoryFromJava(native_factory)); | |
258 factory->StopAecDump(); | |
259 } | |
260 | |
261 JOW(void, PeerConnectionFactory_nativeSetOptions) | |
262 (JNIEnv* jni, jclass, jlong native_factory, jobject options) { | |
263 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( | |
264 factoryFromJava(native_factory)); | |
265 webrtc::PeerConnectionFactoryInterface::Options options_to_set = | |
266 JavaToNativePeerConnectionFactoryOptions(jni, options); | |
267 factory->SetOptions(options_to_set); | |
268 | |
269 if (options_to_set.disable_network_monitor) { | |
270 OwnedFactoryAndThreads* owner = | |
271 reinterpret_cast<OwnedFactoryAndThreads*>(native_factory); | |
272 if (owner->network_monitor_factory()) { | |
273 rtc::NetworkMonitorFactory::ReleaseFactory( | |
274 owner->network_monitor_factory()); | |
275 owner->clear_network_monitor_factory(); | |
276 } | |
277 } | |
278 } | |
279 | |
280 JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection) | |
281 (JNIEnv* jni, | |
282 jclass, | |
283 jlong factory, | |
284 jobject j_rtc_config, | |
285 jobject j_constraints, | |
286 jlong observer_p) { | |
287 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> f( | |
288 reinterpret_cast<webrtc::PeerConnectionFactoryInterface*>( | |
289 factoryFromJava(factory))); | |
290 | |
291 webrtc::PeerConnectionInterface::RTCConfiguration rtc_config( | |
292 webrtc::PeerConnectionInterface::RTCConfigurationType::kAggressive); | |
293 JavaToNativeRTCConfiguration(jni, j_rtc_config, &rtc_config); | |
294 | |
295 jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config); | |
296 jfieldID j_key_type_id = GetFieldID(jni, j_rtc_config_class, "keyType", | |
297 "Lorg/webrtc/PeerConnection$KeyType;"); | |
298 jobject j_key_type = GetObjectField(jni, j_rtc_config, j_key_type_id); | |
299 | |
300 // Generate non-default certificate. | |
301 rtc::KeyType key_type = JavaToNativeKeyType(jni, j_key_type); | |
302 if (key_type != rtc::KT_DEFAULT) { | |
303 rtc::scoped_refptr<rtc::RTCCertificate> certificate = | |
304 rtc::RTCCertificateGenerator::GenerateCertificate( | |
305 rtc::KeyParams(key_type), rtc::Optional<uint64_t>()); | |
306 if (!certificate) { | |
307 LOG(LS_ERROR) << "Failed to generate certificate. KeyType: " << key_type; | |
308 return 0; | |
309 } | |
310 rtc_config.certificates.push_back(certificate); | |
311 } | |
312 | |
313 PeerConnectionObserverJni* observer = | |
314 reinterpret_cast<PeerConnectionObserverJni*>(observer_p); | |
315 observer->SetConstraints(new MediaConstraintsJni(jni, j_constraints)); | |
316 CopyConstraintsIntoRtcConfiguration(observer->constraints(), &rtc_config); | |
317 rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc( | |
318 f->CreatePeerConnection(rtc_config, nullptr, nullptr, observer)); | |
319 return (jlong)pc.release(); | |
320 } | |
321 | |
322 } // namespace webrtc_jni | |
OLD | NEW |