NALU转JT1078的Java工具包
文章目录Java NALU 转 JT/T 1078 媒体包工具实现说明完整工具类配套UDP发送工具发给JT1078平台使用流程示例关键适配要点依赖无Netty纯原生byte数组版本Java NALU 转 JT/T 1078 媒体包工具实现说明JT1078 媒体包结构视频包固定头部24字节 NALU负载4字节魔数0x30 0x31 0x63 0x641字节RTP标志位 V22字节序列号6字节BCD格式SIM卡号1字节逻辑通道号1字节帧分片标记0不分片/1首包/3中间/2尾包8字节时间戳(毫秒)帧间隔2字节负载长度NALU裸流数据完整工具类importio.netty.buffer.ByteBuf;importio.netty.buffer.Unpooled;importjava.nio.ByteOrder;importjava.util.concurrent.atomic.AtomicInteger;/** * NALU - JT/T 1078 媒体数据包封装工具 * 支持不分包、大包自动分片MTU 950 */publicclassJt1078NaluEncoder{// JT1078魔数 0x30316364privatestaticfinalintMAGIC0x30316364;// JT视频固定头部长度 24字节privatestaticfinalintJT_HEAD_LEN24;// 单包最大NALU负载长度留头部空间privatestaticfinalintMAX_NALU_PER_PACK950;// 全局自增序列号privatefinalAtomicIntegerseqGennewAtomicInteger(0);// SIM卡号BCD 12位字符串转6字节BCD数组publicstaticbyte[]simToBcd(Stringsim){if(sim.length()!12){thrownewIllegalArgumentException(SIM必须12位数字);}byte[]bcdnewbyte[6];for(inti0;i6;i){charc1sim.charAt(i*2);charc2sim.charAt(i*21);byteh(byte)(c1-0);bytel(byte)(c2-0);bcd[i](byte)((h4)|l);}returnbcd;}/** * 封装NALU为JT1078媒体包列表自动分片 * param nalu H264/H265完整NALU裸流 * param simBcd 6字节BCD SIM卡 * param channel 逻辑通道号 0~99 * param frameInterval 帧间隔ms如33 * return 多个JT1078数据包ByteBuf */publicByteBuf[]encodeNaluToJt1078(byte[]nalu,byte[]simBcd,intchannel,intframeInterval){intnaluLennalu.length;intsliceCount(naluLenMAX_NALU_PER_PACK-1)/MAX_NALU_PER_PACK;ByteBuf[]resultnewByteBuf[sliceCount];longnowTsSystem.currentTimeMillis();for(inti0;isliceCount;i){intoffseti*MAX_NALU_PER_PACK;intsliceLenMath.min(MAX_NALU_PER_PACK,naluLen-offset);bytesubFlag;if(sliceCount1){subFlag0x00;// 不分包}elseif(i0){subFlag0x01;// 首包}elseif(isliceCount-1){subFlag0x02;// 尾包}else{subFlag0x03;// 中间包}result[i]buildSingleJtPacket(nalu,offset,sliceLen,simBcd,channel,subFlag,nowTs,frameInterval);}returnresult;}/** * 构造单个JT1078媒体包 */privateByteBufbuildSingleJtPacket(byte[]fullNalu,intoffset,intsliceLen,byte[]simBcd,intchannel,bytesubFlag,longtsMs,intframeInterval){inttotalPacketLenJT_HEAD_LENsliceLen;ByteBufbufUnpooled.buffer(totalPacketLen).order(ByteOrder.BIG_ENDIAN);// 1. 4字节魔数buf.writeInt(MAGIC);// 2. 1字节RTP标志 V2buf.writeByte(0x80);// 3. 2字节序列号intseqseqGen.getAndIncrement()0xFFFF;buf.writeShort(seq);// 4. 6字节SIM BCDbuf.writeBytes(simBcd);// 5. 1字节逻辑通道buf.writeByte(channel);// 6. 1字节分片标记(低4位分片高4位帧类型0视频)buf.writeByte(subFlag);// 7. 8字节时间戳(6)帧间隔(2)buf.writeLong((tsMs16)|(frameInterval0xFFFF));// 8. 2字节NALU分片长度buf.writeShort(sliceLen);// 9. NALU分片数据buf.writeBytes(fullNalu,offset,sliceLen);returnbuf;}// 测试示例publicstaticvoidmain(String[]args){Jt1078NaluEncoderencodernewJt1078NaluEncoder();Stringsim1213800138000;byte[]simBcdsimToBcd(sim12);// 模拟一段H264 NALU数据byte[]testNalunewbyte[]{0x00,0x00,0x01,0x67,0x42,(byte)0x80,0x1E,0xDA,0x01};ByteBuf[]jtPacketsencoder.encodeNaluToJt1078(testNalu,simBcd,0,33);for(ByteBufpkt:jtPackets){byte[]rawnewbyte[pkt.readableBytes()];pkt.readBytes(raw);System.out.println(JT包长度:raw.length);pkt.release();}}}配套UDP发送工具发给JT1078平台importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetSocketAddress;publicclassJt1078UdpSender{privatefinalDatagramSocketsocket;privatefinalInetSocketAddresstarget;publicJt1078UdpSender(Stringhost,intport)throwsException{socketnewDatagramSocket();targetnewInetSocketAddress(host,port);}publicvoidsendPacket(byte[]jtData)throwsException{DatagramPacketdpnewDatagramPacket(jtData,jtData.length,target);socket.send(dp);}publicvoidclose(){socket.close();}}使用流程示例// 1. 初始化编码器Jt1078NaluEncoderencodernewJt1078NaluEncoder();byte[]simBcdJt1078NaluEncoder.simToBcd(13912345678);// 2. UDP发送器连接JT1078流媒体服务端口Jt1078UdpSenderudpSendernewJt1078UdpSender(127.0.0.1,8000);// 循环收到H264 NALU裸流 byte[] naluwhile(true){byte[]nalugetH264Nalu();// 封装为JT1078包数组自动分片ByteBuf[]jtBufsencoder.encodeNaluToJt1078(nalu,simBcd,0,33);for(ByteBufbuf:jtBufs){byte[]pktnewbyte[buf.readableBytes()];buf.readBytes(pkt);udpSender.sendPacket(pkt);buf.release();}Thread.sleep(30);}关键适配要点分片机制NALU超过950字节自动拆分包头部标记首/中/尾包平台才能拼接完整帧SIM卡必须12位数字转6字节BCDJT1078强制输出UDP包可直接发给支持JT1078的流媒体服务ZLMediaKit JT1078端口序列号全局自增uint16循环溢出自动处理时间戳使用系统毫秒兼容国标时间格式若需要反向 JT1078包解析为NALU可以配套写解码工具。依赖仅依赖 Netty buffer工程已有Netty直接用无Netty可替换byte数组手动拼接dependencygroupIdio.netty/groupIdartifactIdnetty-buffer/artifactIdversion4.1.94.Final/version/dependency无Netty纯原生byte数组版本如需脱离Netty我可以给你纯byte[]拼接版本不引入任何第三方包。