mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-21 03:52:48 +00:00
Remove pooling code due to higher concurrency latency that resulted in a net loss of performance.
This commit is contained in:
parent
1d7460e8b3
commit
6bb215eddf
@ -4,8 +4,6 @@ import com.limelight.nvstream.NvConnection;
|
|||||||
import com.limelight.nvstream.input.NvControllerPacket;
|
import com.limelight.nvstream.input.NvControllerPacket;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ComponentCallbacks2;
|
|
||||||
import android.graphics.ImageFormat;
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
@ -96,14 +94,6 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
|||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTrimMemory(int trimLevel) {
|
|
||||||
if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW)
|
|
||||||
{
|
|
||||||
conn.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.AvByteBufferPool;
|
|
||||||
import com.limelight.nvstream.av.AvRtpPacket;
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
import com.limelight.nvstream.av.AvShortBufferDescriptor;
|
import com.limelight.nvstream.av.AvShortBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.audio.AvAudioDepacketizer;
|
import com.limelight.nvstream.av.audio.AvAudioDepacketizer;
|
||||||
@ -34,8 +33,6 @@ public class NvAudioStream {
|
|||||||
|
|
||||||
private LinkedList<Thread> threads = new LinkedList<Thread>();
|
private LinkedList<Thread> threads = new LinkedList<Thread>();
|
||||||
|
|
||||||
private AvByteBufferPool pool = new AvByteBufferPool(1500);
|
|
||||||
|
|
||||||
private boolean aborting = false;
|
private boolean aborting = false;
|
||||||
|
|
||||||
public void abort()
|
public void abort()
|
||||||
@ -105,11 +102,6 @@ public class NvAudioStream {
|
|||||||
rtp.connect(InetAddress.getByName(host), RTP_PORT);
|
rtp.connect(InetAddress.getByName(host), RTP_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trim()
|
|
||||||
{
|
|
||||||
depacketizer.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupAudio()
|
private void setupAudio()
|
||||||
{
|
{
|
||||||
int channelConfig;
|
int channelConfig;
|
||||||
@ -166,8 +158,6 @@ public class NvAudioStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
depacketizer.decodeInputData(packet);
|
depacketizer.decodeInputData(packet);
|
||||||
|
|
||||||
pool.free(packet.getBackingBuffer());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -193,8 +183,6 @@ public class NvAudioStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
track.write(samples.data, samples.offset, samples.length);
|
track.write(samples.data, samples.offset, samples.length);
|
||||||
|
|
||||||
depacketizer.releaseBuffer(samples);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -208,7 +196,7 @@ public class NvAudioStream {
|
|||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DatagramPacket packet = new DatagramPacket(pool.allocate(), 1500);
|
DatagramPacket packet = new DatagramPacket(new byte[1500], 1500);
|
||||||
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
|
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
|
||||||
|
|
||||||
while (!isInterrupted())
|
while (!isInterrupted())
|
||||||
@ -228,7 +216,7 @@ public class NvAudioStream {
|
|||||||
packets.add(new AvRtpPacket(desc));
|
packets.add(new AvRtpPacket(desc));
|
||||||
|
|
||||||
// Get a new buffer from the buffer pool
|
// Get a new buffer from the buffer pool
|
||||||
packet.setData(pool.allocate(), 0, 1500);
|
packet.setData(new byte[1500], 0, 1500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -112,12 +112,6 @@ public class NvConnection {
|
|||||||
inputStream = null;
|
inputStream = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trim()
|
|
||||||
{
|
|
||||||
videoStream.trim();
|
|
||||||
audioStream.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start()
|
public void start()
|
||||||
{
|
{
|
||||||
|
@ -82,15 +82,10 @@ public class NvVideoStream {
|
|||||||
|
|
||||||
threads.clear();
|
threads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trim()
|
|
||||||
{
|
|
||||||
depacketizer.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readFirstFrame(String host) throws IOException
|
private void readFirstFrame(String host) throws IOException
|
||||||
{
|
{
|
||||||
byte[] firstFrame = depacketizer.allocatePacketBuffer();
|
byte[] firstFrame = new byte[1500];
|
||||||
|
|
||||||
System.out.println("VID: Waiting for first frame");
|
System.out.println("VID: Waiting for first frame");
|
||||||
firstFrameSocket = new Socket(host, FIRST_FRAME_PORT);
|
firstFrameSocket = new Socket(host, FIRST_FRAME_PORT);
|
||||||
@ -220,8 +215,6 @@ public class NvVideoStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decrend.submitDecodeUnit(du);
|
decrend.submitDecodeUnit(du);
|
||||||
|
|
||||||
depacketizer.releaseDecodeUnit(du);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -262,7 +255,7 @@ public class NvVideoStream {
|
|||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DatagramPacket packet = new DatagramPacket(depacketizer.allocatePacketBuffer(), 1500);
|
DatagramPacket packet = new DatagramPacket(new byte[1500], 1500);
|
||||||
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
|
AvByteBufferDescriptor desc = new AvByteBufferDescriptor(null, 0, 0);
|
||||||
|
|
||||||
while (!isInterrupted())
|
while (!isInterrupted())
|
||||||
@ -282,7 +275,7 @@ public class NvVideoStream {
|
|||||||
packets.add(new AvRtpPacket(desc));
|
packets.add(new AvRtpPacket(desc));
|
||||||
|
|
||||||
// Get a new buffer from the buffer pool
|
// Get a new buffer from the buffer pool
|
||||||
packet.setData(depacketizer.allocatePacketBuffer(), 0, 1500);
|
packet.setData(new byte[1500], 0, 1500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,6 @@ public class AvByteBufferDescriptor {
|
|||||||
public byte[] data;
|
public byte[] data;
|
||||||
public int offset;
|
public int offset;
|
||||||
public int length;
|
public int length;
|
||||||
public Object context;
|
|
||||||
|
|
||||||
public AvByteBufferDescriptor(byte[] data, int offset, int length)
|
public AvByteBufferDescriptor(byte[] data, int offset, int length)
|
||||||
{
|
{
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package com.limelight.nvstream.av;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
public class AvByteBufferPool {
|
|
||||||
private LinkedList<byte[]> bufferList = new LinkedList<byte[]>();
|
|
||||||
private int bufferSize;
|
|
||||||
|
|
||||||
public AvByteBufferPool(int size)
|
|
||||||
{
|
|
||||||
this.bufferSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void purge()
|
|
||||||
{
|
|
||||||
this.bufferList = new LinkedList<byte[]>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized byte[] allocate()
|
|
||||||
{
|
|
||||||
if (bufferList.isEmpty())
|
|
||||||
{
|
|
||||||
return new byte[bufferSize];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return bufferList.removeFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void free(byte[] buffer)
|
|
||||||
{
|
|
||||||
bufferList.addFirst(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.limelight.nvstream.av;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
public class AvShortBufferPool {
|
|
||||||
private LinkedList<short[]> bufferList = new LinkedList<short[]>();
|
|
||||||
private int bufferSize;
|
|
||||||
|
|
||||||
public AvShortBufferPool(int size)
|
|
||||||
{
|
|
||||||
this.bufferSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void purge()
|
|
||||||
{
|
|
||||||
this.bufferList = new LinkedList<short[]>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized short[] allocate()
|
|
||||||
{
|
|
||||||
if (bufferList.isEmpty())
|
|
||||||
{
|
|
||||||
return new short[bufferSize];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return bufferList.removeFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void free(short[] buffer)
|
|
||||||
{
|
|
||||||
bufferList.addFirst(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,26 +5,18 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.AvRtpPacket;
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
import com.limelight.nvstream.av.AvShortBufferDescriptor;
|
import com.limelight.nvstream.av.AvShortBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.AvShortBufferPool;
|
|
||||||
|
|
||||||
public class AvAudioDepacketizer {
|
public class AvAudioDepacketizer {
|
||||||
private LinkedBlockingQueue<AvShortBufferDescriptor> decodedUnits =
|
private LinkedBlockingQueue<AvShortBufferDescriptor> decodedUnits =
|
||||||
new LinkedBlockingQueue<AvShortBufferDescriptor>(15);
|
new LinkedBlockingQueue<AvShortBufferDescriptor>(15);
|
||||||
|
|
||||||
private AvShortBufferPool pool = new AvShortBufferPool(OpusDecoder.getMaxOutputShorts());
|
|
||||||
|
|
||||||
// Sequencing state
|
// Sequencing state
|
||||||
private short lastSequenceNumber;
|
private short lastSequenceNumber;
|
||||||
|
|
||||||
public void trim()
|
|
||||||
{
|
|
||||||
pool.purge();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decodeData(byte[] data, int off, int len)
|
private void decodeData(byte[] data, int off, int len)
|
||||||
{
|
{
|
||||||
// Submit this data to the decoder
|
// Submit this data to the decoder
|
||||||
short[] pcmData = pool.allocate();
|
short[] pcmData = new short[OpusDecoder.getMaxOutputShorts()];
|
||||||
int decodeLen = OpusDecoder.decode(data, off, len, pcmData);
|
int decodeLen = OpusDecoder.decode(data, off, len, pcmData);
|
||||||
|
|
||||||
if (decodeLen > 0) {
|
if (decodeLen > 0) {
|
||||||
@ -32,14 +24,7 @@ public class AvAudioDepacketizer {
|
|||||||
decodeLen *= OpusDecoder.getChannelCount();
|
decodeLen *= OpusDecoder.getChannelCount();
|
||||||
|
|
||||||
// Put it on the decoded queue
|
// Put it on the decoded queue
|
||||||
if (!decodedUnits.offer(new AvShortBufferDescriptor(pcmData, 0, decodeLen)))
|
decodedUnits.offer(new AvShortBufferDescriptor(pcmData, 0, decodeLen));
|
||||||
{
|
|
||||||
pool.free(pcmData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
System.out.println("decode failed: "+decodeLen);
|
|
||||||
pool.free(pcmData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +53,6 @@ public class AvAudioDepacketizer {
|
|||||||
decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length);
|
decodeData(rtpPayload.data, rtpPayload.offset, rtpPayload.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseBuffer(AvShortBufferDescriptor decodedData)
|
|
||||||
{
|
|
||||||
pool.free(decodedData.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AvShortBufferDescriptor getNextDecodedData() throws InterruptedException
|
public AvShortBufferDescriptor getNextDecodedData() throws InterruptedException
|
||||||
{
|
{
|
||||||
return decodedUnits.take();
|
return decodedUnits.take();
|
||||||
|
@ -4,7 +4,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
||||||
import com.limelight.nvstream.av.AvByteBufferPool;
|
|
||||||
import com.limelight.nvstream.av.AvDecodeUnit;
|
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||||
import com.limelight.nvstream.av.AvRtpPacket;
|
import com.limelight.nvstream.av.AvRtpPacket;
|
||||||
|
|
||||||
@ -22,49 +21,12 @@ public class AvVideoDepacketizer {
|
|||||||
|
|
||||||
private LinkedBlockingQueue<AvDecodeUnit> decodedUnits = new LinkedBlockingQueue<AvDecodeUnit>();
|
private LinkedBlockingQueue<AvDecodeUnit> decodedUnits = new LinkedBlockingQueue<AvDecodeUnit>();
|
||||||
|
|
||||||
private AvByteBufferPool pool = new AvByteBufferPool(1500);
|
|
||||||
|
|
||||||
public byte[] allocatePacketBuffer()
|
|
||||||
{
|
|
||||||
return pool.allocate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void trim()
|
|
||||||
{
|
|
||||||
pool.purge();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearAvcNalState()
|
private void clearAvcNalState()
|
||||||
{
|
{
|
||||||
if (avcNalDataChain != null)
|
|
||||||
{
|
|
||||||
for (AvByteBufferDescriptor avbb : avcNalDataChain)
|
|
||||||
{
|
|
||||||
AvVideoPacket packet = (AvVideoPacket) avbb.context;
|
|
||||||
|
|
||||||
if (packet.release() == 0) {
|
|
||||||
pool.free(avbb.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avcNalDataChain = null;
|
avcNalDataChain = null;
|
||||||
avcNalDataLength = 0;
|
avcNalDataLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseDecodeUnit(AvDecodeUnit decodeUnit)
|
|
||||||
{
|
|
||||||
// Remove the reference from each AvVideoPacket (freeing if okay)
|
|
||||||
for (AvByteBufferDescriptor buff : decodeUnit.getBufferList())
|
|
||||||
{
|
|
||||||
AvVideoPacket packet = (AvVideoPacket) buff.context;
|
|
||||||
|
|
||||||
if (packet.release() == 0) {
|
|
||||||
pool.free(buff.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reassembleAvcNal()
|
private void reassembleAvcNal()
|
||||||
{
|
{
|
||||||
// This is the start of a new NAL
|
// This is the start of a new NAL
|
||||||
@ -119,10 +81,7 @@ public class AvVideoDepacketizer {
|
|||||||
|
|
||||||
// Construct the H264 decode unit
|
// Construct the H264 decode unit
|
||||||
AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_H264, avcNalDataChain, avcNalDataLength, flags);
|
AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_H264, avcNalDataChain, avcNalDataLength, flags);
|
||||||
if (!decodedUnits.offer(du))
|
decodedUnits.offer(du);
|
||||||
{
|
|
||||||
releaseDecodeUnit(du);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear old state
|
// Clear old state
|
||||||
avcNalDataChain = null;
|
avcNalDataChain = null;
|
||||||
@ -134,9 +93,6 @@ public class AvVideoDepacketizer {
|
|||||||
{
|
{
|
||||||
AvByteBufferDescriptor location = packet.getNewPayloadDescriptor();
|
AvByteBufferDescriptor location = packet.getNewPayloadDescriptor();
|
||||||
|
|
||||||
// Add an initial reference
|
|
||||||
packet.addRef();
|
|
||||||
|
|
||||||
while (location.length != 0)
|
while (location.length != 0)
|
||||||
{
|
{
|
||||||
// Remember the start of the NAL data in this packet
|
// Remember the start of the NAL data in this packet
|
||||||
@ -214,20 +170,11 @@ public class AvVideoDepacketizer {
|
|||||||
{
|
{
|
||||||
AvByteBufferDescriptor data = new AvByteBufferDescriptor(location.data, start, location.offset-start);
|
AvByteBufferDescriptor data = new AvByteBufferDescriptor(location.data, start, location.offset-start);
|
||||||
|
|
||||||
// Attach the current packet as the buffer context and increment the refcount
|
|
||||||
data.context = packet;
|
|
||||||
packet.addRef();
|
|
||||||
|
|
||||||
// Add a buffer descriptor describing the NAL data in this packet
|
// Add a buffer descriptor describing the NAL data in this packet
|
||||||
avcNalDataChain.add(data);
|
avcNalDataChain.add(data);
|
||||||
avcNalDataLength += location.offset-start;
|
avcNalDataLength += location.offset-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If nothing useful came out of this, release the packet now
|
|
||||||
if (packet.release() == 0) {
|
|
||||||
pool.free(location.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addInputData(AvRtpPacket packet)
|
public void addInputData(AvRtpPacket packet)
|
||||||
|
@ -4,7 +4,6 @@ import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
|||||||
|
|
||||||
public class AvVideoPacket {
|
public class AvVideoPacket {
|
||||||
private AvByteBufferDescriptor buffer;
|
private AvByteBufferDescriptor buffer;
|
||||||
private int refCount;
|
|
||||||
|
|
||||||
public AvVideoPacket(AvByteBufferDescriptor rtpPayload)
|
public AvVideoPacket(AvByteBufferDescriptor rtpPayload)
|
||||||
{
|
{
|
||||||
@ -15,14 +14,4 @@ public class AvVideoPacket {
|
|||||||
{
|
{
|
||||||
return new AvByteBufferDescriptor(buffer.data, buffer.offset+56, buffer.length-56);
|
return new AvByteBufferDescriptor(buffer.data, buffer.offset+56, buffer.length-56);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addRef()
|
|
||||||
{
|
|
||||||
return ++refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int release()
|
|
||||||
{
|
|
||||||
return --refCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user