endpoint.cpp 49 KB

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