RTP GB28181 文件测试工具

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RTP GB28181 文件测试工具相关的知识,希望对你有一定的参考价值。

以下情况时使用了GB28181 中 udp发送视频流的情况,有的相机udp丢包比较严重,有的可以,对有问题的相机着重进行分析

read ps

RTP测试工具进一步升级
今天写了一段程序,为了解决花屏的问题,需要知道问题到底在哪里,保存了几百个ps文件,然后读出按照流程保存成h264文件,使用vlc 工具读,有简单跳帧。

int main_ps()

	int meetkeyframe = 0;
	const char* buffer = "j:/ps/h264save%d.264";
	char filename[128];
	uint8_t* h264buffer = new uint8_t[1024 * 500];
	int h264length = 0;
	int skip = 0;
	FILE* fpw = fopen("j:/out1.264", "wb");
	for (int i = 0; i < 2855; i++)
	
		sprintf(filename, buffer, i);
		FILE* fp = fopen(filename, "rb");
		if (fp != NULL)
		
			fseek(fp, 0, SEEK_END);
			long len = ftell(fp);
			fseek(fp, 0, SEEK_SET);
			//fread(pp, sizeof(char) * 4, 1, fp);
			uint8_t* data = new uint8_t[len];
			fread(data, len, 1, fp);
			if (*data == 0x00 && *(data + 1) == 0x00 && *(data + 2) == 0x01 && *(data + 3) == 0xba)
			
				GetH264FromPs((char*)data, len, (char*)h264buffer, &h264length);
				if (h264length > 0)
				
					if (meetkeyframe == 0)
					
						uint8_t* pos = h264buffer + 4;
						if ((*pos & 0x1f) == 0x07)
							meetkeyframe = 1;
					
					if (meetkeyframe == 1)
					
						std::cout << "the length "<<len<< "--" << h264length << std::endl;
						fwrite(h264buffer, h264length, 1, fpw);
					
					else
					
						std::cout << "skip num" << skip++ << std::endl;
					
				
			
			std::cout << "the file of" << i << std::endl;
			fclose(fp);
		
	
	fclose(fpw);
	return 0;

read rtp

为了进一步确定问题,读了1万6000个RTP包存储成文件,在存储成h264看情况如何

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "../libRtpReceive/analysevideo.h"
#include "../libRtpReceive/c_rtp.h"


s_rtp_context g_ctx;

//解ps流,qianbo 请按照这条路走下去
int live_rtp_unpack_ps(s_rtp_context* ctx, uint8_t* payload, int payloadlen, uint32_t ssrc)

	uint8_t* buffer = ctx->v_buffer;
	int& buflen = ctx->v_len;
	//analyse_struct &as = ctx->v_as;
#define D(x) *(payload+x)
	if (D(0) == 0x00 && D(1) == 0x00 && D(2) == 0x01 && D(3) == 0xc0)
	
		//(音频数据包)
		//std::cout << "audio packet" << std::endl;
		return 0;
	

	if (D(0) == 0x00 && D(1) == 0x00 && D(2) == 0x01 && D(3) == 0xba)
	
		if (buflen > 0)//数据已经凑齐,可以发送或者显示
		
#define B(x) *(buffer+x)
			if (B(0) == 0x00 && B(1) == 0x00 && B(2) == 0x01 && B(3) == 0xba)
			
				int h264length = 0;
				uint8_t* h26xbuffer = new uint8_t[buflen];
				GetH264FromPs((char*)buffer, buflen, (char*)h26xbuffer, &h264length);
				if (h264length > 0)
				
					if (g_ctx.v_meet_keyframe == 0)
					
						uint8_t* pos = h26xbuffer + 4;
						if ((*pos & 0x1f) == 0x07)
							g_ctx.v_meet_keyframe = 1;
					
					if (g_ctx.v_meet_keyframe == 1)
					
						if (g_ctx.fwp == NULL)
							g_ctx.fwp = fopen("j:/out2.264","wb");
						//std::cout << "the length " << len << "--" << h264length << std::endl;
						fwrite(h26xbuffer, h264length, 1, g_ctx.fwp);
					
					else
					
						//std::cout << "skip num" << skip++ << std::endl;
					
				

				if (ctx->v_meet_keyframe == 0)
				
					//写入文件
				
				delete[]h26xbuffer;
			
			buflen = 0;
		
	
	//合帧
	std::memcpy(buffer + buflen, payload, payloadlen);
	buflen += payloadlen;
	return 0;






int ReadRTPPacket(uint8_t* data, int dlen)


	RTPFrame_ frame(data, (int)dlen);
	uint8_t* payload = frame.GetPayloadPtr();
	int payloadlen = frame.GetPayloadSize();
	uint32_t timestamp = frame.GetTimestamp();
	rtp_header* rtp = (rtp_header*)data;
	//big(net) to little(home)
	uint32_t ssrc = b2l(rtp->ssrc);

#define D(x) *(payload+x)
	//if (ctx->v_is_ps == -1)//未曾确定是否ps流
	if (D(0) == 0x00 && D(1) == 0x00 && D(2) == 0x01 && D(3) == 0xba)
	
		//std::cout << " the stream is " << stream << std::endl;
		g_ctx.v_ssrc = ssrc;
		g_ctx.v_is_ps = 1;
	
	if (g_ctx.v_is_ps == 1)
	
		uint16_t nowseq = frame.GetSequenceNumber();
		std::cout << "seq:" << nowseq << " ";
		if (nowseq - g_ctx.v_last_sequenceNum != 1)
		
			std::cout << "not continue seq "<< nowseq - g_ctx.v_last_sequenceNum <<std::endl;
		
		g_ctx.v_last_sequenceNum = frame.GetSequenceNumber();

		g_ctx.v_payloadtype = frame.GetPayloadType();
		live_rtp_unpack_ps(&g_ctx, payload, payloadlen, ssrc);
	
	return 0;

int main()

	const char* buffer = "j:/rtp/h264saveRTP%d.264";
	char filename[128];
	uint8_t* h264buffer = new uint8_t[1024 * 500];
	int h264length = 0;
	int skip = 0;
	//FILE* fpw = fopen("j:/out2.264", "wb");
	for (int i = 0; i < 16445; i++)
	
		sprintf(filename, buffer, i);
		FILE* fp = fopen(filename, "rb");
		if (fp != NULL)
		
			fseek(fp, 0, SEEK_END);
			long len = ftell(fp);
			fseek(fp, 0, SEEK_SET);
			//fread(pp, sizeof(char) * 4, 1, fp);
			uint8_t* data = new uint8_t[len];
			fread(data, len, 1, fp);
			ReadRTPPacket(data, len);

			//std::cout <<i <<" ";
			fclose(fp);
		
	
	if(g_ctx.fwp!=NULL)
		fclose(g_ctx.fwp);


通过打印RTP包的sequence number,相减后发现,丢包较多,平均每隔一定的时间会丢3-4个RTP包,有时会丢掉几十个,上几百个包,乱序的情况比较少,有一次,通过seq number相减后会得到负数。

RTP工具以后会同时增加分析RTP协议的可视化。

以上是关于RTP GB28181 文件测试工具的主要内容,如果未能解决你的问题,请参考以下文章

GB28181技术基础之3 - RTP

rtsp,rtp,gb28181直接转化为html5播放

GB/T28181-2016基于RTP的视音频数据封装和技术实现

GB28181 PS流传输格式详解

GB28181设备端PS流封装和发送

使用ffmpeg来探测GB28181的ps流