组装RTP头 -java

来源:互联网 发布:淘宝可以推广店铺吗 编辑:程序博客网 时间:2024/05/16 11:31


音频


//添加音频头 大小可调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的起始码0x000001CalculateUtil.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); // 版本号,此版本固定为2videoSendbuf[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_payloadSystem.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=0videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xDF);// R=0videoSendbuf[13] = (byte) (videoSendbuf[13] | 0x80);// S=1videoSendbuf[13] = (byte) (videoSendbuf[13] | ((byte) n.nal_unit_type));// 同理将sendbuf[14]赋给nalu_playloadSystem.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位,当前床书的是最后一个分片时该位置1videoSendbuf[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=0videoSendbuf[13] = (byte) (videoSendbuf[13] & 0x7F); // S=0videoSendbuf[13] = (byte) (videoSendbuf[13] | 0x40); // E=1videoSendbuf[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=0videoSendbuf[13] = (byte) (videoSendbuf[13] & 0x7F); // S=0videoSendbuf[13] = (byte) (videoSendbuf[13] & 0xBF); // E=0videoSendbuf[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++;}}}}}



0 0