Files
gb28181/GB28181Device/sip/sua.h
2024-12-15 20:42:32 +08:00

448 lines
18 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/***************************************************************************************
*
* 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均采用同一复用IDRTCP流的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; // 是否支持RFC4028SIP会话定义的一种存活机制
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