使用p2p发送GB28181流的设计

萌思特

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)传输开始
使用p2p发送GB28181流的设计_第1张图片

3.1层次

层次关系以及所需要的协议等等如下图所示
使用p2p发送GB28181流的设计_第2张图片

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<memory_cache*> _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<std::mutex> 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函数中,主线程做收包使用,记录配对的地址和路由,才能做到分发。

其他内容待续。。。。

你可能感兴趣的:(音视频和c++,java,物联网,IoT,物联网,webrtc,p2p,服务器,gb28181,rtp)