endpoint.cpp 46 KB

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