Terminate the connection if we can't receive a key frame in 10 seconds

This commit is contained in:
Cameron Gutman 2020-08-29 21:00:05 -07:00
parent a89fcb8a46
commit 1b022a0d05
5 changed files with 34 additions and 10 deletions

View File

@ -181,8 +181,6 @@ static void ReceiveThreadProc(void* context) {
} }
if (!receivedDataFromPeer) { if (!receivedDataFromPeer) {
// We've received data, so we can stop sending our ping packets
// as quickly, since we're now just keeping the NAT session open.
receivedDataFromPeer = 1; receivedDataFromPeer = 1;
Limelog("Received first audio packet after %d ms\n", waitingForAudioMs); Limelog("Received first audio packet after %d ms\n", waitingForAudioMs);
} }

View File

@ -84,6 +84,7 @@ void requestDecoderRefresh(void);
void initializeVideoStream(void); void initializeVideoStream(void);
void destroyVideoStream(void); void destroyVideoStream(void);
int startVideoStream(void* rendererContext, int drFlags); int startVideoStream(void* rendererContext, int drFlags);
void submitFrame(PQUEUED_DECODE_UNIT qdu);
void stopVideoStream(void); void stopVideoStream(void);
void initializeAudioStream(void); void initializeAudioStream(void);

View File

@ -363,6 +363,11 @@ typedef void(*ConnListenerConnectionTerminated)(int errorCode);
// firewall or port forwarding rules. // firewall or port forwarding rules.
#define ML_ERROR_NO_VIDEO_TRAFFIC -100 #define ML_ERROR_NO_VIDEO_TRAFFIC -100
// This error is passed to ConnListenerConnectionTerminated() if a fully formed
// frame could not be received after waiting several seconds. It likely indicates
// an extremely unstable connection or a bitrate that is far too high.
#define ML_ERROR_NO_VIDEO_FRAME -101
// This callback is invoked to log debug message // This callback is invoked to log debug message
typedef void(*ConnListenerLogMessage)(const char* format, ...); typedef void(*ConnListenerLogMessage)(const char* format, ...);

View File

@ -297,9 +297,8 @@ static void reassembleFrame(int frameNumber) {
} }
} }
else { else {
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit); // Submit the frame to the decoder
submitFrame(qdu);
completeQueuedDecodeUnit(qdu, ret);
} }
// Notify the control connection // Notify the control connection

View File

@ -21,6 +21,8 @@ static PLT_THREAD receiveThread;
static PLT_THREAD decoderThread; static PLT_THREAD decoderThread;
static int receivedDataFromPeer; static int receivedDataFromPeer;
static uint64_t firstDataTimeMs;
static int receivedFullFrame;
// We can't request an IDR frame until the depacketizer knows // We can't request an IDR frame until the depacketizer knows
// that a packet was lost. This timeout bounds the time that // that a packet was lost. This timeout bounds the time that
@ -33,6 +35,8 @@ void initializeVideoStream(void) {
initializeVideoDepacketizer(StreamConfig.packetSize); initializeVideoDepacketizer(StreamConfig.packetSize);
RtpfInitializeQueue(&rtpQueue); //TODO RTP_QUEUE_DELAY RtpfInitializeQueue(&rtpQueue); //TODO RTP_QUEUE_DELAY
receivedDataFromPeer = 0; receivedDataFromPeer = 0;
firstDataTimeMs = 0;
receivedFullFrame = 0;
} }
// Clean up the video stream // Clean up the video stream
@ -120,10 +124,20 @@ static void ReceiveThreadProc(void* context) {
} }
if (!receivedDataFromPeer) { if (!receivedDataFromPeer) {
// We've received data, so we can stop sending our ping packets
// as quickly, since we're now just keeping the NAT session open.
receivedDataFromPeer = 1; receivedDataFromPeer = 1;
Limelog("Received first video packet after %d ms\n", waitingForVideoMs); Limelog("Received first video packet after %d ms\n", waitingForVideoMs);
firstDataTimeMs = PltGetMillis();
}
if (!receivedFullFrame) {
uint64_t now = PltGetMillis();
if (now - firstDataTimeMs >= FIRST_FRAME_TIMEOUT_SEC * 1000) {
Limelog("Terminating connection due to lack of a successful video frame\n");
ListenerCallbacks.connectionTerminated(ML_ERROR_NO_VIDEO_FRAME);
break;
}
} }
// Convert fields to host byte-order // Convert fields to host byte-order
@ -145,6 +159,15 @@ static void ReceiveThreadProc(void* context) {
} }
} }
void submitFrame(PQUEUED_DECODE_UNIT qdu) {
// Pass the frame to the decoder
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
completeQueuedDecodeUnit(qdu, ret);
// Remember that we got a full frame successfully
receivedFullFrame = 1;
}
// Decoder thread proc // Decoder thread proc
static void DecoderThreadProc(void* context) { static void DecoderThreadProc(void* context) {
PQUEUED_DECODE_UNIT qdu; PQUEUED_DECODE_UNIT qdu;
@ -153,9 +176,7 @@ static void DecoderThreadProc(void* context) {
return; return;
} }
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit); submitFrame(qdu);
completeQueuedDecodeUnit(qdu, ret);
} }
} }