Add support for 5.1 surround sound with GFE 2.7

This commit is contained in:
Cameron Gutman 2015-10-25 13:08:20 -07:00
parent 1b3b57ed2f
commit a13e68b042
4 changed files with 81 additions and 6 deletions

View File

@ -17,13 +17,36 @@ static unsigned short lastSeq;
#define RTP_PORT 48000 #define RTP_PORT 48000
#define MAX_PACKET_SIZE 100 #define MAX_PACKET_SIZE 250
// This is much larger than we should typically have buffered, but // This is much larger than we should typically have buffered, but
// it needs to be. We need a cushion in case our thread gets blocked // it needs to be. We need a cushion in case our thread gets blocked
// for longer than normal. // for longer than normal.
#define RTP_RECV_BUFFER (64 * MAX_PACKET_SIZE) #define RTP_RECV_BUFFER (64 * MAX_PACKET_SIZE)
#define SAMPLE_RATE 48000
static OPUS_MULTISTREAM_CONFIGURATION opusStereoConfig = {
.sampleRate = SAMPLE_RATE,
.channelCount = 2,
.streams = 1,
.coupledStreams = 1,
.mapping = {0, 1}
};
static OPUS_MULTISTREAM_CONFIGURATION opus51SurroundConfig = {
.sampleRate = SAMPLE_RATE,
.channelCount = 6,
.streams = 4,
.coupledStreams = 2,
.mapping = {0, 4, 1, 5, 2, 3}
};
static POPUS_MULTISTREAM_CONFIGURATION opusConfigArray[] = {
&opusStereoConfig,
&opus51SurroundConfig,
};
typedef struct _QUEUED_AUDIO_PACKET { typedef struct _QUEUED_AUDIO_PACKET {
// data must remain at the front // data must remain at the front
char data[MAX_PACKET_SIZE]; char data[MAX_PACKET_SIZE];
@ -242,7 +265,8 @@ void stopAudioStream(void) {
int startAudioStream(void) { int startAudioStream(void) {
int err; int err;
AudioCallbacks.init(); AudioCallbacks.init(StreamConfig.audioConfiguration,
opusConfigArray[StreamConfig.audioConfiguration]);
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
if (rtpSocket == INVALID_SOCKET) { if (rtpSocket == INVALID_SOCKET) {

View File

@ -10,7 +10,7 @@ static DECODER_RENDERER_CALLBACKS fakeDrCallbacks = {
.submitDecodeUnit = fakeDrSubmitDecodeUnit, .submitDecodeUnit = fakeDrSubmitDecodeUnit,
}; };
static void fakeArInit(void) {} static void fakeArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) {}
static void fakeArCleanup(void) {} static void fakeArCleanup(void) {}
static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {} static void fakeArDecodeAndPlaySample(char* sampleData, int sampleLength) {}

View File

@ -29,6 +29,10 @@ typedef struct _STREAM_CONFIGURATION {
// streaming optimizations. If unsure, set to 0. // streaming optimizations. If unsure, set to 0.
int streamingRemotely; int streamingRemotely;
// Specifies the channel configuration of the audio stream.
// See AUDIO_CONFIGURATION_XXX constants below.
int audioConfiguration;
// AES encryption data for the remote input stream. This must be // AES encryption data for the remote input stream. This must be
// the same as what was passed as rikey and rikeyid // the same as what was passed as rikey and rikeyid
// in /launch and /resume requests. // in /launch and /resume requests.
@ -59,6 +63,12 @@ typedef struct _DECODE_UNIT {
PLENTRY bufferList; PLENTRY bufferList;
} DECODE_UNIT, *PDECODE_UNIT; } DECODE_UNIT, *PDECODE_UNIT;
// Specifies that the audio stream should be encoded in stereo (default)
#define AUDIO_CONFIGURATION_STEREO 0
// Specifies that the audio stream should be in 5.1 surround sound if the PC is able
#define AUDIO_CONFIGURATION_51_SURROUND 1
// If set in the renderer capabilities field, this flag will cause audio/video data to // If set in the renderer capabilities field, this flag will cause audio/video data to
// be submitted directly from the receive thread. This should only be specified if the // be submitted directly from the receive thread. This should only be specified if the
// renderer is non-blocking. This flag is valid on both audio and video renderers. // renderer is non-blocking. This flag is valid on both audio and video renderers.
@ -97,8 +107,21 @@ typedef struct _DECODER_RENDERER_CALLBACKS {
// Use this function to zero the video callbacks when allocated on the stack or heap // Use this function to zero the video callbacks when allocated on the stack or heap
void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks); void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks);
// This callback initializes the audio renderer // This structure provides the Opus multistream decoder parameters required to successfully
typedef void(*AudioRendererInit)(void); // decode the audio stream being sent from the computer. See opus_multistream_decoder_init docs
// for details about these fields.
typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
int sampleRate;
int channelCount;
int streams;
int coupledStreams;
const unsigned char mapping[6];
} OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION;
// This callback initializes the audio renderer. The audio configuration parameter
// provides the negotiated audio configuration. This may differ from the one
// specified in the stream configuration.
typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
// This callback performs the final teardown of the audio decoder // This callback performs the final teardown of the audio decoder
typedef void(*AudioRendererCleanup)(void); typedef void(*AudioRendererCleanup)(void);

View File

@ -5,6 +5,12 @@
#define MAX_SDP_HEADER_LEN 128 #define MAX_SDP_HEADER_LEN 128
#define MAX_SDP_TAIL_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 { typedef struct _SDP_OPTION {
char name[MAX_OPTION_NAME_LEN+1]; char name[MAX_OPTION_NAME_LEN+1];
void* payload; void* payload;
@ -134,6 +140,8 @@ static int addGen4Options(PSDP_OPTION *head, char* addrStr) {
char payloadStr[92]; char payloadStr[92];
int err = 0; int err = 0;
unsigned char slicesPerFrame; unsigned char slicesPerFrame;
int audioChannelCount;
int audioChannelMask;
sprintf(payloadStr, "rtsp://%s:48010", addrStr); sprintf(payloadStr, "rtsp://%s:48010", addrStr);
err |= addAttributeString(head, "x-nv-general.serverAddress", payloadStr); err |= addAttributeString(head, "x-nv-general.serverAddress", payloadStr);
@ -149,6 +157,26 @@ static int addGen4Options(PSDP_OPTION *head, char* addrStr) {
sprintf(payloadStr, "%d", slicesPerFrame); sprintf(payloadStr, "%d", slicesPerFrame);
err |= addAttributeString(head, "x-nv-video[0].videoEncoderSlicesPerFrame", payloadStr); err |= addAttributeString(head, "x-nv-video[0].videoEncoderSlicesPerFrame", payloadStr);
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;
}
sprintf(payloadStr, "%d", audioChannelCount);
err |= addAttributeString(head, "x-nv-audio.surround.numChannels", payloadStr);
sprintf(payloadStr, "%d", audioChannelMask);
err |= addAttributeString(head, "x-nv-audio.surround.channelMask", payloadStr);
if (audioChannelCount > 2) {
err |= addAttributeString(head, "x-nv-audio.surround.enable", "1");
}
else {
err |= addAttributeString(head, "x-nv-audio.surround.enable", "0");
}
return err; return err;
} }