在 JT/T 1078 协议中视频的传输协议负载包定义如下:
用java开发的首选框架是netty,处理粘包、断包都很轻松,以下是解包的代码:
@Slf4j
public class Jt1078MediaFrameDecoder extends ByteToMessageDecoder {
/**
* RTP包固定字段长度
*/
private static final int BASE_LEN = 18;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
Object decoded = decode(ctx, in);
if (decoded != null) {
out.add(decoded);
}
}
private Object decode(ChannelHandlerContext ctx, ByteBuf buf) {
if (buf.readableBytes() < BASE_LEN) {
log.info("RTP包太小,{}", ByteBufUtil.hexDump(buf));
return null;
}
//寻找包头0x30316364
int headerIdx = -1;
int readerIdx = buf.readerIndex();
for (int i = readerIdx; i < buf.writerIndex() - 3; i++) {
if (buf.getInt(i) == 0x30316364) {
headerIdx = i;
break;
}
}
if (headerIdx == -1) {
log.error("RTP包未找到包头0x30316364,{}", ByteBufUtil.hexDump(buf));
buf.skipBytes(buf.readableBytes());
return null;
}
//检测后续包长度
buf.skipBytes(headerIdx - readerIdx);
if (buf.readableBytes() < BASE_LEN) {
log.info("RTP包后续长度太小,{}", ByteBufUtil.hexDump(buf));
return null;
}
buf.markReaderIndex();
int fullPacketLen = BASE_LEN;
//解析出数据类型
int dataType = buf.getByte(15 + headerIdx) >> 4;
//时间戳,标识此RTP包当前帧的相对时间,单位毫秒,数据类型为0b0100时则没有该字段
if (dataType != Constants.RTP_DATA_TYPE_0100) {
if (buf.readableBytes() > fullPacketLen + 8) {
fullPacketLen += 8;
} else {
log.info("RTP包时间戳后续长度太小,{}", ByteBufUtil.hexDump(buf));
return null;
}
}
//与上一个关键帧或上一帧之间的时间间隔,单位毫秒,数据类型为非视频帧时则没有该字段
if (dataType != Constants.RTP_DATA_TYPE_0011 && dataType != Constants.RTP_DATA_TYPE_0100) {
if (buf.readableBytes() > fullPacketLen + 4) {
fullPacketLen += 4;
} else {
log.info("RTP包Last I Frame Interval和Last Frame Interval后续长度太小,{}", ByteBufUtil.hexDump(buf));
return null;
}
}
//数据体长度
int bodyLen = buf.getShort(headerIdx + fullPacketLen - 2);
//数据体长度太小则将读指针重置到包头,等待下一包后再解码
if (buf.readableBytes() < fullPacketLen + bodyLen) {
log.info("RTP包数据体长度小于{}", bodyLen);
buf.resetReaderIndex();
return null;
}
//解析出完整包,交给下一个处理器处理
fullPacketLen += bodyLen;
ByteBuf frame = buf.readRetainedSlice(fullPacketLen);
return frame;
}
}
官方网站:http://www.gps-pro.cn
开源地址:https://github.com/gnss-pro
微信:17158638841 或扫描下图