blob: 9f17ed09135a0aa35f2ae8c6c9d52f6c3063aab6 [file] [log] [blame]
Jason Long00b84622020-07-20 17:52:12 -04001/*
2 * Copyright 2020 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 "examples/androidvoip/jni/android_voip_client.h"
12
13#include <errno.h>
14#include <sys/socket.h>
15#include <algorithm>
16#include <map>
17#include <memory>
18#include <unordered_map>
19#include <unordered_set>
20#include <utility>
21#include <vector>
22
23#include "absl/memory/memory.h"
24#include "api/audio_codecs/builtin_audio_decoder_factory.h"
25#include "api/audio_codecs/builtin_audio_encoder_factory.h"
26#include "api/task_queue/default_task_queue_factory.h"
27#include "api/voip/voip_codec.h"
28#include "api/voip/voip_engine_factory.h"
29#include "api/voip/voip_network.h"
30#include "examples/androidvoip/generated_jni/VoipClient_jni.h"
31#include "rtc_base/logging.h"
32#include "rtc_base/network.h"
33#include "rtc_base/socket_server.h"
34#include "sdk/android/native_api/audio_device_module/audio_device_android.h"
35#include "sdk/android/native_api/jni/java_types.h"
Jason Long577fc0c2020-08-17 17:23:07 -040036#include "sdk/android/native_api/jni/jvm.h"
37#include "sdk/android/native_api/jni/scoped_java_ref.h"
Jason Long00b84622020-07-20 17:52:12 -040038
39namespace {
40
Jason Long577fc0c2020-08-17 17:23:07 -040041#define RUN_ON_VOIP_THREAD(method, ...) \
42 if (!voip_thread_->IsCurrent()) { \
43 voip_thread_->PostTask( \
Jason Long577fc0c2020-08-17 17:23:07 -040044 std::bind(&AndroidVoipClient::method, this, ##__VA_ARGS__)); \
45 return; \
46 } \
47 RTC_DCHECK_RUN_ON(voip_thread_.get());
48
Jason Long00b84622020-07-20 17:52:12 -040049// Connects a UDP socket to a public address and returns the local
50// address associated with it. Since it binds to the "any" address
51// internally, it returns the default local address on a multi-homed
52// endpoint. Implementation copied from
53// BasicNetworkManager::QueryDefaultLocalAddress.
54rtc::IPAddress QueryDefaultLocalAddress(int family) {
55 const char kPublicIPv4Host[] = "8.8.8.8";
56 const char kPublicIPv6Host[] = "2001:4860:4860::8888";
57 const int kPublicPort = 53;
58 std::unique_ptr<rtc::Thread> thread = rtc::Thread::CreateWithSocketServer();
59
60 RTC_DCHECK(thread->socketserver() != nullptr);
61 RTC_DCHECK(family == AF_INET || family == AF_INET6);
62
Niels Möllerd0b88792021-08-12 10:32:30 +020063 std::unique_ptr<rtc::Socket> socket(
64 thread->socketserver()->CreateSocket(family, SOCK_DGRAM));
Jason Long00b84622020-07-20 17:52:12 -040065 if (!socket) {
Harald Alvestrand5f341302021-11-24 10:01:32 +000066 RTC_LOG_ERR(LS_ERROR) << "Socket creation failed";
Jason Long00b84622020-07-20 17:52:12 -040067 return rtc::IPAddress();
68 }
69
70 auto host = family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host;
71 if (socket->Connect(rtc::SocketAddress(host, kPublicPort)) < 0) {
72 if (socket->GetError() != ENETUNREACH &&
73 socket->GetError() != EHOSTUNREACH) {
74 RTC_LOG(LS_INFO) << "Connect failed with " << socket->GetError();
75 }
76 return rtc::IPAddress();
77 }
78 return socket->GetLocalAddress().ipaddr();
79}
80
81// Assigned payload type for supported built-in codecs. PCMU, PCMA,
82// and G722 have set payload types. Whereas opus, ISAC, and ILBC
83// have dynamic payload types.
84enum class PayloadType : int {
85 kPcmu = 0,
86 kPcma = 8,
87 kG722 = 9,
88 kOpus = 96,
89 kIsac = 97,
90 kIlbc = 98,
91};
92
93// Returns the payload type corresponding to codec_name. Only
94// supports the built-in codecs.
95int GetPayloadType(const std::string& codec_name) {
96 RTC_DCHECK(codec_name == "PCMU" || codec_name == "PCMA" ||
97 codec_name == "G722" || codec_name == "opus" ||
98 codec_name == "ISAC" || codec_name == "ILBC");
99
100 if (codec_name == "PCMU") {
101 return static_cast<int>(PayloadType::kPcmu);
102 } else if (codec_name == "PCMA") {
103 return static_cast<int>(PayloadType::kPcma);
104 } else if (codec_name == "G722") {
105 return static_cast<int>(PayloadType::kG722);
106 } else if (codec_name == "opus") {
107 return static_cast<int>(PayloadType::kOpus);
108 } else if (codec_name == "ISAC") {
109 return static_cast<int>(PayloadType::kIsac);
110 } else if (codec_name == "ILBC") {
111 return static_cast<int>(PayloadType::kIlbc);
112 }
113
Artem Titovd3251962021-11-15 16:57:07 +0100114 RTC_DCHECK_NOTREACHED();
Jason Long00b84622020-07-20 17:52:12 -0400115 return -1;
116}
117
118} // namespace
119
120namespace webrtc_examples {
121
Tim Na9325d342020-12-10 14:01:24 -0800122void AndroidVoipClient::Init(
Jason Long00b84622020-07-20 17:52:12 -0400123 JNIEnv* env,
124 const webrtc::JavaParamRef<jobject>& application_context) {
Jason Long00b84622020-07-20 17:52:12 -0400125 webrtc::VoipEngineConfig config;
126 config.encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
127 config.decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
128 config.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
129 config.audio_device_module =
130 webrtc::CreateJavaAudioDeviceModule(env, application_context.obj());
131 config.audio_processing = webrtc::AudioProcessingBuilder().Create();
132
Jason Long577fc0c2020-08-17 17:23:07 -0400133 voip_thread_->Start();
Tim Na9325d342020-12-10 14:01:24 -0800134
Jason Long00b84622020-07-20 17:52:12 -0400135 // Due to consistent thread requirement on
136 // modules/audio_device/android/audio_device_template.h,
137 // code is invoked in the context of voip_thread_.
Tim Na9325d342020-12-10 14:01:24 -0800138 voip_thread_->Invoke<void>(RTC_FROM_HERE, [this, &config] {
Jason Long577fc0c2020-08-17 17:23:07 -0400139 RTC_DCHECK_RUN_ON(voip_thread_.get());
140
141 supported_codecs_ = config.encoder_factory->GetSupportedEncoders();
142 env_ = webrtc::AttachCurrentThreadIfNeeded();
Jason Long00b84622020-07-20 17:52:12 -0400143 voip_engine_ = webrtc::CreateVoipEngine(std::move(config));
Jason Long00b84622020-07-20 17:52:12 -0400144 });
145}
146
147AndroidVoipClient::~AndroidVoipClient() {
Jason Long577fc0c2020-08-17 17:23:07 -0400148 voip_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
149 RTC_DCHECK_RUN_ON(voip_thread_.get());
150
151 JavaVM* jvm = nullptr;
152 env_->GetJavaVM(&jvm);
153 if (!jvm) {
154 RTC_LOG(LS_ERROR) << "Failed to retrieve JVM";
155 return;
156 }
157 jint res = jvm->DetachCurrentThread();
158 if (res != JNI_OK) {
159 RTC_LOG(LS_ERROR) << "DetachCurrentThread failed: " << res;
160 }
161 });
162
Jason Long00b84622020-07-20 17:52:12 -0400163 voip_thread_->Stop();
164}
165
166AndroidVoipClient* AndroidVoipClient::Create(
167 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400168 const webrtc::JavaParamRef<jobject>& application_context,
169 const webrtc::JavaParamRef<jobject>& j_voip_client) {
Jason Long00b84622020-07-20 17:52:12 -0400170 // Using `new` to access a non-public constructor.
171 auto voip_client =
Jason Long577fc0c2020-08-17 17:23:07 -0400172 absl::WrapUnique(new AndroidVoipClient(env, j_voip_client));
Tim Na9325d342020-12-10 14:01:24 -0800173 voip_client->Init(env, application_context);
Jason Long00b84622020-07-20 17:52:12 -0400174 return voip_client.release();
175}
176
Jason Long577fc0c2020-08-17 17:23:07 -0400177void AndroidVoipClient::GetSupportedCodecs(JNIEnv* env) {
178 RUN_ON_VOIP_THREAD(GetSupportedCodecs, env);
179
Jason Long00b84622020-07-20 17:52:12 -0400180 std::vector<std::string> names;
181 for (const webrtc::AudioCodecSpec& spec : supported_codecs_) {
182 names.push_back(spec.format.name);
183 }
184 webrtc::ScopedJavaLocalRef<jstring> (*convert_function)(
185 JNIEnv*, const std::string&) = &webrtc::NativeToJavaString;
Jason Long577fc0c2020-08-17 17:23:07 -0400186 Java_VoipClient_onGetSupportedCodecsCompleted(
187 env_, j_voip_client_, NativeToJavaList(env_, names, convert_function));
Jason Long00b84622020-07-20 17:52:12 -0400188}
189
Jason Long577fc0c2020-08-17 17:23:07 -0400190void AndroidVoipClient::GetLocalIPAddress(JNIEnv* env) {
191 RUN_ON_VOIP_THREAD(GetLocalIPAddress, env);
192
193 std::string local_ip_address;
Jason Long00b84622020-07-20 17:52:12 -0400194 rtc::IPAddress ipv4_address = QueryDefaultLocalAddress(AF_INET);
195 if (!ipv4_address.IsNil()) {
Jason Long577fc0c2020-08-17 17:23:07 -0400196 local_ip_address = ipv4_address.ToString();
197 } else {
198 rtc::IPAddress ipv6_address = QueryDefaultLocalAddress(AF_INET6);
199 if (!ipv6_address.IsNil()) {
200 local_ip_address = ipv6_address.ToString();
201 }
Jason Long00b84622020-07-20 17:52:12 -0400202 }
Jason Long577fc0c2020-08-17 17:23:07 -0400203 Java_VoipClient_onGetLocalIPAddressCompleted(
204 env_, j_voip_client_, webrtc::NativeToJavaString(env_, local_ip_address));
Jason Long00b84622020-07-20 17:52:12 -0400205}
206
Jason Long577fc0c2020-08-17 17:23:07 -0400207void AndroidVoipClient::SetEncoder(const std::string& encoder) {
208 RTC_DCHECK_RUN_ON(voip_thread_.get());
209
Jason Long00b84622020-07-20 17:52:12 -0400210 if (!channel_) {
211 RTC_LOG(LS_ERROR) << "Channel has not been created";
212 return;
213 }
Jason Long577fc0c2020-08-17 17:23:07 -0400214 for (const webrtc::AudioCodecSpec& codec : supported_codecs_) {
215 if (codec.format.name == encoder) {
Tim Na9325d342020-12-10 14:01:24 -0800216 webrtc::VoipResult result = voip_engine_->Codec().SetSendCodec(
Jason Long577fc0c2020-08-17 17:23:07 -0400217 *channel_, GetPayloadType(codec.format.name), codec.format);
Tim Na9325d342020-12-10 14:01:24 -0800218 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long577fc0c2020-08-17 17:23:07 -0400219 return;
Jason Long00b84622020-07-20 17:52:12 -0400220 }
221 }
222}
223
Jason Long577fc0c2020-08-17 17:23:07 -0400224void AndroidVoipClient::SetEncoder(
Jason Long00b84622020-07-20 17:52:12 -0400225 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400226 const webrtc::JavaParamRef<jstring>& j_encoder_string) {
227 const std::string& chosen_encoder =
228 webrtc::JavaToNativeString(env, j_encoder_string);
229 voip_thread_->PostTask(
Henrik Boström2deee4b2022-01-20 11:58:05 +0100230 [this, chosen_encoder] { SetEncoder(chosen_encoder); });
Jason Long577fc0c2020-08-17 17:23:07 -0400231}
232
233void AndroidVoipClient::SetDecoders(const std::vector<std::string>& decoders) {
234 RTC_DCHECK_RUN_ON(voip_thread_.get());
235
Jason Long00b84622020-07-20 17:52:12 -0400236 if (!channel_) {
237 RTC_LOG(LS_ERROR) << "Channel has not been created";
238 return;
239 }
Jason Long00b84622020-07-20 17:52:12 -0400240 std::map<int, webrtc::SdpAudioFormat> decoder_specs;
Jason Long577fc0c2020-08-17 17:23:07 -0400241 for (const webrtc::AudioCodecSpec& codec : supported_codecs_) {
242 if (std::find(decoders.begin(), decoders.end(), codec.format.name) !=
243 decoders.end()) {
244 decoder_specs.insert({GetPayloadType(codec.format.name), codec.format});
Jason Long00b84622020-07-20 17:52:12 -0400245 }
246 }
247
Tim Na9325d342020-12-10 14:01:24 -0800248 webrtc::VoipResult result =
249 voip_engine_->Codec().SetReceiveCodecs(*channel_, decoder_specs);
250 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long00b84622020-07-20 17:52:12 -0400251}
252
Jason Long577fc0c2020-08-17 17:23:07 -0400253void AndroidVoipClient::SetDecoders(
254 JNIEnv* env,
255 const webrtc::JavaParamRef<jobject>& j_decoder_strings) {
256 const std::vector<std::string>& chosen_decoders =
257 webrtc::JavaListToNativeVector<std::string, jstring>(
258 env, j_decoder_strings, &webrtc::JavaToNativeString);
259 voip_thread_->PostTask(
Henrik Boström2deee4b2022-01-20 11:58:05 +0100260 [this, chosen_decoders] { SetDecoders(chosen_decoders); });
Jason Long577fc0c2020-08-17 17:23:07 -0400261}
262
263void AndroidVoipClient::SetLocalAddress(const std::string& ip_address,
264 const int port_number) {
265 RTC_DCHECK_RUN_ON(voip_thread_.get());
266
267 rtp_local_address_ = rtc::SocketAddress(ip_address, port_number);
268 rtcp_local_address_ = rtc::SocketAddress(ip_address, port_number + 1);
269}
270
Jason Long00b84622020-07-20 17:52:12 -0400271void AndroidVoipClient::SetLocalAddress(
272 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400273 const webrtc::JavaParamRef<jstring>& j_ip_address_string,
Jason Long00b84622020-07-20 17:52:12 -0400274 jint j_port_number_int) {
275 const std::string& ip_address =
276 webrtc::JavaToNativeString(env, j_ip_address_string);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100277 voip_thread_->PostTask([this, ip_address, j_port_number_int] {
Jason Long577fc0c2020-08-17 17:23:07 -0400278 SetLocalAddress(ip_address, j_port_number_int);
279 });
280}
281
282void AndroidVoipClient::SetRemoteAddress(const std::string& ip_address,
283 const int port_number) {
284 RTC_DCHECK_RUN_ON(voip_thread_.get());
285
286 rtp_remote_address_ = rtc::SocketAddress(ip_address, port_number);
287 rtcp_remote_address_ = rtc::SocketAddress(ip_address, port_number + 1);
Jason Long00b84622020-07-20 17:52:12 -0400288}
289
290void AndroidVoipClient::SetRemoteAddress(
291 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400292 const webrtc::JavaParamRef<jstring>& j_ip_address_string,
Jason Long00b84622020-07-20 17:52:12 -0400293 jint j_port_number_int) {
294 const std::string& ip_address =
295 webrtc::JavaToNativeString(env, j_ip_address_string);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100296 voip_thread_->PostTask([this, ip_address, j_port_number_int] {
Jason Long577fc0c2020-08-17 17:23:07 -0400297 SetRemoteAddress(ip_address, j_port_number_int);
298 });
Jason Long00b84622020-07-20 17:52:12 -0400299}
300
Jason Long577fc0c2020-08-17 17:23:07 -0400301void AndroidVoipClient::StartSession(JNIEnv* env) {
302 RUN_ON_VOIP_THREAD(StartSession, env);
303
Tim Na9325d342020-12-10 14:01:24 -0800304 // CreateChannel guarantees to return valid channel id.
Jason Long577fc0c2020-08-17 17:23:07 -0400305 channel_ = voip_engine_->Base().CreateChannel(this, absl::nullopt);
Jason Long00b84622020-07-20 17:52:12 -0400306
307 rtp_socket_.reset(rtc::AsyncUDPSocket::Create(voip_thread_->socketserver(),
308 rtp_local_address_));
309 if (!rtp_socket_) {
Harald Alvestrand5f341302021-11-24 10:01:32 +0000310 RTC_LOG_ERR(LS_ERROR) << "Socket creation failed";
Jason Long577fc0c2020-08-17 17:23:07 -0400311 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
312 /*isSuccessful=*/false);
313 return;
Jason Long00b84622020-07-20 17:52:12 -0400314 }
315 rtp_socket_->SignalReadPacket.connect(
316 this, &AndroidVoipClient::OnSignalReadRTPPacket);
317
318 rtcp_socket_.reset(rtc::AsyncUDPSocket::Create(voip_thread_->socketserver(),
319 rtcp_local_address_));
320 if (!rtcp_socket_) {
Harald Alvestrand5f341302021-11-24 10:01:32 +0000321 RTC_LOG_ERR(LS_ERROR) << "Socket creation failed";
Jason Long577fc0c2020-08-17 17:23:07 -0400322 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
323 /*isSuccessful=*/false);
324 return;
Jason Long00b84622020-07-20 17:52:12 -0400325 }
326 rtcp_socket_->SignalReadPacket.connect(
327 this, &AndroidVoipClient::OnSignalReadRTCPPacket);
Jason Long577fc0c2020-08-17 17:23:07 -0400328 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
329 /*isSuccessful=*/true);
Jason Long00b84622020-07-20 17:52:12 -0400330}
331
Jason Long577fc0c2020-08-17 17:23:07 -0400332void AndroidVoipClient::StopSession(JNIEnv* env) {
333 RUN_ON_VOIP_THREAD(StopSession, env);
334
Jason Long00b84622020-07-20 17:52:12 -0400335 if (!channel_) {
336 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400337 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
338 /*isSuccessful=*/false);
339 return;
Jason Long00b84622020-07-20 17:52:12 -0400340 }
Tim Nab223cb62020-11-20 09:34:47 -0800341 if (voip_engine_->Base().StopSend(*channel_) != webrtc::VoipResult::kOk ||
342 voip_engine_->Base().StopPlayout(*channel_) != webrtc::VoipResult::kOk) {
Jason Long577fc0c2020-08-17 17:23:07 -0400343 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
344 /*isSuccessful=*/false);
345 return;
Jason Long00b84622020-07-20 17:52:12 -0400346 }
347
348 rtp_socket_->Close();
349 rtcp_socket_->Close();
Jason Long577fc0c2020-08-17 17:23:07 -0400350
Tim Na9325d342020-12-10 14:01:24 -0800351 webrtc::VoipResult result = voip_engine_->Base().ReleaseChannel(*channel_);
352 RTC_CHECK(result == webrtc::VoipResult::kOk);
353
Jason Long00b84622020-07-20 17:52:12 -0400354 channel_ = absl::nullopt;
Jason Long577fc0c2020-08-17 17:23:07 -0400355 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
356 /*isSuccessful=*/true);
Jason Long00b84622020-07-20 17:52:12 -0400357}
358
Jason Long577fc0c2020-08-17 17:23:07 -0400359void AndroidVoipClient::StartSend(JNIEnv* env) {
360 RUN_ON_VOIP_THREAD(StartSend, env);
361
Jason Long00b84622020-07-20 17:52:12 -0400362 if (!channel_) {
363 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400364 Java_VoipClient_onStartSendCompleted(env_, j_voip_client_,
365 /*isSuccessful=*/false);
366 return;
Jason Long00b84622020-07-20 17:52:12 -0400367 }
Tim Nab223cb62020-11-20 09:34:47 -0800368 bool sending_started =
369 (voip_engine_->Base().StartSend(*channel_) == webrtc::VoipResult::kOk);
370 Java_VoipClient_onStartSendCompleted(env_, j_voip_client_, sending_started);
Jason Long00b84622020-07-20 17:52:12 -0400371}
372
Jason Long577fc0c2020-08-17 17:23:07 -0400373void AndroidVoipClient::StopSend(JNIEnv* env) {
374 RUN_ON_VOIP_THREAD(StopSend, env);
375
Jason Long00b84622020-07-20 17:52:12 -0400376 if (!channel_) {
377 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400378 Java_VoipClient_onStopSendCompleted(env_, j_voip_client_,
379 /*isSuccessful=*/false);
380 return;
Jason Long00b84622020-07-20 17:52:12 -0400381 }
Tim Nab223cb62020-11-20 09:34:47 -0800382 bool sending_stopped =
383 (voip_engine_->Base().StopSend(*channel_) == webrtc::VoipResult::kOk);
384 Java_VoipClient_onStopSendCompleted(env_, j_voip_client_, sending_stopped);
Jason Long00b84622020-07-20 17:52:12 -0400385}
386
Jason Long577fc0c2020-08-17 17:23:07 -0400387void AndroidVoipClient::StartPlayout(JNIEnv* env) {
388 RUN_ON_VOIP_THREAD(StartPlayout, env);
389
Jason Long00b84622020-07-20 17:52:12 -0400390 if (!channel_) {
391 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400392 Java_VoipClient_onStartPlayoutCompleted(env_, j_voip_client_,
393 /*isSuccessful=*/false);
394 return;
Jason Long00b84622020-07-20 17:52:12 -0400395 }
Tim Nab223cb62020-11-20 09:34:47 -0800396 bool playout_started =
397 (voip_engine_->Base().StartPlayout(*channel_) == webrtc::VoipResult::kOk);
398 Java_VoipClient_onStartPlayoutCompleted(env_, j_voip_client_,
399 playout_started);
Jason Long00b84622020-07-20 17:52:12 -0400400}
401
Jason Long577fc0c2020-08-17 17:23:07 -0400402void AndroidVoipClient::StopPlayout(JNIEnv* env) {
403 RUN_ON_VOIP_THREAD(StopPlayout, env);
404
Jason Long00b84622020-07-20 17:52:12 -0400405 if (!channel_) {
406 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400407 Java_VoipClient_onStopPlayoutCompleted(env_, j_voip_client_,
408 /*isSuccessful=*/false);
409 return;
Jason Long00b84622020-07-20 17:52:12 -0400410 }
Tim Nab223cb62020-11-20 09:34:47 -0800411 bool playout_stopped =
412 (voip_engine_->Base().StopPlayout(*channel_) == webrtc::VoipResult::kOk);
413 Java_VoipClient_onStopPlayoutCompleted(env_, j_voip_client_, playout_stopped);
Jason Long00b84622020-07-20 17:52:12 -0400414}
415
416void AndroidVoipClient::Delete(JNIEnv* env) {
417 delete this;
418}
419
Jason Long577fc0c2020-08-17 17:23:07 -0400420void AndroidVoipClient::SendRtpPacket(const std::vector<uint8_t>& packet_copy) {
421 RTC_DCHECK_RUN_ON(voip_thread_.get());
422
423 if (!rtp_socket_->SendTo(packet_copy.data(), packet_copy.size(),
424 rtp_remote_address_, rtc::PacketOptions())) {
425 RTC_LOG(LS_ERROR) << "Failed to send RTP packet";
426 }
427}
428
Jason Long00b84622020-07-20 17:52:12 -0400429bool AndroidVoipClient::SendRtp(const uint8_t* packet,
430 size_t length,
431 const webrtc::PacketOptions& options) {
Jason Long577fc0c2020-08-17 17:23:07 -0400432 std::vector<uint8_t> packet_copy(packet, packet + length);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100433 voip_thread_->PostTask([this, packet_copy = std::move(packet_copy)] {
434 SendRtpPacket(packet_copy);
435 });
Jason Long00b84622020-07-20 17:52:12 -0400436 return true;
437}
438
Jason Long577fc0c2020-08-17 17:23:07 -0400439void AndroidVoipClient::SendRtcpPacket(
440 const std::vector<uint8_t>& packet_copy) {
441 RTC_DCHECK_RUN_ON(voip_thread_.get());
442
443 if (!rtcp_socket_->SendTo(packet_copy.data(), packet_copy.size(),
444 rtcp_remote_address_, rtc::PacketOptions())) {
Jason Long00b84622020-07-20 17:52:12 -0400445 RTC_LOG(LS_ERROR) << "Failed to send RTCP packet";
Jason Long00b84622020-07-20 17:52:12 -0400446 }
Jason Long577fc0c2020-08-17 17:23:07 -0400447}
448
449bool AndroidVoipClient::SendRtcp(const uint8_t* packet, size_t length) {
450 std::vector<uint8_t> packet_copy(packet, packet + length);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100451 voip_thread_->PostTask([this, packet_copy = std::move(packet_copy)] {
452 SendRtcpPacket(packet_copy);
453 });
Jason Long00b84622020-07-20 17:52:12 -0400454 return true;
455}
456
Jason Long577fc0c2020-08-17 17:23:07 -0400457void AndroidVoipClient::ReadRTPPacket(const std::vector<uint8_t>& packet_copy) {
458 RTC_DCHECK_RUN_ON(voip_thread_.get());
459
460 if (!channel_) {
461 RTC_LOG(LS_ERROR) << "Channel has not been created";
462 return;
463 }
Tim Na9325d342020-12-10 14:01:24 -0800464 webrtc::VoipResult result = voip_engine_->Network().ReceivedRTPPacket(
Jason Long577fc0c2020-08-17 17:23:07 -0400465 *channel_,
466 rtc::ArrayView<const uint8_t>(packet_copy.data(), packet_copy.size()));
Tim Na9325d342020-12-10 14:01:24 -0800467 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long577fc0c2020-08-17 17:23:07 -0400468}
469
Jason Long00b84622020-07-20 17:52:12 -0400470void AndroidVoipClient::OnSignalReadRTPPacket(rtc::AsyncPacketSocket* socket,
471 const char* rtp_packet,
472 size_t size,
473 const rtc::SocketAddress& addr,
474 const int64_t& timestamp) {
Jason Long577fc0c2020-08-17 17:23:07 -0400475 std::vector<uint8_t> packet_copy(rtp_packet, rtp_packet + size);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100476 voip_thread_->PostTask([this, packet_copy = std::move(packet_copy)] {
477 ReadRTPPacket(packet_copy);
478 });
Jason Long577fc0c2020-08-17 17:23:07 -0400479}
480
481void AndroidVoipClient::ReadRTCPPacket(
482 const std::vector<uint8_t>& packet_copy) {
483 RTC_DCHECK_RUN_ON(voip_thread_.get());
484
Jason Long00b84622020-07-20 17:52:12 -0400485 if (!channel_) {
486 RTC_LOG(LS_ERROR) << "Channel has not been created";
487 return;
488 }
Tim Na9325d342020-12-10 14:01:24 -0800489 webrtc::VoipResult result = voip_engine_->Network().ReceivedRTCPPacket(
Jason Long577fc0c2020-08-17 17:23:07 -0400490 *channel_,
491 rtc::ArrayView<const uint8_t>(packet_copy.data(), packet_copy.size()));
Tim Na9325d342020-12-10 14:01:24 -0800492 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long00b84622020-07-20 17:52:12 -0400493}
494
495void AndroidVoipClient::OnSignalReadRTCPPacket(rtc::AsyncPacketSocket* socket,
496 const char* rtcp_packet,
497 size_t size,
498 const rtc::SocketAddress& addr,
499 const int64_t& timestamp) {
Jason Long577fc0c2020-08-17 17:23:07 -0400500 std::vector<uint8_t> packet_copy(rtcp_packet, rtcp_packet + size);
Henrik Boström2deee4b2022-01-20 11:58:05 +0100501 voip_thread_->PostTask([this, packet_copy = std::move(packet_copy)] {
502 ReadRTCPPacket(packet_copy);
503 });
Jason Long00b84622020-07-20 17:52:12 -0400504}
505
506static jlong JNI_VoipClient_CreateClient(
507 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400508 const webrtc::JavaParamRef<jobject>& application_context,
509 const webrtc::JavaParamRef<jobject>& j_voip_client) {
Jason Long00b84622020-07-20 17:52:12 -0400510 return webrtc::NativeToJavaPointer(
Jason Long577fc0c2020-08-17 17:23:07 -0400511 AndroidVoipClient::Create(env, application_context, j_voip_client));
Jason Long00b84622020-07-20 17:52:12 -0400512}
513
514} // namespace webrtc_examples