Add start and stop callbacks for audio and video renderers

This commit is contained in:
Cameron Gutman 2017-05-21 12:50:53 -07:00
parent 92951e1309
commit 86447399a9
4 changed files with 53 additions and 2 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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) {