Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve support for high-resolution stats #95

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode/
limelight-common/ARM/
limelight-common/Debug/
Build/
Expand Down
34 changes: 32 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
cmake_minimum_required(VERSION 3.1)
project(moonlight-common-c LANGUAGES C)

string(TOUPPER "x${CMAKE_BUILD_TYPE}" BUILD_TYPE)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

option(USE_MBEDTLS "Use MbedTLS instead of OpenSSL" OFF)
Expand Down Expand Up @@ -61,7 +62,6 @@ else()
target_include_directories(moonlight-common-c SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()

string(TOUPPER "x${CMAKE_BUILD_TYPE}" BUILD_TYPE)
if("${BUILD_TYPE}" STREQUAL "XDEBUG")
target_compile_definitions(moonlight-common-c PRIVATE LC_DEBUG)
else()
Expand All @@ -74,10 +74,40 @@ else()
endif()
endif()

if (NOT(MSVC OR APPLE))
include(CheckLibraryExists)
CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_CLOCK_GETTIME)

if (NOT HAVE_CLOCK_GETTIME)
set(CMAKE_EXTRA_INCLUDE_FILES time.h)
CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME)
SET(CMAKE_EXTRA_INCLUDE_FILES)
endif()

foreach(clock CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW)
message(STATUS "Testing whether ${clock} can be used")
CHECK_CXX_SOURCE_COMPILES(
"#define _POSIX_C_SOURCE 200112L
#include <time.h>
int main ()
{
struct timespec ts[1];
clock_gettime (${clock}, ts);
return 0;
}" HAVE_${clock})
if(HAVE_${clock})
message(STATUS "Testing whether ${clock} can be used -- Success")
else()
message(STATUS "Testing whether ${clock} can be used -- Failed")
endif()
endforeach()

endif()

target_include_directories(moonlight-common-c SYSTEM PUBLIC src)

target_include_directories(moonlight-common-c PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/reedsolomon
)

target_compile_definitions(moonlight-common-c PRIVATE HAS_SOCKLEN_T)
target_compile_definitions(moonlight-common-c PRIVATE HAS_SOCKLEN_T)
16 changes: 11 additions & 5 deletions src/AudioStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ static void AudioReceiveThreadProc(void* context) {
}
else if (packet->header.size == 0) {
// Receive timed out; try again

if (!receivedDataFromPeer) {
waitingForAudioMs += UDP_RECV_POLL_TIMEOUT_MS;
}
Expand All @@ -299,6 +299,8 @@ static void AudioReceiveThreadProc(void* context) {
Limelog("Received first audio packet after %d ms\n", waitingForAudioMs);

if (firstReceiveTime != 0) {
// XXX firstReceiveTime is never set here...
// We're already dropping 500ms of audio so this probably doesn't matter
packetsToDrop += (uint32_t)(PltGetMillis() - firstReceiveTime) / AudioPacketDuration;
}

Expand Down Expand Up @@ -366,15 +368,15 @@ static void AudioReceiveThreadProc(void* context) {
free(queuedPacket);
}
}

// Break on exit
if (queuedPacket != NULL) {
break;
}
}
}
}

if (packet != NULL) {
free(packet);
}
Expand Down Expand Up @@ -405,12 +407,12 @@ void stopAudioStream(void) {
AudioCallbacks.stop();

PltInterruptThread(&receiveThread);
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
// Signal threads waiting on the LBQ
LbqSignalQueueShutdown(&packetQueue);
PltInterruptThread(&decoderThread);
}

PltJoinThread(&receiveThread);
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
PltJoinThread(&decoderThread);
Expand Down Expand Up @@ -474,3 +476,7 @@ int LiGetPendingAudioFrames(void) {
int LiGetPendingAudioDuration(void) {
return LiGetPendingAudioFrames() * AudioPacketDuration;
}

const RTP_AUDIO_STATS* LiGetRTPAudioStats(void) {
return &rtpAudioQueue.stats;
}
6 changes: 3 additions & 3 deletions src/InputStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ typedef struct _PACKET_HOLDER {
// Initializes the input stream
int initializeInputStream(void) {
memcpy(currentAesIv, StreamConfig.remoteInputAesIv, sizeof(currentAesIv));

// Set a high maximum queue size limit to ensure input isn't dropped
// while the input send thread is blocked for short periods.
LbqInitializeLinkedBlockingQueue(&packetQueue, MAX_QUEUED_INPUT_PACKETS);
Expand Down Expand Up @@ -129,7 +129,7 @@ int initializeInputStream(void) {
// Destroys and cleans up the input stream
void destroyInputStream(void) {
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;

PltDestroyCryptoContext(cryptoContext);

entry = LbqDestroyLinkedBlockingQueue(&packetQueue);
Expand Down Expand Up @@ -740,7 +740,7 @@ int stopInputStream(void) {
if (inputSock != INVALID_SOCKET) {
shutdownTcpSocket(inputSock);
}

if (inputSock != INVALID_SOCKET) {
closeSocket(inputSock);
inputSock = INVALID_SOCKET;
Expand Down
54 changes: 44 additions & 10 deletions src/Limelight.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ typedef struct _STREAM_CONFIGURATION {
// Specifies the channel configuration of the audio stream.
// See AUDIO_CONFIGURATION constants and MAKE_AUDIO_CONFIGURATION() below.
int audioConfiguration;

// Specifies the mask of supported video formats.
// See VIDEO_FORMAT constants below.
int supportedVideoFormats;
Expand Down Expand Up @@ -154,16 +154,15 @@ typedef struct _DECODE_UNIT {
// (happens when the frame is repeated).
uint16_t frameHostProcessingLatency;

// Receive time of first buffer. This value uses an implementation-defined epoch,
// but the same epoch as enqueueTimeMs and LiGetMillis().
uint64_t receiveTimeMs;
// Receive time of first buffer in microseconds.
uint64_t receiveTimeUs;

// Time the frame was fully assembled and queued for the video decoder to process.
// This is also approximately the same time as the final packet was received, so
// enqueueTimeMs - receiveTimeMs is the time taken to receive the frame. At the
// enqueueTimeUs - receiveTimeUs is the time taken to receive the frame. At the
// time the decode unit is passed to submitDecodeUnit(), the total queue delay
// can be calculated by LiGetMillis() - enqueueTimeMs.
uint64_t enqueueTimeMs;
// can be calculated. This value is in microseconds.
uint64_t enqueueTimeUs;

// Presentation time in milliseconds with the epoch at the first captured frame.
// This can be used to aid frame pacing or to drop old frames that were queued too
Expand Down Expand Up @@ -512,10 +511,10 @@ void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks)
typedef struct _SERVER_INFORMATION {
// Server host name or IP address in text form
const char* address;

// Text inside 'appversion' tag in /serverinfo
const char* serverInfoAppVersion;

// Text inside 'GfeVersion' tag in /serverinfo (if present)
const char* serverInfoGfeVersion;

Expand Down Expand Up @@ -825,7 +824,12 @@ int LiSendHighResScrollEvent(short scrollAmount);
int LiSendHScrollEvent(signed char scrollClicks);
int LiSendHighResHScrollEvent(short scrollAmount);

// This function returns a time in microseconds with an implementation-defined epoch.
// It should only ever be compared with the return value from a previous call to itself.
uint64_t LiGetMicroseconds(void);

// This function returns a time in milliseconds with an implementation-defined epoch.
// It should only ever be compared with the return value from a previous call to itself.
uint64_t LiGetMillis(void);

// This is a simplistic STUN function that can assist clients in getting the WAN address
Expand All @@ -848,6 +852,36 @@ int LiGetPendingAudioFrames(void);
// negotiated audio frame duration.
int LiGetPendingAudioDuration(void);

// Returns a pointer to a struct containing various statistics about the RTP audio stream.
// The data should be considered read-only and must not be modified.
typedef struct _RTP_AUDIO_STATS {
uint32_t packetCountAudio; // total audio packets
uint32_t packetCountFec; // total packets of type FEC
uint32_t packetCountFecRecovered; // a packet was saved
uint32_t packetCountFecFailed; // tried to recover but too much was lost
uint32_t packetCountOOS; // out-of-sequence packets
uint32_t packetCountInvalid; // corrupted packets, etc
uint32_t packetCountFecInvalid; // invalid FEC packet
} RTP_AUDIO_STATS, *PRTP_AUDIO_STATS;

const RTP_AUDIO_STATS* LiGetRTPAudioStats(void);

// Returns a pointer to a struct containing various statistics about the RTP video stream.
// The data should be considered read-only and must not be modified.
// Right now this is mainly used to track total video and FEC packets, as there are
// many video stats already implemented at a higher level in moonlight-qt.
typedef struct _RTP_VIDEO_STATS {
uint32_t packetCountVideo; // total video packets
uint32_t packetCountFec; // total packets of type FEC
uint32_t packetCountFecRecovered; // a packet was saved
uint32_t packetCountFecFailed; // tried to recover but too much was lost
uint32_t packetCountOOS; // out-of-sequence packets
uint32_t packetCountInvalid; // corrupted packets, etc
uint32_t packetCountFecInvalid; // invalid FEC packet
} RTP_VIDEO_STATS, *PRTP_VIDEO_STATS;

const RTP_VIDEO_STATS* LiGetRTPVideoStats(void);

// Port index flags for use with LiGetPortFromPortFlagIndex() and LiGetProtocolFromPortFlagIndex()
#define ML_PORT_INDEX_TCP_47984 0
#define ML_PORT_INDEX_TCP_47989 1
Expand Down Expand Up @@ -875,7 +909,7 @@ int LiGetPendingAudioDuration(void);
unsigned int LiGetPortFlagsFromStage(int stage);
unsigned int LiGetPortFlagsFromTerminationErrorCode(int errorCode);

// Returns the IPPROTO_* value for the specified port index
// Returns the IPPROTO_* value for the specified port index
int LiGetProtocolFromPortFlagIndex(int portFlagIndex);

// Returns the port number for the specified port index
Expand Down
6 changes: 5 additions & 1 deletion src/Misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ int extractVersionQuadFromString(const char* string, int* quad) {
nextNumber++;
}
}

return 0;
}

Expand Down Expand Up @@ -148,6 +148,10 @@ uint64_t LiGetMillis(void) {
return PltGetMillis();
}

uint64_t LiGetMicroseconds(void) {
return PltGetMicroseconds();
}

uint32_t LiGetHostFeatureFlags(void) {
return SunshineFeatureFlags;
}
Loading