mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 11:03:01 +00:00
Use a packet buffer pool to reduce memory pressure
This commit is contained in:
parent
e6af9df142
commit
e5126ebe01
@ -16,6 +16,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.limelight.nvstream.av.AvBufferDescriptor;
|
||||
import com.limelight.nvstream.av.AvBufferPool;
|
||||
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||
import com.limelight.nvstream.av.AvPacket;
|
||||
import com.limelight.nvstream.av.AvParser;
|
||||
@ -35,10 +36,11 @@ public class NvVideoStream {
|
||||
public static final int RTCP_PORT = 47999;
|
||||
public static final int FIRST_FRAME_PORT = 47996;
|
||||
|
||||
private static final int FRAME_RATE = 60;
|
||||
private ByteBuffer[] videoDecoderInputBuffers = null;
|
||||
private MediaCodec videoDecoder;
|
||||
|
||||
private AvBufferPool pool = new AvBufferPool(1500);
|
||||
|
||||
private AvParser parser = new AvParser();
|
||||
|
||||
private InputStream getFirstFrame(String host) throws UnknownHostException, IOException
|
||||
@ -151,6 +153,9 @@ public class NvVideoStream {
|
||||
for (AvBufferDescriptor desc : du.getBufferList())
|
||||
{
|
||||
buf.put(desc.data, desc.offset, desc.length);
|
||||
|
||||
// Release the buffer back to the buffer pool
|
||||
pool.free(desc.data);
|
||||
}
|
||||
|
||||
videoDecoder.queueInputBuffer(inputIndex,
|
||||
@ -175,13 +180,11 @@ public class NvVideoStream {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] buffer = new byte[1500];
|
||||
DatagramPacket packet = new DatagramPacket(pool.allocate(), 1500);
|
||||
AvBufferDescriptor desc = new AvBufferDescriptor(null, 0, 0);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||
|
||||
{
|
||||
try {
|
||||
rtp.receive(packet);
|
||||
} catch (IOException e) {
|
||||
@ -198,12 +201,13 @@ public class NvVideoStream {
|
||||
desc.offset += 12;
|
||||
desc.length -= 12;
|
||||
|
||||
// Give the data to the AV parser
|
||||
// !!! We no longer own the data buffer at this point !!!
|
||||
parser.addInputData(new AvPacket(desc));
|
||||
|
||||
// Get a new buffer from the buffer pool
|
||||
packet.setData(pool.allocate(), 0, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
}).start();
|
||||
|
||||
for (;;)
|
||||
@ -232,11 +236,4 @@ public class NvVideoStream {
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the presentation time for frame N, in microseconds.
|
||||
*/
|
||||
private static long computePresentationTime(int frameIndex) {
|
||||
return 132 + frameIndex * 1000000 / FRAME_RATE;
|
||||
}
|
||||
}
|
||||
|
30
src/com/limelight/nvstream/av/AvBufferPool.java
Normal file
30
src/com/limelight/nvstream/av/AvBufferPool.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.limelight.nvstream.av;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class AvBufferPool {
|
||||
private LinkedList<byte[]> bufferList = new LinkedList<byte[]>();
|
||||
private int bufferSize;
|
||||
|
||||
public AvBufferPool(int size)
|
||||
{
|
||||
this.bufferSize = size;
|
||||
}
|
||||
|
||||
public synchronized byte[] allocate()
|
||||
{
|
||||
if (bufferList.isEmpty())
|
||||
{
|
||||
return new byte[bufferSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
return bufferList.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void free(byte[] buffer)
|
||||
{
|
||||
bufferList.addFirst(buffer);
|
||||
}
|
||||
}
|
@ -5,14 +5,11 @@ public class AvPacket {
|
||||
|
||||
public AvPacket(AvBufferDescriptor rtpPayload)
|
||||
{
|
||||
byte[] data = new byte[rtpPayload.length];
|
||||
System.arraycopy(rtpPayload.data, rtpPayload.offset, data, 0, rtpPayload.length);
|
||||
buffer = new AvBufferDescriptor(data, 0, data.length);
|
||||
buffer = new AvBufferDescriptor(rtpPayload.data, rtpPayload.offset, rtpPayload.length);
|
||||
}
|
||||
|
||||
public AvBufferDescriptor getPayload()
|
||||
public AvBufferDescriptor getNewPayloadDescriptor()
|
||||
{
|
||||
int payloadOffset = buffer.offset+56;
|
||||
return new AvBufferDescriptor(buffer.data, payloadOffset, buffer.length-payloadOffset);
|
||||
return new AvBufferDescriptor(buffer.data, buffer.offset+56, buffer.length-56);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.limelight.nvstream.av;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class AvParser {
|
||||
@ -16,7 +15,7 @@ public class AvParser {
|
||||
{
|
||||
// This is the start of a new NAL
|
||||
if (nalDataChain != null && nalDataLength != 0)
|
||||
{
|
||||
{
|
||||
// Construct the H264 decode unit
|
||||
AvDecodeUnit du = new AvDecodeUnit(AvDecodeUnit.TYPE_H264, nalDataChain, nalDataLength);
|
||||
decodedUnits.add(du);
|
||||
@ -28,9 +27,10 @@ public class AvParser {
|
||||
}
|
||||
|
||||
public void addInputData(AvPacket packet)
|
||||
{
|
||||
AvBufferDescriptor payload = packet.getPayload();
|
||||
AvBufferDescriptor location = new AvBufferDescriptor(payload.data, payload.offset, payload.length);
|
||||
{
|
||||
// This payload buffer descriptor belongs to us
|
||||
AvBufferDescriptor location = packet.getNewPayloadDescriptor();
|
||||
int payloadLength = location.length;
|
||||
|
||||
while (location.length != 0)
|
||||
{
|
||||
@ -47,9 +47,9 @@ public class AvParser {
|
||||
nalDataChain = new LinkedList<AvBufferDescriptor>();
|
||||
nalDataLength = 0;
|
||||
|
||||
// Skip the start sequence and the type byte
|
||||
location.length -= 5;
|
||||
location.offset += 5;
|
||||
// Skip the start sequence
|
||||
location.length -= 4;
|
||||
location.offset += 4;
|
||||
}
|
||||
|
||||
// If there's a NAL assembly in progress, add the current data
|
||||
@ -58,7 +58,7 @@ public class AvParser {
|
||||
// FIXME: This is a hack to make parsing full packets
|
||||
// take less time. We assume if they don't start with
|
||||
// a NAL start sequence, they're full of NAL data
|
||||
if (payload.length == 968)
|
||||
if (payloadLength == 968)
|
||||
{
|
||||
location.offset += location.length;
|
||||
location.length = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user