RTP GB28181 udp forwarding bridge

Purpose

Only one node can connect to the external network. At this time, we need a forwarding bridge. It is very simple to make a udp forwarding bridge. It is simple and useful. We use asio c++ to program

principle

Use asio to receive and send asynchronously. After receiving, it will be forwarded on the bridge immediately and forwarded to the external network address. Here is a demonstration, the program uses 127.0.0.1.

the code

#define ASIO_STANDALONE
#include <iostream>
#include <cstdlib>
#include <iostream>
#include "asio.hpp"

using asio::ip::udp;
static const asio::ip::udp::endpoint s_end_point(asio::ip::address::from_string("127.0.0.1"), 6000);

class TicToc
{
    
    
public:
	TicToc()
	{
    
    
		tic();
	}

	void tic()
	{
    
    
		start = std::chrono::system_clock::now();
	}

	double toc()
	{
    
    
		end = std::chrono::system_clock::now();
		std::chrono::duration<double> elapsed_seconds = end - start;
		start = end;
		return elapsed_seconds.count() ;
	}

private:
	std::chrono::time_point<std::chrono::system_clock> start, end;
};

class server
{
    
    
private:
	TicToc v_tock;
public:
	server(asio::io_context& io_context, short port)
		: socket_(io_context, udp::endpoint(udp::v4(), port))
	{
    
    
		do_receive();
	}
	int64_t v_i = 0;
	uint64_t v_recvbytes = 0;
	void do_receive()
	{
    
    
		
		socket_.async_receive_from(
			asio::buffer(data_, max_length), sender_endpoint_,
			[this](std::error_code ec, std::size_t bytes_recvd)
		{
    
    
			if (!ec && bytes_recvd > 0)
			{
    
    
				if (v_i == 0)
					v_tock.tic();
				v_recvbytes += bytes_recvd;
				if (v_i++ > 100) //每一百个包统计一次
				{
    
    
					double res = v_tock.toc();
					float m = v_recvbytes / res /1000.0f;
					std::cout<<"time:"<<res<<" bytes:"<< v_recvbytes<<" recv byte every second:" << m <<"KB"<< std::endl;
					v_i = 0;
					v_recvbytes = 0;
				}
				do_send(bytes_recvd);
			}
			else
			{
    
    
				do_receive();
			}
		});
	}

	void do_send(std::size_t length)
	{
    
    
		socket_.async_send_to(
			asio::buffer(data_, length), s_end_point,
			[this](std::error_code /*ec*/, std::size_t /*bytes_sent*/)
		{
    
    
			do_receive();
		});
	}

private:
	udp::socket socket_;
	udp::endpoint sender_endpoint_;
	udp::endpoint sender_to;
	enum {
    
     max_length = 1500 };
	char data_[max_length];
};

int main(int argc, char* argv[])
{
    
    
	try
	{
    
    
		/*if (argc != 2)
		{
			std::cerr << "Usage: async_udp_echo_server <port>\n";
			return 1;
		}*/

		asio::io_context io_context;

		server s(io_context, 5000);

		io_context.run();
	}
	catch (std::exception& e)
	{
    
    
		std::cerr << "Exception: " << e.what() << "\n";
	}

	return 0;
}

experiment

Write an RTP sending program, use the camera, the camera is forwarded to the port 5000 of the RTP address, and then use the bridge to transfer to the external network IP address, here to demonstrate the use of the local network address 127.0.0.1, we use vlc to forward from Receive data from the bridge
insert image description here
insert image description here
. I use counting in the program, receive once every 100 rtp packets, about 300Kbit-400Kbit per second, open vlc to receive data As shown in the figure,
insert image description here
vlc normally plays after receiving the rtp program data normally.

The advantage of this program is that both rtp and gb28181 ps streams can be forwarded normally.

Extend and iterate

Then do tcp forwarding later, tcp forwarding is obviously much more complicated than udp, for this program also need to develop a http restful, which also needs to add rtp packet data acquisition such as ssrc, http protocol waits for reception to tell the service program which rtp needs to be forwarded Bao, wait for the next one

Guess you like

Origin blog.csdn.net/qianbo042311/article/details/130713808
RTP