blob: 95d3ed407fd38506f85513a075efa17b8f14fc4f [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( \
44 RTC_FROM_HERE, \
45 std::bind(&AndroidVoipClient::method, this, ##__VA_ARGS__)); \
46 return; \
47 } \
48 RTC_DCHECK_RUN_ON(voip_thread_.get());
49
Jason Long00b84622020-07-20 17:52:12 -040050// Connects a UDP socket to a public address and returns the local
51// address associated with it. Since it binds to the "any" address
52// internally, it returns the default local address on a multi-homed
53// endpoint. Implementation copied from
54// BasicNetworkManager::QueryDefaultLocalAddress.
55rtc::IPAddress QueryDefaultLocalAddress(int family) {
56 const char kPublicIPv4Host[] = "8.8.8.8";
57 const char kPublicIPv6Host[] = "2001:4860:4860::8888";
58 const int kPublicPort = 53;
59 std::unique_ptr<rtc::Thread> thread = rtc::Thread::CreateWithSocketServer();
60
61 RTC_DCHECK(thread->socketserver() != nullptr);
62 RTC_DCHECK(family == AF_INET || family == AF_INET6);
63
64 std::unique_ptr<rtc::AsyncSocket> socket(
65 thread->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
66 if (!socket) {
67 RTC_LOG_ERR(LERROR) << "Socket creation failed";
68 return rtc::IPAddress();
69 }
70
71 auto host = family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host;
72 if (socket->Connect(rtc::SocketAddress(host, kPublicPort)) < 0) {
73 if (socket->GetError() != ENETUNREACH &&
74 socket->GetError() != EHOSTUNREACH) {
75 RTC_LOG(LS_INFO) << "Connect failed with " << socket->GetError();
76 }
77 return rtc::IPAddress();
78 }
79 return socket->GetLocalAddress().ipaddr();
80}
81
82// Assigned payload type for supported built-in codecs. PCMU, PCMA,
83// and G722 have set payload types. Whereas opus, ISAC, and ILBC
84// have dynamic payload types.
85enum class PayloadType : int {
86 kPcmu = 0,
87 kPcma = 8,
88 kG722 = 9,
89 kOpus = 96,
90 kIsac = 97,
91 kIlbc = 98,
92};
93
94// Returns the payload type corresponding to codec_name. Only
95// supports the built-in codecs.
96int GetPayloadType(const std::string& codec_name) {
97 RTC_DCHECK(codec_name == "PCMU" || codec_name == "PCMA" ||
98 codec_name == "G722" || codec_name == "opus" ||
99 codec_name == "ISAC" || codec_name == "ILBC");
100
101 if (codec_name == "PCMU") {
102 return static_cast<int>(PayloadType::kPcmu);
103 } else if (codec_name == "PCMA") {
104 return static_cast<int>(PayloadType::kPcma);
105 } else if (codec_name == "G722") {
106 return static_cast<int>(PayloadType::kG722);
107 } else if (codec_name == "opus") {
108 return static_cast<int>(PayloadType::kOpus);
109 } else if (codec_name == "ISAC") {
110 return static_cast<int>(PayloadType::kIsac);
111 } else if (codec_name == "ILBC") {
112 return static_cast<int>(PayloadType::kIlbc);
113 }
114
115 RTC_NOTREACHED();
116 return -1;
117}
118
119} // namespace
120
121namespace webrtc_examples {
122
Tim Na9325d342020-12-10 14:01:24 -0800123void AndroidVoipClient::Init(
Jason Long00b84622020-07-20 17:52:12 -0400124 JNIEnv* env,
125 const webrtc::JavaParamRef<jobject>& application_context) {
Jason Long00b84622020-07-20 17:52:12 -0400126 webrtc::VoipEngineConfig config;
127 config.encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
128 config.decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
129 config.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
130 config.audio_device_module =
131 webrtc::CreateJavaAudioDeviceModule(env, application_context.obj());
132 config.audio_processing = webrtc::AudioProcessingBuilder().Create();
133
Jason Long577fc0c2020-08-17 17:23:07 -0400134 voip_thread_->Start();
Tim Na9325d342020-12-10 14:01:24 -0800135
Jason Long00b84622020-07-20 17:52:12 -0400136 // Due to consistent thread requirement on
137 // modules/audio_device/android/audio_device_template.h,
138 // code is invoked in the context of voip_thread_.
Tim Na9325d342020-12-10 14:01:24 -0800139 voip_thread_->Invoke<void>(RTC_FROM_HERE, [this, &config] {
Jason Long577fc0c2020-08-17 17:23:07 -0400140 RTC_DCHECK_RUN_ON(voip_thread_.get());
141
142 supported_codecs_ = config.encoder_factory->GetSupportedEncoders();
143 env_ = webrtc::AttachCurrentThreadIfNeeded();
Jason Long00b84622020-07-20 17:52:12 -0400144 voip_engine_ = webrtc::CreateVoipEngine(std::move(config));
Jason Long00b84622020-07-20 17:52:12 -0400145 });
146}
147
148AndroidVoipClient::~AndroidVoipClient() {
Jason Long577fc0c2020-08-17 17:23:07 -0400149 voip_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
150 RTC_DCHECK_RUN_ON(voip_thread_.get());
151
152 JavaVM* jvm = nullptr;
153 env_->GetJavaVM(&jvm);
154 if (!jvm) {
155 RTC_LOG(LS_ERROR) << "Failed to retrieve JVM";
156 return;
157 }
158 jint res = jvm->DetachCurrentThread();
159 if (res != JNI_OK) {
160 RTC_LOG(LS_ERROR) << "DetachCurrentThread failed: " << res;
161 }
162 });
163
Jason Long00b84622020-07-20 17:52:12 -0400164 voip_thread_->Stop();
165}
166
167AndroidVoipClient* AndroidVoipClient::Create(
168 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400169 const webrtc::JavaParamRef<jobject>& application_context,
170 const webrtc::JavaParamRef<jobject>& j_voip_client) {
Jason Long00b84622020-07-20 17:52:12 -0400171 // Using `new` to access a non-public constructor.
172 auto voip_client =
Jason Long577fc0c2020-08-17 17:23:07 -0400173 absl::WrapUnique(new AndroidVoipClient(env, j_voip_client));
Tim Na9325d342020-12-10 14:01:24 -0800174 voip_client->Init(env, application_context);
Jason Long00b84622020-07-20 17:52:12 -0400175 return voip_client.release();
176}
177
Jason Long577fc0c2020-08-17 17:23:07 -0400178void AndroidVoipClient::GetSupportedCodecs(JNIEnv* env) {
179 RUN_ON_VOIP_THREAD(GetSupportedCodecs, env);
180
Jason Long00b84622020-07-20 17:52:12 -0400181 std::vector<std::string> names;
182 for (const webrtc::AudioCodecSpec& spec : supported_codecs_) {
183 names.push_back(spec.format.name);
184 }
185 webrtc::ScopedJavaLocalRef<jstring> (*convert_function)(
186 JNIEnv*, const std::string&) = &webrtc::NativeToJavaString;
Jason Long577fc0c2020-08-17 17:23:07 -0400187 Java_VoipClient_onGetSupportedCodecsCompleted(
188 env_, j_voip_client_, NativeToJavaList(env_, names, convert_function));
Jason Long00b84622020-07-20 17:52:12 -0400189}
190
Jason Long577fc0c2020-08-17 17:23:07 -0400191void AndroidVoipClient::GetLocalIPAddress(JNIEnv* env) {
192 RUN_ON_VOIP_THREAD(GetLocalIPAddress, env);
193
194 std::string local_ip_address;
Jason Long00b84622020-07-20 17:52:12 -0400195 rtc::IPAddress ipv4_address = QueryDefaultLocalAddress(AF_INET);
196 if (!ipv4_address.IsNil()) {
Jason Long577fc0c2020-08-17 17:23:07 -0400197 local_ip_address = ipv4_address.ToString();
198 } else {
199 rtc::IPAddress ipv6_address = QueryDefaultLocalAddress(AF_INET6);
200 if (!ipv6_address.IsNil()) {
201 local_ip_address = ipv6_address.ToString();
202 }
Jason Long00b84622020-07-20 17:52:12 -0400203 }
Jason Long577fc0c2020-08-17 17:23:07 -0400204 Java_VoipClient_onGetLocalIPAddressCompleted(
205 env_, j_voip_client_, webrtc::NativeToJavaString(env_, local_ip_address));
Jason Long00b84622020-07-20 17:52:12 -0400206}
207
Jason Long577fc0c2020-08-17 17:23:07 -0400208void AndroidVoipClient::SetEncoder(const std::string& encoder) {
209 RTC_DCHECK_RUN_ON(voip_thread_.get());
210
Jason Long00b84622020-07-20 17:52:12 -0400211 if (!channel_) {
212 RTC_LOG(LS_ERROR) << "Channel has not been created";
213 return;
214 }
Jason Long577fc0c2020-08-17 17:23:07 -0400215 for (const webrtc::AudioCodecSpec& codec : supported_codecs_) {
216 if (codec.format.name == encoder) {
Tim Na9325d342020-12-10 14:01:24 -0800217 webrtc::VoipResult result = voip_engine_->Codec().SetSendCodec(
Jason Long577fc0c2020-08-17 17:23:07 -0400218 *channel_, GetPayloadType(codec.format.name), codec.format);
Tim Na9325d342020-12-10 14:01:24 -0800219 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long577fc0c2020-08-17 17:23:07 -0400220 return;
Jason Long00b84622020-07-20 17:52:12 -0400221 }
222 }
223}
224
Jason Long577fc0c2020-08-17 17:23:07 -0400225void AndroidVoipClient::SetEncoder(
Jason Long00b84622020-07-20 17:52:12 -0400226 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400227 const webrtc::JavaParamRef<jstring>& j_encoder_string) {
228 const std::string& chosen_encoder =
229 webrtc::JavaToNativeString(env, j_encoder_string);
230 voip_thread_->PostTask(
231 RTC_FROM_HERE, [this, chosen_encoder] { SetEncoder(chosen_encoder); });
232}
233
234void AndroidVoipClient::SetDecoders(const std::vector<std::string>& decoders) {
235 RTC_DCHECK_RUN_ON(voip_thread_.get());
236
Jason Long00b84622020-07-20 17:52:12 -0400237 if (!channel_) {
238 RTC_LOG(LS_ERROR) << "Channel has not been created";
239 return;
240 }
Jason Long00b84622020-07-20 17:52:12 -0400241 std::map<int, webrtc::SdpAudioFormat> decoder_specs;
Jason Long577fc0c2020-08-17 17:23:07 -0400242 for (const webrtc::AudioCodecSpec& codec : supported_codecs_) {
243 if (std::find(decoders.begin(), decoders.end(), codec.format.name) !=
244 decoders.end()) {
245 decoder_specs.insert({GetPayloadType(codec.format.name), codec.format});
Jason Long00b84622020-07-20 17:52:12 -0400246 }
247 }
248
Tim Na9325d342020-12-10 14:01:24 -0800249 webrtc::VoipResult result =
250 voip_engine_->Codec().SetReceiveCodecs(*channel_, decoder_specs);
251 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long00b84622020-07-20 17:52:12 -0400252}
253
Jason Long577fc0c2020-08-17 17:23:07 -0400254void AndroidVoipClient::SetDecoders(
255 JNIEnv* env,
256 const webrtc::JavaParamRef<jobject>& j_decoder_strings) {
257 const std::vector<std::string>& chosen_decoders =
258 webrtc::JavaListToNativeVector<std::string, jstring>(
259 env, j_decoder_strings, &webrtc::JavaToNativeString);
260 voip_thread_->PostTask(
261 RTC_FROM_HERE, [this, chosen_decoders] { SetDecoders(chosen_decoders); });
262}
263
264void AndroidVoipClient::SetLocalAddress(const std::string& ip_address,
265 const int port_number) {
266 RTC_DCHECK_RUN_ON(voip_thread_.get());
267
268 rtp_local_address_ = rtc::SocketAddress(ip_address, port_number);
269 rtcp_local_address_ = rtc::SocketAddress(ip_address, port_number + 1);
270}
271
Jason Long00b84622020-07-20 17:52:12 -0400272void AndroidVoipClient::SetLocalAddress(
273 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400274 const webrtc::JavaParamRef<jstring>& j_ip_address_string,
Jason Long00b84622020-07-20 17:52:12 -0400275 jint j_port_number_int) {
276 const std::string& ip_address =
277 webrtc::JavaToNativeString(env, j_ip_address_string);
Jason Long577fc0c2020-08-17 17:23:07 -0400278 voip_thread_->PostTask(RTC_FROM_HERE, [this, ip_address, j_port_number_int] {
279 SetLocalAddress(ip_address, j_port_number_int);
280 });
281}
282
283void AndroidVoipClient::SetRemoteAddress(const std::string& ip_address,
284 const int port_number) {
285 RTC_DCHECK_RUN_ON(voip_thread_.get());
286
287 rtp_remote_address_ = rtc::SocketAddress(ip_address, port_number);
288 rtcp_remote_address_ = rtc::SocketAddress(ip_address, port_number + 1);
Jason Long00b84622020-07-20 17:52:12 -0400289}
290
291void AndroidVoipClient::SetRemoteAddress(
292 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400293 const webrtc::JavaParamRef<jstring>& j_ip_address_string,
Jason Long00b84622020-07-20 17:52:12 -0400294 jint j_port_number_int) {
295 const std::string& ip_address =
296 webrtc::JavaToNativeString(env, j_ip_address_string);
Jason Long577fc0c2020-08-17 17:23:07 -0400297 voip_thread_->PostTask(RTC_FROM_HERE, [this, ip_address, j_port_number_int] {
298 SetRemoteAddress(ip_address, j_port_number_int);
299 });
Jason Long00b84622020-07-20 17:52:12 -0400300}
301
Jason Long577fc0c2020-08-17 17:23:07 -0400302void AndroidVoipClient::StartSession(JNIEnv* env) {
303 RUN_ON_VOIP_THREAD(StartSession, env);
304
Tim Na9325d342020-12-10 14:01:24 -0800305 // CreateChannel guarantees to return valid channel id.
Jason Long577fc0c2020-08-17 17:23:07 -0400306 channel_ = voip_engine_->Base().CreateChannel(this, absl::nullopt);
Jason Long00b84622020-07-20 17:52:12 -0400307
308 rtp_socket_.reset(rtc::AsyncUDPSocket::Create(voip_thread_->socketserver(),
309 rtp_local_address_));
310 if (!rtp_socket_) {
311 RTC_LOG_ERR(LERROR) << "Socket creation failed";
Jason Long577fc0c2020-08-17 17:23:07 -0400312 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
313 /*isSuccessful=*/false);
314 return;
Jason Long00b84622020-07-20 17:52:12 -0400315 }
316 rtp_socket_->SignalReadPacket.connect(
317 this, &AndroidVoipClient::OnSignalReadRTPPacket);
318
319 rtcp_socket_.reset(rtc::AsyncUDPSocket::Create(voip_thread_->socketserver(),
320 rtcp_local_address_));
321 if (!rtcp_socket_) {
322 RTC_LOG_ERR(LERROR) << "Socket creation failed";
Jason Long577fc0c2020-08-17 17:23:07 -0400323 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
324 /*isSuccessful=*/false);
325 return;
Jason Long00b84622020-07-20 17:52:12 -0400326 }
327 rtcp_socket_->SignalReadPacket.connect(
328 this, &AndroidVoipClient::OnSignalReadRTCPPacket);
Jason Long577fc0c2020-08-17 17:23:07 -0400329 Java_VoipClient_onStartSessionCompleted(env_, j_voip_client_,
330 /*isSuccessful=*/true);
Jason Long00b84622020-07-20 17:52:12 -0400331}
332
Jason Long577fc0c2020-08-17 17:23:07 -0400333void AndroidVoipClient::StopSession(JNIEnv* env) {
334 RUN_ON_VOIP_THREAD(StopSession, env);
335
Jason Long00b84622020-07-20 17:52:12 -0400336 if (!channel_) {
337 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400338 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
339 /*isSuccessful=*/false);
340 return;
Jason Long00b84622020-07-20 17:52:12 -0400341 }
Tim Nab223cb62020-11-20 09:34:47 -0800342 if (voip_engine_->Base().StopSend(*channel_) != webrtc::VoipResult::kOk ||
343 voip_engine_->Base().StopPlayout(*channel_) != webrtc::VoipResult::kOk) {
Jason Long577fc0c2020-08-17 17:23:07 -0400344 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
345 /*isSuccessful=*/false);
346 return;
Jason Long00b84622020-07-20 17:52:12 -0400347 }
348
349 rtp_socket_->Close();
350 rtcp_socket_->Close();
Jason Long577fc0c2020-08-17 17:23:07 -0400351
Tim Na9325d342020-12-10 14:01:24 -0800352 webrtc::VoipResult result = voip_engine_->Base().ReleaseChannel(*channel_);
353 RTC_CHECK(result == webrtc::VoipResult::kOk);
354
Jason Long00b84622020-07-20 17:52:12 -0400355 channel_ = absl::nullopt;
Jason Long577fc0c2020-08-17 17:23:07 -0400356 Java_VoipClient_onStopSessionCompleted(env_, j_voip_client_,
357 /*isSuccessful=*/true);
Jason Long00b84622020-07-20 17:52:12 -0400358}
359
Jason Long577fc0c2020-08-17 17:23:07 -0400360void AndroidVoipClient::StartSend(JNIEnv* env) {
361 RUN_ON_VOIP_THREAD(StartSend, env);
362
Jason Long00b84622020-07-20 17:52:12 -0400363 if (!channel_) {
364 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400365 Java_VoipClient_onStartSendCompleted(env_, j_voip_client_,
366 /*isSuccessful=*/false);
367 return;
Jason Long00b84622020-07-20 17:52:12 -0400368 }
Tim Nab223cb62020-11-20 09:34:47 -0800369 bool sending_started =
370 (voip_engine_->Base().StartSend(*channel_) == webrtc::VoipResult::kOk);
371 Java_VoipClient_onStartSendCompleted(env_, j_voip_client_, sending_started);
Jason Long00b84622020-07-20 17:52:12 -0400372}
373
Jason Long577fc0c2020-08-17 17:23:07 -0400374void AndroidVoipClient::StopSend(JNIEnv* env) {
375 RUN_ON_VOIP_THREAD(StopSend, env);
376
Jason Long00b84622020-07-20 17:52:12 -0400377 if (!channel_) {
378 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400379 Java_VoipClient_onStopSendCompleted(env_, j_voip_client_,
380 /*isSuccessful=*/false);
381 return;
Jason Long00b84622020-07-20 17:52:12 -0400382 }
Tim Nab223cb62020-11-20 09:34:47 -0800383 bool sending_stopped =
384 (voip_engine_->Base().StopSend(*channel_) == webrtc::VoipResult::kOk);
385 Java_VoipClient_onStopSendCompleted(env_, j_voip_client_, sending_stopped);
Jason Long00b84622020-07-20 17:52:12 -0400386}
387
Jason Long577fc0c2020-08-17 17:23:07 -0400388void AndroidVoipClient::StartPlayout(JNIEnv* env) {
389 RUN_ON_VOIP_THREAD(StartPlayout, env);
390
Jason Long00b84622020-07-20 17:52:12 -0400391 if (!channel_) {
392 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400393 Java_VoipClient_onStartPlayoutCompleted(env_, j_voip_client_,
394 /*isSuccessful=*/false);
395 return;
Jason Long00b84622020-07-20 17:52:12 -0400396 }
Tim Nab223cb62020-11-20 09:34:47 -0800397 bool playout_started =
398 (voip_engine_->Base().StartPlayout(*channel_) == webrtc::VoipResult::kOk);
399 Java_VoipClient_onStartPlayoutCompleted(env_, j_voip_client_,
400 playout_started);
Jason Long00b84622020-07-20 17:52:12 -0400401}
402
Jason Long577fc0c2020-08-17 17:23:07 -0400403void AndroidVoipClient::StopPlayout(JNIEnv* env) {
404 RUN_ON_VOIP_THREAD(StopPlayout, env);
405
Jason Long00b84622020-07-20 17:52:12 -0400406 if (!channel_) {
407 RTC_LOG(LS_ERROR) << "Channel has not been created";
Jason Long577fc0c2020-08-17 17:23:07 -0400408 Java_VoipClient_onStopPlayoutCompleted(env_, j_voip_client_,
409 /*isSuccessful=*/false);
410 return;
Jason Long00b84622020-07-20 17:52:12 -0400411 }
Tim Nab223cb62020-11-20 09:34:47 -0800412 bool playout_stopped =
413 (voip_engine_->Base().StopPlayout(*channel_) == webrtc::VoipResult::kOk);
414 Java_VoipClient_onStopPlayoutCompleted(env_, j_voip_client_, playout_stopped);
Jason Long00b84622020-07-20 17:52:12 -0400415}
416
417void AndroidVoipClient::Delete(JNIEnv* env) {
418 delete this;
419}
420
Jason Long577fc0c2020-08-17 17:23:07 -0400421void AndroidVoipClient::SendRtpPacket(const std::vector<uint8_t>& packet_copy) {
422 RTC_DCHECK_RUN_ON(voip_thread_.get());
423
424 if (!rtp_socket_->SendTo(packet_copy.data(), packet_copy.size(),
425 rtp_remote_address_, rtc::PacketOptions())) {
426 RTC_LOG(LS_ERROR) << "Failed to send RTP packet";
427 }
428}
429
Jason Long00b84622020-07-20 17:52:12 -0400430bool AndroidVoipClient::SendRtp(const uint8_t* packet,
431 size_t length,
432 const webrtc::PacketOptions& options) {
Jason Long577fc0c2020-08-17 17:23:07 -0400433 std::vector<uint8_t> packet_copy(packet, packet + length);
434 voip_thread_->PostTask(RTC_FROM_HERE,
435 [this, packet_copy = std::move(packet_copy)] {
436 SendRtpPacket(packet_copy);
437 });
Jason Long00b84622020-07-20 17:52:12 -0400438 return true;
439}
440
Jason Long577fc0c2020-08-17 17:23:07 -0400441void AndroidVoipClient::SendRtcpPacket(
442 const std::vector<uint8_t>& packet_copy) {
443 RTC_DCHECK_RUN_ON(voip_thread_.get());
444
445 if (!rtcp_socket_->SendTo(packet_copy.data(), packet_copy.size(),
446 rtcp_remote_address_, rtc::PacketOptions())) {
Jason Long00b84622020-07-20 17:52:12 -0400447 RTC_LOG(LS_ERROR) << "Failed to send RTCP packet";
Jason Long00b84622020-07-20 17:52:12 -0400448 }
Jason Long577fc0c2020-08-17 17:23:07 -0400449}
450
451bool AndroidVoipClient::SendRtcp(const uint8_t* packet, size_t length) {
452 std::vector<uint8_t> packet_copy(packet, packet + length);
453 voip_thread_->PostTask(RTC_FROM_HERE,
454 [this, packet_copy = std::move(packet_copy)] {
455 SendRtcpPacket(packet_copy);
456 });
Jason Long00b84622020-07-20 17:52:12 -0400457 return true;
458}
459
Jason Long577fc0c2020-08-17 17:23:07 -0400460void AndroidVoipClient::ReadRTPPacket(const std::vector<uint8_t>& packet_copy) {
461 RTC_DCHECK_RUN_ON(voip_thread_.get());
462
463 if (!channel_) {
464 RTC_LOG(LS_ERROR) << "Channel has not been created";
465 return;
466 }
Tim Na9325d342020-12-10 14:01:24 -0800467 webrtc::VoipResult result = voip_engine_->Network().ReceivedRTPPacket(
Jason Long577fc0c2020-08-17 17:23:07 -0400468 *channel_,
469 rtc::ArrayView<const uint8_t>(packet_copy.data(), packet_copy.size()));
Tim Na9325d342020-12-10 14:01:24 -0800470 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long577fc0c2020-08-17 17:23:07 -0400471}
472
Jason Long00b84622020-07-20 17:52:12 -0400473void AndroidVoipClient::OnSignalReadRTPPacket(rtc::AsyncPacketSocket* socket,
474 const char* rtp_packet,
475 size_t size,
476 const rtc::SocketAddress& addr,
477 const int64_t& timestamp) {
Jason Long577fc0c2020-08-17 17:23:07 -0400478 std::vector<uint8_t> packet_copy(rtp_packet, rtp_packet + size);
479 voip_thread_->PostTask(RTC_FROM_HERE,
480 [this, packet_copy = std::move(packet_copy)] {
481 ReadRTPPacket(packet_copy);
482 });
483}
484
485void AndroidVoipClient::ReadRTCPPacket(
486 const std::vector<uint8_t>& packet_copy) {
487 RTC_DCHECK_RUN_ON(voip_thread_.get());
488
Jason Long00b84622020-07-20 17:52:12 -0400489 if (!channel_) {
490 RTC_LOG(LS_ERROR) << "Channel has not been created";
491 return;
492 }
Tim Na9325d342020-12-10 14:01:24 -0800493 webrtc::VoipResult result = voip_engine_->Network().ReceivedRTCPPacket(
Jason Long577fc0c2020-08-17 17:23:07 -0400494 *channel_,
495 rtc::ArrayView<const uint8_t>(packet_copy.data(), packet_copy.size()));
Tim Na9325d342020-12-10 14:01:24 -0800496 RTC_CHECK(result == webrtc::VoipResult::kOk);
Jason Long00b84622020-07-20 17:52:12 -0400497}
498
499void AndroidVoipClient::OnSignalReadRTCPPacket(rtc::AsyncPacketSocket* socket,
500 const char* rtcp_packet,
501 size_t size,
502 const rtc::SocketAddress& addr,
503 const int64_t& timestamp) {
Jason Long577fc0c2020-08-17 17:23:07 -0400504 std::vector<uint8_t> packet_copy(rtcp_packet, rtcp_packet + size);
505 voip_thread_->PostTask(RTC_FROM_HERE,
506 [this, packet_copy = std::move(packet_copy)] {
507 ReadRTCPPacket(packet_copy);
508 });
Jason Long00b84622020-07-20 17:52:12 -0400509}
510
511static jlong JNI_VoipClient_CreateClient(
512 JNIEnv* env,
Jason Long577fc0c2020-08-17 17:23:07 -0400513 const webrtc::JavaParamRef<jobject>& application_context,
514 const webrtc::JavaParamRef<jobject>& j_voip_client) {
Jason Long00b84622020-07-20 17:52:12 -0400515 return webrtc::NativeToJavaPointer(
Jason Long577fc0c2020-08-17 17:23:07 -0400516 AndroidVoipClient::Create(env, application_context, j_voip_client));
Jason Long00b84622020-07-20 17:52:12 -0400517}
518
519} // namespace webrtc_examples