RawSession::SendData(unsigned char* pSendbuf, int buflen){ //std::cout << "send packet length : " << buflen << std::endl; char sendbuf[1430]; //发送的数据缓冲 memset(sendbuf, 0, 1430); int status; if ( buflen <= MAX_RTP_PKT_LENGTH ) { memcpy(sendbuf, pSendbuf, buflen); status = this->SendPacket((void *)sendbuf, buflen); CheckError(status); } else if(buflen > MAX_RTP_PKT_LENGTH) { //设置标志位Mark为0 this->SetDefaultMark(false); //printf("buflen = %d/n",buflen); //得到该需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送 int k = 0, l = 0; #ifdef FU buflen = buflen -1; #endif k = buflen / MAX_RTP_PKT_LENGTH; l = buflen % MAX_RTP_PKT_LENGTH; int t = 0;//用指示当前发送的是第几个分片RTP包 char nalHeader = pSendbuf[0]; // NALU 头ª¡¤ while( t < k || ( t==k && l>0 ) ) { if ( ( t < (k-1) ) || ( t== (k-1) && l!=0 ) )//第一包到最后包的前一包 {#ifdef FU sendbuf[0] = (nalHeader & 0x60)|28; sendbuf[1] = (nalHeader & 0x1f); if ( 0 == t ) { sendbuf[1] |= 0x80; } memcpy(sendbuf+2, &pSendbuf[t*MAX_RTP_PKT_LENGTH + 1], MAX_RTP_PKT_LENGTH); status = this->SendPacket((void *)sendbuf, MAX_RTP_PKT_LENGTH+2);#else memcpy(sendbuf, &pSendbuf[t*MAX_RTP_PKT_LENGTH], MAX_RTP_PKT_LENGTH); status = this->SendPacket((void *)sendbuf, MAX_RTP_PKT_LENGTH);#endif CheckError(status); t++; } //最后一包 else if( ( k==t && l>0 ) || ( t== (k-1) && l==0 )) { //设置标志位Mark为1 this->SetDefaultMark(true); int iSendLen; if ( l > 0) { iSendLen = buflen - t * MAX_RTP_PKT_LENGTH; } else { iSendLen = MAX_RTP_PKT_LENGTH; } #ifdef FU sendbuf[0] = (nalHeader & 0x60)|28; sendbuf[1] = (nalHeader & 0x1f); sendbuf[1] |= 0x40; memcpy(sendbuf+2, &pSendbuf[t*MAX_RTP_PKT_LENGTH + 1], iSendLen); status = this->SendPacket((void *)sendbuf, iSendLen+2);#else memcpy(sendbuf, &pSendbuf[t*MAX_RTP_PKT_LENGTH], iSendLen); status = this->SendPacket((void *)sendbuf, iSendLen);#endif CheckError(status); t++; } } }}void RawSession::SendData(unsigned char* pSendbuf, int buflen, uint32_t timestampinc, bool mark, uint8_t pt){ char sendbuf[1430]; //发送的数据缓冲 memset(sendbuf, 0, 1430); timestampinc = timestampinc * 90; int status; if ( buflen <= MAX_RTP_PKT_LENGTH ) { memcpy(sendbuf, pSendbuf, buflen); status = this->SendPacket((void *)sendbuf, buflen, pt, mark, timestampinc); CheckError(status); } else if(buflen > MAX_RTP_PKT_LENGTH) { //设置标志位Mark为0 this->SetDefaultMark(false); //printf("buflen = %d/n",buflen); //得到该需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送 int k = 0, l = 0; #ifdef FU buflen = buflen -1; #endif k = buflen / MAX_RTP_PKT_LENGTH; l = buflen % MAX_RTP_PKT_LENGTH; int t = 0;//用指示当前发送的是第几个分片RTP包 char nalHeader = pSendbuf[0]; // NALU 头ª¡¤ while( t < k || ( t==k && l>0 ) ) { if ( ( t < (k-1) ) || ( t== (k-1) && l!=0 ) )//第一包到最后包的前一包 {#ifdef FU sendbuf[0] = (nalHeader & 0x60)|28; sendbuf[1] = (nalHeader & 0x1f); if ( 0 == t ) { sendbuf[1] |= 0x80; } memcpy(sendbuf+2, &pSendbuf[t*MAX_RTP_PKT_LENGTH + 1], MAX_RTP_PKT_LENGTH); status = this->SendPacket((void *)sendbuf, MAX_RTP_PKT_LENGTH + 2, pt, false, 0);#else memcpy(sendbuf, &pSendbuf[t*MAX_RTP_PKT_LENGTH], MAX_RTP_PKT_LENGTH); status = this->SendPacket((void *)sendbuf, MAX_RTP_PKT_LENGTH, pt, false, 0);#endif CheckError(status); t++; } //最后一包 else if( ( k==t && l>0 ) || ( t== (k-1) && l==0 )) { //设置标志位Mark为1 this->SetDefaultMark(true); int iSendLen; if ( l > 0) { iSendLen = buflen - t * MAX_RTP_PKT_LENGTH; } else { iSendLen = MAX_RTP_PKT_LENGTH; } #ifdef FU sendbuf[0] = (nalHeader & 0x60)|28; sendbuf[1] = (nalHeader & 0x1f); sendbuf[1] |= 0x40; memcpy(sendbuf+2, &pSendbuf[t*MAX_RTP_PKT_LENGTH + 1], iSendLen); status = this->SendPacket((void *)sendbuf, iSendLen+2, pt, true, timestampinc);#else memcpy(sendbuf, &pSendbuf[t*MAX_RTP_PKT_LENGTH], iSendLen); status = this->SendPacket((void *)sendbuf, iSendLen, pt, true, timestampinc);#endif CheckError(status); t++; } } } }
int Init(const std::string& ip, uint16_t destport);
初始化部分有几点需要注意的:
1.H264固定的采样率是90000HZ,对于时间戳单位应为
sessparams.SetOwnTimestampUnit(1.0/90000.0); //时间戳单位
2.如果视频帧率是25fps,那么时间戳间隔就是3600
this->SetDefaultTimestampIncrement(3600);
void SendData(unsigned char* pSendbuf, int buflen);
使用分片封包模式,这里大概介绍一下
当NALU的长度超过MTU时,就必须对NALU单元进行分片封包.也称为Fragmentation Units(FUs).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator | FU header | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| FU payload |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 14. RTP payload format for FU-A
The FU indicator octet has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
别被名字吓到这个格式就是上面提到的RTP h264负载类型,Type为FU-A
The FU header has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
S bit为1表示分片的NAL开始,当它为1时,E不能为1
E bit为1表示结束,当它为1,S不能为1
R bit保留位
Type就是NALU头中的Type,取1-23的那个值
这里有几个问题需要强调一下:
1.就是长度小于MTU时候,一个RTP发送一个nalu
2.每个I帧前面发送一个sps pps,这两个RTP包和接下来的I帧RTP包的时间戳相同
3.当nalu大于MTU,添加FU头,同时注意,要去掉nalu的header,就是第一个字节。FU indicator + FU header + nalu[1]
|
|
2020-11-4 11:30:05
评论
举报
|
|
|