diff --git a/src/Connection.c b/src/Connection.c index 5dab9ed..740ef98 100644 --- a/src/Connection.c +++ b/src/Connection.c @@ -178,6 +178,14 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre OriginalVideoBitrate = streamConfig->bitrate; RemoteAddrString = strdup(serverInfo->address); + // Validate the audio configuration + if (MAGIC_BYTE_FROM_AUDIO_CONFIG(StreamConfig.audioConfiguration) != 0xCA || + CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration) > AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT) { + Limelog("Invalid audio configuration specified\n"); + err = -1; + goto Cleanup; + } + // FEC only works in 16 byte chunks, so we must round down // the given packet size to the nearest multiple of 16. StreamConfig.packetSize -= StreamConfig.packetSize % 16; diff --git a/src/Limelight-internal.h b/src/Limelight-internal.h index 8e32669..763aa7a 100644 --- a/src/Limelight-internal.h +++ b/src/Limelight-internal.h @@ -49,6 +49,9 @@ extern int AudioPacketDuration; // renderer sets CAPABILITY_SUPPORTS_ARBITRARY_AUDIO_DURATION. #define LOW_AUDIO_BITRATE_TRESHOLD 5000 +// Internal macro for checking the magic byte of the audio configuration value +#define MAGIC_BYTE_FROM_AUDIO_CONFIG(x) ((x) & 0xFF) + int serviceEnetHost(ENetHost* client, ENetEvent* event, enet_uint32 timeoutMs); int extractVersionQuadFromString(const char* string, int* quad); int isReferenceFrameInvalidationEnabled(void); diff --git a/src/Limelight.h b/src/Limelight.h index 14bf980..dd54faa 100644 --- a/src/Limelight.h +++ b/src/Limelight.h @@ -52,7 +52,7 @@ typedef struct _STREAM_CONFIGURATION { int streamingRemotely; // Specifies the channel configuration of the audio stream. - // See AUDIO_CONFIGURATION_XXX constants below. + // See MAKE_AUDIO_CONFIGURATION() below. int audioConfiguration; // Specifies that the client can accept an H.265 video stream @@ -153,10 +153,23 @@ typedef struct _DECODE_UNIT { } DECODE_UNIT, *PDECODE_UNIT; // Specifies that the audio stream should be encoded in stereo (default) -#define AUDIO_CONFIGURATION_STEREO 0 +// Deprecated: use MAKE_AUDIO_CONFIGURATION() instead! +#define AUDIO_CONFIGURATION_STEREO MAKE_AUDIO_CONFIGURATION(2, 0x3) // Specifies that the audio stream should be in 5.1 surround sound if the PC is able -#define AUDIO_CONFIGURATION_51_SURROUND 1 +// Deprecated: use MAKE_AUDIO_CONFIGURATION() instead! +#define AUDIO_CONFIGURATION_51_SURROUND MAKE_AUDIO_CONFIGURATION(6, 0xFC) + +// Specifies an audio configuration by channel count and channel mask +#define MAKE_AUDIO_CONFIGURATION(channelCount, channelMask) \ + (((channelMask) << 16) | (channelCount << 8) | 0xCA) + +// Helper macros for retreiving channel count and channel mask from the audio configuration +#define CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(x) (((x) >> 8) & 0xFF) +#define CHANNEL_MASK_FROM_AUDIO_CONFIGURATION(x) (((x) >> 16) & 0xFF) + +// The maximum number of channels supported +#define AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT 6 // Passed to DecoderRendererSetup to indicate that the following video stream will be // in H.264 High Profile. @@ -258,7 +271,7 @@ typedef struct _OPUS_MULTISTREAM_CONFIGURATION { int streams; int coupledStreams; int samplesPerFrame; - unsigned char mapping[6]; + unsigned char mapping[AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; } OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION; // This callback initializes the audio renderer. The audio configuration parameter diff --git a/src/RtspConnection.c b/src/RtspConnection.c index 4943f90..3cbc11a 100644 --- a/src/RtspConnection.c +++ b/src/RtspConnection.c @@ -488,7 +488,7 @@ static int parseOpusConfigurations(PRTSP_MESSAGE response) { HighQualityOpusConfig.sampleRate = NormalQualityOpusConfig.sampleRate = 48000; // Stereo doesn't have any surround-params elements in the RTSP data - if (StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_STEREO) { + if (CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration) == 2) { NormalQualityOpusConfig.channelCount = 2; NormalQualityOpusConfig.streams = 1; NormalQualityOpusConfig.coupledStreams = 1; @@ -501,8 +501,7 @@ static int parseOpusConfigurations(PRTSP_MESSAGE response) { int err; int channelCount; - LC_ASSERT(StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_51_SURROUND); - channelCount = 6; + channelCount = CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration); // Find the correct audio parameter value sprintf(paramsPrefix, "a=fmtp:97 surround-params=%d", channelCount); @@ -548,7 +547,7 @@ static int parseOpusConfigurations(PRTSP_MESSAGE response) { // It's unknown whether all GFE versions that supported surround sound included these // surround sound parameters. In case they didn't, we'll specifically handle 5.1 surround // sound using a hardcoded configuration like we used to before this parsing code existed. - if (StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_51_SURROUND) { + if (channelCount == 6) { NormalQualityOpusConfig.channelCount = 6; NormalQualityOpusConfig.streams = 4; NormalQualityOpusConfig.coupledStreams = 2; diff --git a/src/SdpGenerator.c b/src/SdpGenerator.c index ad958b9..699d246 100644 --- a/src/SdpGenerator.c +++ b/src/SdpGenerator.c @@ -5,12 +5,6 @@ #define MAX_SDP_HEADER_LEN 128 #define MAX_SDP_TAIL_LEN 128 -#define CHANNEL_COUNT_STEREO 2 -#define CHANNEL_COUNT_51_SURROUND 6 - -#define CHANNEL_MASK_STEREO 0x3 -#define CHANNEL_MASK_51_SURROUND 0xFC - typedef struct _SDP_OPTION { char name[MAX_OPTION_NAME_LEN + 1]; void* payload; @@ -266,14 +260,8 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) { err |= addGen5Options(&optionHead); } - if (StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_51_SURROUND) { - audioChannelCount = CHANNEL_COUNT_51_SURROUND; - audioChannelMask = CHANNEL_MASK_51_SURROUND; - } - else { - audioChannelCount = CHANNEL_COUNT_STEREO; - audioChannelMask = CHANNEL_MASK_STEREO; - } + audioChannelCount = CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration); + audioChannelMask = CHANNEL_MASK_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration); if (AppVersionQuad[0] >= 4) { unsigned char slicesPerFrame;