tg_voip_jni.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. //
  2. // libtgvoip is free and unencumbered public domain software.
  3. // For more information, see http://unlicense.org or the UNLICENSE file
  4. // you should have received with this source code distribution.
  5. //
  6. #include <jni.h>
  7. #include <string.h>
  8. #include <map>
  9. #include <string>
  10. #include <vector>
  11. #include "../../VoIPServerConfig.h"
  12. #include "../../VoIPController.h"
  13. #include "../../os/android/AudioOutputOpenSLES.h"
  14. #include "../../os/android/AudioInputOpenSLES.h"
  15. #include "../../os/android/AudioInputAndroid.h"
  16. #include "../../os/android/AudioOutputAndroid.h"
  17. #include "../../os/android/VideoSourceAndroid.h"
  18. #include "../../os/android/VideoRendererAndroid.h"
  19. #include "../../audio/Resampler.h"
  20. #include "../../os/android/JNIUtilities.h"
  21. #include "../../PrivateDefines.h"
  22. #ifdef TGVOIP_HAS_CONFIG
  23. #include <tgvoip_config.h>
  24. #endif
  25. JavaVM* sharedJVM;
  26. jfieldID audioRecordInstanceFld=NULL;
  27. jfieldID audioTrackInstanceFld=NULL;
  28. jmethodID setStateMethod=NULL;
  29. jmethodID setSignalBarsMethod=NULL;
  30. jmethodID setSelfStreamsMethod=NULL;
  31. jmethodID setParticipantAudioEnabledMethod=NULL;
  32. jmethodID groupCallKeyReceivedMethod=NULL;
  33. jmethodID groupCallKeySentMethod=NULL;
  34. jmethodID callUpgradeRequestReceivedMethod=NULL;
  35. jclass jniUtilitiesClass=NULL;
  36. struct ImplDataAndroid{
  37. jobject javaObject;
  38. std::string persistentStateFile="";
  39. };
  40. #ifndef TGVOIP_PACKAGE_PATH
  41. #define TGVOIP_PACKAGE_PATH "org/telegram/messenger/voip"
  42. #endif
  43. #ifndef TGVOIP_PEER_TAG_VARIABLE_NAME
  44. #define TGVOIP_PEER_TAG_VARIABLE_NAME "peer_tag"
  45. #endif
  46. #ifndef TGVOIP_ENDPOINT_CLASS
  47. #define TGVOIP_ENDPOINT_CLASS "org/telegram/tgnet/TLRPC$TL_phoneConnection"
  48. #endif
  49. using namespace tgvoip;
  50. using namespace tgvoip::audio;
  51. namespace tgvoip {
  52. #pragma mark - Callbacks
  53. void updateConnectionState(VoIPController *cntrlr, int state){
  54. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  55. jni::AttachAndCallVoidMethod(setStateMethod, impl->javaObject, state);
  56. }
  57. void updateSignalBarCount(VoIPController *cntrlr, int count){
  58. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  59. jni::AttachAndCallVoidMethod(setSignalBarsMethod, impl->javaObject, count);
  60. }
  61. void updateGroupCallStreams(VoIPGroupController *cntrlr, unsigned char *streams, size_t len){
  62. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  63. if(!impl->javaObject)
  64. return;
  65. jni::DoWithJNI([streams, len, &impl](JNIEnv* env){
  66. if(setSelfStreamsMethod){
  67. jbyteArray jstreams=env->NewByteArray(static_cast<jsize>(len));
  68. jbyte *el=env->GetByteArrayElements(jstreams, NULL);
  69. memcpy(el, streams, len);
  70. env->ReleaseByteArrayElements(jstreams, el, 0);
  71. env->CallVoidMethod(impl->javaObject, setSelfStreamsMethod, jstreams);
  72. }
  73. });
  74. }
  75. void groupCallKeyReceived(VoIPController *cntrlr, const unsigned char *key){
  76. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  77. if(!impl->javaObject)
  78. return;
  79. jni::DoWithJNI([key, &impl](JNIEnv* env){
  80. if(groupCallKeyReceivedMethod){
  81. jbyteArray jkey=env->NewByteArray(256);
  82. jbyte *el=env->GetByteArrayElements(jkey, NULL);
  83. memcpy(el, key, 256);
  84. env->ReleaseByteArrayElements(jkey, el, 0);
  85. env->CallVoidMethod(impl->javaObject, groupCallKeyReceivedMethod, jkey);
  86. }
  87. });
  88. }
  89. void groupCallKeySent(VoIPController *cntrlr){
  90. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  91. jni::AttachAndCallVoidMethod(groupCallKeySentMethod, impl->javaObject);
  92. }
  93. void callUpgradeRequestReceived(VoIPController* cntrlr){
  94. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  95. jni::AttachAndCallVoidMethod(callUpgradeRequestReceivedMethod, impl->javaObject);
  96. }
  97. void updateParticipantAudioState(VoIPGroupController *cntrlr, int32_t userID, bool enabled){
  98. ImplDataAndroid *impl=(ImplDataAndroid *) cntrlr->implData;
  99. jni::AttachAndCallVoidMethod(setParticipantAudioEnabledMethod, impl->javaObject, userID, enabled);
  100. }
  101. #pragma mark - VoIPController
  102. uint32_t AndroidCodecToFOURCC(std::string mime){
  103. if(mime=="video/avc")
  104. return CODEC_AVC;
  105. else if(mime=="video/hevc")
  106. return CODEC_HEVC;
  107. else if(mime=="video/x-vnd.on2.vp8")
  108. return CODEC_VP8;
  109. else if(mime=="video/x-vnd.on2.vp9")
  110. return CODEC_VP9;
  111. return 0;
  112. }
  113. jlong VoIPController_nativeInit(JNIEnv* env, jobject thiz, jstring persistentStateFile) {
  114. ImplDataAndroid* impl=new ImplDataAndroid();
  115. impl->javaObject=env->NewGlobalRef(thiz);
  116. if(persistentStateFile){
  117. impl->persistentStateFile=jni::JavaStringToStdString(env, persistentStateFile);
  118. }
  119. VoIPController* cntrlr=new VoIPController();
  120. cntrlr->implData=impl;
  121. VoIPController::Callbacks callbacks;
  122. callbacks.connectionStateChanged=updateConnectionState;
  123. callbacks.signalBarCountChanged=updateSignalBarCount;
  124. callbacks.groupCallKeyReceived=groupCallKeyReceived;
  125. callbacks.groupCallKeySent=groupCallKeySent;
  126. callbacks.upgradeToGroupCallRequested=callUpgradeRequestReceived;
  127. cntrlr->SetCallbacks(callbacks);
  128. if(!impl->persistentStateFile.empty()){
  129. FILE* f=fopen(impl->persistentStateFile.c_str(), "r");
  130. if(f){
  131. fseek(f, 0, SEEK_END);
  132. size_t len=static_cast<size_t>(ftell(f));
  133. fseek(f, 0, SEEK_SET);
  134. if(len<1024*512 && len>0){
  135. char *fbuf=static_cast<char *>(malloc(len));
  136. fread(fbuf, 1, len, f);
  137. std::vector<uint8_t> state(fbuf, fbuf+len);
  138. free(fbuf);
  139. cntrlr->SetPersistentState(state);
  140. }
  141. fclose(f);
  142. }
  143. }
  144. /*if(video::VideoRendererAndroid::availableDecoders.empty() || video::VideoSourceAndroid::availableEncoders.empty()){
  145. video::VideoRendererAndroid::availableDecoders.clear();
  146. video::VideoSourceAndroid::availableEncoders.clear();
  147. jmethodID getCodecsMethod=env->GetStaticMethodID(jniUtilitiesClass, "getSupportedVideoCodecs", "()[[Ljava/lang/String;");
  148. jobjectArray codecs=static_cast<jobjectArray>(env->CallStaticObjectMethod(jniUtilitiesClass, getCodecsMethod));
  149. jobjectArray encoders=static_cast<jobjectArray>(env->GetObjectArrayElement(codecs, 0));
  150. jobjectArray decoders=static_cast<jobjectArray>(env->GetObjectArrayElement(codecs, 1));
  151. for(jsize i=0;i<env->GetArrayLength(encoders);i++){
  152. std::string codec=jni::JavaStringToStdString(env, static_cast<jstring>(env->GetObjectArrayElement(encoders, i)));
  153. uint32_t id=AndroidCodecToFOURCC(codec);
  154. if(id)
  155. video::VideoSourceAndroid::availableEncoders.push_back(id);
  156. }
  157. for(jsize i=0;i<env->GetArrayLength(decoders);i++){
  158. std::string codec=jni::JavaStringToStdString(env, static_cast<jstring>(env->GetObjectArrayElement(decoders, i)));
  159. uint32_t id=AndroidCodecToFOURCC(codec);
  160. if(id)
  161. video::VideoRendererAndroid::availableDecoders.push_back(id);
  162. }
  163. jmethodID getMaxResolutionMethod=env->GetStaticMethodID(jniUtilitiesClass, "getMaxVideoResolution", "()I");
  164. video::VideoRendererAndroid::maxResolution=env->CallStaticIntMethod(jniUtilitiesClass, getMaxResolutionMethod);
  165. }*/
  166. return (jlong)(intptr_t)cntrlr;
  167. }
  168. void VoIPController_nativeStart(JNIEnv* env, jobject thiz, jlong inst){
  169. ((VoIPController*)(intptr_t)inst)->Start();
  170. }
  171. void VoIPController_nativeConnect(JNIEnv* env, jobject thiz, jlong inst){
  172. ((VoIPController*)(intptr_t)inst)->Connect();
  173. }
  174. void VoIPController_nativeSetProxy(JNIEnv* env, jobject thiz, jlong inst, jstring _address, jint port, jstring _username, jstring _password){
  175. ((VoIPController*)(intptr_t)inst)->SetProxy(PROXY_SOCKS5, jni::JavaStringToStdString(env, _address), (uint16_t)port, jni::JavaStringToStdString(env, _username), jni::JavaStringToStdString(env, _password));
  176. }
  177. void VoIPController_nativeSetEncryptionKey(JNIEnv* env, jobject thiz, jlong inst, jbyteArray key, jboolean isOutgoing){
  178. jbyte* akey=env->GetByteArrayElements(key, NULL);
  179. ((VoIPController*)(intptr_t)inst)->SetEncryptionKey((char *) akey, isOutgoing);
  180. env->ReleaseByteArrayElements(key, akey, JNI_ABORT);
  181. }
  182. void VoIPController_nativeSetRemoteEndpoints(JNIEnv* env, jobject thiz, jlong inst, jobjectArray endpoints, jboolean allowP2p, jboolean tcp, jint connectionMaxLayer){
  183. size_t len=(size_t) env->GetArrayLength(endpoints);
  184. std::vector<Endpoint> eps;
  185. /*public String ip;
  186. public String ipv6;
  187. public int port;
  188. public byte[] peer_tag;*/
  189. jclass epClass=env->GetObjectClass(env->GetObjectArrayElement(endpoints, 0));
  190. jfieldID ipFld=env->GetFieldID(epClass, "ip", "Ljava/lang/String;");
  191. jfieldID ipv6Fld=env->GetFieldID(epClass, "ipv6", "Ljava/lang/String;");
  192. jfieldID portFld=env->GetFieldID(epClass, "port", "I");
  193. jfieldID peerTagFld=env->GetFieldID(epClass, TGVOIP_PEER_TAG_VARIABLE_NAME, "[B");
  194. jfieldID idFld=env->GetFieldID(epClass, "id", "J");
  195. int i;
  196. for(i=0;i<len;i++){
  197. jobject endpoint=env->GetObjectArrayElement(endpoints, i);
  198. jstring ip=(jstring) env->GetObjectField(endpoint, ipFld);
  199. jstring ipv6=(jstring) env->GetObjectField(endpoint, ipv6Fld);
  200. jint port=env->GetIntField(endpoint, portFld);
  201. jlong id=env->GetLongField(endpoint, idFld);
  202. jbyteArray peerTag=(jbyteArray) env->GetObjectField(endpoint, peerTagFld);
  203. IPv4Address v4addr(jni::JavaStringToStdString(env, ip));
  204. IPv6Address v6addr("::0");
  205. if(ipv6 && env->GetStringLength(ipv6)){
  206. v6addr=IPv6Address(jni::JavaStringToStdString(env, ipv6));
  207. }
  208. unsigned char pTag[16];
  209. if(peerTag && env->GetArrayLength(peerTag)){
  210. jbyte* peerTagBytes=env->GetByteArrayElements(peerTag, NULL);
  211. memcpy(pTag, peerTagBytes, 16);
  212. env->ReleaseByteArrayElements(peerTag, peerTagBytes, JNI_ABORT);
  213. }
  214. eps.push_back(Endpoint((int64_t)id, (uint16_t)port, v4addr, v6addr, tcp ? Endpoint::Type::TCP_RELAY : Endpoint::Type::UDP_RELAY, pTag));
  215. }
  216. ((VoIPController*)(intptr_t)inst)->SetRemoteEndpoints(eps, allowP2p, connectionMaxLayer);
  217. }
  218. void VoIPController_nativeSetNativeBufferSize(JNIEnv* env, jclass thiz, jint size){
  219. AudioOutputOpenSLES::nativeBufferSize=(unsigned int) size;
  220. AudioInputOpenSLES::nativeBufferSize=(unsigned int) size;
  221. }
  222. void VoIPController_nativeRelease(JNIEnv* env, jobject thiz, jlong inst){
  223. //env->DeleteGlobalRef(AudioInputAndroid::jniClass);
  224. VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
  225. ImplDataAndroid* impl=(ImplDataAndroid*)ctlr->implData;
  226. ctlr->Stop();
  227. std::vector<uint8_t> state=ctlr->GetPersistentState();
  228. delete ctlr;
  229. env->DeleteGlobalRef(impl->javaObject);
  230. if(!impl->persistentStateFile.empty()){
  231. FILE* f=fopen(impl->persistentStateFile.c_str(), "w");
  232. if(f){
  233. fwrite(state.data(), 1, state.size(), f);
  234. fclose(f);
  235. }
  236. }
  237. delete impl;
  238. }
  239. jstring VoIPController_nativeGetDebugString(JNIEnv* env, jobject thiz, jlong inst){
  240. std::string str=((VoIPController*)(intptr_t)inst)->GetDebugString();
  241. return env->NewStringUTF(str.c_str());
  242. }
  243. void VoIPController_nativeSetNetworkType(JNIEnv* env, jobject thiz, jlong inst, jint type){
  244. ((VoIPController*)(intptr_t)inst)->SetNetworkType(type);
  245. }
  246. void VoIPController_nativeSetMicMute(JNIEnv* env, jobject thiz, jlong inst, jboolean mute){
  247. ((VoIPController*)(intptr_t)inst)->SetMicMute(mute);
  248. }
  249. void VoIPController_nativeSetConfig(JNIEnv* env, jobject thiz, jlong inst, jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath, jstring statsDumpPath, jboolean logPacketStats){
  250. VoIPController::Config cfg;
  251. cfg.initTimeout=initTimeout;
  252. cfg.recvTimeout=recvTimeout;
  253. cfg.dataSaving=dataSavingMode;
  254. cfg.enableAEC=enableAEC;
  255. cfg.enableNS=enableNS;
  256. cfg.enableAGC=enableAGC;
  257. cfg.enableCallUpgrade=false;
  258. cfg.logPacketStats=logPacketStats;
  259. if(logFilePath){
  260. cfg.logFilePath=jni::JavaStringToStdString(env, logFilePath);
  261. }
  262. if(statsDumpPath){
  263. cfg.statsDumpFilePath=jni::JavaStringToStdString(env, statsDumpPath);
  264. }
  265. ((VoIPController*)(intptr_t)inst)->SetConfig(cfg);
  266. }
  267. void VoIPController_nativeDebugCtl(JNIEnv* env, jobject thiz, jlong inst, jint request, jint param){
  268. ((VoIPController*)(intptr_t)inst)->DebugCtl(request, param);
  269. }
  270. jstring VoIPController_nativeGetVersion(JNIEnv* env, jclass clasz){
  271. return env->NewStringUTF(VoIPController::GetVersion());
  272. }
  273. jlong VoIPController_nativeGetPreferredRelayID(JNIEnv* env, jclass clasz, jlong inst){
  274. return ((VoIPController*)(intptr_t)inst)->GetPreferredRelayID();
  275. }
  276. jint VoIPController_nativeGetLastError(JNIEnv* env, jclass clasz, jlong inst){
  277. return ((VoIPController*)(intptr_t)inst)->GetLastError();
  278. }
  279. void VoIPController_nativeGetStats(JNIEnv* env, jclass clasz, jlong inst, jobject stats){
  280. VoIPController::TrafficStats _stats;
  281. ((VoIPController*)(intptr_t)inst)->GetStats(&_stats);
  282. jclass cls=env->GetObjectClass(stats);
  283. env->SetLongField(stats, env->GetFieldID(cls, "bytesSentWifi", "J"), _stats.bytesSentWifi);
  284. env->SetLongField(stats, env->GetFieldID(cls, "bytesSentMobile", "J"), _stats.bytesSentMobile);
  285. env->SetLongField(stats, env->GetFieldID(cls, "bytesRecvdWifi", "J"), _stats.bytesRecvdWifi);
  286. env->SetLongField(stats, env->GetFieldID(cls, "bytesRecvdMobile", "J"), _stats.bytesRecvdMobile);
  287. }
  288. jstring VoIPController_nativeGetDebugLog(JNIEnv* env, jobject thiz, jlong inst){
  289. VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
  290. std::string log=ctlr->GetDebugLog();
  291. return env->NewStringUTF(log.c_str());
  292. }
  293. void VoIPController_nativeSetAudioOutputGainControlEnabled(JNIEnv* env, jclass clasz, jlong inst, jboolean enabled){
  294. ((VoIPController*)(intptr_t)inst)->SetAudioOutputGainControlEnabled(enabled);
  295. }
  296. void VoIPController_nativeSetEchoCancellationStrength(JNIEnv* env, jclass cls, jlong inst, jint strength){
  297. ((VoIPController*)(intptr_t)inst)->SetEchoCancellationStrength(strength);
  298. }
  299. jint VoIPController_nativeGetPeerCapabilities(JNIEnv* env, jclass cls, jlong inst){
  300. return ((VoIPController*)(intptr_t)inst)->GetPeerCapabilities();
  301. }
  302. void VoIPController_nativeSendGroupCallKey(JNIEnv* env, jclass cls, jlong inst, jbyteArray _key){
  303. jbyte* key=env->GetByteArrayElements(_key, NULL);
  304. ((VoIPController*)(intptr_t)inst)->SendGroupCallKey((unsigned char *) key);
  305. env->ReleaseByteArrayElements(_key, key, JNI_ABORT);
  306. }
  307. void VoIPController_nativeRequestCallUpgrade(JNIEnv* env, jclass cls, jlong inst){
  308. ((VoIPController*)(intptr_t)inst)->RequestCallUpgrade();
  309. }
  310. void VoIPController_nativeSetVideoSource(JNIEnv* env, jobject thiz, jlong inst, jlong source){
  311. ((VoIPController*)(intptr_t)inst)->SetVideoSource((video::VideoSource*)(intptr_t)source);
  312. }
  313. void VoIPController_nativeSetVideoRenderer(JNIEnv* env, jobject thiz, jlong inst, jlong renderer){
  314. ((VoIPController*)(intptr_t)inst)->SetVideoRenderer((video::VideoRenderer*)(intptr_t)renderer);
  315. }
  316. jboolean VoIPController_nativeNeedRate(JNIEnv* env, jclass cls, jlong inst){
  317. return static_cast<jboolean>(((VoIPController*)(intptr_t)inst)->NeedRate());
  318. }
  319. jint VoIPController_getConnectionMaxLayer(JNIEnv* env, jclass cls){
  320. return VoIPController::GetConnectionMaxLayer();
  321. }
  322. #pragma mark - AudioRecordJNI
  323. void AudioRecordJNI_nativeCallback(JNIEnv* env, jobject thiz, jobject buffer){
  324. jlong inst=env->GetLongField(thiz, audioRecordInstanceFld);
  325. AudioInputAndroid* in=(AudioInputAndroid*)(intptr_t)inst;
  326. in->HandleCallback(env, buffer);
  327. }
  328. #pragma mark - AudioTrackJNI
  329. void AudioTrackJNI_nativeCallback(JNIEnv* env, jobject thiz, jbyteArray buffer){
  330. jlong inst=env->GetLongField(thiz, audioTrackInstanceFld);
  331. AudioOutputAndroid* in=(AudioOutputAndroid*)(intptr_t)inst;
  332. in->HandleCallback(env, buffer);
  333. }
  334. #pragma mark - VoIPServerConfig
  335. void VoIPServerConfig_nativeSetConfig(JNIEnv* env, jclass clasz, jstring jsonString){
  336. ServerConfig::GetSharedInstance()->Update(jni::JavaStringToStdString(env, jsonString));
  337. }
  338. #pragma mark - Resampler
  339. jint Resampler_convert44to48(JNIEnv* env, jclass cls, jobject from, jobject to){
  340. return (jint)tgvoip::audio::Resampler::Convert44To48((int16_t *) env->GetDirectBufferAddress(from), (int16_t *) env->GetDirectBufferAddress(to), (size_t) (env->GetDirectBufferCapacity(from)/2), (size_t) (env->GetDirectBufferCapacity(to)/2));
  341. }
  342. jint Resampler_convert48to44(JNIEnv* env, jclass cls, jobject from, jobject to){
  343. return (jint)tgvoip::audio::Resampler::Convert48To44((int16_t *) env->GetDirectBufferAddress(from), (int16_t *) env->GetDirectBufferAddress(to), (size_t) (env->GetDirectBufferCapacity(from)/2), (size_t) (env->GetDirectBufferCapacity(to)/2));
  344. }
  345. #pragma mark - VoIPGroupController
  346. #ifndef TGVOIP_NO_GROUP_CALLS
  347. jlong VoIPGroupController_nativeInit(JNIEnv* env, jobject thiz, jint timeDifference){
  348. ImplDataAndroid* impl=(ImplDataAndroid*) malloc(sizeof(ImplDataAndroid));
  349. impl->javaObject=env->NewGlobalRef(thiz);
  350. VoIPGroupController* cntrlr=new VoIPGroupController(timeDifference);
  351. cntrlr->implData=impl;
  352. VoIPGroupController::Callbacks callbacks;
  353. callbacks.connectionStateChanged=updateConnectionState;
  354. callbacks.updateStreams=updateGroupCallStreams;
  355. callbacks.participantAudioStateChanged=updateParticipantAudioState;
  356. callbacks.signalBarCountChanged=NULL;
  357. cntrlr->SetCallbacks(callbacks);
  358. return (jlong)(intptr_t)cntrlr;
  359. }
  360. void VoIPGroupController_nativeSetGroupCallInfo(JNIEnv* env, jclass cls, jlong inst, jbyteArray _encryptionKey, jbyteArray _reflectorGroupTag, jbyteArray _reflectorSelfTag, jbyteArray _reflectorSelfSecret, jbyteArray _reflectorSelfTagHash, jint selfUserID, jstring reflectorAddress, jstring reflectorAddressV6, jint reflectorPort){
  361. VoIPGroupController* ctlr=((VoIPGroupController*)(intptr_t)inst);
  362. jbyte* encryptionKey=env->GetByteArrayElements(_encryptionKey, NULL);
  363. jbyte* reflectorGroupTag=env->GetByteArrayElements(_reflectorGroupTag, NULL);
  364. jbyte* reflectorSelfTag=env->GetByteArrayElements(_reflectorSelfTag, NULL);
  365. jbyte* reflectorSelfSecret=env->GetByteArrayElements(_reflectorSelfSecret, NULL);
  366. jbyte* reflectorSelfTagHash=env->GetByteArrayElements(_reflectorSelfTagHash, NULL);
  367. const char* ipChars=env->GetStringUTFChars(reflectorAddress, NULL);
  368. std::string ipLiteral(ipChars);
  369. IPv4Address v4addr(ipLiteral);
  370. IPv6Address v6addr("::0");
  371. env->ReleaseStringUTFChars(reflectorAddress, ipChars);
  372. if(reflectorAddressV6 && env->GetStringLength(reflectorAddressV6)){
  373. const char* ipv6Chars=env->GetStringUTFChars(reflectorAddressV6, NULL);
  374. v6addr=IPv6Address(ipv6Chars);
  375. env->ReleaseStringUTFChars(reflectorAddressV6, ipv6Chars);
  376. }
  377. ctlr->SetGroupCallInfo((unsigned char *) encryptionKey, (unsigned char *) reflectorGroupTag, (unsigned char *) reflectorSelfTag, (unsigned char *) reflectorSelfSecret, (unsigned char*) reflectorSelfTagHash, selfUserID, v4addr, v6addr, (uint16_t)reflectorPort);
  378. env->ReleaseByteArrayElements(_encryptionKey, encryptionKey, JNI_ABORT);
  379. env->ReleaseByteArrayElements(_reflectorGroupTag, reflectorGroupTag, JNI_ABORT);
  380. env->ReleaseByteArrayElements(_reflectorSelfTag, reflectorSelfTag, JNI_ABORT);
  381. env->ReleaseByteArrayElements(_reflectorSelfSecret, reflectorSelfSecret, JNI_ABORT);
  382. env->ReleaseByteArrayElements(_reflectorSelfTagHash, reflectorSelfTagHash, JNI_ABORT);
  383. }
  384. void VoIPGroupController_nativeAddGroupCallParticipant(JNIEnv* env, jclass cls, jlong inst, jint userID, jbyteArray _memberTagHash, jbyteArray _streams){
  385. VoIPGroupController* ctlr=((VoIPGroupController*)(intptr_t)inst);
  386. jbyte* memberTagHash=env->GetByteArrayElements(_memberTagHash, NULL);
  387. jbyte* streams=_streams ? env->GetByteArrayElements(_streams, NULL) : NULL;
  388. ctlr->AddGroupCallParticipant(userID, (unsigned char *) memberTagHash, (unsigned char *) streams, (size_t) env->GetArrayLength(_streams));
  389. env->ReleaseByteArrayElements(_memberTagHash, memberTagHash, JNI_ABORT);
  390. if(_streams)
  391. env->ReleaseByteArrayElements(_streams, streams, JNI_ABORT);
  392. }
  393. void VoIPGroupController_nativeRemoveGroupCallParticipant(JNIEnv* env, jclass cls, jlong inst, jint userID){
  394. VoIPGroupController* ctlr=((VoIPGroupController*)(intptr_t)inst);
  395. ctlr->RemoveGroupCallParticipant(userID);
  396. }
  397. jfloat VoIPGroupController_nativeGetParticipantAudioLevel(JNIEnv* env, jclass cls, jlong inst, jint userID){
  398. return ((VoIPGroupController*)(intptr_t)inst)->GetParticipantAudioLevel(userID);
  399. }
  400. void VoIPGroupController_nativeSetParticipantVolume(JNIEnv* env, jclass cls, jlong inst, jint userID, jfloat volume){
  401. ((VoIPGroupController*)(intptr_t)inst)->SetParticipantVolume(userID, volume);
  402. }
  403. jbyteArray VoIPGroupController_getInitialStreams(JNIEnv* env, jclass cls){
  404. unsigned char buf[1024];
  405. size_t len=VoIPGroupController::GetInitialStreams(buf, sizeof(buf));
  406. jbyteArray arr=env->NewByteArray(len);
  407. jbyte* arrElems=env->GetByteArrayElements(arr, NULL);
  408. memcpy(arrElems, buf, len);
  409. env->ReleaseByteArrayElements(arr, arrElems, 0);
  410. return arr;
  411. }
  412. void VoIPGroupController_nativeSetParticipantStreams(JNIEnv* env, jclass cls, jlong inst, jint userID, jbyteArray _streams){
  413. jbyte* streams=env->GetByteArrayElements(_streams, NULL);
  414. ((VoIPGroupController*)(intptr_t)inst)->SetParticipantStreams(userID, (unsigned char *) streams, (size_t) env->GetArrayLength(_streams));
  415. env->ReleaseByteArrayElements(_streams, streams, JNI_ABORT);
  416. }
  417. #endif
  418. #pragma mark - VideoSource
  419. jlong VideoSource_nativeInit(JNIEnv* env, jobject thiz){
  420. return (jlong)(intptr_t)new video::VideoSourceAndroid(env->NewGlobalRef(thiz));
  421. }
  422. void VideoSource_nativeRelease(JNIEnv* env, jobject thiz, jlong inst){
  423. delete (video::VideoSource*)(intptr_t)inst;
  424. }
  425. void VideoSource_nativeSetVideoStreamParameters(JNIEnv* env, jobject thiz, jlong inst, jobjectArray _csd, jint width, jint height){
  426. std::vector<Buffer> csd;
  427. if(_csd){
  428. for(int i=0; i<env->GetArrayLength(_csd); i++){
  429. jobject _buf=env->GetObjectArrayElement(_csd, i);
  430. size_t len=static_cast<size_t>(env->GetDirectBufferCapacity(_buf));
  431. Buffer buf(len);
  432. buf.CopyFrom(env->GetDirectBufferAddress(_buf), 0, len);
  433. csd.push_back(std::move(buf));
  434. }
  435. }
  436. ((video::VideoSourceAndroid*)(intptr_t)inst)->SetStreamParameters(std::move(csd), width, height);
  437. }
  438. void VideoSource_nativeSendFrame(JNIEnv* env, jobject thiz, jlong inst, jobject buffer, jint offset, jint length, jint flags){
  439. size_t bufsize=(size_t)env->GetDirectBufferCapacity(buffer);
  440. Buffer buf(static_cast<size_t>(length));
  441. buf.CopyFrom(((char*)env->GetDirectBufferAddress(buffer))+offset, 0, static_cast<size_t>(length));
  442. ((video::VideoSourceAndroid*)(intptr_t)inst)->SendFrame(std::move(buf), static_cast<uint32_t>(flags));
  443. }
  444. #pragma mark - VideoRenderer
  445. jlong VideoRenderer_nativeInit(JNIEnv* env, jobject thiz){
  446. return (jlong)(intptr_t)new video::VideoRendererAndroid(env->NewGlobalRef(thiz));
  447. }
  448. }
  449. extern "C" void tgvoipRegisterNatives(JNIEnv* env){
  450. jclass controller=env->FindClass(TGVOIP_PACKAGE_PATH "/VoIPController");
  451. jclass groupController=env->FindClass(TGVOIP_PACKAGE_PATH "/VoIPGroupController");
  452. if(env->ExceptionCheck()){
  453. env->ExceptionClear(); // is returning NULL from FindClass not enough?
  454. }
  455. jclass audioRecordJNI=env->FindClass(TGVOIP_PACKAGE_PATH "/AudioRecordJNI");
  456. jclass audioTrackJNI=env->FindClass(TGVOIP_PACKAGE_PATH "/AudioTrackJNI");
  457. jclass serverConfig=env->FindClass(TGVOIP_PACKAGE_PATH "/VoIPServerConfig");
  458. jclass resampler=env->FindClass(TGVOIP_PACKAGE_PATH "/Resampler");
  459. jclass videoSource=env->FindClass(TGVOIP_PACKAGE_PATH "/VideoSource");
  460. if(env->ExceptionCheck()){
  461. env->ExceptionClear(); // is returning NULL from FindClass not enough?
  462. }
  463. jclass videoRenderer=env->FindClass(TGVOIP_PACKAGE_PATH "/VideoRenderer");
  464. if(env->ExceptionCheck()){
  465. env->ExceptionClear(); // is returning NULL from FindClass not enough?
  466. }
  467. assert(controller && audioRecordJNI && audioTrackJNI && serverConfig && resampler);
  468. audioRecordInstanceFld=env->GetFieldID(audioRecordJNI, "nativeInst", "J");
  469. audioTrackInstanceFld=env->GetFieldID(audioTrackJNI, "nativeInst", "J");
  470. env->GetJavaVM(&sharedJVM);
  471. if(!AudioInputAndroid::jniClass){
  472. jclass cls=env->FindClass(TGVOIP_PACKAGE_PATH "/AudioRecordJNI");
  473. AudioInputAndroid::jniClass=(jclass) env->NewGlobalRef(cls);
  474. AudioInputAndroid::initMethod=env->GetMethodID(cls, "init", "(IIII)V");
  475. AudioInputAndroid::releaseMethod=env->GetMethodID(cls, "release", "()V");
  476. AudioInputAndroid::startMethod=env->GetMethodID(cls, "start", "()Z");
  477. AudioInputAndroid::stopMethod=env->GetMethodID(cls, "stop", "()V");
  478. AudioInputAndroid::getEnabledEffectsMaskMethod=env->GetMethodID(cls, "getEnabledEffectsMask", "()I");
  479. cls=env->FindClass(TGVOIP_PACKAGE_PATH "/AudioTrackJNI");
  480. AudioOutputAndroid::jniClass=(jclass) env->NewGlobalRef(cls);
  481. AudioOutputAndroid::initMethod=env->GetMethodID(cls, "init", "(IIII)V");
  482. AudioOutputAndroid::releaseMethod=env->GetMethodID(cls, "release", "()V");
  483. AudioOutputAndroid::startMethod=env->GetMethodID(cls, "start", "()V");
  484. AudioOutputAndroid::stopMethod=env->GetMethodID(cls, "stop", "()V");
  485. if(videoRenderer){
  486. video::VideoRendererAndroid::decodeAndDisplayMethod=env->GetMethodID(videoRenderer, "decodeAndDisplay", "(Ljava/nio/ByteBuffer;IJ)V");
  487. video::VideoRendererAndroid::resetMethod=env->GetMethodID(videoRenderer, "reset", "(Ljava/lang/String;II[[B)V");
  488. video::VideoRendererAndroid::setStreamEnabledMethod=env->GetMethodID(videoRenderer, "setStreamEnabled", "(Z)V");
  489. }
  490. }
  491. setStateMethod=env->GetMethodID(controller, "handleStateChange", "(I)V");
  492. setSignalBarsMethod=env->GetMethodID(controller, "handleSignalBarsChange", "(I)V");
  493. groupCallKeyReceivedMethod=env->GetMethodID(controller, "groupCallKeyReceived", "([B)V");
  494. groupCallKeySentMethod=env->GetMethodID(controller, "groupCallKeySent", "()V");
  495. callUpgradeRequestReceivedMethod=env->GetMethodID(controller, "callUpgradeRequestReceived", "()V");
  496. if(!jniUtilitiesClass)
  497. jniUtilitiesClass=(jclass) env->NewGlobalRef(env->FindClass(TGVOIP_PACKAGE_PATH "/JNIUtilities"));
  498. // VoIPController
  499. JNINativeMethod controllerMethods[]={
  500. {"nativeInit", "(Ljava/lang/String;)J", (void*)&tgvoip::VoIPController_nativeInit},
  501. {"nativeStart", "(J)V", (void*)&tgvoip::VoIPController_nativeStart},
  502. {"nativeConnect", "(J)V", (void*)&tgvoip::VoIPController_nativeConnect},
  503. {"nativeSetProxy", "(JLjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V", (void*)&tgvoip::VoIPController_nativeSetProxy},
  504. {"nativeSetEncryptionKey", "(J[BZ)V", (void*)&tgvoip::VoIPController_nativeSetEncryptionKey},
  505. {"nativeSetRemoteEndpoints", "(J[L" TGVOIP_ENDPOINT_CLASS ";ZZI)V", (void*)&tgvoip::VoIPController_nativeSetRemoteEndpoints},
  506. {"nativeSetNativeBufferSize", "(I)V", (void*)&tgvoip::VoIPController_nativeSetNativeBufferSize},
  507. {"nativeRelease", "(J)V", (void*)&tgvoip::VoIPController_nativeRelease},
  508. {"nativeGetDebugString", "(J)Ljava/lang/String;", (void*)&tgvoip::VoIPController_nativeGetDebugString},
  509. {"nativeSetNetworkType", "(JI)V", (void*)&tgvoip::VoIPController_nativeSetNetworkType},
  510. {"nativeSetMicMute", "(JZ)V", (void*)&tgvoip::VoIPController_nativeSetMicMute},
  511. {"nativeSetConfig", "(JDDIZZZLjava/lang/String;Ljava/lang/String;Z)V", (void*)&tgvoip::VoIPController_nativeSetConfig},
  512. {"nativeDebugCtl", "(JII)V", (void*)&tgvoip::VoIPController_nativeDebugCtl},
  513. {"nativeGetVersion", "()Ljava/lang/String;", (void*)&tgvoip::VoIPController_nativeGetVersion},
  514. {"nativeGetPreferredRelayID", "(J)J", (void*)&tgvoip::VoIPController_nativeGetPreferredRelayID},
  515. {"nativeGetLastError", "(J)I", (void*)&tgvoip::VoIPController_nativeGetLastError},
  516. {"nativeGetStats", "(JL" TGVOIP_PACKAGE_PATH "/VoIPController$Stats;)V", (void*)&tgvoip::VoIPController_nativeGetStats},
  517. {"nativeGetDebugLog", "(J)Ljava/lang/String;", (void*)&tgvoip::VoIPController_nativeGetDebugLog},
  518. {"nativeSetAudioOutputGainControlEnabled", "(JZ)V", (void*)&tgvoip::VoIPController_nativeSetAudioOutputGainControlEnabled},
  519. {"nativeSetEchoCancellationStrength", "(JI)V", (void*)&tgvoip::VoIPController_nativeSetEchoCancellationStrength},
  520. {"nativeGetPeerCapabilities", "(J)I", (void*)&tgvoip::VoIPController_nativeGetPeerCapabilities},
  521. {"nativeSendGroupCallKey", "(J[B)V", (void*)&tgvoip::VoIPController_nativeSendGroupCallKey},
  522. {"nativeRequestCallUpgrade", "(J)V", (void*)&tgvoip::VoIPController_nativeRequestCallUpgrade},
  523. {"nativeNeedRate", "(J)Z", (void*)&tgvoip::VoIPController_nativeNeedRate},
  524. {"getConnectionMaxLayer", "()I", (void*)&tgvoip::VoIPController_getConnectionMaxLayer},
  525. //{"nativeSetVideoSource", "(JJ)V", (void*)&tgvoip::VoIPController_nativeSetVideoSource},
  526. //{"nativeSetVideoRenderer", "(JJ)V", (void*)&tgvoip::VoIPController_nativeSetVideoRenderer}
  527. };
  528. env->RegisterNatives(controller, controllerMethods, sizeof(controllerMethods)/sizeof(JNINativeMethod));
  529. // VoIPGroupController
  530. #ifndef TGVOIP_NO_GROUP_CALLS
  531. if(groupController){
  532. setStateMethod=env->GetMethodID(groupController, "handleStateChange", "(I)V");
  533. setParticipantAudioEnabledMethod=env->GetMethodID(groupController, "setParticipantAudioEnabled", "(IZ)V");
  534. setSelfStreamsMethod=env->GetMethodID(groupController, "setSelfStreams", "([B)V");
  535. JNINativeMethod groupControllerMethods[]={
  536. {"nativeInit", "(I)J", (void*)&tgvoip::VoIPGroupController_nativeInit},
  537. {"nativeSetGroupCallInfo", "(J[B[B[B[B[BILjava/lang/String;Ljava/lang/String;I)V", (void*)&tgvoip::VoIPGroupController_nativeSetGroupCallInfo},
  538. {"nativeAddGroupCallParticipant", "(JI[B[B)V", (void*)&tgvoip::VoIPGroupController_nativeAddGroupCallParticipant},
  539. {"nativeRemoveGroupCallParticipant", "(JI)V", (void*)&tgvoip::VoIPGroupController_nativeRemoveGroupCallParticipant},
  540. {"nativeGetParticipantAudioLevel", "(JI)F", (void*)&tgvoip::VoIPGroupController_nativeGetParticipantAudioLevel},
  541. {"nativeSetParticipantVolume", "(JIF)V", (void*)&tgvoip::VoIPGroupController_nativeSetParticipantVolume},
  542. {"getInitialStreams", "()[B", (void*)&tgvoip::VoIPGroupController_getInitialStreams},
  543. {"nativeSetParticipantStreams", "(JI[B)V", (void*)&tgvoip::VoIPGroupController_nativeSetParticipantStreams}
  544. };
  545. env->RegisterNatives(groupController, groupControllerMethods, sizeof(groupControllerMethods)/sizeof(JNINativeMethod));
  546. }
  547. #endif
  548. // AudioRecordJNI
  549. JNINativeMethod audioRecordMethods[]={
  550. {"nativeCallback", "(Ljava/nio/ByteBuffer;)V", (void*)&tgvoip::AudioRecordJNI_nativeCallback}
  551. };
  552. env->RegisterNatives(audioRecordJNI, audioRecordMethods, sizeof(audioRecordMethods)/sizeof(JNINativeMethod));
  553. // AudioTrackJNI
  554. JNINativeMethod audioTrackMethods[]={
  555. {"nativeCallback", "([B)V", (void*)&tgvoip::AudioTrackJNI_nativeCallback}
  556. };
  557. env->RegisterNatives(audioTrackJNI, audioTrackMethods, sizeof(audioTrackMethods)/sizeof(JNINativeMethod));
  558. // VoIPServerConfig
  559. JNINativeMethod serverConfigMethods[]={
  560. {"nativeSetConfig", "(Ljava/lang/String;)V", (void*)&tgvoip::VoIPServerConfig_nativeSetConfig}
  561. };
  562. env->RegisterNatives(serverConfig, serverConfigMethods, sizeof(serverConfigMethods)/sizeof(JNINativeMethod));
  563. // Resampler
  564. JNINativeMethod resamplerMethods[]={
  565. {"convert44to48", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I", (void*)&tgvoip::Resampler_convert44to48},
  566. {"convert48to44", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I", (void*)&tgvoip::Resampler_convert48to44}
  567. };
  568. env->RegisterNatives(resampler, resamplerMethods, sizeof(resamplerMethods)/sizeof(JNINativeMethod));
  569. if(videoSource){
  570. // VideoSource
  571. JNINativeMethod videoSourceMethods[]={
  572. {"nativeInit", "()J", (void *) &tgvoip::VideoSource_nativeInit},
  573. {"nativeRelease", "(J)V", (void *) &tgvoip::VideoSource_nativeRelease},
  574. {"nativeSetVideoStreamParameters", "(J[Ljava/nio/ByteBuffer;II)V", (void *) &tgvoip::VideoSource_nativeSetVideoStreamParameters},
  575. {"nativeSendFrame", "(JLjava/nio/ByteBuffer;III)V", (void *) &tgvoip::VideoSource_nativeSendFrame}
  576. };
  577. env->RegisterNatives(videoSource, videoSourceMethods, sizeof(videoSourceMethods)/sizeof(JNINativeMethod));
  578. }
  579. if(videoRenderer){
  580. // VideoRenderer
  581. JNINativeMethod videoRendererMethods[]={
  582. {"nativeInit", "()J", (void *) &tgvoip::VideoRenderer_nativeInit}
  583. };
  584. env->RegisterNatives(videoRenderer, videoRendererMethods, sizeof(videoRendererMethods)/sizeof(JNINativeMethod));
  585. }
  586. }