1 /*
2 * Copyright (c) 2011 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 <android/log.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #include "webrtc/voice_engine/test/android/android_test/jni/org_webrtc_voiceengine_test_AndroidTest.h"
17
18 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
19
20 #include "webrtc/voice_engine/include/voe_audio_processing.h"
21 #include "webrtc/voice_engine/include/voe_base.h"
22 #include "webrtc/voice_engine/include/voe_codec.h"
23 #include "webrtc/voice_engine/include/voe_file.h"
24 #include "webrtc/voice_engine/include/voe_hardware.h"
25 #include "webrtc/voice_engine/include/voe_network.h"
26 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
27 #include "webrtc/voice_engine/include/voe_volume_control.h"
28
29 #include "webrtc/voice_engine/test/auto_test/voe_test_interface.h"
30
31 //#define INIT_FROM_THREAD
32 //#define START_CALL_FROM_THREAD
33
34 #define WEBRTC_LOG_TAG "*WEBRTCN*" // As in WEBRTC Native...
35 #define VALIDATE_BASE_POINTER \
36 if (!veData1.base) \
37 { \
38 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
39 "Base pointer doesn't exist"); \
40 return -1; \
41 }
42 #define VALIDATE_CODEC_POINTER \
43 if (!veData1.codec) \
44 { \
45 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
46 "Codec pointer doesn't exist"); \
47 return -1; \
48 }
49 #define VALIDATE_FILE_POINTER \
50 if (!veData1.file) \
51 { \
52 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
53 "File pointer doesn't exist"); \
54 return -1; \
55 }
56 #define VALIDATE_NETWORK_POINTER \
57 if (!veData1.netw) \
58 { \
59 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
60 "Network pointer doesn't exist"); \
61 return -1; \
62 }
63 #define VALIDATE_APM_POINTER \
64 if (!veData1.codec) \
65 { \
66 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
67 "Apm pointer doesn't exist"); \
68 return -1; \
69 }
70 #define VALIDATE_VOLUME_POINTER \
71 if (!veData1.volume) \
72 { \
73 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
74 "Volume pointer doesn't exist"); \
75 return -1; \
76 }
77 #define VALIDATE_HARDWARE_POINTER \
78 if (!veData1.hardware) \
79 { \
80 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
81 "Hardware pointer doesn't exist"); \
82 return -1; \
83 }
84 #define VALIDATE_RTP_RTCP_POINTER \
85 if (!veData1.rtp_rtcp) \
86 { \
87 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
88 "RTP / RTCP pointer doesn't exist"); \
89 return -1; \
90 }
91
92 // Register functions in JNI_OnLoad()
93 // How do we ensure that VoE is deleted? JNI_OnUnload?
94 // What happens if class is unloaded? When loaded again, NativeInit will be
95 // called again. Keep what we have?
96 // Should we do something in JNI_OnUnload?
97 // General design: create a class or keep global struct with "C" functions?
98 // Otherwise make sure symbols are as unique as possible.
99
100 // TestType enumerator
101 enum TestType
102 {
103 Invalid = -1,
104 Standard = 0,
105 Extended = 1,
106 Stress = 2,
107 Unit = 3,
108 CPU = 4
109 };
110
111 using namespace webrtc;
112
113 class my_transportation;
114
115 // VoiceEngine data struct
116 typedef struct
117 {
118 // VoiceEngine
119 VoiceEngine* ve;
120 // Sub-APIs
121 VoEBase* base;
122 VoECodec* codec;
123 VoEFile* file;
124 VoENetwork* netw;
125 VoEAudioProcessing* apm;
126 VoEVolumeControl* volume;
127 VoEHardware* hardware;
128 VoERTP_RTCP* rtp_rtcp;
129 // Other
130 my_transportation* extTrans;
131 JavaVM* jvm;
132 } VoiceEngineData;
133
134 // my_transportation is used when useExtTrans is enabled
135 class my_transportation : public Transport
136 {
137 public:
my_transportation(VoENetwork * network)138 my_transportation(VoENetwork * network) :
139 netw(network) {
140 }
141
142 int SendPacket(int channel,const void *data,int len);
143 int SendRTCPPacket(int channel, const void *data, int len);
144 private:
145 VoENetwork * netw;
146 };
147
SendPacket(int channel,const void * data,int len)148 int my_transportation::SendPacket(int channel,const void *data,int len)
149 {
150 netw->ReceivedRTPPacket(channel, data, len);
151 return len;
152 }
153
SendRTCPPacket(int channel,const void * data,int len)154 int my_transportation::SendRTCPPacket(int channel, const void *data, int len)
155 {
156 netw->ReceivedRTCPPacket(channel, data, len);
157 return len;
158 }
159
160 //Global variables visible in this file
161 static VoiceEngineData veData1;
162 static VoiceEngineData veData2;
163
164 // "Local" functions (i.e. not Java accessible)
165 static bool GetSubApis(VoiceEngineData &veData);
166 static bool ReleaseSubApis(VoiceEngineData &veData);
167
168 class ThreadTest
169 {
170 public:
171 ThreadTest();
172 ~ThreadTest();
173 int RunTest();
174 int CloseTest();
175 private:
176 static bool Run(void* ptr);
177 bool Process();
178 private:
179 ThreadWrapper* _thread;
180 };
181
~ThreadTest()182 ThreadTest::~ThreadTest()
183 {
184 if (_thread)
185 {
186 _thread->SetNotAlive();
187 if (_thread->Stop())
188 {
189 delete _thread;
190 _thread = NULL;
191 }
192 }
193 }
194
ThreadTest()195 ThreadTest::ThreadTest() :
196 _thread(NULL)
197 {
198 _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority,
199 "ThreadTest thread");
200 }
201
Run(void * ptr)202 bool ThreadTest::Run(void* ptr)
203 {
204 return static_cast<ThreadTest*> (ptr)->Process();
205 }
206
Process()207 bool ThreadTest::Process()
208 {
209 // Attach this thread to JVM
210 /*JNIEnv* env = NULL;
211 jint res = veData1.jvm->AttachCurrentThread(&env, NULL);
212 char msg[32];
213 sprintf(msg, "res=%d, env=%d", res, env);
214 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, msg);*/
215
216 #ifdef INIT_FROM_THREAD
217 VALIDATE_BASE_POINTER;
218 veData1.base->Init();
219 #endif
220
221 #ifdef START_CALL_FROM_THREAD
222 // receiving instance
223 veData2.ve = VoiceEngine::Create();
224 GetSubApis(veData2);
225 veData2.base->Init();
226 veData2.base->CreateChannel();
227 if(veData2.base->SetLocalReceiver(0, 1234) < 0)
228 {
229 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
230 "set local receiver 2 failed");
231 }
232 veData2.hardware->SetLoudspeakerStatus(false);
233 veData2.volume->SetSpeakerVolume(204);
234 veData2.base->StartReceive(0);
235 if(veData2.base->StartPlayout(0) < 0)
236 {
237 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
238 "start playout failed");
239 }
240
241 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
242 "receiving instance started from thread");
243
244 // sending instance
245 veData1.ve = VoiceEngine::Create();
246 GetSubApis(veData1);
247 veData1.base->Init();
248 if(veData1.base->CreateChannel() < 0)
249 {
250 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
251 "create channel failed");
252 }
253 if(veData1.base->SetLocalReceiver(0, 1256) < 0)
254 {
255 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
256 "set local receiver failed");
257 }
258 if(veData1.base->SetSendDestination(0, 1234, "127.0.0.1") < 0)
259 {
260 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
261 "set send destination failed");
262 }
263 if(veData1.base->StartSend(0) < 0)
264 {
265 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
266 "start send failed");
267 }
268
269 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
270 "sending instance started from thread");
271 #endif
272
273 _thread->SetNotAlive();
274 _thread->Stop();
275
276 //res = veData1.jvm->DetachCurrentThread();
277
278 return true;
279 }
280
RunTest()281 int ThreadTest::RunTest()
282 {
283 if (_thread)
284 {
285 unsigned int id;
286 _thread->Start(id);
287 }
288 return 0;
289 }
290
CloseTest()291 int ThreadTest::CloseTest()
292 {
293 VALIDATE_BASE_POINTER
294
295 veData1.base->DeleteChannel(0);
296 veData2.base->DeleteChannel(0);
297 veData1.base->Terminate();
298 veData2.base->Terminate();
299
300 // Release sub-APIs
301 ReleaseSubApis(veData1);
302 ReleaseSubApis(veData2);
303
304 // Delete
305 VoiceEngine::Delete(veData1.ve);
306 VoiceEngine::Delete(veData2.ve);
307 veData2.ve = NULL;
308 veData2.ve = NULL;
309
310 return 0;
311 }
312
313 ThreadTest threadTest;
314
315 //////////////////////////////////////////////////////////////////
316 // General functions
317 //////////////////////////////////////////////////////////////////
318
319 /////////////////////////////////////////////
320 // JNI_OnLoad
321 //
JNI_OnLoad(JavaVM * vm,void *)322 jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
323 {
324 if (!vm)
325 {
326 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
327 "JNI_OnLoad did not receive a valid VM pointer");
328 return -1;
329 }
330
331 // Get JNI
332 JNIEnv* env;
333 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**> (&env),
334 JNI_VERSION_1_4))
335 {
336 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
337 "JNI_OnLoad could not get JNI env");
338 return -1;
339 }
340
341 // Get class to register the native functions with
342 // jclass regClass = env->FindClass("webrtc/android/AndroidTest");
343 // if (!regClass) {
344 // return -1; // Exception thrown
345 // }
346
347 // Register native functions
348 // JNINativeMethod methods[1];
349 // methods[0].name = NULL;
350 // methods[0].signature = NULL;
351 // methods[0].fnPtr = NULL;
352 // if (JNI_OK != env->RegisterNatives(regClass, methods, 1))
353 // {
354 // return -1;
355 // }
356
357 // Init VoiceEngine data
358 memset(&veData1, 0, sizeof(veData1));
359 memset(&veData2, 0, sizeof(veData2));
360
361 // Store the JVM
362 veData1.jvm = vm;
363 veData2.jvm = vm;
364
365 return JNI_VERSION_1_4;
366 }
367
368 /////////////////////////////////////////////
369 // Native initialization
370 //
371 JNIEXPORT jboolean JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_NativeInit(JNIEnv * env,jclass)372 Java_org_webrtc_voiceengine_test_AndroidTest_NativeInit(
373 JNIEnv * env,
374 jclass)
375 {
376 // Look up and cache any interesting class, field and method IDs for
377 // any used java class here
378
379 return true;
380 }
381
382 /////////////////////////////////////////////
383 // Run auto standard test
384 //
Java_org_webrtc_voiceengine_test_AndroidTest_RunAutoTest(JNIEnv * env,jobject context,jint testType,jint extendedSel)385 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_RunAutoTest(
386 JNIEnv *env,
387 jobject context,
388 jint testType,
389 jint extendedSel)
390 {
391 TestType tType(Invalid);
392
393 switch (testType)
394 {
395 case 0:
396 return 0;
397 case 1:
398 tType = Standard;
399 break;
400 case 2:
401 tType = Extended;
402 break;
403 case 3:
404 tType = Stress;
405 break;
406 case 4:
407 tType = Unit;
408 break;
409 default:
410 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
411 "RunAutoTest - Invalid TestType");
412 return -1;
413 }
414
415 // Set instance independent Java objects
416 VoiceEngine::SetAndroidObjects(veData1.jvm, env, context);
417
418 // Call voe test interface function
419 // TODO(leozwang) add autotest setAndroidObjects(veData1.jvm, context);
420 // jint retVal = runAutoTest(tType);
421
422 // Clear instance independent Java objects
423 VoiceEngine::SetAndroidObjects(NULL, NULL, NULL);
424
425 return 0;
426 }
427
428 //////////////////////////////////////////////////////////////////
429 // VoiceEngine API wrapper functions
430 //////////////////////////////////////////////////////////////////
431
432 /////////////////////////////////////////////
433 // Create VoiceEngine instance
434 //
Java_org_webrtc_voiceengine_test_AndroidTest_Create(JNIEnv * env,jobject context)435 JNIEXPORT jboolean JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Create(
436 JNIEnv *env,
437 jobject context)
438 {
439 // Check if already created
440 if (veData1.ve)
441 {
442 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
443 "VoE already created");
444 return false;
445 }
446
447 // Set instance independent Java objects
448 VoiceEngine::SetAndroidObjects(veData1.jvm, env, context);
449
450 #ifdef START_CALL_FROM_THREAD
451 threadTest.RunTest();
452 #else
453 // Create
454 veData1.ve = VoiceEngine::Create();
455 if (!veData1.ve)
456 {
457 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
458 "Create VoE failed");
459 return false;
460 }
461
462 // Get sub-APIs
463 if (!GetSubApis(veData1))
464 {
465 // If not OK, release all sub-APIs and delete VoE
466 ReleaseSubApis(veData1);
467 if (!VoiceEngine::Delete(veData1.ve))
468 {
469 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
470 "Delete VoE failed");
471 }
472 return false;
473 }
474 #endif
475
476 return true;
477 }
478
479 /////////////////////////////////////////////
480 // Delete VoiceEngine instance
481 //
Java_org_webrtc_voiceengine_test_AndroidTest_Delete(JNIEnv *,jobject)482 JNIEXPORT jboolean JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Delete(
483 JNIEnv *,
484 jobject)
485 {
486 #ifdef START_CALL_FROM_THREAD
487 threadTest.CloseTest();
488 #else
489 // Check if exists
490 if (!veData1.ve)
491 {
492 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
493 "VoE does not exist");
494 return false;
495 }
496
497 // Release sub-APIs
498 ReleaseSubApis(veData1);
499
500 // Delete
501 if (!VoiceEngine::Delete(veData1.ve))
502 {
503 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
504 "Delete VoE failed");
505 return false;
506 }
507
508 veData1.ve = NULL;
509 #endif
510
511 // Clear instance independent Java objects
512 VoiceEngine::SetAndroidObjects(NULL, NULL, NULL);
513
514 return true;
515 }
516
517 /////////////////////////////////////////////
518 // [Base] Initialize VoiceEngine
519 //
Java_org_webrtc_voiceengine_test_AndroidTest_Init(JNIEnv *,jobject,jboolean enableTrace,jboolean useExtTrans)520 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Init(
521 JNIEnv *,
522 jobject,
523 jboolean enableTrace,
524 jboolean useExtTrans)
525 {
526 VALIDATE_BASE_POINTER;
527
528 if (enableTrace)
529 {
530 if (0 != VoiceEngine::SetTraceFile("/sdcard/trace.txt"))
531 {
532 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
533 "Could not enable trace");
534 }
535 if (0 != VoiceEngine::SetTraceFilter(kTraceAll))
536 {
537 __android_log_write(ANDROID_LOG_WARN, WEBRTC_LOG_TAG,
538 "Could not set trace filter");
539 }
540 }
541
542 if (useExtTrans)
543 {
544 VALIDATE_NETWORK_POINTER;
545 veData1.extTrans = new my_transportation(veData1.netw);
546 }
547
548 int retVal = 0;
549 #ifdef INIT_FROM_THREAD
550 threadTest.RunTest();
551 usleep(200000);
552 #else
553 retVal = veData1.base->Init();
554 #endif
555 return retVal;
556 }
557
558 /////////////////////////////////////////////
559 // [Base] Terminate VoiceEngine
560 //
Java_org_webrtc_voiceengine_test_AndroidTest_Terminate(JNIEnv *,jobject)561 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Terminate(
562 JNIEnv *,
563 jobject)
564 {
565 VALIDATE_BASE_POINTER;
566
567 jint retVal = veData1.base->Terminate();
568
569 delete veData1.extTrans;
570 veData1.extTrans = NULL;
571
572 return retVal;
573 }
574
575 /////////////////////////////////////////////
576 // [Base] Create channel
577 //
578 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_CreateChannel(JNIEnv *,jobject)579 Java_org_webrtc_voiceengine_test_AndroidTest_CreateChannel(
580 JNIEnv *,
581 jobject)
582 {
583 VALIDATE_BASE_POINTER;
584 jint channel = veData1.base->CreateChannel();
585
586 if (veData1.extTrans)
587 {
588 VALIDATE_NETWORK_POINTER;
589 __android_log_print(ANDROID_LOG_DEBUG, WEBRTC_LOG_TAG,
590 "Enabling external transport on channel %d",
591 channel);
592 if (veData1.netw->RegisterExternalTransport(channel, *veData1.extTrans)
593 < 0)
594 {
595 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
596 "Could not set external transport");
597 return -1;
598 }
599 }
600
601 return channel;
602 }
603
604 /////////////////////////////////////////////
605 // [Base] Delete channel
606 //
607 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_DeleteChannel(JNIEnv *,jobject,jint channel)608 Java_org_webrtc_voiceengine_test_AndroidTest_DeleteChannel(
609 JNIEnv *,
610 jobject,
611 jint channel)
612 {
613 VALIDATE_BASE_POINTER;
614 return veData1.base->DeleteChannel(channel);
615 }
616
617 /////////////////////////////////////////////
618 // [Base] SetLocalReceiver
619 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetLocalReceiver(JNIEnv *,jobject,jint channel,jint port)620 Java_org_webrtc_voiceengine_test_AndroidTest_SetLocalReceiver(
621 JNIEnv *,
622 jobject,
623 jint channel,
624 jint port)
625 {
626 VALIDATE_BASE_POINTER;
627 return veData1.base->SetLocalReceiver(channel, port);
628 }
629
630 /////////////////////////////////////////////
631 // [Base] SetSendDestination
632 //
633 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSendDestination(JNIEnv * env,jobject,jint channel,jint port,jstring ipaddr)634 Java_org_webrtc_voiceengine_test_AndroidTest_SetSendDestination(
635 JNIEnv *env,
636 jobject,
637 jint channel,
638 jint port,
639 jstring ipaddr)
640 {
641 VALIDATE_BASE_POINTER;
642
643 const char* ipaddrNative = env->GetStringUTFChars(ipaddr, NULL);
644 if (!ipaddrNative)
645 {
646 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
647 "Could not get UTF string");
648 return -1;
649 }
650
651 jint retVal = veData1.base->SetSendDestination(channel, port, ipaddrNative);
652
653 env->ReleaseStringUTFChars(ipaddr, ipaddrNative);
654
655 return retVal;
656 }
657
658 /////////////////////////////////////////////
659 // [Base] StartListen
660 //
Java_org_webrtc_voiceengine_test_AndroidTest_StartListen(JNIEnv *,jobject,jint channel)661 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StartListen(
662 JNIEnv *,
663 jobject,
664 jint channel)
665 {
666 VALIDATE_BASE_POINTER;
667 int retVal = veData1.base->StartReceive(channel);
668
669 return retVal;
670 }
671
672 /////////////////////////////////////////////
673 // [Base] Start playout
674 //
675 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayout(JNIEnv *,jobject,jint channel)676 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayout(
677 JNIEnv *,
678 jobject,
679 jint channel)
680 {
681 VALIDATE_BASE_POINTER;
682 int retVal = veData1.base->StartPlayout(channel);
683
684 return retVal;
685 }
686
687 /////////////////////////////////////////////
688 // [Base] Start send
689 //
Java_org_webrtc_voiceengine_test_AndroidTest_StartSend(JNIEnv *,jobject,jint channel)690 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StartSend(
691 JNIEnv *,
692 jobject,
693 jint channel)
694 {
695 /* int dscp(0), serviceType(-1), overrideDscp(0), res(0);
696 bool gqosEnabled(false), useSetSockOpt(false);
697
698 if (veData1.netw->SetSendTOS(channel, 13, useSetSockOpt) != 0)
699 {
700 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
701 "Failed to set TOS");
702 return -1;
703 }
704
705 res = veData1.netw->GetSendTOS(channel, dscp, useSetSockOpt);
706 if (res != 0 || dscp != 13 || useSetSockOpt != true)
707 {
708 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
709 "Failed to get TOS");
710 return -1;
711 } */
712
713 /* if (veData1.rtp_rtcp->SetREDStatus(channel, 1) != 0)
714 {
715 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
716 "Failed to enable RED");
717 return -1;
718 } */
719
720 VALIDATE_BASE_POINTER;
721 int retVal = veData1.base->StartSend(channel);
722
723 return retVal;
724 }
725
726 /////////////////////////////////////////////
727 // [Base] Stop listen
728 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopListen(JNIEnv *,jobject,jint channel)729 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopListen(
730 JNIEnv *,
731 jobject,
732 jint channel)
733 {
734 VALIDATE_BASE_POINTER;
735 return veData1.base->StopReceive(channel);
736 }
737
738 /////////////////////////////////////////////
739 // [Base] Stop playout
740 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayout(JNIEnv *,jobject,jint channel)741 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayout(
742 JNIEnv *,
743 jobject,
744 jint channel)
745 {
746 VALIDATE_BASE_POINTER;
747 return veData1.base->StopPlayout(channel);
748 }
749
750 /////////////////////////////////////////////
751 // [Base] Stop send
752 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopSend(JNIEnv *,jobject,jint channel)753 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopSend(
754 JNIEnv *,
755 jobject,
756 jint channel)
757 {
758 /* if (veData1.rtp_rtcp->SetREDStatus(channel, 0) != 0)
759 {
760 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
761 "Failed to disable RED");
762 return -1;
763 } */
764
765 VALIDATE_BASE_POINTER;
766 return veData1.base->StopSend(channel);
767 }
768
769 /////////////////////////////////////////////
770 // [codec] Number of codecs
771 //
Java_org_webrtc_voiceengine_test_AndroidTest_NumOfCodecs(JNIEnv *,jobject)772 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_NumOfCodecs(
773 JNIEnv *,
774 jobject)
775 {
776 VALIDATE_CODEC_POINTER;
777 return veData1.codec->NumOfCodecs();
778 }
779
780 /////////////////////////////////////////////
781 // [codec] Set send codec
782 //
783 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSendCodec(JNIEnv *,jobject,jint channel,jint index)784 Java_org_webrtc_voiceengine_test_AndroidTest_SetSendCodec(
785 JNIEnv *,
786 jobject,
787 jint channel,
788 jint index)
789 {
790 VALIDATE_CODEC_POINTER;
791
792 CodecInst codec;
793
794 if (veData1.codec->GetCodec(index, codec) != 0)
795 {
796 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
797 "Failed to get codec");
798 return -1;
799 }
800
801 return veData1.codec->SetSendCodec(channel, codec);
802 }
803
804 /////////////////////////////////////////////
805 // [codec] Set VAD status
806 //
807 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetVADStatus(JNIEnv *,jobject,jint channel,jboolean enable,jint mode)808 Java_org_webrtc_voiceengine_test_AndroidTest_SetVADStatus(
809 JNIEnv *,
810 jobject,
811 jint channel,
812 jboolean enable,
813 jint mode)
814 {
815 VALIDATE_CODEC_POINTER;
816
817 VadModes VADmode = kVadConventional;
818
819 switch (mode)
820 {
821 case 0:
822 break; // already set
823 case 1:
824 VADmode = kVadAggressiveLow;
825 break;
826 case 2:
827 VADmode = kVadAggressiveMid;
828 break;
829 case 3:
830 VADmode = kVadAggressiveHigh;
831 break;
832 default:
833 VADmode = (VadModes) 17; // force error
834 break;
835 }
836
837 return veData1.codec->SetVADStatus(channel, enable, VADmode);
838 }
839
840 /////////////////////////////////////////////
841 // [apm] SetNSStatus
842 //
Java_org_webrtc_voiceengine_test_AndroidTest_SetNSStatus(JNIEnv *,jobject,jboolean enable,jint mode)843 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_SetNSStatus(
844 JNIEnv *,
845 jobject,
846 jboolean enable,
847 jint mode)
848 {
849 VALIDATE_APM_POINTER;
850
851 NsModes NSmode = kNsDefault;
852
853 switch (mode)
854 {
855 case 0:
856 NSmode = kNsUnchanged;
857 break;
858 case 1:
859 break; // already set
860 case 2:
861 NSmode = kNsConference;
862 break;
863 case 3:
864 NSmode = kNsLowSuppression;
865 break;
866 case 4:
867 NSmode = kNsModerateSuppression;
868 break;
869 case 5:
870 NSmode = kNsHighSuppression;
871 break;
872 case 6:
873 NSmode = kNsVeryHighSuppression;
874 break;
875 default:
876 NSmode = (NsModes) 17; // force error
877 break;
878 }
879
880 return veData1.apm->SetNsStatus(enable, NSmode);
881 }
882
883 /////////////////////////////////////////////
884 // [apm] SetAGCStatus
885 //
886 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetAGCStatus(JNIEnv *,jobject,jboolean enable,jint mode)887 Java_org_webrtc_voiceengine_test_AndroidTest_SetAGCStatus(
888 JNIEnv *,
889 jobject,
890 jboolean enable,
891 jint mode)
892 {
893 VALIDATE_APM_POINTER;
894
895 AgcModes AGCmode = kAgcDefault;
896
897 switch (mode)
898 {
899 case 0:
900 AGCmode = kAgcUnchanged;
901 break;
902 case 1:
903 break; // already set
904 case 2:
905 AGCmode = kAgcAdaptiveAnalog;
906 break;
907 case 3:
908 AGCmode = kAgcAdaptiveDigital;
909 break;
910 case 4:
911 AGCmode = kAgcFixedDigital;
912 break;
913 default:
914 AGCmode = (AgcModes) 17; // force error
915 break;
916 }
917
918 /* AgcConfig agcConfig;
919 agcConfig.targetLeveldBOv = 3;
920 agcConfig.digitalCompressionGaindB = 50;
921 agcConfig.limiterEnable = 0;
922
923 if (veData1.apm->SetAGCConfig(agcConfig) != 0)
924 {
925 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
926 "Failed to set AGC config");
927 return -1;
928 } */
929
930 return veData1.apm->SetAgcStatus(enable, AGCmode);
931 }
932
933 /////////////////////////////////////////////
934 // [apm] SetECStatus
935 //
Java_org_webrtc_voiceengine_test_AndroidTest_SetECStatus(JNIEnv *,jobject,jboolean enable,jint mode)936 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_SetECStatus(
937 JNIEnv *,
938 jobject,
939 jboolean enable,
940 jint mode)
941 {
942 VALIDATE_APM_POINTER;
943
944 EcModes ECmode = kEcDefault;
945
946 switch (mode)
947 {
948 case 0:
949 ECmode = kEcDefault;
950 break;
951 case 1:
952 break; // already set
953 case 2:
954 ECmode = kEcConference;
955 break;
956 case 3:
957 ECmode = kEcAec;
958 break;
959 case 4:
960 ECmode = kEcAecm;
961 break;
962 default:
963 ECmode = (EcModes) 17; // force error
964 break;
965 }
966
967 return veData1.apm->SetEcStatus(enable, ECmode);
968 }
969
970 /////////////////////////////////////////////
971 // [File] Start play file locally
972 //
973 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileLocally(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean loop)974 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileLocally(
975 JNIEnv * env,
976 jobject,
977 jint channel,
978 jstring fileName,
979 jboolean loop)
980 {
981 VALIDATE_FILE_POINTER;
982
983 const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
984 if (!fileNameNative)
985 {
986 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
987 "Could not get UTF string");
988 return -1;
989 }
990
991 jint retVal = veData1.file->StartPlayingFileLocally(channel,
992 fileNameNative, loop);
993
994 env->ReleaseStringUTFChars(fileName, fileNameNative);
995
996 return retVal;
997 }
998
999 /////////////////////////////////////////////
1000 // [File] Stop play file locally
1001 //
1002 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileLocally(JNIEnv *,jobject,jint channel)1003 Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileLocally(
1004 JNIEnv *,
1005 jobject,
1006 jint channel)
1007 {
1008 VALIDATE_FILE_POINTER;
1009 return veData1.file->StopPlayingFileLocally(channel);
1010 }
1011
1012 /*
1013 * Class: org_webrtc_voiceengine_test_AndroidTest
1014 * Method: StartRecordingPlayout
1015 * Signature: (ILjava/lang/String;Z)I
1016 */
1017 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartRecordingPlayout(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean)1018 Java_org_webrtc_voiceengine_test_AndroidTest_StartRecordingPlayout(
1019 JNIEnv * env,
1020 jobject,
1021 jint channel,
1022 jstring fileName,
1023 jboolean)
1024 {
1025 VALIDATE_FILE_POINTER;
1026
1027 const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
1028 if (!fileNameNative)
1029 {
1030 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1031 "Could not get UTF string");
1032 return -1;
1033 }
1034
1035 jint retVal = veData1.file->StartRecordingPlayout(channel, fileNameNative,
1036 0);
1037
1038 env->ReleaseStringUTFChars(fileName, fileNameNative);
1039
1040 return retVal;
1041 }
1042
1043 /////////////////////////////////////////////
1044 // [File] Stop Recording Playout
1045 //
1046 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopRecordingPlayout(JNIEnv *,jobject,jint channel)1047 Java_org_webrtc_voiceengine_test_AndroidTest_StopRecordingPlayout(
1048 JNIEnv *,
1049 jobject,
1050 jint channel)
1051 {
1052 VALIDATE_FILE_POINTER;
1053 return veData1.file->StopRecordingPlayout(channel);
1054 }
1055
1056 /////////////////////////////////////////////
1057 // [File] Start playing file as microphone
1058 //
1059 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileAsMicrophone(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean loop)1060 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileAsMicrophone(
1061 JNIEnv *env,
1062 jobject,
1063 jint channel,
1064 jstring fileName,
1065 jboolean loop)
1066 {
1067 VALIDATE_FILE_POINTER;
1068
1069 const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
1070 if (!fileNameNative)
1071 {
1072 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1073 "Could not get UTF string");
1074 return -1;
1075 }
1076
1077 jint retVal = veData1.file->StartPlayingFileAsMicrophone(channel,
1078 fileNameNative,
1079 loop);
1080
1081 env->ReleaseStringUTFChars(fileName, fileNameNative);
1082
1083 return retVal;
1084 }
1085
1086 /////////////////////////////////////////////
1087 // [File] Stop playing file as microphone
1088 //
1089 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileAsMicrophone(JNIEnv *,jobject,jint channel)1090 Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileAsMicrophone(
1091 JNIEnv *,
1092 jobject,
1093 jint channel)
1094 {
1095 VALIDATE_FILE_POINTER;
1096 return veData1.file->StopPlayingFileAsMicrophone(channel);
1097 }
1098
1099 /////////////////////////////////////////////
1100 // [Volume] Set speaker volume
1101 //
1102 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSpeakerVolume(JNIEnv *,jobject,jint level)1103 Java_org_webrtc_voiceengine_test_AndroidTest_SetSpeakerVolume(
1104 JNIEnv *,
1105 jobject,
1106 jint level)
1107 {
1108 VALIDATE_VOLUME_POINTER;
1109 if (veData1.volume->SetSpeakerVolume(level) != 0)
1110 {
1111 return -1;
1112 }
1113
1114 unsigned int storedVolume = 0;
1115 if (veData1.volume->GetSpeakerVolume(storedVolume) != 0)
1116 {
1117 return -1;
1118 }
1119
1120 if (storedVolume != level)
1121 {
1122 return -1;
1123 }
1124
1125 return 0;
1126 }
1127
1128 /////////////////////////////////////////////
1129 // [Hardware] Set loudspeaker status
1130 //
1131 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetLoudspeakerStatus(JNIEnv *,jobject,jboolean enable)1132 Java_org_webrtc_voiceengine_test_AndroidTest_SetLoudspeakerStatus(
1133 JNIEnv *,
1134 jobject,
1135 jboolean enable)
1136 {
1137 VALIDATE_HARDWARE_POINTER;
1138 if (veData1.hardware->SetLoudspeakerStatus(enable) != 0)
1139 {
1140 return -1;
1141 }
1142
1143 /*VALIDATE_RTP_RTCP_POINTER;
1144
1145 if (veData1.rtp_rtcp->SetREDStatus(0, enable, -1) != 0)
1146 {
1147 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1148 "Could not set RED");
1149 return -1;
1150 }
1151 else if(enable)
1152 {
1153 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1154 "Could enable RED");
1155 }
1156 else
1157 {
1158 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1159 "Could disable RED");
1160 }*/
1161
1162 return 0;
1163 }
1164
1165 //////////////////////////////////////////////////////////////////
1166 // "Local" functions (i.e. not Java accessible)
1167 //////////////////////////////////////////////////////////////////
1168
1169 /////////////////////////////////////////////
1170 // Get all sub-APIs
1171 //
GetSubApis(VoiceEngineData & veData)1172 bool GetSubApis(VoiceEngineData &veData)
1173 {
1174 bool getOK = true;
1175
1176 // Base
1177 veData.base = VoEBase::GetInterface(veData.ve);
1178 if (!veData.base)
1179 {
1180 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1181 "Get base sub-API failed");
1182 getOK = false;
1183 }
1184
1185 // Codec
1186 veData.codec = VoECodec::GetInterface(veData.ve);
1187 if (!veData.codec)
1188 {
1189 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1190 "Get codec sub-API failed");
1191 getOK = false;
1192 }
1193
1194 // File
1195 veData.file = VoEFile::GetInterface(veData.ve);
1196 if (!veData.file)
1197 {
1198 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1199 "Get file sub-API failed");
1200 getOK = false;
1201 }
1202
1203 // Network
1204 veData.netw = VoENetwork::GetInterface(veData.ve);
1205 if (!veData.netw)
1206 {
1207 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1208 "Get network sub-API failed");
1209 getOK = false;
1210 }
1211
1212 // AudioProcessing module
1213 veData.apm = VoEAudioProcessing::GetInterface(veData.ve);
1214 if (!veData.apm)
1215 {
1216 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1217 "Get apm sub-API failed");
1218 getOK = false;
1219 }
1220
1221 // Volume
1222 veData.volume = VoEVolumeControl::GetInterface(veData.ve);
1223 if (!veData.volume)
1224 {
1225 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1226 "Get volume sub-API failed");
1227 getOK = false;
1228 }
1229
1230 // Hardware
1231 veData.hardware = VoEHardware::GetInterface(veData.ve);
1232 if (!veData.hardware)
1233 {
1234 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1235 "Get hardware sub-API failed");
1236 getOK = false;
1237 }
1238
1239 // RTP / RTCP
1240 veData.rtp_rtcp = VoERTP_RTCP::GetInterface(veData.ve);
1241 if (!veData.rtp_rtcp)
1242 {
1243 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1244 "Get rtp_rtcp sub-API failed");
1245 getOK = false;
1246 }
1247
1248 return getOK;
1249 }
1250
1251 /////////////////////////////////////////////
1252 // Release all sub-APIs
1253 //
ReleaseSubApis(VoiceEngineData & veData)1254 bool ReleaseSubApis(VoiceEngineData &veData)
1255 {
1256 bool releaseOK = true;
1257
1258 // Base
1259 if (veData.base)
1260 {
1261 if (0 != veData.base->Release())
1262 {
1263 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1264 "Release base sub-API failed");
1265 releaseOK = false;
1266 }
1267 else
1268 {
1269 veData.base = NULL;
1270 }
1271 }
1272
1273 // Codec
1274 if (veData.codec)
1275 {
1276 if (0 != veData.codec->Release())
1277 {
1278 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1279 "Release codec sub-API failed");
1280 releaseOK = false;
1281 }
1282 else
1283 {
1284 veData.codec = NULL;
1285 }
1286 }
1287
1288 // File
1289 if (veData.file)
1290 {
1291 if (0 != veData.file->Release())
1292 {
1293 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1294 "Release file sub-API failed");
1295 releaseOK = false;
1296 }
1297 else
1298 {
1299 veData.file = NULL;
1300 }
1301 }
1302
1303 // Network
1304 if (veData.netw)
1305 {
1306 if (0 != veData.netw->Release())
1307 {
1308 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1309 "Release network sub-API failed");
1310 releaseOK = false;
1311 }
1312 else
1313 {
1314 veData.netw = NULL;
1315 }
1316 }
1317
1318 // apm
1319 if (veData.apm)
1320 {
1321 if (0 != veData.apm->Release())
1322 {
1323 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1324 "Release apm sub-API failed");
1325 releaseOK = false;
1326 }
1327 else
1328 {
1329 veData.apm = NULL;
1330 }
1331 }
1332
1333 // Volume
1334 if (veData.volume)
1335 {
1336 if (0 != veData.volume->Release())
1337 {
1338 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1339 "Release volume sub-API failed");
1340 releaseOK = false;
1341 }
1342 else
1343 {
1344 veData.volume = NULL;
1345 }
1346 }
1347
1348 // Hardware
1349 if (veData.hardware)
1350 {
1351 if (0 != veData.hardware->Release())
1352 {
1353 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1354 "Release hardware sub-API failed");
1355 releaseOK = false;
1356 }
1357 else
1358 {
1359 veData.hardware = NULL;
1360 }
1361 }
1362
1363 // RTP RTCP
1364 if (veData.rtp_rtcp)
1365 {
1366 if (0 != veData.rtp_rtcp->Release())
1367 {
1368 __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1369 "Release rtp_rtcp sub-API failed");
1370 releaseOK = false;
1371 }
1372 else
1373 {
1374 veData.rtp_rtcp = NULL;
1375 }
1376 }
1377
1378 return releaseOK;
1379 }
1380