您当前的位置: 首页 > 

qianbo_insist

暂无认证

  • 0浏览

    0关注

    399博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用p2p发送GB28181流的设计

qianbo_insist 发布时间:2022-03-10 16:05:17 ,浏览量:0

萌思特 1、p2p链接的必要性

其必要性在于: 1 能够显著减少服务器压力负担 2 随着国内带宽上传能力增加,非对称网络上传视频可能大大提升 3 减少服务费用

2、前提条件

1、由于p2p链接需要很多条件限制,因此并非所有网络方式能够打通p2p方式的链接,我们限制在cone net p2p上进行网关程序间分发。 2、限制udp方式分发流 3、限制联通和电信这类4g网络只能使用turn方式。

3、程序架构

1、udp服务器-主服务器 2、udp服务器-分发中转服务器 3、分发架构路由 4、ps读写构造器客户端进行解包,渲染 5、存储器 —部署在p2p的各端可进行 6、sip gb28181 ----信令服务 7、rtsp proxy 8、webrtc proxy 9、redis 订阅发布 10、tcpserver 可选 流程为: a)在sip 接收到命令之后,可以invite相应的邀请流进入,这一部分不使用p2p方式,和webrtc本身所使用的方式一致,信令为直接tcp服务或者udp服务的传输,可以使用传统udp服务sip 5060端口。 b) 客户端负责打洞,根据分发配置信令来给服务器来通知,这时stun服务必须由分发内容。 c)打洞完毕(成功),信令服务sdp协议中可以加入接收rtp服务地址 d)传输开始 在这里插入图片描述

3.1层次

层次关系以及所需要的协议等等如下图所示 在这里插入图片描述

3.2程序框架辅助

分发功能 —config 分发配置 —config 路由

sipserver —gb28181 分发信令服务器 rtp ps 分析器 — 投屏协议 — DLNA协议

p2p 服务 —传统的stun和turn服务器是可选项 更佳的配置是得到分析,p2p 打洞探测如果为对称立刻进行转发服务。

3.3 程序制作
 给出udpserver的声明,p2p udp server如果使用非异步方式一定要使用多个线程接收,在接收线程中使用recvfrom来得到客户端的外网地址,才能帮助双方打通。
#include "c_decode.h"
#include "c_thread.h"
#include "c_sock.h"
#include 
using namespace std;

typedef struct _RTP_HEAD
{
	unsigned char    version : 2;
	unsigned char    padding : 1;
	unsigned char    extension : 1;
	unsigned char    count : 4;
	unsigned char    marker : 1;
	unsigned char    payload : 7;
	uint16_t            sn;        //16bits 
	uint32_t            ts;        //32 
	uint32_t            ssrc;            //32 
	uint32_t            csrc;            //32 
}RTP_HEAD, *pRTP_HEAD;
typedef struct _RTCP_HEAD
{
	unsigned char    version : 2;
	unsigned char    padding : 1;
	unsigned char    count : 5;
	unsigned char    payload;            //8bits 
	uint16_t         length;           //16bits 
	uint32_t         ssrc; //5,6,7,8 char

}RTCP_HEAD, *pRTCP_HEAD;

//NACK报文是类型为205的RTCP 扩展反馈报文,在RFC4585中定义。

class c_udp:public c_thread
{
private:
   queue _memcache;
   
private:
   c_sock _udpserver;
   unsigned int _port;
   H264DecoderContext* _decoder;

public:
	c_udp(void);
	~c_udp(void);
	void Run();

	void StartReceive(unsigned int port,H264DecoderContext *decoder);
	void StopServer();
	memory_cache * GetBufferToDecode();


protected:
	void HandlePacket(char * buffer, int len);
};

给出一个常用的thread class,以上udp 从thread类继承

#include 
#include 
#include 
#include 
#include 
using namespace std;

class c_thread
{
private:

	//线程
	thread _thread;
	//等待信号
	std::mutex _signal_mutex;
	std::condition_variable _cond;
protected:
	//char  _running = false;
	char _stop = true;
	//锁定运行状态
	std::mutex _mutex;
public:
	c_thread()
	{}
	virtual ~c_thread()
	{}

public:
	char * status(){
		return &_stop;
	}
	
	void Join()
	{
		if (_thread.joinable())
			_thread.join();
	}
	bool  IsStop()
	{
		return _stop == 1 ? true : false;
	}

	void WaitForSignal()
	{
		std::unique_lock ul(_signal_mutex);
		_cond.wait(ul);
	}
	void Notify()
	{
		_cond.notify_one();
	}

	virtual int Start()
	{
		if (_stop == 1)//非運行中
		{
			_stop = 0;
			_thread = std::thread(std::bind(&c_thread::Run, this));
			return 0;
		}
		return -1;
	}	
	
	virtual void Stop()
	{
		_stop = 1; // true;
	}

	virtual void Run() = 0;
};
#endif

线程内容就放在run函数中,主线程做收包使用,记录配对的地址和路由,才能做到分发。

其他内容待续。。。。

关注
打赏
1663161521
查看更多评论
立即登录/注册

微信扫码登录

0.1090s