mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-18 01:15:46 +00:00
Add start and stop callbacks for audio and video renderers
This commit is contained in:
parent
92951e1309
commit
86447399a9
@ -250,6 +250,8 @@ static void DecoderThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stopAudioStream(void) {
|
void stopAudioStream(void) {
|
||||||
|
AudioCallbacks.stop();
|
||||||
|
|
||||||
PltInterruptThread(&udpPingThread);
|
PltInterruptThread(&udpPingThread);
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
@ -301,8 +303,11 @@ int startAudioStream(void) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioCallbacks.start();
|
||||||
|
|
||||||
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
AudioCallbacks.stop();
|
||||||
PltInterruptThread(&udpPingThread);
|
PltInterruptThread(&udpPingThread);
|
||||||
PltJoinThread(&udpPingThread);
|
PltJoinThread(&udpPingThread);
|
||||||
PltCloseThread(&udpPingThread);
|
PltCloseThread(&udpPingThread);
|
||||||
@ -314,6 +319,7 @@ int startAudioStream(void) {
|
|||||||
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) {
|
||||||
|
AudioCallbacks.stop();
|
||||||
PltInterruptThread(&udpPingThread);
|
PltInterruptThread(&udpPingThread);
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
PltJoinThread(&udpPingThread);
|
PltJoinThread(&udpPingThread);
|
||||||
|
@ -1,21 +1,29 @@
|
|||||||
#include "Limelight-internal.h"
|
#include "Limelight-internal.h"
|
||||||
|
|
||||||
static int fakeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { return 0; }
|
static int fakeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { return 0; }
|
||||||
|
static void fakeDrStart(void) {}
|
||||||
|
static void fakeDrStop(void) {}
|
||||||
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; }
|
||||||
|
|
||||||
static DECODER_RENDERER_CALLBACKS fakeDrCallbacks = {
|
static DECODER_RENDERER_CALLBACKS fakeDrCallbacks = {
|
||||||
.setup = fakeDrSetup,
|
.setup = fakeDrSetup,
|
||||||
|
.start = fakeDrStart,
|
||||||
|
.stop = fakeDrStop,
|
||||||
.cleanup = fakeDrCleanup,
|
.cleanup = fakeDrCleanup,
|
||||||
.submitDecodeUnit = fakeDrSubmitDecodeUnit,
|
.submitDecodeUnit = fakeDrSubmitDecodeUnit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int fakeArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) { return 0; }
|
static int fakeArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) { return 0; }
|
||||||
|
static void fakeArStart(void) {}
|
||||||
|
static void fakeArStop(void) {}
|
||||||
static void fakeArCleanup(void) {}
|
static void fakeArCleanup(void) {}
|
||||||
static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {}
|
static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {}
|
||||||
|
|
||||||
AUDIO_RENDERER_CALLBACKS fakeArCallbacks = {
|
AUDIO_RENDERER_CALLBACKS fakeArCallbacks = {
|
||||||
.init = fakeArInit,
|
.init = fakeArInit,
|
||||||
|
.start = fakeArStart,
|
||||||
|
.stop = fakeArStop,
|
||||||
.cleanup = fakeArCleanup,
|
.cleanup = fakeArCleanup,
|
||||||
.decodeAndPlaySample = fakeArDecodeAndPlaySample,
|
.decodeAndPlaySample = fakeArDecodeAndPlaySample,
|
||||||
};
|
};
|
||||||
@ -48,6 +56,12 @@ void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_REND
|
|||||||
if ((*drCallbacks)->setup == NULL) {
|
if ((*drCallbacks)->setup == NULL) {
|
||||||
(*drCallbacks)->setup = fakeDrSetup;
|
(*drCallbacks)->setup = fakeDrSetup;
|
||||||
}
|
}
|
||||||
|
if ((*drCallbacks)->start == NULL) {
|
||||||
|
(*drCallbacks)->start = fakeDrStart;
|
||||||
|
}
|
||||||
|
if ((*drCallbacks)->stop == NULL) {
|
||||||
|
(*drCallbacks)->stop = fakeDrStop;
|
||||||
|
}
|
||||||
if ((*drCallbacks)->cleanup == NULL) {
|
if ((*drCallbacks)->cleanup == NULL) {
|
||||||
(*drCallbacks)->cleanup = fakeDrCleanup;
|
(*drCallbacks)->cleanup = fakeDrCleanup;
|
||||||
}
|
}
|
||||||
@ -63,6 +77,12 @@ void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_REND
|
|||||||
if ((*arCallbacks)->init == NULL) {
|
if ((*arCallbacks)->init == NULL) {
|
||||||
(*arCallbacks)->init = fakeArInit;
|
(*arCallbacks)->init = fakeArInit;
|
||||||
}
|
}
|
||||||
|
if ((*arCallbacks)->start == NULL) {
|
||||||
|
(*arCallbacks)->start = fakeArStart;
|
||||||
|
}
|
||||||
|
if ((*arCallbacks)->stop == NULL) {
|
||||||
|
(*arCallbacks)->stop = fakeArStop;
|
||||||
|
}
|
||||||
if ((*arCallbacks)->cleanup == NULL) {
|
if ((*arCallbacks)->cleanup == NULL) {
|
||||||
(*arCallbacks)->cleanup = fakeArCleanup;
|
(*arCallbacks)->cleanup = fakeArCleanup;
|
||||||
}
|
}
|
||||||
|
@ -105,9 +105,16 @@ typedef struct _DECODE_UNIT {
|
|||||||
// Returns 0 on success, non-zero on failure.
|
// Returns 0 on success, non-zero on failure.
|
||||||
typedef int(*DecoderRendererSetup)(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags);
|
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 notifies the decoder that the stream is starting. No frames can be submitted before this callback returns.
|
||||||
|
typedef void(*DecoderRendererStart)(void);
|
||||||
|
|
||||||
|
// This callback notifies the decoder that the stream is stopping. Frames may still be submitted but they may be safely discarded.
|
||||||
|
typedef void(*DecoderRendererStop)(void);
|
||||||
|
|
||||||
|
// This callback performs the teardown of the video decoder. No more frames will be submitted when this callback is invoked.
|
||||||
typedef void(*DecoderRendererCleanup)(void);
|
typedef void(*DecoderRendererCleanup)(void);
|
||||||
|
|
||||||
|
|
||||||
// This callback provides Annex B formatted elementary stream data to the
|
// This callback provides Annex B formatted elementary stream data to the
|
||||||
// decoder. If the decoder is unable to process the submitted data for some reason,
|
// decoder. If the decoder is unable to process the submitted data for some reason,
|
||||||
// it must return DR_NEED_IDR to generate a keyframe.
|
// it must return DR_NEED_IDR to generate a keyframe.
|
||||||
@ -117,6 +124,8 @@ typedef int(*DecoderRendererSubmitDecodeUnit)(PDECODE_UNIT decodeUnit);
|
|||||||
|
|
||||||
typedef struct _DECODER_RENDERER_CALLBACKS {
|
typedef struct _DECODER_RENDERER_CALLBACKS {
|
||||||
DecoderRendererSetup setup;
|
DecoderRendererSetup setup;
|
||||||
|
DecoderRendererStart start;
|
||||||
|
DecoderRendererStop stop;
|
||||||
DecoderRendererCleanup cleanup;
|
DecoderRendererCleanup cleanup;
|
||||||
DecoderRendererSubmitDecodeUnit submitDecodeUnit;
|
DecoderRendererSubmitDecodeUnit submitDecodeUnit;
|
||||||
int capabilities;
|
int capabilities;
|
||||||
@ -152,7 +161,13 @@ typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
|
|||||||
// specified in the stream configuration. Returns 0 on success, non-zero on failure.
|
// specified in the stream configuration. Returns 0 on success, non-zero on failure.
|
||||||
typedef int(*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 notifies the decoder that the stream is starting. No audio can be submitted before this callback returns.
|
||||||
|
typedef void(*AudioRendererStart)(void);
|
||||||
|
|
||||||
|
// This callback notifies the decoder that the stream is stopping. Audio samples may still be submitted but they may be safely discarded.
|
||||||
|
typedef void(*AudioRendererStop)(void);
|
||||||
|
|
||||||
|
// This callback performs the final teardown of the audio decoder. No additional audio will be submitted when this callback is invoked.
|
||||||
typedef void(*AudioRendererCleanup)(void);
|
typedef void(*AudioRendererCleanup)(void);
|
||||||
|
|
||||||
// This callback provides Opus audio data to be decoded and played. sampleLength is in bytes.
|
// This callback provides Opus audio data to be decoded and played. sampleLength is in bytes.
|
||||||
@ -160,6 +175,8 @@ typedef void(*AudioRendererDecodeAndPlaySample)(char* sampleData, int sampleLeng
|
|||||||
|
|
||||||
typedef struct _AUDIO_RENDERER_CALLBACKS {
|
typedef struct _AUDIO_RENDERER_CALLBACKS {
|
||||||
AudioRendererInit init;
|
AudioRendererInit init;
|
||||||
|
AudioRendererStart start;
|
||||||
|
AudioRendererStop stop;
|
||||||
AudioRendererCleanup cleanup;
|
AudioRendererCleanup cleanup;
|
||||||
AudioRendererDecodeAndPlaySample decodeAndPlaySample;
|
AudioRendererDecodeAndPlaySample decodeAndPlaySample;
|
||||||
int capabilities;
|
int capabilities;
|
||||||
|
@ -151,6 +151,8 @@ int readFirstFrame(void) {
|
|||||||
|
|
||||||
// Terminate the video stream
|
// Terminate the video stream
|
||||||
void stopVideoStream(void) {
|
void stopVideoStream(void) {
|
||||||
|
VideoCallbacks.stop();
|
||||||
|
|
||||||
// Wake up client code that may be waiting on the decode unit queue
|
// Wake up client code that may be waiting on the decode unit queue
|
||||||
stopVideoDepacketizer();
|
stopVideoDepacketizer();
|
||||||
|
|
||||||
@ -209,8 +211,11 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
return LastSocketError();
|
return LastSocketError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoCallbacks.start();
|
||||||
|
|
||||||
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
VideoCallbacks.stop();
|
||||||
closeSocket(rtpSocket);
|
closeSocket(rtpSocket);
|
||||||
VideoCallbacks.cleanup();
|
VideoCallbacks.cleanup();
|
||||||
return err;
|
return err;
|
||||||
@ -219,6 +224,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
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) {
|
||||||
|
VideoCallbacks.stop();
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
PltJoinThread(&receiveThread);
|
PltJoinThread(&receiveThread);
|
||||||
PltCloseThread(&receiveThread);
|
PltCloseThread(&receiveThread);
|
||||||
@ -233,6 +239,7 @@ 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) {
|
||||||
|
VideoCallbacks.stop();
|
||||||
stopVideoDepacketizer();
|
stopVideoDepacketizer();
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
@ -256,6 +263,7 @@ 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) {
|
||||||
|
VideoCallbacks.stop();
|
||||||
stopVideoDepacketizer();
|
stopVideoDepacketizer();
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user