diff --git a/src/deploy/conf/server.yaml b/src/deploy/conf/server.yaml index 379bb9c..bceafe1 100644 --- a/src/deploy/conf/server.yaml +++ b/src/deploy/conf/server.yaml @@ -13,12 +13,14 @@ streaming: file: class: Filesystem conf: + max_rtp_size: 65536 # path to video folder (/opt/video_samples for example) basedir: video file: jellyfish-5-mbps-hd-h264.mkv picture: class: Generated conf: + max_rtp_size: 65536 picture: width: 640 height: 480 diff --git a/src/main/java/me/vzhilin/bstreamer/server/RtpEncoder.java b/src/main/java/me/vzhilin/bstreamer/server/RtpEncoder.java index e6ed03d..f65619e 100644 --- a/src/main/java/me/vzhilin/bstreamer/server/RtpEncoder.java +++ b/src/main/java/me/vzhilin/bstreamer/server/RtpEncoder.java @@ -4,12 +4,19 @@ import me.vzhilin.bstreamer.server.streaming.file.MediaPacket; public class RtpEncoder { - private static final int MTU = 65536; + private final int maxRtpSize; private long seqNo = 0; + public RtpEncoder(int maxRtpSize) { + this.maxRtpSize = maxRtpSize; + if (this.maxRtpSize > 65536 || this.maxRtpSize <= 18) { + throw new RuntimeException("incorrect maxRtpSize"); + } + } + public void encode(ByteBuf buffer, MediaPacket pkt, long rtpTimestamp) { int sz = pkt.getPayload().readableBytes(); - if (sz + 16 > MTU) { + if (sz + 16 > maxRtpSize) { writeFuA(buffer, pkt, rtpTimestamp); } else { writeNalu(buffer, pkt, rtpTimestamp); @@ -54,7 +61,7 @@ private void writeFuA(ByteBuf buffer, MediaPacket pkt, long rtpTimestamp) { // 12 (RTP header) // 1 (FU header) // 1 (FU indicator) - int numberOfPackets = (sz - 2) / (MTU - 18) + 1; + int numberOfPackets = (sz - 2) / (maxRtpSize - 18) + 1; byte firstByte = payload.readByte(); int fuIndicator = firstByte & 0b11100000 | 28; @@ -74,7 +81,7 @@ private void writeFuA(ByteBuf buffer, MediaPacket pkt, long rtpTimestamp) { fuHeader |= (r & 1) << 5; - int dataLen = Math.min(MTU - 18, sz - offset); + int dataLen = Math.min(maxRtpSize - 18, sz - offset); writeInterleavedHeader(buffer, dataLen + 12 + 2); writeRtpHeader(buffer, pkt.isKey(), rtpTimestamp); @@ -87,8 +94,8 @@ private void writeFuA(ByteBuf buffer, MediaPacket pkt, long rtpTimestamp) { } public int estimateSize(int payloadSize) { - if (payloadSize + 16 > MTU) { - int numberOfPackets = (payloadSize - 2) / (MTU - 18) + 1; + if (payloadSize + 16 > maxRtpSize) { + int numberOfPackets = (payloadSize - 2) / (maxRtpSize - 18) + 1; return numberOfPackets * (12 + 2 + 4) + payloadSize; } else { return payloadSize + 16; diff --git a/src/main/java/me/vzhilin/bstreamer/server/RtspServerHandler.java b/src/main/java/me/vzhilin/bstreamer/server/RtspServerHandler.java index d44ee4a..772313a 100644 --- a/src/main/java/me/vzhilin/bstreamer/server/RtspServerHandler.java +++ b/src/main/java/me/vzhilin/bstreamer/server/RtspServerHandler.java @@ -108,7 +108,7 @@ private FullHttpResponse description(RtspUriParser uri, SourceDescription descri String profileLevelId = String.format("%02x%02x%02x", sps[0], sps[1], sps[2]); String sdpMessage = "v=0\r\n" + "o=RTSP 50539017935697 1 IN IP4 0.0.0.0\r\n" + - "s=1234\r\n" + + "s=bserver\r\n" + "a=control:*\r\n" + "m=video 0 RTP/AVP 98\r\n" + "a=fmtp:98 sprop-parameter-sets=" + diff --git a/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushSource.java b/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushSource.java index e454b19..8a886f0 100644 --- a/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushSource.java +++ b/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushSource.java @@ -19,10 +19,11 @@ public final class PushSource { public PushSource(Supplier pullSourceSupplier, PropertyMap props, ScheduledExecutorService pullExecutor, - BufferingLimits limits) { + BufferingLimits bufferingLimits) { this.pullExecutor = pullExecutor; this.props = props; - task = new PushTask(pullSourceSupplier, limits, pullExecutor); + int maxRtpSize = props.getInt("max_rtp_size", 65536); + task = new PushTask(pullSourceSupplier, bufferingLimits, maxRtpSize, pullExecutor); } public SourceDescription describe() { diff --git a/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushTask.java b/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushTask.java index f11dca1..9cb81b9 100644 --- a/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushTask.java +++ b/src/main/java/me/vzhilin/bstreamer/server/scheduler/PushTask.java @@ -26,7 +26,7 @@ final class PushTask implements Runnable { private boolean finished; private long startTimeMillis; private long startDtsMillis; - private final RtpEncoder interleavedEncoder = new RtpEncoder(); + private final RtpEncoder interleavedEncoder; private ScheduledFuture advanceFuture = null; private long lastDts; @@ -36,7 +36,9 @@ final class PushTask implements Runnable { PushTask(Supplier pullSource, BufferingLimits limits, + int maxRtpSize, ScheduledExecutorService executor) { + this.interleavedEncoder = new RtpEncoder(maxRtpSize); this.limits = limits; this.sourceSupplier = pullSource; this.executor = executor;