Skip to content

Commit

Permalink
Add sequence and session numbers to audio callbacks. jcalifornia#3
Browse files Browse the repository at this point in the history
  • Loading branch information
slomkowski committed Nov 17, 2015
1 parent a67dced commit ae1e71f
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 48 deletions.
2 changes: 1 addition & 1 deletion include/mumlib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace mumlib {

Mumlib(Callback &callback, io_service &ioService);

~Mumlib();
virtual ~Mumlib();

void connect(string host, int port, string user, string password);

Expand Down
18 changes: 15 additions & 3 deletions include/mumlib/Audio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,27 @@ namespace mumlib {
AudioException(string message) : MumlibException(message) { }
};

struct IncomingAudioPacket {
AudioPacketType type;
int target;
int64_t sessionId;
int64_t sequenceNumber;
uint8_t *audioPayload;
int audioPayloadLength;
};

class Audio : boost::noncopyable {
public:
Audio();

~Audio();
virtual ~Audio();

IncomingAudioPacket decodeIncomingAudioPacket(uint8_t *inputBuffer, int inputBufferLength);

int decodeAudioPacket(AudioPacketType type, uint8_t *inputBuffer, int inputLength, int16_t *pcmBuffer,
int pcmBufferSize);
std::pair<int, bool> decodeOpusPayload(uint8_t *inputBuffer,
int inputLength,
int16_t *pcmBuffer,
int pcmBufferSize);

int encodeAudioPacket(
int target,
Expand Down
12 changes: 12 additions & 0 deletions include/mumlib/Callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ namespace mumlib {
string os_version) { };

virtual void audio(
int target,
int sessionId,
int sequenceNumber,
int16_t *pcm_data,
uint32_t pcm_data_size) { };

virtual void unsupportedAudio(
int target,
int sessionId,
int sequenceNumber,
uint8_t *encoded_audio_data,
uint32_t encoded_audio_data_size) { };

Expand Down Expand Up @@ -156,10 +162,16 @@ namespace mumlib {
string os_version);

virtual void audio(
int target,
int sessionId,
int sequenceNumber,
int16_t *pcm_data,
uint32_t pcm_data_size);

virtual void unsupportedAudio(
int target,
int sessionId,
int sequenceNumber,
uint8_t *encoded_audio_data,
uint32_t encoded_audio_data_size);

Expand Down
6 changes: 5 additions & 1 deletion mumlib_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ class MyCallback : public mumlib::BasicCallback {
public:
mumlib::Mumlib *mum;

virtual void audio(int16_t *pcm_data, uint32_t pcm_data_size) {
virtual void audio(int target,
int sessionId,
int sequenceNumber,
int16_t *pcm_data,
uint32_t pcm_data_size) {
mum->sendAudioData(pcm_data, pcm_data_size);
}

Expand Down
83 changes: 51 additions & 32 deletions src/Audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,34 +37,25 @@ mumlib::Audio::~Audio() {
}
}

int mumlib::Audio::decodeAudioPacket(AudioPacketType type,
uint8_t *inputBuffer,
int inputLength,
int16_t *pcmBuffer,
int pcmBufferSize) {

if (type != AudioPacketType::OPUS) {
throw AudioException("codecs other than OPUS are not supported");
}

int target = inputBuffer[0] & 0x1F;

int64_t sessionId;
int64_t sequenceNumber;
std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
int inputLength,
int16_t *pcmBuffer,
int pcmBufferSize) {
int64_t opusDataLength;

std::array<int64_t *, 3> varInts = {&sessionId, &sequenceNumber, &opusDataLength};

int dataPointer = 1;
for (int64_t *val : varInts) {
VarInt varInt(&inputBuffer[dataPointer]);
*val = varInt.getValue();
dataPointer += varInt.getEncoded().size();
}
int dataPointer = 0;
VarInt varInt(inputBuffer);
opusDataLength = varInt.getValue();
dataPointer += varInt.getEncoded().size();

bool lastPacket = (opusDataLength & 0x2000) != 0;
opusDataLength = opusDataLength & 0x1fff;

if (inputLength < opusDataLength + dataPointer) {
throw AudioException((boost::format("invalid Opus payload (%d B): header %d B, expected Opus data length %d B")
% inputLength % dataPointer % opusDataLength).str());
}

int outputSize = opus_decode(opusDecoder,
reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]),
opusDataLength,
Expand All @@ -77,17 +68,10 @@ int mumlib::Audio::decodeAudioPacket(AudioPacketType type,
opus_strerror(outputSize)).str());
}

logger.debug(
"Received %d B of OPUS data, decoded to %d B (target: %d, sessionID: %ld, seq num: %ld, last: %d).",
opusDataLength,
outputSize,
target,
sessionId,
sequenceNumber,
lastPacket);

logger.debug("%d B of Opus data decoded to %d PCM samples, last packet: %d.",
opusDataLength, outputSize, lastPacket);

return outputSize;
return std::make_pair(outputSize, lastPacket);
}

int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int inputLength, uint8_t *outputBuffer,
Expand Down Expand Up @@ -147,3 +131,38 @@ void mumlib::Audio::resetEncoder() {

outgoingSequenceNumber = 0;
}

mumlib::IncomingAudioPacket mumlib::Audio::decodeIncomingAudioPacket(uint8_t *inputBuffer, int inputBufferLength) {
mumlib::IncomingAudioPacket incomingAudioPacket;

incomingAudioPacket.type = static_cast<AudioPacketType >((inputBuffer[0] & 0xE0) >> 5);
incomingAudioPacket.target = inputBuffer[0] & 0x1F;

std::array<int64_t *, 2> varInts = {&incomingAudioPacket.sessionId, &incomingAudioPacket.sequenceNumber};

int dataPointer = 1;
for (int64_t *val : varInts) {
VarInt varInt(&inputBuffer[dataPointer]);
*val = varInt.getValue();
dataPointer += varInt.getEncoded().size();
}

incomingAudioPacket.audioPayload = &inputBuffer[dataPointer];
incomingAudioPacket.audioPayloadLength = inputBufferLength - dataPointer;

if (dataPointer >= inputBufferLength) {
throw AudioException((boost::format("invalid incoming audio packet (%d B): header %d B") % inputBufferLength %
dataPointer).str());
}

logger.debug(
"Received %d B of audio packet, %d B header, %d B payload (target: %d, sessionID: %ld, seq num: %ld).",
inputBufferLength,
dataPointer,
incomingAudioPacket.audioPayloadLength,
incomingAudioPacket.target,
incomingAudioPacket.sessionId,
incomingAudioPacket.sequenceNumber);

return incomingAudioPacket;
}
20 changes: 15 additions & 5 deletions src/Callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,23 @@ void mumlib::BasicCallback::version(
}

void mumlib::BasicCallback::audio(
int target,
int sessionId,
int sequenceNumber,
int16_t *pcmData,
uint32_t pcm_data_size) {
impl->logger.debug("audio: %d bytes of raw PCM data.", pcm_data_size);
}

void BasicCallback::unsupportedAudio(uint8_t *encoded_audio_data, uint32_t encoded_audio_data_size) {
impl->logger.debug("unsupportedAudio: received %d bytes of encoded data.", encoded_audio_data_size);
impl->logger.debug("audio: %d bytes of raw PCM data, target: %d, session: %d, seq: %d.",
pcm_data_size, target, sessionId, sequenceNumber);
}

void BasicCallback::unsupportedAudio(
int target,
int sessionId,
int sequenceNumber,
uint8_t *encoded_audio_data,
uint32_t encoded_audio_data_size) {
impl->logger.debug("unsupportedAudio: received %d bytes of encoded data, target: %d, session: %d, seq: %d.",
encoded_audio_data_size, target, sessionId, sequenceNumber);
}

void BasicCallback::serverSync(string welcome_text, int32_t session, int32_t max_bandwidth, int64_t permissions) {
Expand Down
33 changes: 27 additions & 6 deletions src/mumlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace mumlib {
transport(ioService, boost::bind(&_Mumlib_Private::processIncomingTcpMessage, this, _1, _2, _3),
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3)) { }

~_Mumlib_Private() {
virtual ~_Mumlib_Private() {
if (not externalIoService) {
delete &ioService;
}
Expand All @@ -54,13 +54,34 @@ namespace mumlib {
bool processAudioPacket(AudioPacketType type, uint8_t *buffer, int length) {
logger.info("Got %d B of encoded audio data.", length);
try {
int16_t pcmData[5000];
int pcmDataLength = audio.decodeAudioPacket(type, buffer, length, pcmData, 5000);
callback.audio(pcmData, pcmDataLength);
auto incomingAudioPacket = audio.decodeIncomingAudioPacket(buffer, length);

if (type == AudioPacketType::OPUS) {
int16_t pcmData[5000];
auto status = audio.decodeOpusPayload(incomingAudioPacket.audioPayload,
incomingAudioPacket.audioPayloadLength,
pcmData,
5000);

callback.audio(incomingAudioPacket.target,
incomingAudioPacket.sessionId,
incomingAudioPacket.sequenceNumber,
pcmData,
status.first);
} else {
logger.warn("Incoming audio packet doesn't contain Opus data, calling unsupportedAudio callback.");
callback.unsupportedAudio(incomingAudioPacket.target,
incomingAudioPacket.sessionId,
incomingAudioPacket.sequenceNumber,
incomingAudioPacket.audioPayload,
incomingAudioPacket.audioPayloadLength);
}

} catch (mumlib::AudioException &exp) {
logger.warn("Audio decode error: %s, calling unsupportedAudio callback.", exp.what());
callback.unsupportedAudio(buffer, length);
logger.error("Audio decode error: %s.", exp.what());
}

return true;
}

private:
Expand Down

0 comments on commit ae1e71f

Please sign in to comment.