mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-18 01:15:46 +00:00
Fix state cleanup if LiStartConnection() fails
This commit is contained in:
parent
ec6c569130
commit
2d7bf5be82
@ -281,27 +281,47 @@ void stopAudioStream(void) {
|
|||||||
int startAudioStream(void) {
|
int startAudioStream(void) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
AudioCallbacks.init(StreamConfig.audioConfiguration,
|
err = AudioCallbacks.init(StreamConfig.audioConfiguration,
|
||||||
opusConfigArray[StreamConfig.audioConfiguration]);
|
opusConfigArray[StreamConfig.audioConfiguration]);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
|
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
|
||||||
if (rtpSocket == INVALID_SOCKET) {
|
if (rtpSocket == INVALID_SOCKET) {
|
||||||
return LastSocketFail();
|
err = LastSocketFail();
|
||||||
|
AudioCallbacks.cleanup();
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
|
err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
AudioCallbacks.cleanup();
|
||||||
|
closeSocket(rtpSocket);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
PltInterruptThread(&udpPingThread);
|
||||||
|
PltJoinThread(&udpPingThread);
|
||||||
|
PltCloseThread(&udpPingThread);
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
AudioCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
|
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
PltInterruptThread(&udpPingThread);
|
||||||
|
PltInterruptThread(&receiveThread);
|
||||||
|
PltJoinThread(&udpPingThread);
|
||||||
|
PltJoinThread(&receiveThread);
|
||||||
|
PltCloseThread(&udpPingThread);
|
||||||
|
PltCloseThread(&receiveThread);
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
AudioCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,5 +374,9 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
|
|||||||
ListenerCallbacks.connectionStarted();
|
ListenerCallbacks.connectionStarted();
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
|
if (err != 0) {
|
||||||
|
// Undo any work we've done here before failing
|
||||||
|
LiStopConnection();
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -680,7 +680,19 @@ int startControlStream(void) {
|
|||||||
payloadLengths[IDX_START_A],
|
payloadLengths[IDX_START_A],
|
||||||
preconstructedPayloads[IDX_START_A])) {
|
preconstructedPayloads[IDX_START_A])) {
|
||||||
Limelog("Start A failed: %d\n", (int)LastSocketError());
|
Limelog("Start A failed: %d\n", (int)LastSocketError());
|
||||||
return LastSocketFail();
|
err = LastSocketFail();
|
||||||
|
stopping = 1;
|
||||||
|
if (ctlSock != INVALID_SOCKET) {
|
||||||
|
closeSocket(ctlSock);
|
||||||
|
ctlSock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enet_peer_disconnect_now(peer, 0);
|
||||||
|
peer = NULL;
|
||||||
|
enet_host_destroy(client);
|
||||||
|
client = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send START B
|
// Send START B
|
||||||
@ -688,16 +700,63 @@ int startControlStream(void) {
|
|||||||
payloadLengths[IDX_START_B],
|
payloadLengths[IDX_START_B],
|
||||||
preconstructedPayloads[IDX_START_B])) {
|
preconstructedPayloads[IDX_START_B])) {
|
||||||
Limelog("Start B failed: %d\n", (int)LastSocketError());
|
Limelog("Start B failed: %d\n", (int)LastSocketError());
|
||||||
return LastSocketFail();
|
err = LastSocketFail();
|
||||||
|
stopping = 1;
|
||||||
|
if (ctlSock != INVALID_SOCKET) {
|
||||||
|
closeSocket(ctlSock);
|
||||||
|
ctlSock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enet_peer_disconnect_now(peer, 0);
|
||||||
|
peer = NULL;
|
||||||
|
enet_host_destroy(client);
|
||||||
|
client = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PltCreateThread(lossStatsThreadFunc, NULL, &lossStatsThread);
|
err = PltCreateThread(lossStatsThreadFunc, NULL, &lossStatsThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
stopping = 1;
|
||||||
|
if (ctlSock != INVALID_SOCKET) {
|
||||||
|
closeSocket(ctlSock);
|
||||||
|
ctlSock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enet_peer_disconnect_now(peer, 0);
|
||||||
|
peer = NULL;
|
||||||
|
enet_host_destroy(client);
|
||||||
|
client = NULL;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PltCreateThread(invalidateRefFramesFunc, NULL, &invalidateRefFramesThread);
|
err = PltCreateThread(invalidateRefFramesFunc, NULL, &invalidateRefFramesThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
stopping = 1;
|
||||||
|
|
||||||
|
if (ctlSock != INVALID_SOCKET) {
|
||||||
|
shutdownTcpSocket(ctlSock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer != NULL) {
|
||||||
|
enet_peer_disconnect_now(peer, 0);
|
||||||
|
peer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PltInterruptThread(&lossStatsThread);
|
||||||
|
PltJoinThread(&lossStatsThread);
|
||||||
|
PltCloseThread(&lossStatsThread);
|
||||||
|
|
||||||
|
if (ctlSock != INVALID_SOCKET) {
|
||||||
|
closeSocket(ctlSock);
|
||||||
|
ctlSock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
enet_host_destroy(client);
|
||||||
|
client = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "Limelight-internal.h"
|
#include "Limelight-internal.h"
|
||||||
|
|
||||||
static void fakeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {}
|
static int fakeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { return 0; }
|
||||||
static void fakeDrCleanup(void) {}
|
static void fakeDrCleanup(void) {}
|
||||||
static int fakeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) { return DR_OK; }
|
static int fakeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) { return DR_OK; }
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ static DECODER_RENDERER_CALLBACKS fakeDrCallbacks = {
|
|||||||
.submitDecodeUnit = fakeDrSubmitDecodeUnit,
|
.submitDecodeUnit = fakeDrSubmitDecodeUnit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fakeArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) {}
|
static int fakeArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) { return 0; }
|
||||||
static void fakeArCleanup(void) {}
|
static void fakeArCleanup(void) {}
|
||||||
static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {}
|
static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {}
|
||||||
|
|
||||||
|
@ -394,6 +394,10 @@ int startInputStream(void) {
|
|||||||
|
|
||||||
err = PltCreateThread(inputSendThreadProc, NULL, &inputSendThread);
|
err = PltCreateThread(inputSendThreadProc, NULL, &inputSendThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
if (inputSock != INVALID_SOCKET) {
|
||||||
|
closeSocket(inputSock);
|
||||||
|
inputSock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +101,9 @@ typedef struct _DECODE_UNIT {
|
|||||||
// number of slices per frame. This capability is only valid on video renderers.
|
// number of slices per frame. This capability is only valid on video renderers.
|
||||||
#define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24)
|
#define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24)
|
||||||
|
|
||||||
// This callback is invoked to provide details about the video stream and allow configuration of the decoder
|
// This callback is invoked to provide details about the video stream and allow configuration of the decoder.
|
||||||
typedef void(*DecoderRendererSetup)(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags);
|
// Returns 0 on success, non-zero on failure.
|
||||||
|
typedef int(*DecoderRendererSetup)(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags);
|
||||||
|
|
||||||
// This callback performs the teardown of the video decoder
|
// This callback performs the teardown of the video decoder
|
||||||
typedef void(*DecoderRendererCleanup)(void);
|
typedef void(*DecoderRendererCleanup)(void);
|
||||||
@ -148,8 +149,8 @@ typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
|
|||||||
|
|
||||||
// This callback initializes the audio renderer. The audio configuration parameter
|
// This callback initializes the audio renderer. The audio configuration parameter
|
||||||
// provides the negotiated audio configuration. This may differ from the one
|
// provides the negotiated audio configuration. This may differ from the one
|
||||||
// specified in the stream configuration.
|
// specified in the stream configuration. Returns 0 on success, non-zero on failure.
|
||||||
typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
|
typedef int(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
|
||||||
|
|
||||||
// This callback performs the final teardown of the audio decoder
|
// This callback performs the final teardown of the audio decoder
|
||||||
typedef void(*AudioRendererCleanup)(void);
|
typedef void(*AudioRendererCleanup)(void);
|
||||||
|
@ -192,25 +192,38 @@ void stopVideoStream(void) {
|
|||||||
int startVideoStream(void* rendererContext, int drFlags) {
|
int startVideoStream(void* rendererContext, int drFlags) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
firstFrameSocket = INVALID_SOCKET;
|
||||||
|
|
||||||
// This must be called before the decoder thread starts submitting
|
// This must be called before the decoder thread starts submitting
|
||||||
// decode units
|
// decode units
|
||||||
LC_ASSERT(NegotiatedVideoFormat != 0);
|
LC_ASSERT(NegotiatedVideoFormat != 0);
|
||||||
VideoCallbacks.setup(NegotiatedVideoFormat, StreamConfig.width,
|
err = VideoCallbacks.setup(NegotiatedVideoFormat, StreamConfig.width,
|
||||||
StreamConfig.height, StreamConfig.fps, rendererContext, drFlags);
|
StreamConfig.height, StreamConfig.fps, rendererContext, drFlags);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
|
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
|
||||||
if (rtpSocket == INVALID_SOCKET) {
|
if (rtpSocket == INVALID_SOCKET) {
|
||||||
|
VideoCallbacks.cleanup();
|
||||||
return LastSocketError();
|
return LastSocketError();
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
VideoCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
|
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
PltInterruptThread(&receiveThread);
|
||||||
|
PltJoinThread(&receiveThread);
|
||||||
|
PltCloseThread(&receiveThread);
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
VideoCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,6 +233,21 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
|
firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
|
||||||
FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
|
FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
|
||||||
if (firstFrameSocket == INVALID_SOCKET) {
|
if (firstFrameSocket == INVALID_SOCKET) {
|
||||||
|
stopVideoDepacketizer();
|
||||||
|
PltInterruptThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltInterruptThread(&decoderThread);
|
||||||
|
}
|
||||||
|
PltJoinThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltJoinThread(&decoderThread);
|
||||||
|
}
|
||||||
|
PltCloseThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltCloseThread(&decoderThread);
|
||||||
|
}
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
VideoCallbacks.cleanup();
|
||||||
return LastSocketError();
|
return LastSocketError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,6 +256,25 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
// to send UDP data
|
// to send UDP data
|
||||||
err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
|
err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
stopVideoDepacketizer();
|
||||||
|
PltInterruptThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltInterruptThread(&decoderThread);
|
||||||
|
}
|
||||||
|
PltJoinThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltJoinThread(&decoderThread);
|
||||||
|
}
|
||||||
|
PltCloseThread(&receiveThread);
|
||||||
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
PltCloseThread(&decoderThread);
|
||||||
|
}
|
||||||
|
closeSocket(rtpSocket);
|
||||||
|
if (firstFrameSocket != INVALID_SOCKET) {
|
||||||
|
closeSocket(firstFrameSocket);
|
||||||
|
firstFrameSocket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
VideoCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +282,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
// Read the first frame to start the flow of video
|
// Read the first frame to start the flow of video
|
||||||
err = readFirstFrame();
|
err = readFirstFrame();
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
stopVideoStream();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user