Add a recording mode for debugging purposes

This commit is contained in:
Cameron Gutman 2021-06-20 11:15:30 -05:00
parent 75999a6e07
commit 5e3aa93479
3 changed files with 103 additions and 0 deletions

View File

@ -190,6 +190,11 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
memcpy(&VideoCallbacks, drCallbacks, sizeof(VideoCallbacks)); memcpy(&VideoCallbacks, drCallbacks, sizeof(VideoCallbacks));
memcpy(&AudioCallbacks, arCallbacks, sizeof(AudioCallbacks)); memcpy(&AudioCallbacks, arCallbacks, sizeof(AudioCallbacks));
#ifdef LC_DEBUG_RECORD_MODE
// Install the pass-through recorder callbacks
setRecorderCallbacks(&VideoCallbacks, &AudioCallbacks);
#endif
// Hook the termination callback so we can avoid issuing a termination callback // Hook the termination callback so we can avoid issuing a termination callback
// after LiStopConnection() is called. // after LiStopConnection() is called.
// //

View File

@ -70,6 +70,7 @@ void* extendBuffer(void* ptr, size_t newSize);
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks, void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks,
PCONNECTION_LISTENER_CALLBACKS* clCallbacks); PCONNECTION_LISTENER_CALLBACKS* clCallbacks);
void setRecorderCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks);
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int* length); char* getSdpPayloadForStreamConfig(int rtspClientVersion, int* length);

97
src/RecorderCallbacks.c Normal file
View File

@ -0,0 +1,97 @@
#include "Limelight-internal.h"
static FILE* videoFile;
static FILE* audioFile;
static DECODER_RENDERER_CALLBACKS realDrCallbacks;
static AUDIO_RENDERER_CALLBACKS realArCallbacks;
static int recDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags)
{
const char* path = context;
if (path != NULL) {
videoFile = fopen(path, "wb");
if (videoFile == NULL) {
return -1;
}
}
else {
Limelog("Video recording will not be enabled - file path not specified in drContext!\n");
}
return realDrCallbacks.setup(videoFormat, width, height, redrawRate, NULL, drFlags);
}
static void recDrCleanup(void)
{
if (videoFile != NULL) {
fclose(videoFile);
videoFile = NULL;
}
realDrCallbacks.cleanup();
}
static int recDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
{
if (videoFile != NULL) {
PLENTRY entry = decodeUnit->bufferList;
while (entry != NULL) {
fwrite(entry->data, 1, entry->length, videoFile);
entry = entry->next;
}
}
return realDrCallbacks.submitDecodeUnit(decodeUnit);
}
static int recArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, void* context, int arFlags)
{
const char* path = context;
if (path != NULL) {
audioFile = fopen(path, "wb");
if (audioFile == NULL) {
return -1;
}
}
else {
Limelog("Audio recording will not be enabled - file path not specified in arContext!\n");
}
return realArCallbacks.init(audioConfiguration, opusConfig, NULL, arFlags);
}
static void recArCleanup(void)
{
if (audioFile != NULL) {
fclose(audioFile);
audioFile = NULL;
}
realArCallbacks.cleanup();
}
static void recArDecodeAndPlaySample(char* sampleData, int sampleLength)
{
if (audioFile != NULL) {
fwrite(sampleData, 1, sampleLength, audioFile);
}
realArCallbacks.decodeAndPlaySample(sampleData, sampleLength);
}
void setRecorderCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks)
{
realDrCallbacks = *drCallbacks;
realArCallbacks = *arCallbacks;
drCallbacks->setup = recDrSetup;
drCallbacks->cleanup = recDrCleanup;
drCallbacks->submitDecodeUnit = recDrSubmitDecodeUnit;
arCallbacks->init = recArInit;
arCallbacks->cleanup = recArCleanup;
arCallbacks->decodeAndPlaySample = recArDecodeAndPlaySample;
}