Puente de reenvío RTP GB28181 UDP

Objetivo

Solo un nodo puede conectarse a la red externa. En este momento, necesitamos un puente de reenvío. Es muy simple hacer un puente de reenvío udp. Es simple y útil. Usamos asio c ++ para programar

principio

Use asio para recibir y enviar de forma asíncrona. Después de recibir, se reenviará en el puente inmediatamente y se reenviará a la dirección de la red externa. Aquí hay una demostración, el programa usa 127.0.0.1.

el código

#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;
}

experimento

Escriba un programa de envío RTP, use la cámara, la cámara se reenvía al puerto 5000 de la dirección RTP y luego usa el puente para transferir a la dirección IP de la red externa, aquí para demostrar el uso de la dirección de red local 127.0.0.1 , usamos vlc para reenviar desde Recibir datos del puente
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
.Utilizo el conteo en el programa, recibo una vez cada 100 paquetes rtp, alrededor de 300Kbit-400Kbit por segundo, abro vlc para recibir datos Como se muestra en la figura, vlc normalmente se reproduce después de
inserte la descripción de la imagen aquí
recibir los datos del programa rtp normalmente.

La ventaja de este programa es que las secuencias rtp y gb28181 ps se pueden reenviar normalmente.

Extender e iterar

Luego, realice el reenvío tcp más tarde, el reenvío tcp es obviamente mucho más complicado que el udp, para este programa también es necesario desarrollar un http tranquilo, que también necesita agregar la adquisición de datos de paquetes rtp como ssrc, el protocolo http espera la recepción para decirle al programa de servicio qué rtp necesita ser reenviado Bao, espera el siguiente

Supongo que te gusta

Origin blog.csdn.net/qianbo042311/article/details/130713808
Recomendado
Clasificación