做直播,音视频通讯。经常需要通过rtp协议封装音视频数据来发送。网上找到的基本都是c或c++版本的,没有JAVA版本的。就算千辛万苦找到一篇java版本的,要么不能用,要么就是一些片段,要么有封包没解包。
很是蛋疼,本人也是这样,刚开始不太熟悉rtp协议,不太明白怎么封包组包,痛苦了几天,终于搞出来了,分享给有需要的朋友,希望对你们有所帮助。
直接看代码吧。不多说了。
首先看看关键类:
package com.imsdk.socket.udp.codec;
import android.os.SystemClock;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class RtspPacketEncode {
private static final String TAG = "RtspPacketEncode";
//------------视频转换数据监听-----------
public interface H264ToRtpLinsener {
void h264ToRtpResponse(byte[] out, int len);
}
private H264ToRtpLinsener h264ToRtpLinsener;
//执行回调
private void exceuteH264ToRtpLinsener(byte[] out, int len) {
if (this.h264ToRtpLinsener != null) {
h264ToRtpLinsener.h264ToRtpResponse(out, len);
}
}
// -------视频--------
private int framerate = 10;
private byte[] sendbuf = new byte[1500];
private int packageSize = 1400;
private int seq_num = 0;
private int timestamp_increse = (int) (90000.0 / framerate);//framerate是帧率
private int ts_current = 0;
private int bytes = 0;
// -------视频END--------
public RtspPacketEncode(H264ToRtpLinsener h264ToRtpLinsener) {
this.h264ToRtpLinsener = h264ToRtpLinsener;
}
/**
* 一帧一帧的RTP封包
*
* @param r
* @return
*/
public void h264ToRtp(byte[] r, int h264len) throws Exception {
CalculateUtil.memset(sendbuf, 0, 1500);
sendbuf[1] = (byte) (sendbuf[1] | 96); // 负载类型号96,其值为:01100000
sendbuf[0] = (byte) (sendbuf[0] | 0x80); // 版本号,此版本固定为2
sendbuf[1] = (byte) (sendbuf[1] & 254); //标志位,由具体协议规定其值,其值为:01100000
sendbuf[11] = 10;//随机指定10,并在本RTP回话中全局唯一,java默认采用网络字节序号 不用转换(同源标识符的最后一个字节)
if (h264len <= packageSize) {
sendbuf[1] = (byte) (sendbuf[1] | 0x80); // 设置rtp M位为1,其值为:11100000,分包的最后一片,M位(第一位)为0,后7位是十进制的96,表示负载类型
sendbuf[3] = (byte) seq_num++;
System.arraycopy(CalculateUtil.intToByte(seq_num++), 0, sendbuf, 2, 2);//send[2]和send[3]为序列号,共两位
{
// java默认的网络字节序是大端字节序(无论在什么平台上),因为windows为小字节序,所以必须倒序
/**参考:
* http://blog.csdn.net/u011068702/article/details/51857557
* http://cpjsjxy.iteye.com/blog/1591261
*/
byte temp = 0;
temp = sendbuf[3];
sendbuf[3] = sendbuf[2];
sendbuf[2] = temp;
}
// FU-A HEADER, 并将这个HEADER填入sendbuf[12]
sendbuf[12] = (byte) (sendbuf[12] | ((byte)