/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #ifndef H_SIP_UA_H #define H_SIP_UA_H #include "hqueue.h" #include "media_info.h" #include "rtp.h" #include "sua_sdp.h" #include "ps.h" #include "aac_rtp_rx.h" #include "pcm_rtp_rx.h" #ifdef MEDIA_FILE #include "file_demux.h" #endif #ifdef MEDIA_DEVICE #ifdef ANDROID #include "audio_capture_android.h" #include "video_capture_qt.h" #include "screen_capture.h" #include "window_capture.h" #elif defined(IOS) #include "audio_capture_mac.h" #include "video_capture_mac.h" #include "screen_capture_mac.h" #include "window_capture_mac.h" #elif __WINDOWS_OS__ #include "video_capture_win.h" #include "audio_capture_win.h" #include "screen_capture_win.h" #include "window_capture_win.h" #elif __LINUX_OS__ #include "video_capture_linux.h" #include "audio_capture_linux.h" #include "screen_capture_linux.h" #include "window_capture_linux.h" #endif #endif #ifdef MEDIA_PROXY #include "media_proxy.h" #endif #ifdef MEDIA_LIVE #include "live_video.h" #include "live_audio.h" #endif #if defined(MEDIA_FILE) || defined(MEDIA_DEVICE) #include "audio_decoder.h" #include "audio_play.h" #endif /*************************************************************************/ typedef enum sua_call_state_enum // 服务器端UA的状态 { SUA_CS_IDLE = 0, SUAC_CS_INVITE_SENT, // 已经发送Invite消息 SUAS_CS_TRYING, // 呼叫进入,准备状态 SUAS_CS_1XX_SENT, // 已经向用户端发送1xx应答 SUAS_CS_2XX_SENT, // 已经向用户端发送2xx应答,等待ACK请求 SUAC_CS_1XX_RECV, // 已经收到对端1xx应答 SUA_CS_ESTABLISHED, // 通话阶段 SUAS_CS_4XX_SENT, // 已经向用户端发送4xx应答,等待ACK请求 SUA_CS_BYE_SENT, // 等待BYE 200 OK SUA_CS_ERR_EXIT // 错误正在退出,需要依靠超时退出 } SUACS; typedef struct sua_cs_name { SUACS state; char state_name[32]; } SUACN; typedef struct { uint32 has_audio : 1; // has audio ? uint32 has_video : 1; // has video ? uint32 is_file : 1; // is media file uint32 is_device : 1; // is media device uint32 is_screen : 1; // is screen live uint32 is_window : 1; // is window uint32 is_proxy : 1; // is proxy stream uint32 is_live : 1; // is live stream uint32 reserved : 24; char media_url[256]; // file name uint8 v_index; // video stream index uint8 a_index; // audio stream index VIDEO_INFO v_info; // video information AUDIO_INFO a_info; // audio information HQUEUE * v_queue; // video queue HQUEUE * a_queue; // audio queue pthread_t v_thread; // video thread pthread_t a_thread; // audio thread #ifdef MEDIA_FILE CFileDemux * file_demuxer; // file demuxer object #endif #ifdef MEDIA_DEVICE char window_title[256]; // window title CVideoCapture * video_capture; // video capture CAudioCapture * audio_capture; // audio capture CScreenCapture* screen_capture; // screen capture CWindowCapture* window_capture; // window capture #endif #ifdef MEDIA_PROXY CMediaProxy * proxy; // media proxy #endif #ifdef MEDIA_LIVE CLiveVideo * live_video; // live video object CLiveAudio * live_audio; // live audio object #endif #if defined(MEDIA_FILE) || defined(MEDIA_DEVICE) CAudioDecoder * audio_decoder; CAudioPlay * audio_play; #endif } UA_MEDIA_INFO; typedef struct play_context { uint32 b_pausing : 1; // 播放暂停 uint32 b_backing : 1; // 正在快退 uint32 b_seek_req : 1; // 客户端请求重新定位 uint32 b_seek_finish : 1; // 重新定位完成 uint32 b_scale_req : 1; // 客户端请求快进/慢进 uint32 b_scale_finish : 1; // 快进/慢进完成 uint32 b_step_req : 1; // 客户端请求单步进或退 uint32 b_step_finish : 1; // 单步进或退完成 uint32 b_resvd : 24; long seek_pos; // 要求重新定位偏移量 float scale; // 文件播放快进/慢进倍数 int step; // 单步前进或后退 } PLAYCTX; typedef struct sua_session { uint32 uaf_uas : 1; // UAS,UAC标志 uint32 uaf_uac : 1; // UAS,UAC标志 uint32 uaf_cancel_sent : 1; // Cancel发送标志 uint32 uaf_183_recv : 1; // 183消息已经接收过 uint32 uaf_reinvite_s : 1; // ReInvite发送,但还没有收到回应 uint32 uaf_state_timer : 1; // 状态机标志: 定时器启动,在特定状态设置,在定时器任务中检测并处理 uint32 uaf_a_remote_nrx: 1; // 对方语音是sendonly uint32 uaf_v_remote_nrx: 1; // 对方视频是sendonly uint32 uaf_a_rx_flag : 1; // 语音接收已经打开标志 uint32 uaf_a_tx_flag : 1; // 语音发送已经打开标志 uint32 uaf_v_rx_flag : 1; // 视频接收已经打开标志 uint32 uaf_v_tx_flag : 1; // 视频发送已经打开标志 uint32 uaf_rtp_tx : 1; // RTP thread starts, is sending RTP uint32 uaf_rtp_mux : 1; // 使用UDP-RTP端口复用模式,音频、视频RTP均采用同一复用ID,RTCP流的ID? uint32 uaf_v_tcp_rtp : 1; // 使用TCP-RTP模式传输视频 uint32 uaf_a_tcp_rtp : 1; // 使用TCP-RTP模式传输音频 uint32 uaf_multicast : 1; // 使用组播传输模式 uint32 uaf_state_wait : 1; // 当前有外部线程在状态等待 uint32 uaf_v_ps : 1; // 视频参数是PS uint32 uaf_v_h264 : 1; // 视频参数是H264,RFC3984 uint32 uaf_v_h265 : 1; // 视频参数是H265 uint32 uaf_v_jpeg : 1; // 视频参数是JPEG uint32 uaf_v_file : 1; // 视频参数是任意文件 uint32 uaf_iframe_tx : 1; // 是否已经发送I帧 uint32 uaf_iframe_rx : 1; // 是否已经接收到IDR帧 uint32 uaf_timer : 1; // 是否支持RFC4028:SIP会话定义的一种存活机制 uint32 uaf_refresher : 1; // 是否由自己来进行刷新动作 uint32 uaf_playback : 1; // 录像回放标志 uint32 uaf_download : 1; // 录像下载标志 uint32 uaf_ps_audio_tx : 1; // 发送PS音频数据 uint32 uaf_reserved : 2; // 标志: 保留 uint32 guid; SUACS call_state; // 当前呼叫状态 SUACS wait_state; // 当前等待状态 void * wait_sig; // 当前等待信号量 int s_v_mode; // a=setup:active:passive,TCP链接下对端主被动模式, 0-passive,1-active int s_a_mode; // a=setup:active:passive,TCP链接下对端主被动模式, 0-passive,1-active char s_name[128]; // SDP会话名称, sdp s=Upload Play Playback char u_name[64]; // 回放时设备ID:通道 time_t st; // 回放开始时间 time_t et; // 回放结束时间 time_t play_st; // 播放开始时间 char y_name[12]; // sdp y=0100000001, 第1位为历史或实时媒体流的标识位,0为实时,1为历史; // 第2位至第6位取20位SIP监控域ID之中的4到8位作为域标识, // 例如"13010000002000000001"中取数字"10000"; // 第7位至第10位作为域内媒体流标识 char call_id_str[128]; // 呼叫ID uint32 call_cseq; uint32 mansrtsp_cseq; char sua_deviceid[64]; // 代理的设备ID char sua_name[64]; // 代理的用户名 char sua_sip_address[128]; // 代理的SIP地址 char sua_disp_name[128]; // 代理的显示名称 char sua_domain[64]; // 代理所处的域 char sua_sip_tag[128]; // 代理的SIP TAG char sua_ipstr[24]; // 代理的IP地址 uint16 sua_port; // 代理的信令端口 char req_name[64]; // SIP请求用户名 char remote_name[64]; // 远端用户名 char remote_sip_address[128]; // 远端的SIP地址 char remote_disp_name[128]; // 远端的显示名称 char remote_domain[64]; // 远端所处的域 char remote_sip_tag[128]; // 远端的SIP TAG char remote_contact_uri[128]; // 终端的地址,开始是空 HSIP_USER * p_user; // 实际对应的用户信息,注意这里在向外呼叫时作为电话路由接口 HD_AUTH_INFO user_auth_info; uint32 remote_real_ip; // 用户真正的IP地址(网络字节序) uint16 remote_real_port; // 用户的端口(网络字节序) uint32 remote_media_ip; // 远端媒体地址 int l_a_cap_cnt; // 本地音频能力个数 uint8 l_a_cap[MAX_AVN]; // 本地音频能力 SDPINFO l_a_sdp[MAX_AVN]; // 本地音频SDP信息 int l_v_cap_cnt; // 本地视频能力个数 uint8 l_v_cap[MAX_AVN]; // 本地视频能力 SDPINFO l_v_sdp[MAX_AVN]; // 本地视频SDP信息 int r_a_cap_cnt; // 远端音频能力个数 uint8 r_a_cap[MAX_AVN]; // 远端音频能力 SDPINFO r_a_sdp[MAX_AVN]; // 音频SDP描述信息解析结果 int r_v_cap_cnt; // 远端视频能力个数 uint8 r_v_cap[MAX_AVN]; // 远端视频能力 SDPINFO r_v_sdp[MAX_AVN]; // 视频SDP描述信息解析结果 RTPMAPE r_rtp_map[256]; // 远端RTP pt映射表,用于快速判断复用接收到的RTP是音频还是视频 int same_audio_cap_count; // 相同音频能力个数 uint8 same_audio_cap[MAX_AVN]; // 相同音频能力 int same_video_cap_count; // 相同视频能力个数 uint8 same_video_cap[MAX_AVN]; // 相同视频能力 char last_tx_packet[2048]; // 最近发送的呼叫包 int last_tx_packet_len; uint32 last_tx_time; // 最近发送呼叫包的时间 uint32 state_timer_interval; // 定时器的间隔时间 uint32 state_retx_count; // 定时器重传次数计数 uint32 state_retx_max_times; // 定时器最大重传次数 SUACS state_retx_fail_state; // 超过最大重传次数后的状态 UA_MEDIA audio_rtp_media; // 用来接收和发送音频的媒体结构 UA_MEDIA audio_rtcp_media; // 用来接收和发送音频的媒体结构 UA_MEDIA video_rtp_media; // 用来接收和发送视频的媒体结构 UA_MEDIA video_rtcp_media; // 用来接收和发送视频的媒体结构 UA_RTP_INFO a_rtp_info; // audio rtp information UA_RTP_INFO v_rtp_info; // video rtp information UA_MEDIA_INFO media_info; // 媒体信息 PLAYCTX play_ctx; // 当前播放上下文 uint32 r_mux_id; // 远端音视频UDP端口复用ID uint32 l_mux_id; // 本地音视频UDP端口复用ID int mux_fd; // 复用接收/发送socket文件 int mux_lport; // 复用接收/发送本地端口 uint32 multicast_addr; // 组播地址 PSPKTI pstxi; // PS组包发送信息 void * pstxi_mutex; // mutex int SessionExpires; // 会话保活刷新时间间隔 int MinSE; // 会话保活刷新时间间隔 uint32 last_tx_refresh; // 最近发送刷新时间 uint32 last_rx_refresh; // 最近接收刷新时间 char a_recv_buf[16]; // 音频接收缓冲区 char * a_dyn_recv_buf; // 音频动态接收缓冲区 uint32 a_data_offset; // 音频接收缓冲区偏移 pthread_t a_rtp_rx_tid; // 语音RTP接收线程 HSIP_CRPTY_MODE user_crpty_mode; // 该用户消息加密模式 PPSN_CTX via_ctx; // 在作被叫时需要记录请求所经过的路径 PPSN_CTX rr_ctx; // Record-Route/Route pthread_t tid_media; // media send thread id pthread_t tid_audio; // audio send thread id void * user_data; // 回调函数用户数据指针 SIPCALLCBF call_state_cb; // 呼叫状态回调函数 RTPRXCBF audio_rx_cb; // 音频数据接收回调函数 union { AACRXI aacrxi; PCMRXI pcmrxi; }; uint32 s_time; // 分配出来时的时间(ms) } SUA; /*************************************************************************/ #define sua_tx_free_msg(p_sua,tx_msg) do{sip_sua_send_msg(p_sua,tx_msg); sip_free_msg(tx_msg); }while(0) #define user_tx_free_msg(p_user,tx_msg) do{sip_user_send_msg(p_user,tx_msg); sip_free_msg(tx_msg); }while(0) /*************************************************************************/ #ifdef __cplusplus extern "C" { #endif /*************************************************************************/ void sua_timer_set(SUA * p_sua, uint32 interval, uint32 max_times, SUACS fail_state); void sua_timer_clear(SUA * p_sua); void sua_set_state_cb(SUA * p_sua, SIPCALLCBF state_cb, void * user_data); void sua_set_audio_cb(SUA * p_sua, RTPRXCBF rtp_cb); /*************************************************************************/ char * sua_get_call_state_name(SUACS state); void sua_build_from(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_to(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_contact(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_route(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_record_route(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_response_from(HSIP_MSG * tx_msg, SUA * p_sua); void sua_build_response_to(HSIP_MSG * tx_msg, SUA * p_sua); HSIP_MSG * sua_build_invite_msg(SUA * p_sua); HSIP_MSG * sua_build_invite_auth_msg(SUA * p_sua, HSIP_MSG * rx_msg); HSIP_MSG * sua_build_iok_msg(SUA * p_sua); HSIP_MSG * sua_build_18xsdp_msg(SUA * p_sua, const char * response_hdr); HSIP_MSG * sua_build_bye_msg(SUA * p_sua); HSIP_MSG * sua_build_cancel_msg(SUA * p_sua); HSIP_MSG * sua_build_ack_msg(SUA * p_sua); HSIP_MSG * sua_build_prack_msg(SUA * p_sua); HSIP_MSG * sua_build_update_response_msg(HSIP_MSG * rx_msg, const char * response_hdr); HSIP_MSG * sua_build_response_msg(HSIP_MSG * rx_msg, const char * response_hdr); HSIP_MSG * sua_build_invite_response(SUA * p_sua, const char * response_hdr); BOOL sua_get_session_timer_info(SUA * p_sua, HSIP_MSG * rx_msg); /*************************************************************************/ void sua_proxy_init(); void sua_proxy_deinit(); void sua_user_init(HSIP_USER * p_user, SUA * p_sua); SUA * sua_get_idle_sua(HSIP_USER * p_user); void sua_set_idle_sua(SUA * p_sua); SUA * sua_lookup_start(); SUA * sua_lookup_next(SUA * p_sua); void sua_lookup_stop(); uint32 sua_get_index(SUA * p_sua); SUA * sua_get_by_index(uint32 index); SUA * sua_lookup_by_callid(char * p_callid); void sua_state_set(SUA * p_sua, SUACS state); void sua_stop_used_sua(SUA * sua); void sua_free_used_sua(SUA * sua); /*************************************************************************/ void * sua_new_handle(); void * sua_get_handle(uint32 index); int sua_get_handle_index(void * p_handle); void sua_del_handle(void * p_handle); BOOL sua_post_del_handle(uint32 ua_index, uint32 ua_guid); void sua_del_native(uint32 ua_index, uint32 ua_guid); /*************************************************************************/ BOOL sua_start_audio(SUA * p_sua); BOOL sua_start_audio_rx(SUA * p_sua); BOOL sua_stop_audio(SUA * p_sua); BOOL sua_start_video(SUA * p_sua); BOOL sua_start_video_rx(SUA * p_sua); BOOL sua_stop_video(SUA * p_sua); int sua_mux_rtp_tx(SUA * p_sua, void * p_rtp, int len); void sua_set_media_rtp(SUA * p_sua); BOOL sua_start_mux_media(SUA * p_sua); BOOL sua_start_mux_media_rx(SUA * p_sua); BOOL sua_stop_mux_rtp(SUA * p_sua); BOOL sua_start_media(SUA * sua); BOOL sua_start_media_rx(SUA * p_sua); void sua_stop_media(SUA * sua); void * sua_audio_rtp_rx(void * argv); BOOL sua_start_media_tx(SUA * p_sua); void sua_stop_stream_tx(SUA * p_sua); /*************************************************************************/ BOOL sua_build_sdp_msg(SUA * p_sua, HSIP_MSG * tx_msg); int sua_calc_sdp_length(HSIP_MSG * tx_msg); BOOL sua_get_msg_media_info(SUA * p_sua, HSIP_MSG * rx_msg); void sua_clear_self_sdp(SUA * p_sua, const char * cap_name); int sua_add_self_sdp(SUA * p_sua, SDPINFO * p_sdp); int sua_add_remote_sdp(SUA * p_sua, SDPINFO * p_sdp); int sua_get_video_sdp_cnt(SUA * p_sua, int lr); int sua_get_video_sdp(SUA * p_sua, int lr, int index, SDPINFO * p_sdp); int sua_get_audio_sdp_cnt(SUA * p_sua, int lr); int sua_get_audio_sdp(SUA * p_sua, int lr, int index, SDPINFO * p_sdp); SDPINFO * sua_get_sdp_by_codec(SUA * p_sua, const char * codec_name); uint8 sua_get_rtp_pt(SUA * p_sua, const char * codec_name); SDPINFO * sua_get_l_sdp_by_pt(SUA * p_sua, const uint8 rtp_pt); SDPINFO * sua_get_r_sdp_by_pt(SUA * p_sua, const uint8 rtp_pt); void sua_rtp_map_entry_set(RTPMAPE * p_map, int index, const char * name, int channel, int hz, int mtype, int sdp_index); void sua_default_rtp_map_init(); void sua_r_rtp_map_init(SUA * p_sua); void sua_r_map_update(SUA * p_sua); int sua_call_in_sdp_parse(SUA * p_sua, HSIP_MSG * rx_msg); int sua_check_same_cap(SUA * p_sua); int sua_adjust_l_sdp_set(SUA * p_sua); #ifdef __cplusplus } #endif #endif // H_SIP_UA_H