海思Hi3531||瑞芯微RK1109用rtsp服务器实现h264推流

了解RTP包头

一般RTSP流都是以UDP协议为主,每个包的包头(12个字节)我们称为RTP包头
在这里插入图片描述

了解H264的nalu头

RTP包的格式一:RTP包头+nalu头(一个字节 )+数据
格式二:RTP包头+fu分包头(两个字节)+数据

格式一

当nalu数据小于等于RTP包最大长度时会采用
nalu头格式:
在这里插入图片描述
F:forbidden_zero_bit.1 位,如果有语法冲突,则为 1。当网络识别此单元存在比特错误时,可将其设为 1,以便接收方丢掉该单元。

NRI:nal_ref_idc.2 位,用来指示该NALU 的重要性等级。值越大,表示当前NALU越重要。具体大于0 时取何值,没有具体规定。

Type:5 位,指出NALU 的类型。具体如表所示:
在这里插入图片描述

格式二

当nalu数据大于RTP包最大长度时会采用
fu分包头格式:
第一个字节:
在这里插入图片描述
跟上面nalu头一样,只是Type=28而已
第二个字节:
在这里插入图片描述
S: 1 bit 当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。

E: 1 bit 当设置成1, 结束位指示分片NAL单元的结束,即, 荷载的最后字节也是分片NAL单元的最后一个字节。
当跟随的FU荷载不是分片NAL单元的最后分片,结束位设置为0。

如果不是首包和尾包S和E设置为0

R: 1 bit
保留位必须设置为0,接收者必须忽略该位。

Type: 5 bits
此处的Type就是NALU头中的Type,取1-23的那个值,表示 NAL单元荷载类型定义

服务器源码

main函数

在这里插入图片描述

RTSP_PROGRESS_1函数

在这里插入图片描述

EventLoop_1函数

在这里插入图片描述

ScheduleConnections函数调用RtspServer

RtspServer函数

这个函数是RTSP服务器处理接收的各种数据并返回数据的过程。如果调用更改函数出现ERR_CONNECTION_CLOSE和ERR_GENERIC这两种错误,会进行一些资源的释放,主要是连接出现问题后的处理。

int RtspServer(RTSP_buffer *rtsp, int rtsp_num)
{
	fd_set rset,wset;       /*读写I/O描述集*/
	struct timeval t;
	int size;
	static char buffer[RTSP_BUFFERSIZE+1]; /* +1 to control the final '\0'*/
	int n;
	int res;
	struct sockaddr ClientAddr;
#ifdef RTSP_DEBUG
//    fprintf(stderr, "%s, %d\n", __FUNCTION__, __LINE__);
#endif
//    memset((void *)&ClientAddr,0,sizeof(ClientAddr));
	if (rtsp == NULL)
	{
		return ERR_NOERROR;
	}
	/*变量初始化*/
	FD_ZERO(&rset);
	FD_ZERO(&wset);
	t.tv_sec=0;				/*select 时间间隔*/
	t.tv_usec=100000;
	FD_SET(rtsp->fd,&rset);
	/*调用select等待对应描述符变化*/
	if (select(g_s32Maxfd+1,&rset,0,0,&t)<0)
	{
		fprintf(stderr,"select error %s %d\n", __FILE__, __LINE__);
		send_reply(500, NULL, rtsp);
		return ERR_GENERIC; //errore interno al server
	}
	/*有可供读进的rtsp包*/
	if (FD_ISSET(rtsp->fd,&rset))
	{
		memset(buffer,0,sizeof(buffer));
		size=sizeof(buffer)-1;  /*最后一位用于填充字符串结束标识*/
		/*读入数据到缓冲区中*/
#ifdef RTSP_DEBUG
//    fprintf(stderr, "tcp_read, %d\n", __LINE__);
#endif
		n= tcp_read(rtsp->fd, buffer, size, &ClientAddr);
		if (n==0)
		{
			return ERR_CONNECTION_CLOSE;
		}
		if (n<0)
		{
			fprintf(stderr,"read() error %s %d\n", __FILE__, __LINE__);
			send_reply(500, NULL, rtsp);                //服务器内部错误消息
			return ERR_GENERIC;
		}
		//检查读入的数据是否产生溢出
		if (rtsp->in_size+n>RTSP_BUFFERSIZE)
		{
			fprintf(stderr,"RTSP buffer overflow (input RTSP message is most likely invalid).\n");
			send_reply(500, NULL, rtsp);
			return ERR_GENERIC;//数据溢出错误
		}
#ifdef RTSP_DEBUG
		fprintf(stderr,"INPUT_BUFFER was:%s\n", buffer);
#endif
		/*填充数据*/
		memcpy(&(rtsp->in_buffer[rtsp->in_size]),buffer,n);
		rtsp->in_size+=n;
		//清空buffer
		memset(buffer, 0, n);
		//添加客户端地址信息
		memcpy(	&rtsp->stClientAddr, &ClientAddr, sizeof(ClientAddr));
		/*处理缓冲区的数据,进行rtsp处理*/
		if ((res=RTSP_handler(rtsp, rtsp_num))==ERR_GENERIC)
		{
			fprintf(stderr,"Invalid input message.\n");
			return ERR_NOERROR;
		}
	}
	/*有发送数据*/
	if (rtsp->out_size>0)
	{
		//将数据发送出去
		n= tcp_write(rtsp->fd,rtsp->out_buffer,rtsp->out_size);
		if (n<0)
		{
			fprintf(stderr,"tcp_write error %s %i\n", __FILE__, __LINE__);
			send_reply(500, NULL, rtsp);
			return ERR_GENERIC; //errore interno al server
		}
#ifdef 	RTSP_DEBUG
		//fprintf(stderr,"OUTPUT_BUFFER length %d\n%s\n", rtsp->out_size, rtsp->out_buffer);
#endif
		//清空发送缓冲区
		memset(rtsp->out_buffer, 0, rtsp->out_size);
		rtsp->out_size = 0;
	}
	//如果需要RTCP在此出加入对RTCP数据的接收,并存放在缓存中。
	//继而在schedule_do线程中对其处理。
	//rtcp控制处理,检查读入RTCP数据报
	return ERR_NOERROR;
}

RTSP_handler函数

在这里插入图片描述

RTSP_state_machine函数

主要调用RTSP_state_machine(pRtspBuf, s32Meth);函数来进行各种客户端请求报文的处理,然后应答对应的响应报文。
在这里插入图片描述
附图,客户端和服务器的RTSP交互协议
在这里插入图片描述

schedule1_do函数

函数太长就不贴出来了
这个是在RTSP_PROGRESS_1中的ScheduleInit_1函数中调用
schedule_do主要功能就是打开h264文件调用RtpSend函数把数据打包RTP发送出去。

VLC播放成功

在这里插入图片描述

源码下载

写博客不易,如果对你有关注,记得点赞收藏谢谢~~~~;有问题可加VX:a812417530

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I&You

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值