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: 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 148 int my_transportation::SendPacket(int channel,const void *data,int len) 149 { 150 netw->ReceivedRTPPacket(channel, data, len); 151 return len; 152 } 153 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 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 195 ThreadTest::ThreadTest() : 196 _thread(NULL) 197 { 198 _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority, 199 "ThreadTest thread"); 200 } 201 202 bool ThreadTest::Run(void* ptr) 203 { 204 return static_cast<ThreadTest*> (ptr)->Process(); 205 } 206 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 281 int ThreadTest::RunTest() 282 { 283 if (_thread) 284 { 285 unsigned int id; 286 _thread->Start(id); 287 } 288 return 0; 289 } 290 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 // 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 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 // 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 // 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 // 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 // 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 // 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 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 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 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 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 // 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 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 // 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 // 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 // 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 // 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 // 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 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 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 // 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 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 // 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 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 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 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 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 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 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 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 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 // 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 // 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