From 678269c561bd86facc15dde45561ef033a93c7d4 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 9 Mar 2015 01:35:53 -0500 Subject: [PATCH] Create a new UnsynchronizedPopulatedBufferList implementation that can be used for better direct submit performance --- .../nvstream/av/audio/AudioDepacketizer.java | 7 +- .../buffer/AbstractPopulatedBufferList.java | 41 +++++++++++ .../AtomicPopulatedBufferList.java} | 36 ++++------ .../UnsynchronizedPopulatedBufferList.java | 68 +++++++++++++++++++ 4 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 moonlight-common/src/com/limelight/nvstream/av/buffer/AbstractPopulatedBufferList.java rename moonlight-common/src/com/limelight/nvstream/av/{PopulatedBufferList.java => buffer/AtomicPopulatedBufferList.java} (62%) create mode 100644 moonlight-common/src/com/limelight/nvstream/av/buffer/UnsynchronizedPopulatedBufferList.java 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 769d6d31..fd550c88 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java @@ -2,14 +2,15 @@ package com.limelight.nvstream.av.audio; import com.limelight.LimeLog; import com.limelight.nvstream.av.ByteBufferDescriptor; -import com.limelight.nvstream.av.PopulatedBufferList; import com.limelight.nvstream.av.RtpPacket; import com.limelight.nvstream.av.SequenceHelper; +import com.limelight.nvstream.av.buffer.AbstractPopulatedBufferList; +import com.limelight.nvstream.av.buffer.AtomicPopulatedBufferList; public class AudioDepacketizer { private static final int DU_LIMIT = 30; - private PopulatedBufferList decodedUnits; + private AbstractPopulatedBufferList decodedUnits; // Direct submit state private AudioRenderer directSubmitRenderer; @@ -28,7 +29,7 @@ public class AudioDepacketizer { this.directSubmitData = new byte[OpusDecoder.getMaxOutputShorts()*2]; } else { - decodedUnits = new PopulatedBufferList(DU_LIMIT, new PopulatedBufferList.BufferFactory() { + decodedUnits = new AtomicPopulatedBufferList(DU_LIMIT, new AbstractPopulatedBufferList.BufferFactory() { public Object createFreeBuffer() { return new ByteBufferDescriptor(new byte[OpusDecoder.getMaxOutputShorts()*2], 0, OpusDecoder.getMaxOutputShorts()*2); } diff --git a/moonlight-common/src/com/limelight/nvstream/av/buffer/AbstractPopulatedBufferList.java b/moonlight-common/src/com/limelight/nvstream/av/buffer/AbstractPopulatedBufferList.java new file mode 100644 index 00000000..a673746e --- /dev/null +++ b/moonlight-common/src/com/limelight/nvstream/av/buffer/AbstractPopulatedBufferList.java @@ -0,0 +1,41 @@ +package com.limelight.nvstream.av.buffer; + +public abstract class AbstractPopulatedBufferList { + protected final int maxQueueSize; + protected final BufferFactory factory; + + public AbstractPopulatedBufferList(int maxQueueSize, BufferFactory factory) { + this.factory = factory; + this.maxQueueSize = maxQueueSize; + } + + public abstract int getPopulatedCount(); + + public abstract int getFreeCount(); + + public abstract T pollFreeObject(); + + public abstract void addPopulatedObject(T object); + + public abstract void freePopulatedObject(T object); + + public void clearPopulatedObjects() { + T object; + while ((object = pollPopulatedObject()) != null) { + freePopulatedObject(object); + } + } + + public abstract T pollPopulatedObject(); + + public abstract T peekPopulatedObject(); + + public T takePopulatedObject() throws InterruptedException { + throw new UnsupportedOperationException("Blocking is unsupported on this buffer list"); + } + + public static interface BufferFactory { + public Object createFreeBuffer(); + public void cleanupObject(Object o); + } +} diff --git a/moonlight-common/src/com/limelight/nvstream/av/PopulatedBufferList.java b/moonlight-common/src/com/limelight/nvstream/av/buffer/AtomicPopulatedBufferList.java similarity index 62% rename from moonlight-common/src/com/limelight/nvstream/av/PopulatedBufferList.java rename to moonlight-common/src/com/limelight/nvstream/av/buffer/AtomicPopulatedBufferList.java index 88b4b90a..ddd386c8 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/PopulatedBufferList.java +++ b/moonlight-common/src/com/limelight/nvstream/av/buffer/AtomicPopulatedBufferList.java @@ -1,16 +1,14 @@ -package com.limelight.nvstream.av; +package com.limelight.nvstream.av.buffer; import java.util.concurrent.ArrayBlockingQueue; -public class PopulatedBufferList { - private ArrayBlockingQueue populatedList; - private ArrayBlockingQueue freeList; - - private BufferFactory factory; +public class AtomicPopulatedBufferList extends AbstractPopulatedBufferList { + private final ArrayBlockingQueue populatedList; + private final ArrayBlockingQueue freeList; @SuppressWarnings("unchecked") - public PopulatedBufferList(int maxQueueSize, BufferFactory factory) { - this.factory = factory; + public AtomicPopulatedBufferList(int maxQueueSize, BufferFactory factory) { + super(maxQueueSize, factory); this.populatedList = new ArrayBlockingQueue(maxQueueSize, false); this.freeList = new ArrayBlockingQueue(maxQueueSize, false); @@ -20,48 +18,44 @@ public class PopulatedBufferList { } } + @Override public int getPopulatedCount() { return populatedList.size(); } + @Override public int getFreeCount() { return freeList.size(); } + @Override public T pollFreeObject() { return freeList.poll(); } + @Override public void addPopulatedObject(T object) { populatedList.add(object); } + @Override public void freePopulatedObject(T object) { factory.cleanupObject(object); freeList.add(object); } - public void clearPopulatedObjects() { - T object; - while ((object = populatedList.poll()) != null) { - freePopulatedObject(object); - } - } - + @Override public T pollPopulatedObject() { return populatedList.poll(); } - + + @Override public T peekPopulatedObject() { return populatedList.peek(); } + @Override public T takePopulatedObject() throws InterruptedException { return populatedList.take(); } - - public static interface BufferFactory { - public Object createFreeBuffer(); - public void cleanupObject(Object o); - } } diff --git a/moonlight-common/src/com/limelight/nvstream/av/buffer/UnsynchronizedPopulatedBufferList.java b/moonlight-common/src/com/limelight/nvstream/av/buffer/UnsynchronizedPopulatedBufferList.java new file mode 100644 index 00000000..b14044d3 --- /dev/null +++ b/moonlight-common/src/com/limelight/nvstream/av/buffer/UnsynchronizedPopulatedBufferList.java @@ -0,0 +1,68 @@ +package com.limelight.nvstream.av.buffer; + +import java.util.ArrayList; + +public class UnsynchronizedPopulatedBufferList extends AbstractPopulatedBufferList { + private final ArrayList populatedList; + private final ArrayList freeList; + + @SuppressWarnings("unchecked") + public UnsynchronizedPopulatedBufferList(int maxQueueSize, BufferFactory factory) { + super(maxQueueSize, factory); + + this.populatedList = new ArrayList(maxQueueSize); + this.freeList = new ArrayList(maxQueueSize); + + for (int i = 0; i < maxQueueSize; i++) { + freeList.add((T) factory.createFreeBuffer()); + } + } + + @Override + public int getPopulatedCount() { + return populatedList.size(); + } + + @Override + public int getFreeCount() { + return freeList.size(); + } + + @Override + public T pollFreeObject() { + if (freeList.isEmpty()) { + return null; + } + + return freeList.remove(0); + } + + @Override + public void addPopulatedObject(T object) { + populatedList.add(object); + } + + @Override + public void freePopulatedObject(T object) { + factory.cleanupObject(object); + freeList.add(object); + } + + @Override + public T pollPopulatedObject() { + if (populatedList.isEmpty()) { + return null; + } + + return populatedList.remove(0); + } + + @Override + public T peekPopulatedObject() { + if (populatedList.isEmpty()) { + return null; + } + + return populatedList.get(0); + } +}