Display messages if we detect that the device is having issues streaming

This commit is contained in:
Cameron Gutman 2014-02-19 19:03:51 -05:00
parent 21116f90a7
commit cdf634dc41
4 changed files with 42 additions and 5 deletions

View File

@ -29,4 +29,5 @@ public interface NvConnectionListener {
public void connectionTerminated(Exception e); public void connectionTerminated(Exception e);
public void displayMessage(String message); public void displayMessage(String message);
public void displayTransientMessage(String message);
} }

View File

@ -3,5 +3,7 @@ package com.limelight.nvstream.av;
public interface ConnectionStatusListener { public interface ConnectionStatusListener {
public void connectionTerminated(); public void connectionTerminated();
public void connectionNeedsResync(); public void connectionDetectedPacketLoss();
public void connectionSinkTooSlow();
} }

View File

@ -23,7 +23,7 @@ public class VideoDepacketizer {
private ConnectionStatusListener controlListener; private ConnectionStatusListener controlListener;
private static final int DU_LIMIT = 15; private static final int DU_LIMIT = 7;
private LinkedBlockingQueue<DecodeUnit> decodedUnits = new LinkedBlockingQueue<DecodeUnit>(DU_LIMIT); private LinkedBlockingQueue<DecodeUnit> decodedUnits = new LinkedBlockingQueue<DecodeUnit>(DU_LIMIT);
public VideoDepacketizer(ConnectionStatusListener controlListener) public VideoDepacketizer(ConnectionStatusListener controlListener)
@ -47,7 +47,7 @@ public class VideoDepacketizer {
// We need a new IDR frame since we're discarding data now // We need a new IDR frame since we're discarding data now
System.out.println("Video decoder is too slow! Forced to drop decode units"); System.out.println("Video decoder is too slow! Forced to drop decode units");
decodedUnits.clear(); decodedUnits.clear();
controlListener.connectionNeedsResync(); controlListener.connectionSinkTooSlow();
} }
// Clear old state // Clear old state
@ -208,7 +208,7 @@ public class VideoDepacketizer {
clearAvcNalState(); clearAvcNalState();
// Request an IDR frame // Request an IDR frame
controlListener.connectionNeedsResync(); controlListener.connectionDetectedPacketLoss();
} }
lastSequenceNumber = seq; lastSequenceNumber = seq;

View File

@ -44,6 +44,15 @@ public class ControlStream implements ConnectionStatusListener {
private InetAddress host; private InetAddress host;
private Config config; private Config config;
public static final int LOSS_PERIOD_MS = 5000;
public static final int MAX_LOSS_COUNT_IN_PERIOD = 5;
public static final int MAX_SLOW_SINK_COUNT = 3;
public static final int MESSAGE_DELAY_FACTOR = 5;
private long lossTimestamp;
private int lossCount;
private int slowSinkCount;
private Socket s; private Socket s;
private InputStream in; private InputStream in;
private OutputStream out; private OutputStream out;
@ -404,10 +413,35 @@ public class ControlStream implements ConnectionStatusListener {
abort(); abort();
} }
public void connectionNeedsResync() { private void resyncConnection() {
synchronized (resyncNeeded) { synchronized (resyncNeeded) {
// Wake up the resync thread // Wake up the resync thread
resyncNeeded.notify(); resyncNeeded.notify();
} }
} }
public void connectionDetectedPacketLoss() {
if (System.currentTimeMillis() > LOSS_PERIOD_MS + lossTimestamp) {
lossCount++;
lossTimestamp = System.currentTimeMillis();
}
else {
if (++lossCount == MAX_LOSS_COUNT_IN_PERIOD) {
listener.displayTransientMessage("Detected excessive A/V data loss. Try improving your network connection or lowering stream settings.");
lossCount = -MAX_LOSS_COUNT_IN_PERIOD * MESSAGE_DELAY_FACTOR;
lossTimestamp = 0;
}
}
resyncConnection();
}
public void connectionSinkTooSlow() {
if (++slowSinkCount == MAX_SLOW_SINK_COUNT) {
listener.displayTransientMessage("Your device is processing the A/V data too slowly. Try lowering stream settings.");
slowSinkCount = -MAX_SLOW_SINK_COUNT * MESSAGE_DELAY_FACTOR;
}
resyncConnection();
}
} }