endpoint.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664
  1. #include "SpBase.h"
  2. #ifdef RVC_OS_WIN
  3. #include "stdafx.h"
  4. #include <ObjBase.h>
  5. #else
  6. #endif
  7. #include "endpoint.h"
  8. #include <sofia-sip/su.h>
  9. #include <sofia-sip/su_tag_class.h>
  10. #include <sofia-sip/nua.h>
  11. #include <sofia-sip/sip_status.h>
  12. #include <sofia-sip/sdp.h>
  13. #include <sofia-sip/sip_header.h>
  14. #include <sofia-sip/su_log.h>
  15. #include <sofia-sip/su_tagarg.h>
  16. #include <sofia-sip/su_tag_io.h>
  17. #include <sofia-sip/soa_tag.h>
  18. #include <sofia-sip/su_wait.h>
  19. #include <sofia-sip/nua_tag.h>
  20. #include "refcnt.h"
  21. #include "list.h"
  22. #include "sockutil.h"
  23. #include "hash.h"
  24. #include "video_session.h"
  25. #include "audio_session.h"
  26. #include "rvc_media_common.h"
  27. #include "Event.h"
  28. bool g_IsExternalTerminalted = false;
  29. // default: ptime = 20ms
  30. #define CONDITION_PARAMS \
  31. int status, \
  32. char const *phrase, \
  33. nua_t *nua, \
  34. struct endpoint_t *ep, \
  35. nua_handle_t *nh, \
  36. struct endpoint_call_t *call, \
  37. sip_t const *sip, \
  38. tagi_t tags[]
  39. // the same with rtp payload type, the same as huawei open-eye
  40. enum e_audio_rtp_pt
  41. {
  42. PCMU = 0, // 64kbps, 4.17
  43. PCMA = 8, // 64kbps, 4.11
  44. G729 = 18, // 8kbps, 3.9
  45. };
  46. enum e_video_rtp_pt
  47. {
  48. H263 = 34, // h263
  49. };
  50. enum e_media_dir
  51. {
  52. DIR_NONE = 0,
  53. DIR_TX = 1,
  54. DIR_RX = 2,
  55. DIR_BOTH = 3,
  56. };
  57. typedef struct sdpvideo_desc_t
  58. {
  59. unsigned long local_rtp_ip;
  60. int local_rtp_port;
  61. unsigned long remote_rtp_ip;
  62. int remote_rtp_port;
  63. int local_pt;
  64. int remote_pt;
  65. };
  66. typedef struct media_desc_t
  67. {
  68. unsigned long remote_ip;
  69. int remote_port;
  70. unsigned long local_ip;
  71. int local_port;
  72. int media_dir;
  73. int local_pt;
  74. int local_ptime;
  75. int remote_pt;
  76. int remote_ptime;
  77. int local_telephone_event_pt;
  78. int remote_telephone_event_pt;
  79. int param[16];
  80. }media_desc_t;
  81. // 1. how to exit
  82. struct endpoint_call_t {
  83. struct list_head entry;
  84. endpoint_call_callback_t cb;
  85. endpoint_t *ep;
  86. audio_session_t *audio;
  87. video_session_t *video;
  88. int id;
  89. su_home_t *home;
  90. nua_handle_t *nh;
  91. char *to_uri;
  92. char *from_uri;
  93. char *call_id;
  94. sdp_session_t *last_sdp;
  95. int connected;
  96. int local_media_port;
  97. int local_video_port;
  98. unsigned int last_media_desc_hash;
  99. char local_ip[RVC_MAX_IP_LEN];
  100. DeviceTypeEnum eDeviceType;
  101. CallingTypeEnum nCallType;
  102. sdpvideo_desc_t sdpvieo_desc;
  103. DECLARE_REF_COUNT_MEMBER(ref_cnt);
  104. };
  105. DECLARE_REF_COUNT_STATIC(endpoint_call, endpoint_call_t)
  106. struct endpoint_t {
  107. su_home_t home[1];
  108. su_root_t *root;
  109. nua_t *nua;
  110. endpoint_call_t *active_call;
  111. #ifdef RVC_OS_WIN
  112. HANDLE event_thread;
  113. #else
  114. pthread_t ievent_threadid;
  115. #endif
  116. int call_seq;
  117. int media_port_seq;
  118. CEntityBase *entity;
  119. struct list_head call_list;
  120. endpoint_conf_t conf;
  121. int curr_audio_dev_type; // handfree or pickup
  122. };
  123. static const char *state_desc[] = {
  124. "STATE::INIT",
  125. "STATE::CALLING",
  126. "STATE::PROCEEDING",
  127. "STATE::COMPLETING",
  128. "STATE::READY",
  129. "STATE::TERMINATING",
  130. "STATE::TERMINATED",
  131. };
  132. static const char* call_type_table[] = {
  133. "NORMAL_CALLTYPE",
  134. "PADRINGUP_CALLTYPE",
  135. "PADTOPAD_CALLTYPE",
  136. "MOBILETOPAD_CALLTYPE",
  137. "DOUBLERECORD_CALLTYPE"
  138. };
  139. #ifndef VIDEOPLAYER_FLAG_DOUBLESIZE
  140. #define VIDEOPLAYER_FLAG_DOUBLESIZE 0x01
  141. #endif
  142. #ifndef VIDEOPLAYER_FLAG_NOTIMER
  143. #define VIDEOPLAYER_FLAG_NOTIMER 0x02
  144. #endif
  145. #ifndef VIDEOPLAYER_FLAG_PUSH
  146. #define VIDEOPLAYER_FLAG_PUSH 0x04
  147. #endif
  148. #ifndef VIDEOPLAYER_FLAG_PULL
  149. #define VIDEOPLAYER_FLAG_PULL 0x08
  150. #endif
  151. #ifndef VIDEOPLAYER_FLAG_CHECKTOP
  152. #define VIDEOPLAYER_FLAG_CHECKTOP 0x10
  153. #endif
  154. #ifndef VIDEOPLAYER_FLAG_ZOOMOUTSIZE
  155. #define VIDEOPLAYER_FLAG_ZOOMOUTSIZE 0x100
  156. #endif
  157. static void endpoint_media_change_audio_dev(endpoint_call_t *call, e_dev_type current_dev_type)
  158. {
  159. if (call->audio) {
  160. LogWarn(Severity_Low, Error_Debug, EVENT_MOD_SIP_AUDIO_DEVICE_SWITCH, CSimpleStringA::Format("change audio device to %s mode.", DEV_PICKUP == current_dev_type ? "pickup" : "hand free").GetData());
  161. audio_session_change_dev(call->audio, current_dev_type);
  162. }
  163. }
  164. static __inline struct in_addr __lton(unsigned long ip)
  165. {
  166. struct in_addr addr;
  167. addr.s_addr = ip;
  168. return addr;
  169. }
  170. #ifdef RVC_OS_WIN
  171. static void endpoint_media_update_video(endpoint_call_t *call, media_desc_t *video_desc, video_session_callback_t* cb)
  172. {
  173. if (video_desc->media_dir == DIR_NONE) {
  174. if (call->video) {
  175. video_session_stop(call->video);
  176. video_session_destroy(call->video);
  177. call->video = NULL;
  178. }
  179. else{
  180. if (DOUBLERECORD_CALLTYPE == call->nCallType){
  181. double_record_broadcast_video_session_stop();
  182. }
  183. }
  184. }
  185. else
  186. {
  187. int rc;
  188. endpoint_conf_t *ep_conf = &call->ep->conf;
  189. if (!call->audio){
  190. audio_session_conf_t conf = {0};
  191. strcpy(&conf.in_dev[DEV_PICKUP][0], ep_conf->audio_pickup_in_dev);
  192. strcpy(&conf.in_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_in_dev);
  193. strcpy(&conf.out_dev[DEV_PICKUP][0], ep_conf->audio_pickup_out_dev);
  194. strcpy(&conf.out_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_out_dev);
  195. conf.agc_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_agc;
  196. conf.agc_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_agc;
  197. conf.agc_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_agc;
  198. conf.agc_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_agc;
  199. conf.ns_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_ns;
  200. conf.ns_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_ns;
  201. conf.ns_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_ns;
  202. conf.ns_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_ns;
  203. conf.aec[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_aec;
  204. conf.aec[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_aec;
  205. rc = audio_session_create(&conf, &call->audio);
  206. if (rc != 0) {
  207. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create audio session failed! rc = %d", rc);
  208. return;
  209. }
  210. }
  211. if (call->video) {
  212. video_session_destroy(call->video);
  213. call->video = NULL;
  214. }
  215. int i = 0;
  216. int local_view_x = video_desc->param[i++];
  217. int local_view_y = video_desc->param[i++];
  218. int local_view_cx = video_desc->param[i++];
  219. int local_view_cy = video_desc->param[i++];
  220. int remote_view_x = video_desc->param[i++];
  221. int remote_view_y = video_desc->param[i++];
  222. int remote_view_cx = video_desc->param[i++];
  223. int remote_view_cy = video_desc->param[i++];
  224. int remote_width = video_desc->param[i++];
  225. int remote_height = video_desc->param[i++];
  226. int local_hwd_move = video_desc->param[i++];
  227. int remote_hwd_move = video_desc->param[i++];
  228. video_session_conf_t video_conf = {0};
  229. video_conf.bit_rate = 256 * 1024;
  230. video_conf.local_rtp_ip = video_desc->local_ip;
  231. video_conf.local_rtp_port = video_desc->local_port;
  232. video_conf.local_video_view_x = local_view_x;
  233. video_conf.local_video_view_y = local_view_y;
  234. video_conf.local_video_view_cx = local_view_cx;
  235. video_conf.local_video_view_cy = local_view_cy;
  236. video_conf.mtu = ep_conf->mtu;
  237. video_conf.video_quant = ep_conf->quant;
  238. video_conf.remote_rtp_ip = video_desc->remote_ip;
  239. video_conf.remote_rtp_port = video_desc->remote_port;
  240. video_conf.remote_video_view_x = remote_view_x;
  241. video_conf.remote_video_view_y = remote_view_y;
  242. video_conf.remote_video_view_cx = remote_view_cx;
  243. video_conf.remote_video_view_cy = remote_view_cy;
  244. video_conf.remote_video_width = remote_width;
  245. video_conf.remote_video_height = remote_height;
  246. video_conf.ref_active_camera = call->ep->conf.ref_active_camera;
  247. video_conf.ref_camera_switch = call->ep->conf.ref_camera_switch;
  248. video_conf.ref_camera_state = call->ep->conf.ref_camera_state;
  249. video_conf.ref_window_state = call->ep->conf.ref_window_state;
  250. video_conf.ref_Is_showPersonArea = call->ep->conf.ref_Is_showPersonArea;
  251. video_conf.ref_active_img = NULL;
  252. video_conf.ref_Is_ActiveInspect = NULL;
  253. video_conf.camera_count = call->ep->conf.camera_count;
  254. video_conf.screen_count = call->ep->conf.screen_count;
  255. video_conf.ref_Up_Fps = call->ep->conf.ref_Up_Fps;
  256. video_conf.eDeviceType = call->eDeviceType;
  257. video_conf.nCallType = call->nCallType;
  258. video_conf.local_move = local_hwd_move;
  259. video_conf.remote_move = remote_hwd_move;
  260. video_conf.video_echo_cb = cb;
  261. video_conf.ilocal_wind_flags = VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP;
  262. video_conf.iremote_wind_flags = VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP;
  263. video_conf.eType = (eVideoRenderType)call->ep->conf.irendertype;
  264. video_conf.local_pt = REC_COMMON_VIDEO_H264_PT;
  265. video_conf.remote_pt = REC_COMMON_VIDEO_H264_PT;
  266. rc = video_session_create(&video_conf, &call->video);
  267. if (rc != 0) {
  268. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create video session failed! rc = %d", rc);
  269. return;
  270. }
  271. rc = video_session_start(call->video);
  272. if (rc != 0) {
  273. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("start video session failed! rc = %d", rc);
  274. video_session_destroy(call->video);
  275. call->video = NULL;
  276. return;
  277. }
  278. }
  279. }
  280. #else
  281. static void endpoint_media_update_video(endpoint_call_t *call, media_desc_t *video_desc, rvc_video_render_callback_t* cb)
  282. {
  283. if (video_desc->media_dir == DIR_NONE) {
  284. if (call->video) {
  285. video_session_stop(call->video);
  286. video_session_destroy(call->video);
  287. call->video = NULL;
  288. }
  289. }
  290. else
  291. {
  292. int rc;
  293. endpoint_conf_t *ep_conf = &call->ep->conf;
  294. if (!call->audio){
  295. audio_session_conf_t conf = {0};
  296. strcpy(&conf.in_dev[DEV_PICKUP][0], ep_conf->audio_pickup_in_dev);
  297. strcpy(&conf.in_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_in_dev);
  298. strcpy(&conf.out_dev[DEV_PICKUP][0], ep_conf->audio_pickup_out_dev);
  299. strcpy(&conf.out_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_out_dev);
  300. conf.agc_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_agc;
  301. conf.agc_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_agc;
  302. conf.agc_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_agc;
  303. conf.agc_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_agc;
  304. conf.ns_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_ns;
  305. conf.ns_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_ns;
  306. conf.ns_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_ns;
  307. conf.ns_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_ns;
  308. conf.aec[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_aec;
  309. conf.aec[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_aec;
  310. rc = audio_session_create(&conf, &call->audio);
  311. if (rc != 0) {
  312. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create audio session failed! rc = %d", rc);
  313. return;
  314. }
  315. }
  316. if (call->video) {
  317. video_session_destroy(call->video);
  318. call->video = NULL;
  319. }
  320. int i = 0;
  321. int remote_width = video_desc->param[i++];
  322. int remote_height = video_desc->param[i++];
  323. video_session_conf_t video_conf = {0};
  324. video_conf.bit_rate = 256 * 1024;
  325. video_conf.local_rtp_ip = video_desc->local_ip;
  326. video_conf.local_rtp_port = video_desc->local_port;
  327. video_conf.mtu = ep_conf->mtu;
  328. video_conf.video_quant = ep_conf->quant;
  329. video_conf.remote_rtp_ip = video_desc->remote_ip;
  330. video_conf.remote_rtp_port = video_desc->remote_port;
  331. video_conf.remote_video_width = remote_width;
  332. video_conf.remote_video_height = remote_height;
  333. video_conf.ref_active_camera = call->ep->conf.ref_active_camera;
  334. video_conf.ref_camera_switch = call->ep->conf.ref_camera_switch;
  335. video_conf.ref_camera_state = call->ep->conf.ref_camera_state;
  336. video_conf.ref_window_state = call->ep->conf.ref_window_state;
  337. video_conf.ref_Is_showPersonArea = call->ep->conf.ref_Is_showPersonArea;
  338. video_conf.ref_active_img = NULL;
  339. video_conf.ref_Is_ActiveInspect = NULL;
  340. video_conf.camera_count = call->ep->conf.camera_count;
  341. video_conf.screen_count = call->ep->conf.screen_count;
  342. video_conf.ref_Up_Fps = call->ep->conf.ref_Up_Fps;
  343. video_conf.eDeviceType = call->eDeviceType;
  344. video_conf.nCallType = call->nCallType;
  345. memcpy(&video_conf.video_render_cb, cb, sizeof(rvc_video_render_callback_t));
  346. video_conf.ilocal_wind_flags = VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP;
  347. video_conf.iremote_wind_flags = VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP;
  348. video_conf.local_pt = REC_COMMON_VIDEO_H264_PT;
  349. video_conf.remote_pt = REC_COMMON_VIDEO_H264_PT;
  350. rc = video_session_create(&video_conf, &call->video);
  351. if (rc != 0) {
  352. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create video session failed! rc = %d", rc);
  353. return;
  354. }
  355. rc = video_session_start(call->video);
  356. if (rc != 0) {
  357. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("start video session failed! rc = %d", rc);
  358. video_session_destroy(call->video);
  359. call->video = NULL;
  360. return;
  361. }
  362. }
  363. }
  364. #endif
  365. static void endpoint_media_update_audio(endpoint_call_t *call, media_desc_t *audio_desc, int dev_type)
  366. {
  367. if (audio_desc->media_dir == DIR_NONE) {
  368. if (call->audio) {
  369. audio_session_stop(call->audio);
  370. audio_session_destroy(call->audio);
  371. call->audio = NULL;
  372. }
  373. else{
  374. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("call->audio is null.");
  375. }
  376. if (call->video) { // close video also
  377. video_session_stop(call->video);
  378. video_session_destroy(call->video);
  379. call->video = NULL;
  380. }
  381. else{
  382. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("call->video is null.");
  383. #ifdef RVC_OS_WIN
  384. if (DOUBLERECORD_CALLTYPE == call->nCallType){
  385. double_record_broadcast_video_session_stop();
  386. }
  387. #endif
  388. }
  389. } else {
  390. int rc;
  391. if (call->audio) {
  392. audio_session_stop(call->audio);
  393. audio_session_destroy(call->audio);
  394. call->audio = NULL;
  395. }
  396. if (!call->audio) {
  397. endpoint_conf_t *ep_conf = &call->ep->conf;
  398. audio_session_conf_t conf = {0};
  399. strcpy(&conf.in_dev[DEV_PICKUP][0], ep_conf->audio_pickup_in_dev);
  400. strcpy(&conf.in_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_in_dev);
  401. strcpy(&conf.out_dev[DEV_PICKUP][0], ep_conf->audio_pickup_out_dev);
  402. strcpy(&conf.out_dev[DEV_HANDFREE][0], ep_conf->audio_handfree_out_dev);
  403. conf.agc_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_agc;
  404. conf.agc_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_agc;
  405. conf.agc_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_agc;
  406. conf.agc_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_agc;
  407. conf.ns_in[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_in_ns;
  408. conf.ns_in[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_in_ns;
  409. conf.ns_out[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_out_ns;
  410. conf.ns_out[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_out_ns;
  411. conf.aec[DEV_PICKUP] = !!ep_conf->audio_dsp.audio_pickup_aec;
  412. conf.aec[DEV_HANDFREE] = !!ep_conf->audio_dsp.audio_handfree_aec;
  413. rc = audio_session_create(&conf, &call->audio);
  414. if (rc != 0) {
  415. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create audio session failed! rc = %d", rc);
  416. return;
  417. }
  418. }
  419. audio_session_phonemedia_conf_t phone_conf = {0};
  420. phone_conf.dir = audio_desc->media_dir;
  421. phone_conf.dev_type = (e_dev_type)dev_type;
  422. phone_conf.local_dtmf_pt = audio_desc->local_telephone_event_pt;
  423. phone_conf.local_pt = audio_desc->local_pt;
  424. phone_conf.local_ptime = audio_desc->local_ptime;
  425. phone_conf.local_rtp_ip = audio_desc->local_ip;
  426. phone_conf.local_rtp_port = audio_desc->local_port;
  427. phone_conf.remote_dtmf_pt = audio_desc->remote_telephone_event_pt;
  428. phone_conf.remote_pt = audio_desc->remote_pt;
  429. phone_conf.remote_ptime = audio_desc->remote_ptime;
  430. phone_conf.remote_rtp_ip = audio_desc->remote_ip;
  431. phone_conf.remote_rtp_port = audio_desc->remote_port;
  432. if (NULL != call){
  433. phone_conf.eCalltype = call->nCallType;
  434. phone_conf.eDeviceType = call->eDeviceType;
  435. }
  436. rc = audio_session_start_phonemedia(call->audio, &phone_conf);
  437. if (rc != 0)
  438. {
  439. LogWarn(Severity_Middle, Error_Debug, ERROR_MOD_SIP_AUDIO_INITFAIL, CSimpleStringA::Format("start audio session failed! rc = %d.", rc).GetData());
  440. audio_session_destroy(call->audio);
  441. call->audio = NULL;
  442. return;
  443. }
  444. }
  445. }
  446. static unsigned int __hash_media_desc(media_desc_t *media_desc, unsigned int hash_code)
  447. {
  448. if (media_desc) {
  449. hash_code += (unsigned int)media_desc->local_ip * 33;
  450. hash_code += (unsigned int)media_desc->remote_ip * 33;
  451. hash_code += (unsigned int)media_desc->local_port * 33;
  452. hash_code += (unsigned int)media_desc->remote_port * 33;
  453. hash_code += (unsigned int)media_desc->media_dir * 33;
  454. hash_code += (unsigned int)media_desc->local_pt * 33;
  455. hash_code += (unsigned int)media_desc->local_ptime * 33;
  456. hash_code += (unsigned int)media_desc->remote_pt * 33;
  457. hash_code += (unsigned int)media_desc->remote_ptime * 33;
  458. hash_code += (unsigned int)media_desc->local_telephone_event_pt * 33;
  459. hash_code += (unsigned int)media_desc->remote_telephone_event_pt * 33;
  460. }
  461. return hash_code;
  462. }
  463. static unsigned int hash_media_desc(media_desc_t *audio)
  464. {
  465. unsigned int hash_code = 0;
  466. hash_code = __hash_media_desc(audio, hash_code);
  467. return hash_code;
  468. }
  469. #define USE_ALAW 1
  470. static const char *call_make_offer(endpoint_call_t *call, char *buf, int size)
  471. {
  472. int local_audio_rtp_port = call->local_media_port;
  473. int local_video_rtp_port = call->local_video_port;
  474. int local_video_pt = REC_COMMON_VIDEO_PT;
  475. int need;
  476. const char *fmt;
  477. {
  478. fmt =
  479. "c=IN IP4 %s\r\n"
  480. #ifdef USE_ALAW
  481. "m=audio %d RTP/AVP 8\r\n"
  482. "a=rtpmap:8 PCMA/8000\r\n"
  483. "a=ptime:30\r\n"
  484. #elif defined(USE_G729)
  485. "m=audio %d RTP/AVP 18\r\n"
  486. "a=rtpmap:18 G729/8000\r\n"
  487. "a=fmtp:18 annexb=no\r\n"
  488. "a=ptime:30\r\n"
  489. #endif
  490. //"a=rtpmap:97 telephone-event/8000\r\n"
  491. //"a=fmtp:97 0-15\r\n"
  492. #ifdef USE_H263_VIDEO
  493. "m=video %d RTP/AVP 34\r\n"
  494. "a=rtpmap:34 H263/90000\r\n"
  495. "a=fmtp:34 QCIF=2 MaxBR=5040\r\n"
  496. #endif
  497. //"a=inactive\r\n" //for debug only
  498. ;
  499. }
  500. need = _scprintf(fmt, call->local_ip, local_audio_rtp_port);
  501. if (size < 0 || size > need) {
  502. sprintf(buf, fmt, call->local_ip, local_audio_rtp_port);
  503. return buf;
  504. } else {
  505. return NULL;
  506. }
  507. }
  508. static int new_call_id(endpoint_t *ep)
  509. {
  510. return ++ep->call_seq;
  511. }
  512. int new_media_port(endpoint_t *ep)
  513. {
  514. ep->media_port_seq += 2;
  515. if (ep->media_port_seq >= ep->conf.media_stop_port) {
  516. ep->media_port_seq = ep->conf.media_start_port;
  517. }
  518. return ep->media_port_seq;
  519. }
  520. static void handle_invite(CONDITION_PARAMS)
  521. {
  522. // we are client only, not accept in-comming call
  523. nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
  524. }
  525. static void handle_reinvite(CONDITION_PARAMS)
  526. {
  527. char sdp[512] = {0};
  528. sip_content_type_t const *ct = NULL;
  529. tl_gets(tags,
  530. SIPTAG_CONTENT_TYPE_REF(ct),
  531. TAG_END());
  532. if (ct) {
  533. call_make_offer(call, sdp, sizeof(sdp));
  534. }
  535. nua_respond(nh,
  536. SIP_200_OK,
  537. TAG_IF(ct, SOATAG_USER_SDP_STR(sdp)),
  538. TAG_IF(ct, SOATAG_AUDIO_AUX("telephone-event")),
  539. TAG_END());
  540. }
  541. static void handle_r_invite(CONDITION_PARAMS)
  542. {
  543. // nothing to do
  544. }
  545. static int dir_from_attr(const sdp_media_t *m)
  546. {
  547. int dir = DIR_NONE;
  548. if (m) {
  549. if (m->m_attributes) {
  550. static const char *ds[] = {
  551. "inactive", "sendonly", "recvonly", "sendrecv"
  552. };
  553. int i;
  554. int n = array_size(ds);
  555. for (i = 0; i < n; ++i) {
  556. sdp_attribute_t *attr = sdp_attribute_find(m->m_attributes, ds[i]);
  557. if (attr) {
  558. dir = i;
  559. break;
  560. }
  561. }
  562. if (i >= n)
  563. dir = DIR_BOTH;
  564. } else {
  565. dir = DIR_BOTH;
  566. }
  567. }
  568. return dir;
  569. }
  570. static int ptime_from_attr(const sdp_media_t *m)
  571. {
  572. int ptime = 0; // zero for default
  573. if (m) {
  574. if (m->m_attributes) {
  575. sdp_attribute_t *attr = sdp_attribute_find(m->m_attributes, "ptime");
  576. if (attr && attr->a_value) {
  577. ptime = atoi(attr->a_value);
  578. if (ptime < 0)
  579. ptime = 0;
  580. }
  581. }
  582. }
  583. return ptime;
  584. }
  585. static const sdp_rtpmap_t *find_codec(const sdp_rtpmap_t *list, const char *codec)
  586. {
  587. if (!codec)
  588. return NULL;
  589. for (;list; list=list->rm_next) {
  590. if (!_stricmp(list->rm_encoding, codec)) {
  591. break;
  592. }
  593. }
  594. return list;
  595. }
  596. static int get_telephone_event_pt(const sdp_rtpmap_t *list)
  597. {
  598. int pt = -1;
  599. const sdp_rtpmap_t *rm = find_codec(list, "telephone-event");
  600. if (rm) {
  601. pt = rm->rm_pt;
  602. }
  603. return pt;
  604. }
  605. static int get_media_direction(const sdp_media_t *lm, const sdp_media_t *rm)
  606. {
  607. int media_dir = DIR_NONE;
  608. if (rm->m_port == 0 || lm->m_port == 0) {
  609. media_dir = DIR_NONE;
  610. } else {
  611. int ldir = dir_from_attr(lm);
  612. int rdir = dir_from_attr(rm);
  613. if (ldir == DIR_NONE || rdir == DIR_NONE) {
  614. media_dir = DIR_NONE;
  615. } else if (ldir == DIR_TX || rdir == DIR_RX) {
  616. media_dir = DIR_TX;
  617. } else if (ldir == DIR_RX || rdir == DIR_TX) {
  618. media_dir = DIR_RX;
  619. } else {
  620. media_dir = DIR_BOTH;
  621. }
  622. }
  623. return media_dir;
  624. }
  625. static int negotiate_audio(endpoint_call_t *call, media_desc_t *audio_desc, const sdp_media_t *lm, const sdp_media_t *rm)
  626. {
  627. memset(audio_desc, 0, sizeof(media_desc_t));
  628. const char *local_ip;
  629. const char *remote_ip;
  630. local_ip = lm->m_connections ? lm->m_connections->c_address : lm->m_session->sdp_connection->c_address;
  631. remote_ip = rm->m_connections ? rm->m_connections->c_address : rm->m_session->sdp_connection->c_address;
  632. audio_desc->local_ip = strlen(call->local_ip) ? inet_addr(call->local_ip) : 0;
  633. audio_desc->local_port = call->local_media_port;
  634. audio_desc->remote_ip = remote_ip ? inet_addr(remote_ip) : 0;
  635. audio_desc->remote_port = rm->m_port;
  636. audio_desc->local_telephone_event_pt = 97;
  637. audio_desc->remote_telephone_event_pt = get_telephone_event_pt(rm->m_rtpmaps);
  638. audio_desc->local_ptime = ptime_from_attr(lm);
  639. audio_desc->remote_ptime = ptime_from_attr(rm);
  640. int pt = -1;
  641. for (sdp_rtpmap_t *t = lm->m_rtpmaps; t; t = t->rm_next) {
  642. sdp_rtpmap_t *tt = sdp_rtpmap_find_matching(rm->m_rtpmaps, t);
  643. if (tt && tt->rm_pt < 96) {
  644. pt = tt->rm_pt;
  645. break;
  646. }
  647. }
  648. audio_desc->local_pt = audio_desc->remote_pt = pt;
  649. audio_desc->media_dir = get_media_direction(lm, rm);
  650. return 0;
  651. }
  652. static int negotiate_video(endpoint_call_t *call, media_desc_t *video_desc, const sdp_media_t *lm, const sdp_media_t *rm)
  653. {
  654. memset(video_desc, 0, sizeof(media_desc_t));
  655. const char *local_ip;
  656. const char *remote_ip;
  657. local_ip = lm->m_connections ? lm->m_connections->c_address : lm->m_session->sdp_connection->c_address;
  658. remote_ip = rm->m_connections ? rm->m_connections->c_address : rm->m_session->sdp_connection->c_address;
  659. video_desc->local_ip = strlen(call->local_ip) ? inet_addr(call->local_ip) : 0;
  660. video_desc->local_port = call->local_video_port;
  661. video_desc->remote_ip = remote_ip ? inet_addr(remote_ip) : 0;
  662. video_desc->remote_port = rm->m_port;
  663. video_desc->local_telephone_event_pt = 97;
  664. video_desc->remote_telephone_event_pt = get_telephone_event_pt(rm->m_rtpmaps);
  665. video_desc->local_ptime = ptime_from_attr(lm);
  666. video_desc->remote_ptime = ptime_from_attr(rm);
  667. int pt = -1;
  668. for (sdp_rtpmap_t *t = lm->m_rtpmaps; t; t = t->rm_next) {
  669. sdp_rtpmap_t *tt = sdp_rtpmap_find_matching(rm->m_rtpmaps, t);
  670. if (tt) {
  671. pt = tt->rm_pt;
  672. break;
  673. }
  674. }
  675. video_desc->local_pt = video_desc->remote_pt = pt;
  676. video_desc->media_dir = get_media_direction(lm, rm);
  677. return 0;
  678. }
  679. static void negotiate_sdp(endpoint_call_t *call, const sdp_session_t *local_sdp, const sdp_session_t* remote_sdp)
  680. {
  681. const sdp_media_t *lm = local_sdp->sdp_media;
  682. const sdp_media_t *rm = remote_sdp->sdp_media;
  683. media_desc_t audio_desc = {0}, video_desc = {0};
  684. int rc = -1, rv = -1;
  685. for(; lm; lm = lm->m_next)
  686. {
  687. if (0 == lm->m_port)
  688. {
  689. continue;
  690. }
  691. const sdp_media_t *rm = remote_sdp->sdp_media;
  692. for (; rm; rm = rm->m_next)
  693. {
  694. if (rm->m_type == lm->m_type)
  695. {
  696. if (sdp_media_audio == rm->m_type)
  697. {
  698. rc = negotiate_audio(call, &audio_desc, lm, rm);
  699. }
  700. if (call->nCallType != NORMAL_CALLTYPE && call->nCallType != DOUBLERECORD_CALLTYPE)
  701. {
  702. if (sdp_media_video == rm->m_type)
  703. {
  704. rv = negotiate_video(call, &video_desc, lm, rm);
  705. }
  706. }
  707. }
  708. }
  709. }
  710. if (rc == 0)
  711. {
  712. unsigned int hash_code = hash_media_desc(&audio_desc);
  713. if (hash_code != call->last_media_desc_hash)
  714. {
  715. endpoint_media_update_audio(call, &audio_desc, call->ep->curr_audio_dev_type);
  716. call->last_media_desc_hash = hash_code;
  717. //char strmsg[MAX_PATH] = {0};
  718. //snprintf(strmsg, MAX_PATH, "negotiate audio success!local audio ip=%s port=%d pt=%d,remote audio ip=%s port=%d,pt=%d",str_local,audio_desc.local_port,audio_desc.local_pt,str_remote,audio_desc.remote_port,audio_desc.remote_pt);
  719. //LogWarn(Severity_Low, Error_Debug, EVENT_MOD_SIP_CALL_AUDIO_NEGOTIATE, strmsg);
  720. }
  721. }
  722. if (rv == 0)
  723. {
  724. unsigned int hash_code = hash_media_desc(&video_desc);
  725. if (hash_code != call->last_media_desc_hash)
  726. {
  727. call->sdpvieo_desc.local_pt = video_desc.local_pt;
  728. call->sdpvieo_desc.local_rtp_ip = video_desc.local_ip;
  729. call->sdpvieo_desc.local_rtp_port = video_desc.local_port;
  730. call->sdpvieo_desc.remote_pt = video_desc.remote_pt;
  731. call->sdpvieo_desc.remote_rtp_ip = video_desc.remote_ip;
  732. call->sdpvieo_desc.remote_rtp_port = video_desc.remote_port;
  733. call->last_media_desc_hash = hash_code;
  734. //char strmsg[MAX_PATH] = {0};
  735. //_snprintf(strmsg, MAX_PATH, "negotiate video success!local video ip=%s port=%d pt=%d,remote video ip=%s port=%d pt=%d",str_local,video_desc.local_port,video_desc.local_pt,str_remote,video_desc.remote_port,video_desc.remote_pt);
  736. //LogWarn(Severity_Low, Error_Debug, EVENT_MOD_SIP_CALL_VIDEO_NEGOTIATE, strmsg);
  737. }
  738. }
  739. else
  740. {
  741. if (call->nCallType != NORMAL_CALLTYPE && call->nCallType != DOUBLERECORD_CALLTYPE)
  742. {
  743. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("negotiate video Fail!!!");
  744. }
  745. }
  746. }
  747. static void on_state(CONDITION_PARAMS)
  748. {
  749. int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0;
  750. int state = nua_callstate_init;
  751. const char *replaces_str = NULL;
  752. const sdp_session_t *remote_sdp = NULL;
  753. const char *remote_sdp_str = NULL;
  754. const sdp_session_t *local_sdp = NULL;
  755. const char *local_sdp_str = NULL;
  756. int st;
  757. if (!call) {
  758. nua_handle_destroy(nh);
  759. return;
  760. }
  761. if (g_IsExternalTerminalted)
  762. {
  763. return;
  764. }
  765. tl_gets(tags,
  766. NUTAG_CALLSTATE_REF(state),
  767. NUTAG_OFFER_RECV_REF(offer_recv),
  768. NUTAG_ANSWER_RECV_REF(answer_recv),
  769. NUTAG_OFFER_SENT_REF(offer_sent),
  770. NUTAG_ANSWER_SENT_REF(answer_sent),
  771. SIPTAG_REPLACES_STR_REF(replaces_str),
  772. SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str),
  773. SOATAG_LOCAL_SDP_STR_REF(local_sdp_str),
  774. TAG_END());
  775. switch (state)
  776. {
  777. case nua_callstate_calling:
  778. {
  779. if (local_sdp_str) {
  780. sdp_parser_t* parser = sdp_parse(call->home, local_sdp_str, strlen(local_sdp_str), -1);
  781. assert(call->last_sdp == NULL);
  782. call->last_sdp = sdp_session_dup(call->home, sdp_session(parser));
  783. sdp_parser_free(parser);
  784. }
  785. st = CALLING;
  786. call->cb.on_call_state(st, state_desc[st], phrase, call->cb.user_data);
  787. }
  788. break;
  789. case nua_callstate_proceeding:
  790. {
  791. st = PROCEEDING;
  792. call->cb.on_call_state(st, state_desc[st], phrase, call->cb.user_data);
  793. if (remote_sdp_str) {
  794. sdp_parser_t* parser = sdp_parse(call->home, remote_sdp_str, strlen(remote_sdp_str), -1);
  795. remote_sdp = sdp_session(parser);
  796. if (call->last_sdp) {
  797. negotiate_sdp(call, call->last_sdp, remote_sdp);
  798. su_free(call->home, call->last_sdp);
  799. call->last_sdp = NULL;
  800. }
  801. sdp_parser_free(parser);
  802. }
  803. }
  804. break;
  805. case nua_callstate_completing:
  806. {
  807. st = COMPLETING;
  808. call->cb.on_call_state(st, state_desc[st], phrase, call->cb.user_data);
  809. if (remote_sdp_str) {
  810. sdp_parser_t* parser = sdp_parse(call->home, remote_sdp_str, strlen(remote_sdp_str), -1);
  811. remote_sdp = sdp_session(parser);
  812. if (call->last_sdp) {
  813. negotiate_sdp(call, call->last_sdp, remote_sdp);
  814. su_free(call->home, call->last_sdp);
  815. call->last_sdp = NULL;
  816. }
  817. sdp_parser_free(parser);
  818. }
  819. }
  820. break;
  821. case nua_callstate_completed:
  822. {
  823. if (remote_sdp_str) {
  824. if (!call->last_sdp) {
  825. sdp_parser_t* parser = sdp_parse(call->home, remote_sdp_str, strlen(remote_sdp_str), -1);
  826. call->last_sdp = sdp_session_dup(call->home, sdp_session(parser));
  827. sdp_parser_free(parser);
  828. }
  829. }
  830. if (local_sdp_str) {
  831. if (call->last_sdp) {
  832. sdp_parser_t* parser = sdp_parse(call->home, local_sdp_str, strlen(local_sdp_str), -1);
  833. local_sdp = sdp_session(parser);
  834. negotiate_sdp(call, local_sdp, call->last_sdp);
  835. su_free(call->home, call->last_sdp);
  836. call->last_sdp = NULL;
  837. sdp_parser_free(parser);
  838. }
  839. }
  840. }
  841. break;
  842. case nua_callstate_ready:
  843. {
  844. call->connected = true;
  845. st = READY;
  846. call->cb.on_call_state(st, state_desc[st], phrase, call->cb.user_data);
  847. if (remote_sdp_str) {
  848. sdp_parser_t* parser = sdp_parse(call->home, remote_sdp_str, strlen(remote_sdp_str), -1);
  849. remote_sdp = sdp_session(parser);
  850. if (call->last_sdp) {
  851. negotiate_sdp(call, call->last_sdp, remote_sdp);
  852. su_free(call->home, call->last_sdp);
  853. call->last_sdp = NULL;
  854. }
  855. sdp_parser_free(parser);
  856. }
  857. #if 0
  858. if (remote_sdp_str) {
  859. sdp_parser_t* parser = sdp_parse(call->home, remote_sdp_str, strlen(remote_sdp_str), -1);
  860. remote_sdp = sdp_session(parser);
  861. negotiate_sdp(call, call->last_sdp, remote_sdp);
  862. sdp_parser_free(parser);
  863. }
  864. else if (local_sdp_str) {
  865. sdp_parser_t* parser = sdp_parse(call->home, local_sdp_str, strlen(local_sdp_str), -1);
  866. local_sdp = sdp_session(parser);
  867. negotiate_sdp(call, local_sdp, call->last_sdp);
  868. sdp_parser_free(parser);
  869. }
  870. #endif
  871. }
  872. break;
  873. case nua_callstate_terminated:
  874. {
  875. st = TERMINATED;
  876. {
  877. media_desc_t audio_desc = { 0 };
  878. audio_desc.media_dir = DIR_NONE;
  879. endpoint_media_update_audio(call, &audio_desc, call->ep->curr_audio_dev_type);
  880. }
  881. call->cb.on_call_state(st, state_desc[st], phrase, call->cb.user_data);
  882. nua_handle_bind(nh, NULL);
  883. nua_handle_destroy(nh);
  884. call->nh = NULL;
  885. }
  886. break;
  887. default:
  888. break;
  889. }
  890. }
  891. void terminatedcall(endpoint_call_t *call)
  892. {
  893. int st = TERMINATED;
  894. g_IsExternalTerminalted = true;
  895. {
  896. media_desc_t audio_desc = {0};
  897. audio_desc.media_dir = DIR_NONE;
  898. endpoint_media_update_audio(call, &audio_desc, call->ep->curr_audio_dev_type);
  899. }
  900. }
  901. static void endpoint_callback(nua_event_t event,
  902. int status,
  903. char const *phrase,
  904. nua_t *nua,
  905. nua_magic_t *magic,
  906. nua_handle_t *nh,
  907. nua_hmagic_t *hmagic,
  908. sip_t const *sip,
  909. tagi_t tags[])
  910. {
  911. switch (event)
  912. {
  913. if (!g_IsExternalTerminalted)
  914. {
  915. case nua_i_invite:
  916. if (hmagic == NULL) {
  917. handle_invite(status, phrase, nua, (endpoint_t*)magic, nh, (endpoint_call_t*)hmagic, sip, tags);
  918. } else {
  919. handle_reinvite(status, phrase, nua, (endpoint_t*)magic, nh, (endpoint_call_t*)hmagic, sip, tags);
  920. }
  921. break;
  922. case nua_r_invite:
  923. handle_r_invite(status, phrase, nua, (endpoint_t*)magic, nh, (endpoint_call_t*)hmagic, sip, tags);
  924. break;
  925. case nua_i_bye:
  926. //.....
  927. break;
  928. case nua_i_info:
  929. break;
  930. case nua_i_state:
  931. on_state(status, phrase, nua, (endpoint_t*)magic, nh, (endpoint_call_t*)hmagic, sip, tags);
  932. break;
  933. case nua_i_active:
  934. break;
  935. case nua_i_options:
  936. //nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), SOATAG_USER_SDP_STR(NULL), TAG_END());
  937. nua_respond(nh, SIP_200_OK, TAG_END());
  938. break;
  939. case nua_r_cancel:
  940. if (status > 300) {
  941. nua_bye(nh, TAG_END());
  942. }
  943. break;
  944. case nua_i_prack:
  945. case nua_r_prack:
  946. break;
  947. case nua_r_bye:
  948. //LOG_TRACE("nua_r_bye");
  949. if (status > 300) {
  950. nua_bye(nh, TAG_END());
  951. }
  952. break;
  953. /* and so on ... */
  954. default:
  955. if (status > 100) { /* unknown event -> print out error message */
  956. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unknown event %d: %03d %s.",
  957. event,
  958. status,
  959. phrase);
  960. } else {
  961. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unknown event %d.", event);
  962. }
  963. break;
  964. }
  965. }
  966. if (!hmagic)
  967. {
  968. nua_handle_destroy(nh);
  969. return;
  970. }
  971. }
  972. #ifdef RVC_OS_WIN
  973. static unsigned int __stdcall __event_thread(void* arg)
  974. #else
  975. void* __event_thread(void* arg)
  976. #endif
  977. {
  978. endpoint_t *ep = (endpoint_t *)arg;
  979. ep->entity->GetFunction()->InitLogCurrentThread();
  980. #ifdef RVC_OS_WIN
  981. CoInitialize(NULL);
  982. #else
  983. #endif // RVC_OS_WIN
  984. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("enter event_thread.");
  985. ep->root = su_root_create(ep);
  986. ep->nua = nua_create(ep->root,
  987. &endpoint_callback,
  988. ep,
  989. NUTAG_URL(ep->conf.uri),
  990. TAG_END());
  991. nua_set_params(ep->nua,
  992. SIPTAG_ALLOW_STR("INVITE,CANCEL,BYE,ACK,INFO,OPTIONS"),
  993. NUTAG_AUTOALERT(1),
  994. NUTAG_ALLOW("PRACK"),
  995. NUTAG_EARLY_MEDIA(1),
  996. NUTAG_SESSION_TIMER(1),
  997. NUTAG_AUTOANSWER(0),
  998. NUTAG_AUTOACK(1),
  999. NTATAG_SIP_T1X64(8000),
  1000. TAG_NULL());
  1001. su_root_run(ep->root);
  1002. nua_shutdown(ep->nua);
  1003. ep->nua = NULL;
  1004. su_root_destroy(ep->root);
  1005. ep->root = NULL;
  1006. #ifdef RVC_OS_WIN
  1007. CoUninitialize();
  1008. #else
  1009. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("leave event_thread.");
  1010. #endif // RVC_OS_WIN
  1011. return 0;
  1012. }
  1013. static int __endpoint_break(void *arg)
  1014. {
  1015. endpoint_t *ep = (endpoint_t *)arg;
  1016. //.....nua_shutdown
  1017. su_root_break(ep->root);
  1018. return 0;
  1019. }
  1020. #ifdef RVC_OS_WIN
  1021. #else
  1022. unsigned long GetTickCount()
  1023. {
  1024. struct timespec ts;
  1025. clock_gettime(CLOCK_MONOTONIC, &ts);
  1026. return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
  1027. }
  1028. #endif
  1029. static endpoint_t *__endpoint_create(CEntityBase *pEntity, const endpoint_conf_t *conf,int nDev)
  1030. {
  1031. endpoint_t *ep;
  1032. ep = ZALLOC_T(endpoint_t);
  1033. su_home_init(ep->home);
  1034. memcpy(&ep->conf, conf, sizeof(endpoint_conf_t));
  1035. ep->media_port_seq = (conf->media_start_port + (GetTickCount() % (conf->media_stop_port - conf->media_start_port))) & 0xfffc;
  1036. ep->entity = pEntity;
  1037. ep->call_seq = GetTickCount();
  1038. ep->curr_audio_dev_type = nDev;
  1039. INIT_LIST_HEAD(&ep->call_list);
  1040. return ep;
  1041. }
  1042. static void __endpoint_destroy(endpoint_t *ep)
  1043. {
  1044. su_root_destroy(ep->root);
  1045. su_home_deinit(ep->home);
  1046. free(ep);
  1047. }
  1048. static int __endpoint_start(endpoint_t *ep)
  1049. {
  1050. #ifdef RVC_OS_WIN
  1051. ep->event_thread = (HANDLE)_beginthreadex(NULL, 0, &__event_thread, ep, 0, NULL);
  1052. if (ep->event_thread)
  1053. {
  1054. while (!ep->root)
  1055. {
  1056. DWORD dwRet = WaitForSingleObject(ep->event_thread, 1);
  1057. if (dwRet == WAIT_OBJECT_0)
  1058. {
  1059. CloseHandle(ep->event_thread);
  1060. ep->event_thread = NULL;
  1061. break;
  1062. }
  1063. }
  1064. }
  1065. return ep->event_thread ? 0 : -1;
  1066. #else
  1067. //pthread_attr_t attr;
  1068. //pthread_attr_init(&attr);
  1069. //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  1070. int err = pthread_create(&ep->ievent_threadid, NULL, __event_thread, ep);
  1071. //pthread_attr_destroy(&attr);
  1072. if (0 == err) {
  1073. while (!ep->root) {
  1074. struct timespec ts;
  1075. clock_gettime(CLOCK_REALTIME, &ts);
  1076. long unsec = ts.tv_nsec + (1000 * 1000);
  1077. ts.tv_sec += (unsec / 1000000000);
  1078. ts.tv_nsec = (unsec % 1000000000);
  1079. if (0 == pthread_timedjoin_np(ep->ievent_threadid, NULL, &ts)) {
  1080. ep->ievent_threadid = 0;
  1081. break;
  1082. }
  1083. }
  1084. }
  1085. else {
  1086. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create event thread failed.");
  1087. }
  1088. return ep->ievent_threadid > 0 ? 0 : -1;
  1089. #endif
  1090. }
  1091. static void __endpoint_stop(endpoint_t *ep)
  1092. {
  1093. #ifdef RVC_OS_WIN
  1094. if (ep->event_thread)
  1095. {
  1096. int rc;
  1097. su_task_execute(su_root_task(ep->root), &__endpoint_break, ep, &rc);
  1098. WaitForSingleObject(ep->event_thread, INFINITE);
  1099. CloseHandle(ep->event_thread);
  1100. ep->event_thread = NULL;
  1101. }
  1102. #else
  1103. if (ep->ievent_threadid > 0)
  1104. {
  1105. int rc;
  1106. su_task_execute(su_root_task(ep->root), &__endpoint_break, ep, &rc);
  1107. if (0 == pthread_join(ep->ievent_threadid, NULL)) {
  1108. ep->ievent_threadid = 0;
  1109. }
  1110. else {
  1111. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("pthread join error for %s", strerror(errno));
  1112. }
  1113. }
  1114. #endif
  1115. }
  1116. static void rvc_sofia_logger(void* stream, char const* fmt, va_list ap) {
  1117. if (!fmt)
  1118. return;
  1119. char line[255];
  1120. vsnprintf(line, sizeof(line), fmt, ap);
  1121. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("rvc_sofia_logger : %s", line);
  1122. }
  1123. int endpoint_init_lib()
  1124. {
  1125. int result = su_init();
  1126. //su_log_set_level(NULL, 9);
  1127. //su_log_redirect(NULL, rvc_sofia_logger, NULL);
  1128. return result;
  1129. }
  1130. void endpoint_deinit_lib()
  1131. {
  1132. su_deinit();
  1133. }
  1134. endpoint_t *endpoint_create(CEntityBase *pEntity, const endpoint_conf_t *conf,int nDev)
  1135. {
  1136. endpoint_t *endpt;
  1137. endpt = __endpoint_create(pEntity, conf,nDev);
  1138. if (endpt) {
  1139. int rc = __endpoint_start(endpt);
  1140. if (rc != 0)
  1141. {
  1142. __endpoint_destroy(endpt);
  1143. endpt = NULL;
  1144. }
  1145. }
  1146. return endpt;
  1147. }
  1148. void endpoint_destroy(endpoint_t *ep)
  1149. {
  1150. if (ep)
  1151. {
  1152. __endpoint_stop(ep);
  1153. __endpoint_destroy(ep);
  1154. }
  1155. }
  1156. int endpoint_invoke(endpoint_t *ep, int (*func)(void*), void *user_data, int *result)
  1157. {
  1158. if (ep){
  1159. return su_task_execute(su_root_task(ep->root), func, user_data, result);
  1160. }
  1161. else
  1162. {
  1163. *result = Error_Param;
  1164. return -1;
  1165. }
  1166. }
  1167. void endpoint_change_audio_dev(endpoint_t *ep, int dev_type)
  1168. {
  1169. if (ep){
  1170. if (ep->curr_audio_dev_type != dev_type) {
  1171. ep->curr_audio_dev_type = dev_type;
  1172. if (ep->active_call) {
  1173. endpoint_media_change_audio_dev(ep->active_call, (e_dev_type)dev_type);
  1174. } else {
  1175. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("active call is null!");
  1176. }
  1177. }
  1178. }
  1179. }
  1180. endpoint_call_t *endpoint_call_create(endpoint_t *ep, const endpoint_call_params_t* pcallparam, const endpoint_call_callback_t *cb)
  1181. {
  1182. endpoint_call_t *call = NULL;
  1183. su_home_t *home = NULL;
  1184. if (!pcallparam || !pcallparam->to_uri){
  1185. return NULL;
  1186. }
  1187. home = su_home_create();
  1188. if (!home){
  1189. goto on_error;
  1190. }
  1191. call = (endpoint_call_t*)su_home_new(sizeof(endpoint_call_t));
  1192. if (!call){
  1193. goto on_error;
  1194. }
  1195. memset(call, 0, sizeof(endpoint_call_t));
  1196. call->connected = 0;
  1197. call->ep = ep;
  1198. call->home = home;
  1199. call->last_media_desc_hash = 0;
  1200. call->to_uri = su_strdup(home, pcallparam->to_uri);
  1201. if (pcallparam->from_uri != NULL){
  1202. call->from_uri = su_strdup(home, pcallparam->from_uri);
  1203. }
  1204. if (pcallparam->call_id != NULL){
  1205. call->call_id = su_strdup(home, pcallparam->call_id);
  1206. }
  1207. if (NULL != pcallparam->local_ip){
  1208. _snprintf(call->local_ip, RVC_MAX_IP_LEN, "%s", pcallparam->local_ip);
  1209. }
  1210. call->eDeviceType = pcallparam->nDeviceType;
  1211. call->nCallType = pcallparam->nCallType;
  1212. memcpy(&call->cb, cb, sizeof(endpoint_call_callback_t));
  1213. call->id = new_call_id(ep);
  1214. call->local_media_port = pcallparam->ilocal_audio_port;
  1215. call->local_video_port = pcallparam->ilocal_video_port;
  1216. REF_COUNT_INIT(&call->ref_cnt);
  1217. list_add_tail(&call->entry, &ep->call_list);
  1218. ep->active_call = call;
  1219. return call;
  1220. on_error:
  1221. if (home)
  1222. su_home_unref(home);
  1223. return call;
  1224. }
  1225. void endpoint_call_destroy(endpoint_call_t *call)
  1226. {
  1227. endpoint_call_dec_ref(call);
  1228. }
  1229. int endpoint_call_start(endpoint_call_t *call)
  1230. {
  1231. char sdp[512] = {0};
  1232. if (call->nh)
  1233. return -1;
  1234. if (call->from_uri != NULL && call->call_id != NULL){
  1235. call->nh = nua_handle(call->ep->nua,
  1236. call,
  1237. SIPTAG_CALL_ID_STR(call->call_id),
  1238. SIPTAG_FROM_STR(call->from_uri),
  1239. SIPTAG_TO_STR(call->to_uri),
  1240. TAG_END());
  1241. } else if (call->from_uri != NULL){
  1242. call->nh = nua_handle(call->ep->nua,
  1243. call,
  1244. SIPTAG_FROM_STR(call->from_uri),
  1245. SIPTAG_TO_STR(call->to_uri),
  1246. TAG_END());
  1247. }else if (call->call_id != NULL){
  1248. call->nh = nua_handle(call->ep->nua,
  1249. call,
  1250. SIPTAG_FROM_STR(call->ep->conf.uri),
  1251. SIPTAG_CALL_ID_STR(call->call_id),
  1252. SIPTAG_TO_STR(call->to_uri),
  1253. TAG_END());
  1254. }else{
  1255. call->nh = nua_handle(call->ep->nua,
  1256. call,
  1257. SIPTAG_FROM_STR(call->ep->conf.uri),
  1258. SIPTAG_TO_STR(call->to_uri),
  1259. TAG_END());
  1260. }
  1261. call_make_offer(call, sdp, -1);
  1262. if (0 == strlen(sdp)){
  1263. LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_INVALID_SDP, "invalid sdp.");
  1264. }
  1265. nua_invite(call->nh,
  1266. //NUTAG_URL(call->remote_uri),
  1267. SOATAG_USER_SDP_STR(sdp),
  1268. NUTAG_SESSION_TIMER(20000),
  1269. //SOATAG_AUDIO_AUX("telephone-event"),
  1270. TAG_END());
  1271. return 0;
  1272. }
  1273. int endpoint_call_hangup(endpoint_call_t *call)
  1274. {
  1275. if (call->nh) {
  1276. if (call->connected) {
  1277. nua_bye(call->nh, NUTAG_SESSION_TIMER(8000),TAG_END());
  1278. } else {
  1279. nua_cancel(call->nh, NUTAG_SESSION_TIMER(8000),TAG_END());
  1280. }
  1281. }
  1282. return 0;
  1283. }
  1284. #ifdef RVC_OS_WIN
  1285. int endpoint_call_start_video(endpoint_call_t *call, unsigned long remote_ip, int remote_video_rtp,
  1286. unsigned long local_ip, int local_video_rtp,
  1287. int remote_width, int remote_height,
  1288. int local_view_x, int local_view_y, int local_view_cx, int local_view_cy,
  1289. int remote_view_x, int remote_view_y, int remote_view_cx, int remote_view_cy,
  1290. int local_move, int remote_move, video_session_callback_t* cb)
  1291. {
  1292. if (call)
  1293. {
  1294. int i = 0;
  1295. media_desc_t video_desc = {0};
  1296. video_desc.media_dir = DIR_BOTH;
  1297. if (call->nCallType == NORMAL_CALLTYPE || call->nCallType == DOUBLERECORD_CALLTYPE)//如果是可视柜台模式,使用协助通道的协商结果
  1298. {
  1299. video_desc.local_ip = local_ip;
  1300. video_desc.local_port = local_video_rtp;
  1301. video_desc.remote_port = remote_video_rtp;
  1302. video_desc.remote_ip = remote_ip;
  1303. }
  1304. else //如果是非可视柜台模式,使用SDP协商的参数
  1305. {
  1306. video_desc.local_ip = call->sdpvieo_desc.local_rtp_ip;
  1307. video_desc.local_port = call->sdpvieo_desc.local_rtp_port;
  1308. video_desc.local_pt = call->sdpvieo_desc.local_pt;
  1309. video_desc.remote_ip = call->sdpvieo_desc.remote_rtp_ip;
  1310. video_desc.remote_port = call->sdpvieo_desc.remote_rtp_port;
  1311. video_desc.remote_pt = call->sdpvieo_desc.remote_pt;
  1312. }
  1313. video_desc.param[i++] = local_view_x;
  1314. video_desc.param[i++] = local_view_y;
  1315. video_desc.param[i++] = local_view_cx;
  1316. video_desc.param[i++] = local_view_cy;
  1317. video_desc.param[i++] = remote_view_x;
  1318. video_desc.param[i++] = remote_view_y;
  1319. video_desc.param[i++] = remote_view_cx;
  1320. video_desc.param[i++] = remote_view_cy;
  1321. video_desc.param[i++] = remote_width;
  1322. video_desc.param[i++] = remote_height;
  1323. video_desc.param[i++] = local_move;
  1324. video_desc.param[i++] = remote_move;
  1325. endpoint_media_update_video(call, &video_desc, cb);
  1326. return 0;
  1327. }
  1328. else
  1329. {
  1330. return Error_Param;
  1331. }
  1332. }
  1333. #else
  1334. int endpoint_call_start_video(endpoint_call_t* call, endpoint_call_param_t* pcallparam, rvc_video_render_callback_t* render_cb)
  1335. {
  1336. if (call)
  1337. {
  1338. int i = 0;
  1339. media_desc_t video_desc = {0};
  1340. video_desc.media_dir = DIR_BOTH;
  1341. if (call->nCallType == NORMAL_CALLTYPE || call->nCallType == DOUBLERECORD_CALLTYPE)//如果是可视柜台模式,使用协助通道的协商结果
  1342. {
  1343. video_desc.local_ip = pcallparam->local_ip;
  1344. video_desc.local_port = pcallparam->local_port;
  1345. video_desc.remote_port = pcallparam->remote_port;
  1346. video_desc.remote_ip = pcallparam->remote_ip;
  1347. }
  1348. else //如果是非可视柜台模式,使用SDP协商的参数
  1349. {
  1350. video_desc.local_ip = call->sdpvieo_desc.local_rtp_ip;
  1351. video_desc.local_port = call->sdpvieo_desc.local_rtp_port;
  1352. video_desc.local_pt = call->sdpvieo_desc.local_pt;
  1353. video_desc.remote_ip = call->sdpvieo_desc.remote_rtp_ip;
  1354. video_desc.remote_port = call->sdpvieo_desc.remote_rtp_port;
  1355. video_desc.remote_pt = call->sdpvieo_desc.remote_pt;
  1356. }
  1357. video_desc.param[i++] = pcallparam->remote_width;
  1358. video_desc.param[i++] = pcallparam->remote_height;
  1359. endpoint_media_update_video(call, &video_desc, render_cb);
  1360. return 0;
  1361. }
  1362. else
  1363. {
  1364. return Error_Param;
  1365. }
  1366. }
  1367. #endif
  1368. int endpoint_call_stop_video(endpoint_call_t *call)
  1369. {
  1370. if (call) {
  1371. media_desc_t video_desc = {0};
  1372. video_desc.media_dir = DIR_NONE;
  1373. endpoint_media_update_video(call, &video_desc,NULL);
  1374. return 0;
  1375. } else {
  1376. return Error_Param;
  1377. }
  1378. }
  1379. #ifdef RVC_OS_WIN
  1380. int endpoint_call_stop_double_record_broadcast_video()
  1381. {
  1382. double_record_broadcast_video_session_stop();
  1383. return Error_Succeed;
  1384. }
  1385. int local_remote_show_video(endpoint_call_t *call,int local_view_x, int local_view_y, int local_view_cx, int local_view_cy,int remote_view_x, int remote_view_y, int remote_view_cx, int remote_view_cy, int local_move, int remote_move, video_session_callback_t* cb)
  1386. {
  1387. int rc;
  1388. endpoint_conf_t *ep_conf = &call->ep->conf;
  1389. if (call->video)
  1390. {
  1391. video_session_destroy(call->video);
  1392. call->video = NULL;
  1393. }
  1394. int remote_video_width = REC_COMMON_VIDEO_SSM_AGENT_WIDTH;
  1395. int remote_video_height = REC_COMMON_VIDEO_SSM_AGENT_HEIGHT;
  1396. if (eStand2sType == call->eDeviceType){
  1397. remote_video_width = REC_COMMON_VIDEO_DSM_AGENT_WIDTH;
  1398. remote_video_height = REC_COMMON_VIDEO_DSM_AGENT_HEIGHT;
  1399. }
  1400. video_session_conf_t video_conf = {0};
  1401. video_conf.bit_rate = 256 * 1024;
  1402. video_conf.local_rtp_ip = 0;
  1403. video_conf.local_rtp_port = 0;
  1404. video_conf.local_video_view_x = local_view_x;
  1405. video_conf.local_video_view_y = local_view_y;
  1406. video_conf.local_video_view_cx = local_view_cx;
  1407. video_conf.local_video_view_cy = local_view_cy;
  1408. video_conf.local_move = local_move;
  1409. video_conf.mtu = ep_conf->mtu;
  1410. video_conf.video_quant = ep_conf->quant;
  1411. video_conf.remote_rtp_ip = 0;
  1412. video_conf.remote_rtp_port = 0;
  1413. video_conf.remote_video_view_x = remote_view_x;
  1414. video_conf.remote_video_view_y = remote_view_y;
  1415. video_conf.remote_video_view_cx = remote_view_cx;
  1416. video_conf.remote_video_view_cy = remote_view_cy;
  1417. video_conf.remote_move = remote_move;
  1418. video_conf.remote_video_width = remote_video_width;
  1419. video_conf.remote_video_height = remote_video_height;
  1420. video_conf.ref_active_camera = call->ep->conf.ref_active_camera;
  1421. video_conf.ref_camera_switch = call->ep->conf.ref_camera_switch;
  1422. video_conf.ref_camera_state = call->ep->conf.ref_camera_state;
  1423. video_conf.ref_window_state = call->ep->conf.ref_window_state;
  1424. video_conf.ref_active_img = call->ep->conf.ref_active_img;
  1425. video_conf.ref_Is_ActiveInspect = call->ep->conf.ref_Is_ActiveInspect;
  1426. video_conf.ref_Is_showPersonArea = call->ep->conf.ref_Is_showPersonArea;
  1427. video_conf.camera_count = call->ep->conf.camera_count;
  1428. video_conf.screen_count = call->ep->conf.screen_count;
  1429. video_conf.eDeviceType = call->eDeviceType;
  1430. video_conf.video_echo_cb = cb;
  1431. video_conf.ilocal_wind_flags = VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP;
  1432. video_conf.iremote_wind_flags = VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP;
  1433. video_conf.eType = (eVideoRenderType)call->ep->conf.irendertype;
  1434. rc = local_video_session_create(&video_conf, &call->video, true);
  1435. if (rc != 0){
  1436. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create video session failed! rc = %d", rc);
  1437. return -1;
  1438. }
  1439. rc = video_session_start(call->video);
  1440. if (rc != 0){
  1441. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("start video session failed! rc = %d", rc);
  1442. video_session_destroy(call->video);
  1443. call->video = NULL;
  1444. return -1;
  1445. }
  1446. return 0;
  1447. }
  1448. int local_play_stop_video(endpoint_call_t *call)
  1449. {
  1450. if (call) {
  1451. media_desc_t video_desc = {0};
  1452. video_desc.media_dir = DIR_NONE;
  1453. endpoint_media_update_video(call, &video_desc,NULL);
  1454. return 0;
  1455. } else
  1456. {
  1457. return Error_Param;
  1458. }
  1459. }
  1460. #endif
  1461. static void __endpoint_call_destroy(endpoint_call_t *call)
  1462. {
  1463. list_del(&call->entry);
  1464. if (call->ep && call->ep->active_call == call) {
  1465. call->ep->active_call = NULL;
  1466. }
  1467. su_home_unref(call->home);
  1468. }
  1469. IMPLEMENT_REF_COUNT_MT_STATIC(endpoint_call, endpoint_call_t, ref_cnt, __endpoint_call_destroy)