From afe371d39a054b2f2a9e5875b945584eec8a8141 Mon Sep 17 00:00:00 2001 From: 18045010223 <zjbassadmin@> Date: 星期一, 28 七月 2025 09:09:05 +0800 Subject: [PATCH] 解决2019协议设备播放问题 --- src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java | 157 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 131 insertions(+), 26 deletions(-) diff --git a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java index 926e658..738023e 100644 --- a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java +++ b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java @@ -24,18 +24,28 @@ static Logger logger = LoggerFactory.getLogger(Jtt1078Handler.class); private static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session-key"); - @Override - protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception - { + // @Override + protected void channelRead011(ChannelHandlerContext ctx, Packet packet) throws Exception { io.netty.channel.Channel nettyChannel = ctx.channel(); + // 妫�鏌ュ崗璁増鏈� + packet.seek(14); + byte b14 = packet.nextByte(); + byte b15 = packet.nextByte(); + boolean is2019Protocol = (b14 & 0xFF) == 0x00 && (b15 & 0xFF) == 0x00; + int simLength = is2019Protocol ? 10 : 6; + + // 璇诲彇SIM鍗″拰閫氶亾鍙� packet.seek(8); - String sim = packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD(); + StringBuilder simBuilder = new StringBuilder(); + for(int i=0; i<simLength; i++) { + simBuilder.append(packet.nextBCD()); + } + String sim = simBuilder.toString(); int channel = packet.nextByte() & 0xff; String tag = sim + "-" + channel; - if (SessionManager.contains(nettyChannel, "tag") == false) - { + if (!SessionManager.contains(nettyChannel, "tag")) { Channel chl = PublishManager.getInstance().open(tag); SessionManager.set(nettyChannel, "tag", tag); logger.info("start publishing: {} -> {}-{}", Long.toHexString(chl.hashCode() & 0xffffffffL), sim, channel); @@ -43,36 +53,131 @@ Integer sequence = SessionManager.get(nettyChannel, "video-sequence"); if (sequence == null) sequence = 0; - // 1. 鍋氬ソ搴忓彿 - // 2. 闊抽闇�瑕佽浆鐮佸悗鎻愪緵璁㈤槄 - int lengthOffset = 28; - int dataType = (packet.seek(15).nextByte() >> 4) & 0x0f; - int pkType = packet.seek(15).nextByte() & 0x0f; - // 閫忎紶鏁版嵁绫诲瀷锛�0100锛屾病鏈夊悗闈㈢殑鏃堕棿浠ュ強Last I Frame Interval鍜孡ast Frame Interval瀛楁 - if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; - else if (dataType == 0x03) lengthOffset = 28 - 4; + + // 鍔ㄦ�佽幏鍙栨暟鎹被鍨嬪拰鍖呯被鍨� + int dataTypePos = is2019Protocol ? 19 : 15; + packet.seek(dataTypePos); + int dataType = (packet.nextByte() >> 4) & 0x0f; + int pkType = packet.nextByte() & 0x0f; + + // 璁$畻鏁版嵁鍋忕Щ閲� + int baseOffset = is2019Protocol ? 32 : 28; + int lengthOffset = baseOffset; + if (dataType == 0x04) { + lengthOffset = baseOffset - 8 - 2 - 2; + } else if (dataType == 0x03) { + lengthOffset = baseOffset - 4; + } int pt = packet.seek(5).nextByte() & 0x7f; + int timestampOffset = is2019Protocol ? 20 : 16; - if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) - { - // 纰板埌缁撴潫鏍囪鏃讹紝搴忓彿+1 - if (pkType == 0 || pkType == 2) - { + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) { + if (pkType == 0 || pkType == 2) { sequence += 1; SessionManager.set(nettyChannel, "video-sequence", sequence); } - long timestamp = packet.seek(16).nextLong(); - PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, packet.seek(lengthOffset + 2).nextBytes()); + long timestamp = packet.seek(timestampOffset).nextLong(); + byte[] videoData = packet.seek(lengthOffset + 2).nextBytes(); + logger.debug("Publishing video data - size: {}, seq: {}, ts: {}", videoData.length, sequence, timestamp); + PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, videoData); } - else if (dataType == 0x03) - { - long timestamp = packet.seek(16).nextLong(); - byte[] data = packet.seek(lengthOffset + 2).nextBytes(); - PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, data); + else if (dataType == 0x03) { + long timestamp = packet.seek(timestampOffset).nextLong(); + byte[] audioData = packet.seek(lengthOffset + 2).nextBytes(); + logger.debug("Publishing audio data - size: {}, seq: {}, ts: {}", audioData.length, sequence, timestamp); + PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, audioData); + } + } + @Override + protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception { + io.netty.channel.Channel nettyChannel = ctx.channel(); + + // 1. 鍗忚鐗堟湰妫�娴� + boolean is2019Protocol = detectProtocolVersion(packet); + int simLength = is2019Protocol ? 10 : 6; + + // 2. 璇诲彇SIM鍗″彿鍜岄�氶亾鍙� + packet.seek(8); + StringBuilder simBuilder = new StringBuilder(); + for (int i = 0; i < simLength; i++) { + simBuilder.append(packet.nextBCD()); + } + String sim = simBuilder.toString(); + + int channelPos = is2019Protocol ? 18 : 14; + packet.seek(channelPos); + int channel = packet.nextByte() & 0xff; + String tag = sim + "-" + channel; + + // 3. 浼氳瘽绠$悊 + if (!SessionManager.contains(nettyChannel, "tag")) { + Channel chl = PublishManager.getInstance().open(tag); + SessionManager.set(nettyChannel, "tag", tag); + logger.info("start publishing: {} -> {}-{} (Protocol: {})", + Long.toHexString(chl.hashCode() & 0xffffffffL), + sim, channel, + is2019Protocol ? "2019" : "2016"); + } + + // 4. 鏁版嵁澶勭悊 + Integer sequence = SessionManager.get(nettyChannel, "video-sequence"); + if (sequence == null) sequence = 0; + + int dataTypePos = is2019Protocol ? 19 : 15; + packet.seek(dataTypePos); + int dataType = (packet.nextByte() >> 4) & 0x0f; + int pkType = packet.nextByte() & 0x0f; + + int baseOffset = is2019Protocol ? 32 : 28; + int lengthOffset = baseOffset; + if (dataType == 0x04) lengthOffset = baseOffset - 8 - 2 - 2; + else if (dataType == 0x03) lengthOffset = baseOffset - 4; + + int pt = packet.seek(5).nextByte() & 0x7f; + int timestampOffset = is2019Protocol ? 20 : 16; + + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) { + if (pkType == 0 || pkType == 2) { + sequence += 1; + SessionManager.set(nettyChannel, "video-sequence", sequence); + } + long timestamp = packet.seek(timestampOffset).nextLong(); + byte[] videoData = packet.seek(lengthOffset + 2).nextBytes(); + PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, videoData); + } + else if (dataType == 0x03) { + long timestamp = packet.seek(timestampOffset).nextLong(); + byte[] audioData = packet.seek(lengthOffset + 2).nextBytes(); + PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, audioData); } } + private boolean detectProtocolVersion(Packet packet) { + // 鏂规硶1锛氭鏌�6瀛楄妭SIM鍗″彿鍚庣殑濉厖 + packet.seek(8 + 6); // 2016鍗忚SIM鍗$粨鏉熶綅缃� + byte b14 = packet.nextByte(); + byte b15 = packet.nextByte(); + + // 濡傛灉鏄�2019鍗忚锛岃繖閲屽簲璇ユ槸0x00濉厖 + if ((b14 & 0xFF) == 0x00 && (b15 & 0xFF) == 0x00) { + return true; + } + + // 鏂规硶2锛氭鏌ユ暟鎹被鍨嬩綅缃殑鏈夋晥鎬� + packet.seek(15); + byte dtByte = packet.nextByte(); + int dataType = (dtByte >> 4) & 0x0F; + int frameType = dtByte & 0x0F; + + // 濡傛灉鏁版嵁绫诲瀷鎴栧抚绫诲瀷鏃犳晥锛屽彲鑳芥槸2019鍗忚 + if (dataType > 4 || frameType > 3) { + return true; + } + + // 榛樿杩斿洖2016鍗忚 + return false; + } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { -- Gitblit v1.9.3