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/util/ByteHolder.java | 3 ffmpeg.zip | 0 src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java | 157 ++++++++++++++-- src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java | 316 +++++++++++++++++++++++++++++++--- src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java | 8 src/main/resources/app.properties | 3 src/main/java/cn/org/hentai/jtt1078/app/Test.java | 19 ++ src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java | 2 8 files changed, 451 insertions(+), 57 deletions(-) diff --git a/src/main/resources/ffmpeg.zip b/ffmpeg.zip similarity index 100% rename from src/main/resources/ffmpeg.zip rename to ffmpeg.zip Binary files differ diff --git a/src/main/java/cn/org/hentai/jtt1078/app/Test.java b/src/main/java/cn/org/hentai/jtt1078/app/Test.java new file mode 100644 index 0000000..430d33d --- /dev/null +++ b/src/main/java/cn/org/hentai/jtt1078/app/Test.java @@ -0,0 +1,19 @@ +package cn.org.hentai.jtt1078.app; + +public class Test { + public static void main(String[] args) { + byte[] buffer = { + 48, 49, 99, 100, -127, 98, 0, 0, 0, 0, 0, 0, 1, 51, 7, 68, 67, -128, 1, 1, 0, 0, 1, -104, 53, -33, -2, 57, 0, 0, 0, 100, 3, -74, 0, 0, 0, 1, 103, 77, 0, 10, -106, 84, 2, -128, 45, -120, 0, 0, 0, 1, 104, -18, 60, -128, 0, 0, 0, 1, 101, -120, -128, 64, 5, -1, -96, -32, 64, 111, 81}; + + /* byte[] buffer = { + 48, 49, 99, 100, -127, + 98, 0, 2, 2, 2, + 50,80, 2, 32, 1, + 3,0, 0, 1, -104, 55, -112, 118, 111, 0, 0, 0, 0, 3, -74, 114, 66, 70, -114, -16, -109, 45, 86, -20,};*/ + int position = 28; + int h = buffer[position] & 0xff; + int l = buffer[position + 1] & 0xff; + int result = ((h << 8) | l) & 0xffff; + System.out.println("result = " + result); + } +} diff --git a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java index 9c2344c..4c07b05 100644 --- a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java +++ b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java @@ -4,48 +4,306 @@ import cn.org.hentai.jtt1078.util.ByteUtils; import cn.org.hentai.jtt1078.util.Packet; -/** - * Created by matrixy on 2019/4/9. - */ -public class Jtt1078Decoder -{ - //4096 - ByteHolder buffer = new ByteHolder(4096); +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; - public void write(byte[] block) - { +/** + * JTT1078 Protocol Decoder + */ + +public class Jtt1078Decoder { + private ByteHolder buffer = new ByteHolder(4096); + private int simLen = 0; + private String sim = ""; + private byte channel = 0; + private static final byte[] HEAD1078 = {0x30, 0x31, 0x63, 0x64}; + + public void write(byte[] block) { buffer.write(block); } - public void write(byte[] block, int startIndex, int length) - { + public void write(byte[] block, int startIndex, int length) { byte[] buff = new byte[length]; System.arraycopy(block, startIndex, buff, 0, length); write(buff); } - public Packet decode() - { - if (this.buffer.size() < 30) return null; + public Packet decode() { + if (buffer.size() < 4) return null; - if ((buffer.getInt(0) & 0x7fffffff) != 0x30316364) - { - String header = ByteUtils.toString(buffer.array(30)); - throw new RuntimeException("invalid protocol header: " + header); + // Check header + if (!Arrays.equals(buffer.array(4), HEAD1078)) { +// log.warn("Invalid protocol header, expected:30316364, actual:{}", +// ByteUtils.toHexString(buffer.array(4))); + buffer.clear(); + return null; } - int lengthOffset = 28; - int dataType = (this.buffer.get(15) >> 4) & 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 bodyLength = this.buffer.getShort(lengthOffset); + // Try to determine protocol version if not set + if (simLen == 0) { + // Try version 16 (2013 protocol) + Packet packet = decodePacket(16); + if (packet != null) { + Analyze analyze = parse16(packet.getBytes()); + sim = analyze.getSim(); + channel = analyze.getCh(); + simLen = 6; + System.out.printf("%s-%d device started output%n", sim, channel); + return packet; + } - int packetLength = bodyLength + lengthOffset + 2; + // Try version 19 (2019 protocol) + packet = decodePacket(19); + if (packet != null) { + Analyze analyze = parse19(packet.getBytes()); + sim = analyze.getSim(); + channel = analyze.getCh(); + simLen = 10; + System.out.printf("%s-%d device started output%n", sim, channel); + return packet; + } - if (this.buffer.size() < packetLength) return null; - byte[] block = new byte[packetLength]; - this.buffer.sliceInto(block, packetLength); - return Packet.create(block); + return null; + } else { + return decodePacket(simLen == 6 ? 16 : 19); + } + } + + private Packet decodePacket(int version) { + int dataTypeIndex = version == 16 ? 15 : 19; + if (buffer.size() < dataTypeIndex + 1) return null; + + byte dataType = (byte) ((buffer.get(dataTypeIndex) >> 4) & 0x0F); + int dataLenIndex; + + switch (dataType) { + case 3: + dataLenIndex = dataTypeIndex + 9; + break; + case 4: + dataLenIndex = dataTypeIndex + 1; + break; + default: + dataLenIndex = dataTypeIndex + 13; + } + //log.info("dataType:"+dataType); + if (buffer.size() < dataLenIndex + 2) return null; + int dataLen = buffer.getShort(dataLenIndex) & 0xFFFF; + int packetLength = dataLenIndex + 2 + dataLen; + + if (buffer.size() < packetLength) return null; + + // Check next packet header + if (buffer.size() >= packetLength + 4) { + byte[] nextHeader = new byte[4]; + for (int i = 0; i < 4; i++) { + nextHeader[i] = buffer.get(packetLength + i); + } + if (!Arrays.equals(nextHeader, HEAD1078)) { + // log.warn("Invalid data type: {}", dataType); + buffer.clear(); + return null; + } + } + + byte[] packetData = new byte[packetLength]; + buffer.sliceInto(packetData, packetLength); + // printPacketInfo(packetData, version); + return Packet.create(packetData); + } + + private Analyze parse16(byte[] data) { + Analyze analyze = new Analyze(); + analyze.setPt((byte) (data[5] & 0x7F)); + analyze.setSn((short) (((data[6] & 0xFF) << 8) | (data[7] & 0xFF))); + + StringBuilder simBuilder = new StringBuilder(); + for (int i = 0; i < 6; i++) { + simBuilder.append(nextBcd(data, 8 + i)); + } + analyze.setSim(simBuilder.toString()); + + analyze.setCh(data[14]); + analyze.setDt((byte) ((data[15] >> 4) & 0x0F)); + analyze.setFi((byte) (data[15] & 0x0F)); + + int dataLenIndex; + switch (analyze.getDt()) { + case 3: + analyze.setTimestamp(setTimestamp(data, 16)); + dataLenIndex = 24; + break; + case 4: + dataLenIndex = 16; + break; + default: + analyze.setTimestamp(setTimestamp(data, 16)); + analyze.setLastIInterval((short) (((data[24] & 0xFF) << 8) | (data[25] & 0xFF))); + analyze.setLastInterval((short) (((data[26] & 0xFF) << 8) | (data[27] & 0xFF))); + dataLenIndex = 28; + } + + analyze.setDataLen((short) (((data[dataLenIndex] & 0xFF) << 8) | (data[dataLenIndex + 1] & 0xFF))); + byte[] payload = new byte[analyze.getDataLen()]; + System.arraycopy(data, dataLenIndex + 2, payload, 0, payload.length); + analyze.setData(payload); + + return analyze; + } + + private Analyze parse19(byte[] data) { + Analyze analyze = new Analyze(); + analyze.setPt((byte) (data[5] & 0x7F)); + analyze.setSn((short) (((data[6] & 0xFF) << 8) | (data[7] & 0xFF))); + + StringBuilder simBuilder = new StringBuilder(); + for (int i = 0; i < 10; i++) { + simBuilder.append(nextBcd(data, 8 + i)); + } + analyze.setSim(simBuilder.toString()); + + analyze.setCh(data[18]); + analyze.setDt((byte) ((data[19] >> 4) & 0x0F)); + analyze.setFi((byte) (data[19] & 0x0F)); + + int dataLenIndex; + switch (analyze.getDt()) { + case 3: + analyze.setTimestamp(setTimestamp(data, 20)); + dataLenIndex = 28; + break; + case 4: + dataLenIndex = 20; + break; + default: + analyze.setTimestamp(setTimestamp(data, 20)); + analyze.setLastIInterval((short) (((data[28] & 0xFF) << 8) | (data[29] & 0xFF))); + analyze.setLastInterval((short) (((data[30] & 0xFF) << 8) | (data[31] & 0xFF))); + dataLenIndex = 32; + } + + analyze.setDataLen((short) (((data[dataLenIndex] & 0xFF) << 8) | (data[dataLenIndex + 1] & 0xFF))); + byte[] payload = new byte[analyze.getDataLen()]; + System.arraycopy(data, dataLenIndex + 2, payload, 0, payload.length); + analyze.setData(payload); + + return analyze; + } + + private long setTimestamp(byte[] data, int offset) { + long timestamp = 0; + for (int i = 0; i < 8; i++) { + timestamp = (timestamp << 8) | (data[offset + i] & 0xFF); + } + return timestamp; + } + + private String nextBcd(byte[] data, int offset) { + byte val = data[offset]; + int ch1 = (val >> 4) & 0x0F; + int ch2 = val & 0x0F; + return String.format("%d%d", ch1, ch2); + } + + private void printPacketInfo(byte[] packet, int version) { + System.out.println("\n=== JTT1078 " + (version == 16 ? "2013" : "2019") + " Protocol Packet ==="); + System.out.println("Header: " + ByteUtils.toHexString(packet, 0, 4)); + + Analyze analyze = version == 16 ? parse16(packet) : parse19(packet); + System.out.println("Payload Type: " + analyze.getPt()); + System.out.println("Sequence Number: " + analyze.getSn()); + System.out.println("SIM: " + analyze.getSim()); + System.out.println("Channel: " + analyze.getCh()); + System.out.println("Data Type: " + getDataTypeDescription(analyze.getDt())); + System.out.println("Frame Info: " + getFrameInfoDescription(analyze.getFi())); + + if (analyze.getTimestamp() != 0) { + Instant instant = Instant.ofEpochMilli(analyze.getTimestamp()); + ZonedDateTime beijingTime = instant.atZone(ZoneOffset.ofHours(8)); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + System.out.println("Timestamp: " + formatter.format(beijingTime)); + } + + if (analyze.getLastIInterval() != 0) { + System.out.println("Last I Frame Interval: " + analyze.getLastIInterval()); + } + if (analyze.getLastInterval() != 0) { + System.out.println("Last Frame Interval: " + analyze.getLastInterval()); + } + + System.out.println("Data Length: " + analyze.getDataLen()); + System.out.println("=================================\n"); + } + + private String getDataTypeDescription(int dataType) { + switch (dataType) { + case 0: return "Video I Frame"; + case 1: return "Video P Frame"; + case 2: return "Video B Frame"; + case 3: return "Audio Frame"; + case 4: return "Transparent Data"; + default: return "Unknown (" + dataType + ")"; + } + } + + private String getFrameInfoDescription(int fi) { + switch (fi) { + case 0: return "Atomic Packet"; + case 1: return "First Packet"; + case 2: return "Last Packet"; + case 3: return "Middle Packet"; + default: return "Unknown (" + fi + ")"; + } } } + +class Analyze { + private byte pt; + private short sn; + private String sim; + private byte ch; + private byte dt; + private byte fi; + private long timestamp; + private short lastIInterval; + private short lastInterval; + private short dataLen; + private byte[] data; + + // Getters and setters + public byte getPt() { return pt; } + public void setPt(byte pt) { this.pt = pt; } + + public short getSn() { return sn; } + public void setSn(short sn) { this.sn = sn; } + + public String getSim() { return sim; } + public void setSim(String sim) { this.sim = sim; } + + public byte getCh() { return ch; } + public void setCh(byte ch) { this.ch = ch; } + + public byte getDt() { return dt; } + public void setDt(byte dt) { this.dt = dt; } + + public byte getFi() { return fi; } + public void setFi(byte fi) { this.fi = fi; } + + public long getTimestamp() { return timestamp; } + public void setTimestamp(long timestamp) { this.timestamp = timestamp; } + + public short getLastIInterval() { return lastIInterval; } + public void setLastIInterval(short lastIInterval) { this.lastIInterval = lastIInterval; } + + public short getLastInterval() { return lastInterval; } + public void setLastInterval(short lastInterval) { this.lastInterval = lastInterval; } + + public short getDataLen() { return dataLen; } + public void setDataLen(short dataLen) { this.dataLen = dataLen; } + + public byte[] getData() { return data; } + public void setData(byte[] data) { this.data = data; } +} \ No newline at end of file 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 { diff --git a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java index de69111..f3fa7ba 100644 --- a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java +++ b/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java @@ -28,7 +28,7 @@ { int l = i < k - 1 ? 512 : length - (i * 512); in.readBytes(block, 0, l); - + //System.out.println("block:"+block.length); decoder.write(block, 0, l); while (true) diff --git a/src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java b/src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java index 21d141d..c7dd166 100644 --- a/src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java +++ b/src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java @@ -13,6 +13,8 @@ public ByteHolder(int bufferSize) { + System.out.print("ByteHolder(bufferSize:"+bufferSize+")"); + this.buffer = new byte[bufferSize]; } @@ -56,6 +58,7 @@ public void sliceInto(byte[] dest, int length) { + //System.out.println(); System.arraycopy(this.buffer, 0, dest, 0, length); // 寰�鍓嶆尓length涓綅 System.arraycopy(this.buffer, length, this.buffer, 0, this.size - length); diff --git a/src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java b/src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java index 34a4d94..52214aa 100644 --- a/src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java +++ b/src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java @@ -5,6 +5,14 @@ */ public final class ByteUtils { + public static String toHexString(byte[] bytes, int offset, int length) { + StringBuilder sb = new StringBuilder(length * 3); + for (int i = offset; i < offset + length && i < bytes.length; i++) { + sb.append(String.format("%02X ", bytes[i])); + } + return sb.toString().trim(); + } + public static byte[] parse(String hexString) { String[] hexes = hexString.split(" "); diff --git a/src/main/resources/app.properties b/src/main/resources/app.properties index 848917e..e77c267 100644 --- a/src/main/resources/app.properties +++ b/src/main/resources/app.properties @@ -7,6 +7,7 @@ # ffmpeg鍙墽琛屾枃浠惰矾寰勶紝鍙互鐣欑┖ ffmpeg.path = E:/jtt1078/ffmpeg/bin/ffmpeg.exe +//ffmpeg.path = D:/vehicle/ffmpeg/bin/ffmpeg.exe # 閰嶇疆rtmp鍦板潃灏嗗湪缁堢鍙戦�丷TP娑堟伅鍖呮椂锛岄澶栫殑鍚慠TMP鏈嶅姟鍣ㄦ帹娴� # TAG鐨勫舰寮忓氨鏄疭IM-CHANNEL锛屽13800138999-2 @@ -15,4 +16,4 @@ #rtmp.url = rtmp://47.104.204.210/live/{TAG} # 璁剧疆涓簅n鏃讹紝鎺у埗鍙板皢杈撳嚭ffmpeg鐨勮緭鍑� -debug.mode = off \ No newline at end of file +debug.mode = on \ No newline at end of file -- Gitblit v1.9.3