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