448 lines
18 KiB
C
448 lines
18 KiB
C
/***************************************************************************************
|
||
*
|
||
* 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
|
||
|
||
|