音频
//添加音频头 大小可调
private byte[] audioBufferSend = new byte[32 + 1 + 12];
addAudioTitle(audioBufferSend);
/***
* RTP 头
* @param audioBufferSend
*/
private void addAudioTitle(byte[] audioBufferSend) {
CalculateUtil.memset(audioBufferSend, 0, audioBufferSend.length);// 情况sendbuf,此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值
audioBufferSend[0] = (byte) 0x80;
audioBufferSend[1] = (byte)(audioBufferSend[1] | AUDIO_RTP_FH);//(byte) 0x68; // 104 16进制68
// Log.i(TAG, "@@@@@@@@@@@@@@@@@audioSeq_num: " + audioSeq_num);
System.arraycopy(CalculateUtil.intToByte(audioSeq_num++), 0, audioBufferSend, 2, 2);
{
byte temp = 0;
temp = audioBufferSend[3];
audioBufferSend[3] = audioBufferSend[2];
audioBufferSend[2] = temp;
}
audioTs_current = audioTs_current + audioTimestamp_increse;
// rtp_hdr.timestamp = ts_current;// htonl(ts_current)
// java默认网络字节序
System.arraycopy(CalculateUtil.intToByte(audioTs_current), 0, audioBufferSend, 4, 4);
{
byte temp = 0;
temp = audioBufferSend[4];
audioBufferSend[4] = audioBufferSend[7];
audioBufferSend[7] = temp;
temp = audioBufferSend[5];
audioBufferSend[5] = audioBufferSend[6];
audioBufferSend[6] = temp;
}
audioBufferSend[8] = (byte) 0x68;
audioBufferSend[9] = (byte) 0x87;
audioBufferSend[10] = (byte) 0x58;
audioBufferSend[11] = (byte) 0xde;
audioBufferSend[12] = (byte) 0xf0;
}
// 时间戳增量
private float audioFramerate = 500;
private int audioTimestamp_increse = (int) (80000.0 / audioFramerate); // +0.5);
private int audioTs_current = 0;
private int AUDIO_RTP_FH = 0;
private int audioSeq_num = 0;
/***
* RTP 头
* @param audioBufferSend
*/
private void addAudioTitle(byte[] audioBufferSend) {
// CalculateUtil.memset(audioBufferSend, 0, audioBufferSend.length);// 情况sendbuf,此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值
audioBufferSend[0] = (byte) 0x80;
audioBufferSend[1] = (byte)(audioBufferSend[1] | AUDIO_RTP_FH);//PCMU; // 104
// Log.i(TAG, "@@@@@@@@@@@@@@@@@audioSeq_num: " + audioSeq_num);
System.arraycopy(CalculateUtil.intToByte(audioSeq_num++), 0, audioBufferSend, 2, 2);
{
byte temp = 0;
temp = audioBufferSend[3];
audioBufferSend[3] = audioBufferSend[2];
audioBufferSend[2] = temp;
}
audioTs_current = audioTs_current + audioTimestamp_increse;
// rtp_hdr.timestamp = ts_current;// htonl(ts_current)
// java默认网络字节序
System.arraycopy(CalculateUtil.intToByte(audioTs_current), 0, audioBufferSend, 4, 4);
{
byte temp = 0;
temp = audioBufferSend[4];
audioBufferSend[4] = audioBufferSend[7];
audioBufferSend[7] = temp;
temp = audioBufferSend[5];
audioBufferSend[5] = audioBufferSend[6];
audioBufferSend[6] = temp;
}
audioBufferSend[8] = (byte) ((new Random()).nextInt() % 256);
audioBufferSend[9] = (byte) ((new Random()).nextInt() % 256);
audioBufferSend[10] = (byte) ((new Random()).nextInt() % 256);
audioBufferSend[11] = (byte) ((new Random()).nextInt() % 256);
}
}
/**
* 视频流 分包
* @param bForIn
* @throws Exception
*/
protected void sendByteForIn(byte[] bForIn) throws Exception {
videoBais = new ByteArrayInputStream(bForIn);
while (!(0 == videoBais.available())) {
// Log.i(TAG, "GetAnnexbNALU start:" + (System.currentTimeMillis() - start));
GetAnnexbNALU(n, bForIn); // 每执行一次, 文件指针指向本次找到的NALU的末尾,
// Log.i(TAG, "GetAnnexbNALU end:" + (System.currentTimeMillis() - start));
// 下一位置即为下个NALU的起始码0x000001
CalculateUtil.dump(n);// 输出NALU的长度和NALU
// 从文件中 获取一个nalu大小
// 判断其大小 分包发送
CalculateUtil.memset(videoSendbuf, 0, 1500);// 情况sendbuf,此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值
// Log.i(TAG, "memset :" + (System.currentTimeMillis() - start));
videoSendbuf[1] = (byte) (videoSendbuf[1] | RTP_FH); // 负载类型号96
// System.out.println("-----!"+sendbuf[1]);
videoSendbuf[0] = (byte) (videoSendbuf[0] | 0x80); // 版本号,此版本固定为2
videoSendbuf[1] = (byte) (videoSendbuf[1] & 254); // 标志位,由具体协议规定其值
videoSendbuf[11] = 10; // 随即指定10,并在本RTP回话中全局唯一,java默认采用网络字节序号 不用转换
// Log.i(TAG, "@@@@@@@@@@@@@@@@@seq_num: " + videoSeq_num);
// Log.i(TAG, "n.len start :" + (System.currentTimeMillis() - start));
if (n.len <= 1400) {
videoSendbuf[1] = (byte) (videoSendbuf[1] | 0x80); // 设置rtp M位为1
// sendbug[2], sendbuf[3]赋值seq_num ++ 每发送一次rtp包增1
// sendbuf[3] = (byte) seq_num ++
// Log.i(TAG, "arraycopy start :" + (System.currentTimeMillis() - start));
System.arraycopy(CalculateUtil.intToByte(videoSeq_num++), 0, videoSendbuf, 2, 2);
// Log.i(TAG, "System.arraycopy start end :" + (System.currentTimeMillis() - start));
{
// 倒序
byte temp = 0;
temp = videoSendbuf[3];
videoSendbuf[3] = videoSendbuf[2];
videoSendbuf[2] = temp;
}
// 设置NALU HEADER, 并将这个HEADER填入sendbuf[12]
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) n.forbidden_bit) << 7);
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) (n.nal_reference_idc >> 5)) << 5);
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) n.nal_unit_type));
// Log.i(TAG, "arraycopy start :" + (System.currentTimeMillis() - start));
// 同理将sendbuf[13]赋给nalu_payload
System.arraycopy(n.buf, 1, videoSendbuf, 13, n.len - 1);// 去掉nalu头的nalu剩余类容写入sendbuf[13]开始的字符串
// Log.i(TAG, "System.arraycopy start end :" + (System.currentTimeMillis() - start));
videoTs_current = videoTs_current + videoTimestamp_increse;
// rtp_hdr.timestamp = ts_current;// htonl(ts_current)
// java默认网络字节序
// Log.i(TAG, "arraycopy start :" + (System.currentTimeMillis() - start));
System.arraycopy(CalculateUtil.intToByte(videoTs_current), 0, videoSendbuf, 4, 4);
// Log.i(TAG, "arraycopy end :" + (System.currentTimeMillis() - start));
{
// 倒序
byte temp = 0;
temp = videoSendbuf[4];
videoSendbuf[4] = videoSendbuf[7];
videoSendbuf[7] = temp;
temp = videoSendbuf[5];
videoSendbuf[5] = videoSendbuf[6];
videoSendbuf[6] = temp;
}
bytes = n.len + 12; // 获sendbuf的长度,为nalu的长度(包含nalu头但取出起始前缀,加上rtp_header固定长度12个字节)
// Log.i(TAG, "l1400:" + (System.currentTimeMillis() - start) + ", 包长:" + bytes);
sendVideoPacket(videoSendbuf, bytes, 12, (int)(System.currentTimeMillis() - start));// 发送rtp包
// Log.i(TAG, "发送时间: " + (System.currentTimeMillis() - start)+"线程标示"+Thread.currentThread().getId());
} else if (n.len > 1400) {
// 得到该nalu需要用多少长度为1400字节的rtp包来发送
int k = 0, l = 0;
k = n.len / 1400; // 需要k个1400字节的rtp包
l = n.len % 1400; // 最后一个rtp包需要装载的字节数
int t = 0; // 用于指示当前发送的第几个分片RTP包
videoTs_current = videoTs_current + videoTimestamp_increse;
// rtp_hdr->timestamp=htonl(ts_current);
System.arraycopy(CalculateUtil.intToByte(videoTs_current), 0, videoSendbuf, 4, 4);
{
// 倒序
byte temp = 0;
temp = videoSendbuf[4];
videoSendbuf[4] = videoSendbuf[7];
videoSendbuf[7] = temp;
temp = videoSendbuf[5];
videoSendbuf[5] = videoSendbuf[6];
videoSendbuf[6] = temp;
}
while (t <= k) {
// rtp_hdr->seq_no = htons(seq_num ++);//序列号, 每发送一个rtp包增加1
// sendbuf[3] = (byte) seq_num ++;
System.arraycopy(CalculateUtil.intToByte(videoSeq_num++), 0, videoSendbuf, 2, 2);
{
// 倒序
byte temp = 0;
temp = videoSendbuf[3];
videoSendbuf[3] = videoSendbuf[2];
videoSendbuf[2] = temp;
}
if (0 == t) {
// 设置rtp M位
videoSendbuf[1] = (byte) (videoSendbuf[1] & 0x7F); // M=0
// 设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) n.forbidden_bit) << 7);
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) (n.nal_reference_idc >> 5)) << 5);
videoSendbuf[12] = (byte) (videoSendbuf[12] | (byte) (28));
// 设置FU HEADER,并将这个HEADER填入snedbuf[13]
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xBF);// E=0
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xDF);// R=0
videoSendbuf[13] = (byte) (videoSendbuf[13] | 0x80);// S=1
videoSendbuf[13] = (byte) (videoSendbuf[13] | ((byte) n.nal_unit_type));
// 同理将sendbuf[14]赋给nalu_playload
System.arraycopy(n.buf, 1, videoSendbuf, 14, 1400);
bytes = 1400 + 14;
// Log.i(TAG, "0 == t包:" + (System.currentTimeMillis() - start) + ", 包长:" + bytes);
sendVideoPacket(videoSendbuf, bytes, 12, (int)(System.currentTimeMillis() - start));
// Log.i(TAG, "0 == t发送时间: " + (System.currentTimeMillis() - start));
t++;
}
// 发送一个需要分片的NALU的非第一个分片,清零FU HEADER
// 的S位,如果该分片是该NALU的最后一个分片,置FU HEADER的E位
else if (k == t) // 发送的是最后一个分片,注意最后一个分片的长度可能超过1400字节(当l>1386时)
{
// 设置rtp M位,当前床书的是最后一个分片时该位置1
videoSendbuf[1] = (byte) (videoSendbuf[1] | 0x80);
// 设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) n.forbidden_bit) << 7);
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) (n.nal_reference_idc >> 5)) << 5);
videoSendbuf[12] = (byte) (videoSendbuf[12] | (byte) (28));
// 设置FU HEADER,并将这个HEADER填入sendbuf[13]
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xDF); // R=0
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0x7F); // S=0
videoSendbuf[13] = (byte) (videoSendbuf[13] | 0x40); // E=1
videoSendbuf[13] = (byte) (videoSendbuf[13] | ((byte) n.nal_unit_type));
// 将nalu的最后神域的l-1(去掉了一个字节的nalu头)字节类容写入sendbuf[14]开始的字符串
System.arraycopy(n.buf, t * 1400 + 1, videoSendbuf, 14,
l - 1);
bytes = l - 1 + 14;
// Log.i(TAG, "k == t包:" + (System.currentTimeMillis() - start) + ", 包长:" + bytes);
sendVideoPacket(videoSendbuf, bytes, 11, (int)(System.currentTimeMillis() - start));// 发送rtp包
// Log.i(TAG, "k == t发送时间: " + (System.currentTimeMillis() - start));
t++;
} else if (t < k && 0 != t) {
// 设置rtp M位
videoSendbuf[1] = (byte) (videoSendbuf[1] & 0x7F); // M=0
// 设置FU INDICATOR,并将这个HEADER填入sendbuf[12]
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) n.forbidden_bit) << 7);
videoSendbuf[12] = (byte) (videoSendbuf[12] | ((byte) (n.nal_reference_idc >> 5)) << 5);
videoSendbuf[12] = (byte) (videoSendbuf[12] | (byte) (28));
// 设置FU HEADER,并将这个HEADER填入sendbuf[13]
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xDF); // R=0
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0x7F); // S=0
videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xBF); // E=0
videoSendbuf[13] = (byte) (videoSendbuf[13] | ((byte) n.nal_unit_type));
System.arraycopy(n.buf, t * 1400 + 1, videoSendbuf, 14, 1400);// 去掉起始前缀的nalu剩余内容写入sendbuf[14]开始的字符串。
bytes = 1400 + 14; // 获得sendbuf的长度,为nalu的长度(除去原NALU头)加上rtp_header,fu_ind,fu_hdr的固定长度14字节
// Log.i(TAG, "t < k包:" + (System.currentTimeMillis() - start) + ", 包长:" + bytes);
sendVideoPacket(videoSendbuf, bytes, 11, (int)(System.currentTimeMillis() - start));// 发送rtp包
// Log.i(TAG, "t < k发送时间: " + (System.currentTimeMillis() - start));
t++;
}
}
}
}
}