GB28181——实时视频显示

一、主要实现功能
1、支持四路设备接入
2、实时视频分屏显示
3、接入设备信息存储
二、待完善功能(现阶段)
1、设备的删除 (已更新)
2、语音对讲 (暂时不处理)
3、视频输出通道的实时修改 (已更新)
三、运行效果
1、参数配置
GB28181——实时视频显示_第1张图片
2、设备显示,显示所有添加的设备以及实时显示在线状态
GB28181——实时视频显示_第2张图片
3、视频输出
视频输出采用的GB28181协议通过UDP接收数据,ffmpeg进行数据处理显示,后面准备添加rtsp拉流功能
因为只有一台设备,暂时只能通过修改输出通道进行测试分屏显示
GB28181——实时视频显示_第3张图片

GB28181——实时视频显示_第4张图片
GB28181——实时视频显示_第5张图片
四、部分代码

//实现分屏
M_VideoWidget::M_VideoWidget(QWidget* parent)
	: QWidget{ parent }
{

}

void M_VideoWidget::init()
{
#ifndef no_style
	QStringList qss;
	qss.append("QFrame{border:2px solid #000000;}");
	qss.append("QLabel{font:75 25px;color:#F0F0F0;border:2px solid #AAAAAA;background:#303030;}");
	qss.append("QLabel:focus{border:2px solid #00BB9E;background:#555555;}");
	//将所有字符串接
	this->setStyleSheet(qss.join(""));
#endif

	//表格布局存放通道
	QGridLayout* gridLayout = new QGridLayout(this);

	gridLayout->setSpacing(1);
	gridLayout->setContentsMargins(0, 0, 0, 0);
	int height = this->height() / 2;
	int width = this->width() / 2;
	qDebug() << this->height() << this->width();
	int m_videoNume = 4;
	for (int i = 0; i < m_videoNume; ++i)
	{
		My_Glabel* widget = new My_Glabel(this);
		widget->setFixedHeight(height - 7);
		widget->setFixedWidth(width - 7);
		widget->setObjectName(QString("video%1").arg(i + 1));
		widget->installEventFilter(this);
		widget->setFocusPolicy(Qt::StrongFocus);
		// widget->setAlignment(Qt::AlignCenter);
		widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

		m_widget << widget;
	}
	gridLayout->addWidget(m_widget.at(0), 0, 0, 1, 1);
	gridLayout->addWidget(m_widget.at(1), 0, 1, 1, 1);
	gridLayout->addWidget(m_widget.at(2), 1, 0, 1, 1);
	gridLayout->addWidget(m_widget.at(3), 1, 1, 1, 1);

	this->setLayout(gridLayout);
}
void M_VideoWidget::setheight(int height)
{
	this->setFixedHeight(height);
}

void M_VideoWidget::setwidth(int width)
{
	this->setFixedWidth(width);
}

void M_VideoWidget::getWidgets(QList<My_Glabel*>& widget)
{
	int num = m_widget.size();


	widget = m_widget;
}

int M_VideoWidget::setIamge(int num, QImage image)
{
	m_widget.at(num)->setPixmap(image);
	return 0;
}
//UDP接收视频数据,对数据包进行处理,接收到一定数量的udp包后再进行数据的解析
void My_UdpServer::run()
{
	//ffmpeg初始化
	m_peg->init();

	int c;
	static struct {
		const char* name;
		t_format format;
	} formats[] = {
	  {"dump",    F_dump},
	  {"header",  F_header},
	  {"hex",     F_hex},
	  {"rtcp",    F_rtcp},
	  {"short",   F_short},
	  {"payload", F_payload},
	  {"ascii",   F_ascii}
	};

	t_format format = F_ascii;
	struct sockaddr_in sin, rtp;
	struct timeval start;
	struct timeval timeout;   /* timeout to limit recording */
	double dstart;            /* time as double */
	float duration = 1000000; /* maximum duration in seconds */
	int trunc = 1000000;   /* bytes to show for F_hex and F_dump */
	enum { FromFile, FromNetwork } source;
	int sock[2];
	
	fd_set readfds;
	extern char* optarg;
	extern int optind;
	int i;
	int nfds = 0;
	extern double tdbl(struct timeval*);	
	startupSocket();

	/* set maximum time to gather packets */
	timeout.tv_sec = duration;
	timeout.tv_usec = (duration - (float)timeout.tv_sec) * 1000000.0;

	/* if no optional arguments, we are reading from a file */
	source = FromNetwork;
	char ip[] = "192.168.1.22/30004";    //为测试方便这里暂时将ip与端口固定
	if (hpt(ip, &sin, NULL) == -1) {

		exit(1);
	}

	rtp = sin;
	nfds = open_network(ip, format != F_rtcp, sock, &sin);
	gettimeofday(&start, 0);
	dstart = tdbl(&start);
	format = F_payload;

#if 1	
	while (1)
	{
		int len;
		RD_buffer_t packet;
		struct timeval now;
		double dnow;

		if (source == FromNetwork)
		{
			FD_ZERO(&readfds);
			if (sock[0] >= 0) FD_SET(sock[0], &readfds);
			if (sock[1] >= 0) FD_SET(sock[1], &readfds);
			c = select(nfds + 1, &readfds, 0, 0, &timeout);
			if (c < 0)
			{
				perror("select");
				exit(1);
			}
			/* end of recording time reached */
			else if (c == 0)
			{
				if (verbose)
					fprintf(stderr, "Time limit reached.\n");
				exit(0);
			}
			for (i = 0; i < 2; i++)
			{
				if (sock[i] >= 0 && FD_ISSET(sock[i], &readfds))
				{
					int alen = sizeof(sin);

					/* subtract elapsed time from remaining timeout ,如果应用再linux 下需要注意以下的几个函数有所变化*/
					gettimeofday(&now, 0);
					dnow = tdbl(&now);
					timeout.tv_sec = duration - (dnow - dstart);
					if (timeout.tv_sec < 0) timeout.tv_sec = 0;
					
					len = recvfrom(sock[i], packet.p.data, sizeof(packet.p.data),
						0, (struct sockaddr*)&sin, &alen);
					qDebug("----- %s",inet_ntoa(sin.sin_addr));
					int channel = -1;
					M_Sqlite::inst()->findChannel(inet_ntoa(sin.sin_addr), channel);
					//data_Process(packet.p.data, len);
					data_Process(channel,packet.p.data, len);
				}
			}
		}
	}
#endif
}

五、补(两路摄像机数据显示)
GB28181——实时视频显示_第6张图片

你可能感兴趣的:(GB28181,音视频,ffmpeg,qt)