GB28181---基于pjsip库的开发(一)

   《GBT 28181-2016 公共安全视频监控联网系统信息传输、交换、控制技术要求》规定了公共安全视频监控联网系统的互联结构、传输、交换、控制的基本要求和安全性要求、以及控制传输流程和协议接口等技术要求。

在音视频领域内,如果你们产品定位不是消费级别的,而是需要做走平台,做对接。那gb28181协议是避不开的。

而该协议对外有2011和2016两版,其后主要更新了TCP传输、强制I帧等内容。具体的内容我就不介绍了,网上一搜一大把。我们主要说说对该协议的开发吧。

由于gb28181是基于sip协议进行传输的一项协议,那我们就有目标了,先找个开源sip库,不管你选的是osip、exosip、还是pjsip都没关系,他们都只是载体,大佬们都说pjsip代码优雅,那我们就选pjsip吧,接下来我们就具体讲讲pjsip库的一些东西吧(不会有人选opensip吧)。

PJSIP is a free and open source multimedia communication library written in C language implementing standard based protocols such as SIP, SDP, RTP, STUN, TURN, and ICE. It combines signaling protocol (SIP) with rich multimedia framework and NAT traversal functionality into high level API that is portable and suitable for almost any type of systems ranging from desktops, embedded systems, to mobile handsets.

介绍你们想了解的就去他们官网 https://www.pjsip.org/ 吧。

里面有开发指南,说的很全面。

将开源库编译完之后我们会用到他们的三个库,分别为pjlib、pjlib-util、以及pjsip。将他们的头文件及库加入到我们的项目中,我们就能使用了。

现在我们来将pj库进行初始化。好的,上代码。献丑了

typedef struct 
{

	pjsip_endpoint  *pj_endpt;
	pjsip_transport *pj_port;
	pj_caching_pool pj_cach_pool;
	pj_thread_t *thread_id;
	
}PJSIP_PARAM_S,*PPJSIP_PARAM_S;
#define PJSIP_PARAM_S_LEN sizeof(PJSIP_PARAM_S)

static PJSIP_PARAM_S gb_pjsip;

static pj_bool_t pjsip_msg_request(pjsip_rx_data *rdata);
static pjsip_method  pjsip_message_method = {PJSIP_OTHER_METHOD, { "MESSAGE", 7 }};

static pjsip_module mod_msg = 
{
    NULL, NULL,						/* prev, next.		*/
    { "mod_msg", 7 },				/* Name.		*/
    -1,								/* Id			*/
    PJSIP_MOD_PRIORITY_APPLICATION,	/* Priority	       */
    NULL,							/* load()			*/
    NULL,							/* start()		*/
    NULL,							/* stop()		*/
    NULL,							/* unload()		*/
    &pjsip_msg_request,				/* on_rx_request()	*/
    NULL,							/* on_rx_response()	*/
    NULL,							/* on_tx_request.		*/
    NULL,							/* on_tx_response()	*/
    NULL,							/* on_tsx_state()		*/
};


/*初始化pj库;分配内存,开启链路*/
int init_pjlib(void)
{
	pj_status_t 	status; 
	pj_sockaddr_in	addr;
	pjsip_ua_init_param  ua_init_param;
	pj_pool_t	   *pool;
	
	memset(&gb_pjsip, 0, PJSIP_PARAM_S_LEN);

	//屏蔽系统日志
	pj_log_set_level(0);
	pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC);

	if (pj_init() != PJ_SUCCESS)
	{
		return -1;
	}
	
	/*	init pjlib_util  */
	if (pjlib_util_init() != PJ_SUCCESS)
	{
		return -1;
	}

	pj_caching_pool_init(&gb_pjsip.pj_cach_pool, &pj_pool_factory_default_policy, (2<<20));

	/*	create endpoint  */
	status = pjsip_endpt_create(&gb_pjsip.pj_cach_pool.factory, "endpt", &gb_pjsip.pj_endpt);
	if (status != PJ_SUCCESS)
	{
		pj_caching_pool_destroy(&gb_pjsip.pj_cach_pool);
		return -1;
	}
	
	/* Start transaction layer module. */
	status = pjsip_tsx_layer_init_module(gb_pjsip.pj_endpt);
	if (status != PJ_SUCCESS)
	{
		pjsip_endpt_destroy(gb_pjsip.pj_endpt);
		pj_caching_pool_destroy(&gb_pjsip.pj_cach_pool);
		return -1;
	}
	
	/* Start UDP transport. */
	pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)5060);
	status = pjsip_udp_transport_start(gb_pjsip.pj_endpt,&addr, NULL, 1, &gb_pjsip.pj_port);
	if (status != PJ_SUCCESS) 
	{
		pjsip_endpt_destroy(gb_pjsip.pj_endpt);
		pj_caching_pool_destroy(&gb_pjsip.pj_cach_pool);
		return -1;
	}
	
	pj_bzero(&ua_init_param, sizeof(ua_init_param));
	status = pjsip_ua_init_module(gb_pjsip.pj_endpt, &ua_init_param);
	if (status != PJ_SUCCESS) 
	{
		pjsip_transport_destroy(gb_pjsip.pj_port);
		pjsip_endpt_destroy(gb_pjsip.pj_endpt);
		pj_caching_pool_destroy(&gb_pjsip.pj_cach_pool);
		return -1;
	}
	
	/*注册pjsip消息模块*/
	status = pjsip_endpt_register_module(gb_pjsip.pj_endpt, &mod_msg);
	if (status != PJ_SUCCESS)
	{
		return -1;
	}
	
	pool = pjsip_endpt_create_pool(gb_pjsip.pj_endpt, "thread%p", 2048, 2048);
	status = pj_thread_create(pool, "pjsip_task", &pjsip_thread_task, NULL, 0, 0, &gb_pjsip.thread_id);//create thread
	if (status != PJ_SUCCESS)
	{
		pjsip_transport_destroy(gb_pjsip.pj_port);
		pjsip_endpt_destroy(gb_pjsip.pj_endpt);
		pj_caching_pool_destroy(&gb_pjsip.pj_cach_pool);
		return -1;
	}
	printf("init_pjlib finish\n");
	
	return 0;
}

初始化完成之后,sip消息都会通过pj库处理进入回调函数pj_bool_t pjsip_msg_request(pjsip_rx_data *rdata);来处理我们的逻辑业务了。

虽然我们完成了pjsip的初始化,但是想要灵活运用还得多研究研究,之后我们花几篇文章来了解了解这个pj库吧。

有错误请留言,谢谢

下篇继续

GB28181---基于pjsip库的开发(二)

---------------bob 2020/5/6

上一篇:网络流——从入门到入土


下一篇:洛谷 P6619 [省选联考 2020 A/B 卷] 冰火战士