From c2401e7a75cc738215e3b7c9958cdec1b552a35f Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 12 Jul 2014 12:21:57 -0700 Subject: [PATCH] Remove object allocations from audio decoding path --- .../com/limelight/nvstream/av/RtpPacket.java | 26 ++++++++++++------- .../nvstream/av/audio/AudioDepacketizer.java | 7 +++-- .../nvstream/av/audio/AudioStream.java | 9 ++++--- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/moonlight-common/src/com/limelight/nvstream/av/RtpPacket.java b/moonlight-common/src/com/limelight/nvstream/av/RtpPacket.java index 1e60a728..0d0d15ed 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/RtpPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/av/RtpPacket.java @@ -1,29 +1,37 @@ package com.limelight.nvstream.av; import java.nio.ByteBuffer; +import java.nio.ByteOrder; public class RtpPacket { private byte packetType; private short seqNum; + private ByteBufferDescriptor buffer; + private ByteBuffer bb; public static final int HEADER_SIZE = 12; - public RtpPacket(ByteBufferDescriptor buffer) + public RtpPacket(byte[] buffer) + { + this.buffer = new ByteBufferDescriptor(buffer, 0, buffer.length); + this.bb = ByteBuffer.wrap(buffer).order(ByteOrder.BIG_ENDIAN); + } + + public void initializeWithLength(int length) { - this.buffer = new ByteBufferDescriptor(buffer); - - ByteBuffer bb = ByteBuffer.wrap(buffer.data, buffer.offset, buffer.length); - // Discard the first byte - bb.position(bb.position()+1); + bb.position(1); // Get the packet type packetType = bb.get(); // Get the sequence number seqNum = bb.getShort(); + + // Update descriptor length + buffer.length = length; } public byte getPacketType() @@ -36,13 +44,13 @@ public class RtpPacket { return seqNum; } - public byte[] getBackingBuffer() + public byte[] getBuffer() { return buffer.data; } - public ByteBufferDescriptor getNewPayloadDescriptor() + public void initializePayloadDescriptor(ByteBufferDescriptor bb) { - return new ByteBufferDescriptor(buffer.data, buffer.offset+HEADER_SIZE, buffer.length-HEADER_SIZE); + bb.reinitialize(buffer.data, buffer.offset+HEADER_SIZE, buffer.length-HEADER_SIZE); } } diff --git a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java index 1002589c..d8a6a707 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java @@ -20,6 +20,9 @@ public class AudioDepacketizer { private byte[][] pcmRing; private int ringIndex; + // Cached objects + private ByteBufferDescriptor cachedDesc = new ByteBufferDescriptor(null, 0, 0); + // Sequencing state private short lastSequenceNumber; @@ -88,8 +91,8 @@ public class AudioDepacketizer { lastSequenceNumber = seq; // This is all the depacketizing we need to do - ByteBufferDescriptor rtpPayload = packet.getNewPayloadDescriptor(); - decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length); + packet.initializePayloadDescriptor(cachedDesc); + decodeData(cachedDesc.data, cachedDesc.offset, cachedDesc.length); } public ByteBufferDescriptor getNextDecodedData() throws InterruptedException diff --git a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioStream.java b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioStream.java index 1b73188c..5aa3fe15 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioStream.java +++ b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioStream.java @@ -152,17 +152,18 @@ public class AudioStream { Thread t = new Thread() { @Override public void run() { - ByteBufferDescriptor desc = new ByteBufferDescriptor(new byte[MAX_PACKET_SIZE], 0, MAX_PACKET_SIZE); - DatagramPacket packet = new DatagramPacket(desc.data, desc.length); + byte[] buffer = new byte[MAX_PACKET_SIZE]; + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + RtpPacket rtpPacket = new RtpPacket(buffer); while (!isInterrupted()) { try { rtp.receive(packet); - desc.length = packet.getLength(); // DecodeInputData() doesn't hold onto the buffer so we are free to reuse it - depacketizer.decodeInputData(new RtpPacket(desc)); + rtpPacket.initializeWithLength(packet.getLength()); + depacketizer.decodeInputData(rtpPacket); packet.setLength(MAX_PACKET_SIZE); } catch (IOException e) {