mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 19:13:03 +00:00
Request an IDR frame if a previous frame was lost or
This commit is contained in:
parent
e52b85a883
commit
80fdae3673
@ -27,7 +27,7 @@ public class NvConnection {
|
||||
private NvControl controlStream;
|
||||
private NvController inputStream;
|
||||
private Surface video;
|
||||
private NvVideoStream videoStream = new NvVideoStream();
|
||||
private NvVideoStream videoStream;
|
||||
private NvAudioStream audioStream = new NvAudioStream();
|
||||
|
||||
private ThreadPoolExecutor threadPool;
|
||||
@ -100,8 +100,12 @@ public class NvConnection {
|
||||
{
|
||||
threadPool.shutdownNow();
|
||||
|
||||
videoStream.abort();
|
||||
audioStream.abort();
|
||||
if (videoStream != null) {
|
||||
videoStream.abort();
|
||||
}
|
||||
if (audioStream != null) {
|
||||
audioStream.abort();
|
||||
}
|
||||
|
||||
if (controlStream != null) {
|
||||
controlStream.abort();
|
||||
@ -131,9 +135,10 @@ public class NvConnection {
|
||||
try {
|
||||
startSteamBigPicture();
|
||||
performHandshake();
|
||||
beginControlStream();
|
||||
videoStream = new NvVideoStream(controlStream);
|
||||
videoStream.startVideoStream(host, video);
|
||||
audioStream.startAudioStream(host);
|
||||
beginControlStream();
|
||||
controlStream.startJitterPackets();
|
||||
startController();
|
||||
activity.hideSystemUi();
|
||||
|
@ -8,7 +8,9 @@ import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class NvControl {
|
||||
import com.limelight.nvstream.av.ConnectionStatusListener;
|
||||
|
||||
public class NvControl implements ConnectionStatusListener {
|
||||
|
||||
public static final int PORT = 47995;
|
||||
|
||||
@ -31,27 +33,8 @@ public class NvControl {
|
||||
public static final short PTYPE_1405 = 0x1405;
|
||||
public static final short PPAYLEN_1405 = 0x0000;
|
||||
|
||||
public static final short PTYPE_1404 = 0x1404;
|
||||
public static final short PPAYLEN_1404 = 0x0010;
|
||||
public static final byte[] PPAYLOAD_1404 = new byte[]
|
||||
{
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
public static final short PTYPE_RESYNC = 0x1404;
|
||||
public static final short PPAYLEN_RESYNC = 16;
|
||||
|
||||
public static final short PTYPE_CONFIG = 0x1205;
|
||||
public static final short PPAYLEN_CONFIG = 0x0004;
|
||||
@ -217,6 +200,12 @@ public class NvControl {
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
public void requestResync() throws IOException
|
||||
{
|
||||
System.out.println("CTL: Requesting IDR frame");
|
||||
sendResync();
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
System.out.println("CTL: Sending hello");
|
||||
@ -227,8 +216,6 @@ public class NvControl {
|
||||
pingPong();
|
||||
System.out.println("CTL: Sending and waiting for 1405");
|
||||
send1405AndGetResponse();
|
||||
//System.out.println("CTL: Sending 1404");
|
||||
//send1404();
|
||||
System.out.println("CTL: Launching heartbeat thread");
|
||||
|
||||
heartbeatThread = new Thread() {
|
||||
@ -243,6 +230,7 @@ public class NvControl {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
@ -291,6 +279,16 @@ public class NvControl {
|
||||
sendPacket(new NvCtlPacket(PTYPE_HELLO, PPAYLEN_HELLO, PPAYLOAD_HELLO));
|
||||
}
|
||||
|
||||
private void sendResync() throws IOException
|
||||
{
|
||||
ByteBuffer conf = ByteBuffer.wrap(new byte[PPAYLEN_RESYNC]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
conf.putLong(0);
|
||||
conf.putLong(0xFFFF);
|
||||
|
||||
sendAndGetReply(new NvCtlPacket(PTYPE_RESYNC, PPAYLEN_RESYNC, conf.array()));
|
||||
}
|
||||
|
||||
private void sendConfig() throws IOException
|
||||
{
|
||||
ByteBuffer conf = ByteBuffer.wrap(new byte[PPAYLOAD_CONFIG.length * 4 + 3]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
@ -453,4 +451,24 @@ public class NvControl {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionTerminated() {
|
||||
abort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionNeedsResync() {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
requestResync();
|
||||
} catch (IOException e1) {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
||||
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||
import com.limelight.nvstream.av.AvRtpPacket;
|
||||
import com.limelight.nvstream.av.ConnectionStatusListener;
|
||||
import com.limelight.nvstream.av.video.AvVideoDepacketizer;
|
||||
import com.limelight.nvstream.av.video.AvVideoPacket;
|
||||
import com.limelight.nvstream.av.video.CpuDecoderRenderer;
|
||||
@ -35,13 +36,20 @@ public class NvVideoStream {
|
||||
|
||||
private LinkedList<Thread> threads = new LinkedList<Thread>();
|
||||
|
||||
private AvVideoDepacketizer depacketizer = new AvVideoDepacketizer();
|
||||
private ConnectionStatusListener listener;
|
||||
private AvVideoDepacketizer depacketizer;
|
||||
|
||||
private DecoderRenderer decrend;
|
||||
private boolean startedRendering;
|
||||
|
||||
private boolean aborting = false;
|
||||
|
||||
public NvVideoStream(ConnectionStatusListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
depacketizer = new AvVideoDepacketizer(listener);
|
||||
}
|
||||
|
||||
public void abort()
|
||||
{
|
||||
if (aborting) {
|
||||
|
@ -6,6 +6,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import com.limelight.nvstream.av.AvByteBufferDescriptor;
|
||||
import com.limelight.nvstream.av.AvDecodeUnit;
|
||||
import com.limelight.nvstream.av.AvRtpPacket;
|
||||
import com.limelight.nvstream.av.ConnectionStatusListener;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
|
||||
@ -19,8 +20,15 @@ public class AvVideoDepacketizer {
|
||||
// Sequencing state
|
||||
private short lastSequenceNumber;
|
||||
|
||||
private ConnectionStatusListener controlListener;
|
||||
|
||||
private LinkedBlockingQueue<AvDecodeUnit> decodedUnits = new LinkedBlockingQueue<AvDecodeUnit>();
|
||||
|
||||
public AvVideoDepacketizer(ConnectionStatusListener controlListener)
|
||||
{
|
||||
this.controlListener = controlListener;
|
||||
}
|
||||
|
||||
private void clearAvcNalState()
|
||||
{
|
||||
avcNalDataChain = null;
|
||||
@ -191,6 +199,9 @@ public class AvVideoDepacketizer {
|
||||
// Reset the depacketizer state
|
||||
currentlyDecoding = AvDecodeUnit.TYPE_UNKNOWN;
|
||||
clearAvcNalState();
|
||||
|
||||
// Request an IDR frame
|
||||
controlListener.connectionNeedsResync();
|
||||
}
|
||||
|
||||
lastSequenceNumber = seq;
|
||||
|
@ -144,13 +144,13 @@ public class CpuDecoderRenderer implements DecoderRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitDecodeUnit(AvDecodeUnit decodeUnit) {
|
||||
public boolean submitDecodeUnit(AvDecodeUnit decodeUnit) {
|
||||
decoderBuffer.clear();
|
||||
|
||||
for (AvByteBufferDescriptor bbd : decodeUnit.getBufferList()) {
|
||||
decoderBuffer.put(bbd.data, bbd.offset, bbd.length);
|
||||
}
|
||||
|
||||
AvcDecoder.decode(decoderBuffer.array(), 0, decodeUnit.getDataLength());
|
||||
return (AvcDecoder.decode(decoderBuffer.array(), 0, decodeUnit.getDataLength()) == 0);
|
||||
}
|
||||
}
|
||||
|
@ -13,5 +13,5 @@ public interface DecoderRenderer {
|
||||
|
||||
public void release();
|
||||
|
||||
public void submitDecodeUnit(AvDecodeUnit decodeUnit);
|
||||
public boolean submitDecodeUnit(AvDecodeUnit decodeUnit);
|
||||
}
|
||||
|
@ -121,10 +121,10 @@ public class MediaCodecDecoderRenderer implements DecoderRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitDecodeUnit(AvDecodeUnit decodeUnit) {
|
||||
public boolean submitDecodeUnit(AvDecodeUnit decodeUnit) {
|
||||
if (decodeUnit.getType() != AvDecodeUnit.TYPE_H264) {
|
||||
System.err.println("Unknown decode unit type");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int inputIndex = videoDecoder.dequeueInputBuffer(-1);
|
||||
@ -145,5 +145,7 @@ public class MediaCodecDecoderRenderer implements DecoderRenderer {
|
||||
0, decodeUnit.getDataLength(),
|
||||
0, decodeUnit.getFlags());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user