Fix video streaming issues

This commit is contained in:
Anton Tananaev
2026-04-19 11:57:29 -07:00
parent 012c5cb7da
commit ef2ea05611
3 changed files with 54 additions and 10 deletions

View File

@@ -58,6 +58,7 @@ public class VideoStreamManager {
private final LinkedHashMap<Integer, ByteBuf> segments = new LinkedHashMap<>();
private ByteBuf currentSegment;
private int segmentIndex;
private long firstTimestamp;
synchronized void addFrame(ByteBuf nalData, long timestamp, boolean isKeyFrame) {
if (isKeyFrame && currentSegment != null) {
@@ -66,9 +67,12 @@ public class VideoStreamManager {
if (currentSegment == null) {
currentSegment = Unpooled.buffer();
if (firstTimestamp == 0) {
firstTimestamp = timestamp;
}
}
writer.write(currentSegment, nalData, timestamp, isKeyFrame);
writer.write(currentSegment, nalData, timestamp - firstTimestamp, isKeyFrame);
}
private void finalizeSegment() {

View File

@@ -36,8 +36,9 @@ public class VideoStreamWriter {
writePmt(output);
}
ByteBuf pesPacket = createPes(nalData, pts);
writePesPackets(output, pesPacket, isKeyFrame, pts * 90);
long pts90k = pts * 90;
ByteBuf pesPacket = createPes(nalData, pts90k);
writePesPackets(output, pesPacket, isKeyFrame, pts90k);
pesPacket.release();
}
@@ -113,8 +114,7 @@ public class VideoStreamWriter {
}
}
private ByteBuf createPes(ByteBuf nalData, long pts) {
long pts90k = pts * 90; // convert ms to 90kHz
private ByteBuf createPes(ByteBuf nalData, long pts90k) {
ByteBuf pes = Unpooled.buffer();

View File

@@ -16,6 +16,8 @@
package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
import org.traccar.Protocol;
@@ -31,6 +33,10 @@ public class Jt1078ProtocolDecoder extends BaseProtocolDecoder {
private DeviceLookupService deviceLookupService;
private VideoStreamManager streamManager;
private CompositeByteBuf frameBuffer;
private int frameDataType;
private long frameTimestamp;
public Jt1078ProtocolDecoder(Protocol protocol) {
super(protocol);
}
@@ -58,7 +64,9 @@ public class Jt1078ProtocolDecoder extends BaseProtocolDecoder {
String uniqueId = HuabaoProtocolDecoder.decodeId(buf.readSlice(6));
int logicalChannel = buf.readUnsignedByte();
int dataType = BitUtil.from(buf.readUnsignedByte(), 4);
int rawType = buf.readUnsignedByte();
int dataType = BitUtil.from(rawType, 4);
int subpackageType = BitUtil.to(rawType, 4);
long timestamp = buf.readLong();
if (dataType <= 2) {
@@ -68,16 +76,48 @@ public class Jt1078ProtocolDecoder extends BaseProtocolDecoder {
int bodyLength = buf.readUnsignedShort();
if (bodyLength == 0 || dataType > 2) {
return null; // skip audio and transparent data
return null;
}
boolean isKeyFrame = dataType == 0; // i-frame
if (deviceLookupService.lookup(new String[]{uniqueId}) == null) {
return null;
}
streamManager.handleFrame(uniqueId, logicalChannel, buf.readSlice(bodyLength), timestamp, isKeyFrame);
ByteBuf body = buf.readRetainedSlice(bodyLength);
if (subpackageType == 0) {
// atomic packet - complete frame
boolean isKeyFrame = dataType == 0;
streamManager.handleFrame(uniqueId, logicalChannel, body, timestamp, isKeyFrame);
body.release();
} else if (subpackageType == 1) {
// first subpackage
if (frameBuffer != null) {
frameBuffer.release();
}
frameBuffer = Unpooled.compositeBuffer();
frameBuffer.addComponent(true, body);
frameDataType = dataType;
frameTimestamp = timestamp;
} else if (subpackageType == 3) {
// middle subpackage
if (frameBuffer != null) {
frameBuffer.addComponent(true, body);
} else {
body.release();
}
} else if (subpackageType == 2) {
// last subpackage
if (frameBuffer != null) {
frameBuffer.addComponent(true, body);
boolean isKeyFrame = frameDataType == 0;
streamManager.handleFrame(uniqueId, logicalChannel, frameBuffer, frameTimestamp, isKeyFrame);
frameBuffer.release();
frameBuffer = null;
} else {
body.release();
}
}
return null;
}