rtp传输h264每隔两三秒出现卡顿和马赛克的现象

佳亮 2017-03-06 02:36:15
给h264数据添加报头,分包和发送
    private void SendR(byte[] r,int h264len)throws IOException {
//showMessage("in send rtp");

codecTotal += h264len;
Log.d(TAG,"SendR:"+h264len);
memset(sendbuf, 0, 1500);
sendbuf[1] = (byte) (sendbuf[1] | 96); // 负载类型号96
sendbuf[0] = (byte) (sendbuf[0] | 0x80); // 版本号,此版本固定为2
sendbuf[1] = (byte) (sendbuf[1] & 254); //标志位,由具体协议规定其值
sendbuf[11] = 10;//随即指定10,并在本RTP回话中全局唯一,java默认采用网络字节序号 不用转换
if (h264len <= packageSize) {
sendbuf[1] = (byte) (sendbuf[1] | 0x80); // 设置rtp M位为1
System.arraycopy(intToByte(seq_num++), 0, sendbuf, 2, 2);
{
// 倒序
byte temp = 0;
temp = sendbuf[3];
sendbuf[3] = sendbuf[2];
sendbuf[2] = temp;
}
// 设置NALU HEADER, 并将这个HEADER填入sendbuf[12]
sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x80)) << 7);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) ((r[0] & 0x60) >> 5)) << 5);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x1f)));
// 同理将sendbuf[13]赋给nalu_payload
System.arraycopy(r, 1, sendbuf, 13, h264len - 1);
ts_current = ts_current + timestamp_increse;
System.arraycopy(intToByte(ts_current), 0, sendbuf, 4, 4);
{
byte temp = 0;
temp = sendbuf[4];
sendbuf[4] = sendbuf[7];
sendbuf[7] = temp;
temp = sendbuf[5];
sendbuf[5] = sendbuf[6];
sendbuf[6] = temp;
}
bytes = h264len + 12;//获sendbuf的长度,为nalu的长度(包含nalu头但取出起始前缀,加上rtp_header固定长度12个字节)
client.send(new DatagramPacket(sendbuf, bytes, addr, port/*9200*/));
//send(sendbuf,bytes);

} else if (h264len > packageSize) {
int k = 0, l = 0;
k = h264len / packageSize;
l = h264len % packageSize;
int t = 0;
ts_current = ts_current + timestamp_increse;
System.arraycopy(intToByte(ts_current), 0, sendbuf, 4, 4);
{
byte temp = 0;
temp = sendbuf[4];
sendbuf[4] = sendbuf[7];
sendbuf[7] = temp;
temp = sendbuf[5];
sendbuf[5] = sendbuf[6];
sendbuf[6] = temp;
}
while (t <= k) {
System.arraycopy(intToByte(seq_num++), 0, sendbuf, 2, 2);
{
byte temp = 0;
temp = sendbuf[3];
sendbuf[3] = sendbuf[2];
sendbuf[2] = temp;
}
if (t == 0) {
sendbuf[1] = (byte) (sendbuf[1] & 0x7F);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x80)) << 7);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) ((r[0] & 0x60) >> 5)) << 5);
sendbuf[12] = (byte) (sendbuf[12] | (byte) (28));
sendbuf[13] = (byte) (sendbuf[13] & 0xBF);//E=0
sendbuf[13] = (byte) (sendbuf[13] & 0xDF);//R=0
sendbuf[13] = (byte) (sendbuf[13] | 0x80);//S=1
sendbuf[13] = (byte) (sendbuf[13] | ((byte) (r[0] & 0x1f)));
System.arraycopy(r, 1, sendbuf, 14, packageSize);
client.send(new DatagramPacket(sendbuf, packageSize+14, addr, port/*9200*/));
//send(sendbuf,1414);
t++;
} else if (t == k) {
sendbuf[1] = (byte) (sendbuf[1] | 0x80);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x80)) << 7);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) ((r[0] & 0x60) >> 5)) << 5);
sendbuf[12] = (byte) (sendbuf[12] | (byte) (28));
sendbuf[13] = (byte) (sendbuf[13] & 0xDF); //R=0
sendbuf[13] = (byte) (sendbuf[13] & 0x7F); //S=0
sendbuf[13] = (byte) (sendbuf[13] | 0x40); //E=1
sendbuf[13] = (byte) (sendbuf[13] | ((byte) (r[0] & 0x1f)));

if (0 != l) {
System.arraycopy(r, t * packageSize + 1, sendbuf, 14, l - 1);//l-1
bytes = l - 1 + 14; //bytes=l-1+14;
client.send(new DatagramPacket(sendbuf, bytes, addr, port/*9200*/));
//send(sendbuf,bytes);
}//pl
t++;
} else if (t < k && 0 != t) {
sendbuf[1] = (byte) (sendbuf[1] & 0x7F); //M=0
sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x80)) << 7);
sendbuf[12] = (byte) (sendbuf[12] | ((byte) ((r[0] & 0x60) >> 5)) << 5);
sendbuf[12] = (byte) (sendbuf[12] | (byte) (28));
sendbuf[13] = (byte) (sendbuf[13] & 0xDF); //R=0
sendbuf[13] = (byte) (sendbuf[13] & 0x7F); //S=0
sendbuf[13] = (byte) (sendbuf[13] & 0xBF); //E=0

sendbuf[13] = (byte) (sendbuf[13] | ((byte) (r[0] & 0x1f)));
System.arraycopy(r, t * packageSize + 1, sendbuf, 14, packageSize);
client.send(new DatagramPacket(sendbuf, packageSize+14, addr, port/*9200*/));
//send(sendbuf,1414);
t++;
}
}
}
}


从对摄像头取出的数据后,判断每帧的类型,然后发送
       try {

while (outputBufferIndex >= 0) {
//Log.i("AvcEncoder", "Get H264 Buffer Success! flag = "+bufferInfo.flags+",pts = "+bufferInfo.presentationTimeUs+"");
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);

int type = outputBuffer.get(4) & 0x07;
if (type == 7 || type == 8) {//SPS和PPS
mPpsSps = outData;
int sps_length = outData.length - 8 -4;
SPS=new byte[sps_length];
System.arraycopy(outData,4,SPS,0,sps_length);
PPS=new byte[4];
System.arraycopy(outData,8+sps_length,PPS,0,4);
Log.e("liang", "SPS是"+Util.bytesToHexString(SPS) );
Log.e("liang", "PPS是"+Util.bytesToHexString(PPS) );
//Sendspspps();
}else if(type==5){//关键帧
byte[] iframeData = new byte[mPpsSps.length + outData.length];
System.arraycopy(mPpsSps, 0, iframeData, 0, mPpsSps.length);
System.arraycopy(outData, 0, iframeData, mPpsSps.length, outData.length);
outData = iframeData;
Log.e("liang", "关键帧是"+Util.bytesToHexString(outData) );
byte[] newData = new byte[outData.length-4];
System.arraycopy(outData, 4, newData, 0, outData.length-4);
SendR(newData, outData.length - 4);
outputStream.write(outData, 0, outData.length);

}else {//B帧
Log.e("liang", "普通帧是"+Util.bytesToHexString(outData) );
byte[] newData = new byte[outData.length-4];
System.arraycopy(outData, 4, newData, 0, outData.length-4);
SendR(newData, outData.length - 4);
outputStream.write(outData, 0, outData.length);
}


mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);
}

} catch (Throwable t) {
t.printStackTrace();
}

使用vlc进行播放,每隔两三秒就会出现卡顿和马赛克,但延迟不高,两三秒
...全文
2245 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
CyberLogix 2017-07-26
  • 打赏
  • 举报
回复
解决了就好,帮顶
Gogym 2017-05-23
  • 打赏
  • 举报
回复
请问一下,有收到rtp后对H264进行组包的代码吗?可以分享一下吗?
佳亮 2017-03-20
  • 打赏
  • 举报
回复
问题已经解决,只要设置下vlc的网络缓冲即可
qprevf 2017-03-06
  • 打赏
  • 举报
回复
/* byte 0 */ /* CSRC count :4*/ /* header extension flag :1*/ /* padding flag :1*/ /* protocol version :2*/ byte byte0; /* byte 1 */ /* payload type :7*/ /* marker bit :1*/ byte byte1; /* bytes 2, 3 */ /* sequence number */ short seqno; /* bytes 4-7 */ /* timestamp in ms */ int ts; /* bytes 8-11 */ /* synchronization source */ int ssrc;
佳亮 2017-03-06
  • 打赏
  • 举报
回复
C/C++不是很熟,关于rtp head,能再多说一点吗,还有那些东西没有进行设置?
qprevf 2017-03-06
  • 打赏
  • 举报
回复
你的rtp head 都没设置完, 你找ffmpeg里的nal_send和ff_rtp_send_data 两个函数看看, 老老实实参考的移植过来
rightorwrong 2017-03-06
  • 打赏
  • 举报
回复
出现马赛克应该是丢包了 你把rtp的序号打下

2,541

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧