rtsp 概念啥的就不介绍了,记不住。
简单分析下。 海思板子是服务器,电脑为客服端。
首先 socket setsockopt bind listen (注意:port为554,http的port为80)
while(1) accept 接收客户端 ,accept 返回值作为新的socket ,然后运行新线程,分析rtsp中的控制信息。
nRes = recv(pClient->socket, pRecvBuf, RTSP_RECV_SIZE,0);
接收客户端的数据。 分析。
char cmdName[PARAM_STRING_MAX];
char urlPreSuffix[PARAM_STRING_MAX];
char urlSuffix[PARAM_STRING_MAX];
char cseq[PARAM_STRING_MAX];
cmdName 一般为 “OPTIONS”,“DESCRIBE”,“SETUP”,“PLAY”,“PAUSE”,“TEARDOWN”
OPTIONS 一般是客户端支持的命令。例如"OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN
DESCRIBE,音视频等信息。
SETUP 建立连接
PLAY开始。 根据 SETUP里面的port号,建立udp,通过udp传输视频信息。
然后 如何在mpp 中插入发送的数据那。首先建立一个发送线程:
while(1)
{
if(!list_empty(&RTPbuf_head))
{
RTPbuf_s *p = get_first_item(&RTPbuf_head,RTPbuf_s,list);
VENC_Sent(p->buf,p->len);
list_del(&(p->list));
free(p->buf);
free(p);
p = NULL;
count--;
//printf("count = %d\n",count);
}
usleep(5000);
}
在venc的编码里面把编码数据放在链表里面。 生产者和消费者的关系。
主要为VENC_Sent 发送函数,是对压缩数据的一种封装。解释为,VCL需要封装到NAL单元中进行传输存储。
下个分析rtp的格式。
HI_S32 VENC_Sent(char *buffer,int buflen)
{
HI_S32 i;
int is=0;
int nChanNum=0;
for(is=0;is
{
if(g_rtspClients[is].status!=RTSP_SENDING)
{
continue;
}
int heart = g_rtspClients[is].seqnum % 10000;
char* nalu_payload;
int nAvFrmLen = 0;
int nIsIFrm = 0;
int nNaluType = 0;
char sendbuf[500*1024+32];
nAvFrmLen = buflen;
struct sockaddr_in server;
server.sin_family=AF_INET;
server.sin_port=htons(g_rtspClients[is].rtpport[0]);
server.sin_addr.s_addr=inet_addr(g_rtspClients[is].IP);
intbytes=0;
unsigned int timestamp_increse=0;
timestamp_increse=(unsigned int)(90000.0 / 25);
rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0];
rtp_hdr->payload = RTP_H264;
rtp_hdr->version = 2;
rtp_hdr->marker = 0;
rtp_hdr->ssrc = htonl(10);
if(nAvFrmLen<=nalu_sent_len)
{
rtp_hdr->marker=1;
// htons是将整型变量从主机字节顺序转变成网络字节顺序,
rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++);
nalu_hdr =(NALU_HEADER*)&sendbuf[12];
nalu_hdr->F=0;
nalu_hdr->NRI= nIsIFrm;
nalu_hdr->TYPE= nNaluType;
nalu_payload=&sendbuf[13];
memcpy(nalu_payload,buffer,nAvFrmLen);
g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse;
rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid);
bytes=nAvFrmLen+ 13 ;
sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
}
else if(nAvFrmLen>nalu_sent_len)
{
int k=0,l=0;
k=nAvFrmLen/nalu_sent_len;
l=nAvFrmLen%nalu_sent_len;
int t=0;
g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse;
rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid);
while(t<=k)
{
rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++);
if(t==0)
{
rtp_hdr->marker=0;
fu_ind =(FU_INDICATOR*)&sendbuf[12];
fu_ind->F= 0;
fu_ind->NRI= nIsIFrm;
fu_ind->TYPE=28;
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->E=0;
fu_hdr->R=0;
fu_hdr->S=1;
fu_hdr->TYPE=nNaluType;
nalu_payload=&sendbuf[14];
memcpy(nalu_payload,buffer,nalu_sent_len);
bytes=nalu_sent_len+14;
sendto( udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
t++;
}
else if(k==t)
{
rtp_hdr->marker=1;
fu_ind =(FU_INDICATOR*)&sendbuf[12];
fu_ind->F= 0 ;
fu_ind->NRI= nIsIFrm ;
fu_ind->TYPE=28;
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->R=0;
fu_hdr->S=0;
fu_hdr->TYPE= nNaluType;
fu_hdr->E=1;
nalu_payload=&sendbuf[14];
memcpy(nalu_payload,buffer+t*nalu_sent_len,l);
bytes=l+14;
sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
t++;
}
else if(t
{
rtp_hdr->marker=0;
fu_ind =(FU_INDICATOR*)&sendbuf[12];
fu_ind->F=0;
fu_ind->NRI=nIsIFrm;
fu_ind->TYPE=28;
fu_hdr =(FU_HEADER*)&sendbuf[13];
//fu_hdr->E=0;
fu_hdr->R=0;
fu_hdr->S=0;
fu_hdr->E=0;
fu_hdr->TYPE=nNaluType;
nalu_payload=&sendbuf[14];
memcpy(nalu_payload,buffer+t*nalu_sent_len,nalu_sent_len);
bytes=nalu_sent_len+14;
sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
t++;
}
}
}
}
//------------------------------------------------------------
}