Add sequence and session numbers to audio callbacks. #3

This commit is contained in:
Michał Słomkowski 2015-11-17 22:53:57 +01:00
parent a67dcedf0c
commit ae1e71fffc
7 changed files with 124 additions and 46 deletions

View File

@ -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);

View File

@ -17,14 +17,26 @@ 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,
std::pair<int, bool> decodeOpusPayload(uint8_t *inputBuffer,
int inputLength,
int16_t *pcmBuffer,
int pcmBufferSize);
int encodeAudioPacket(

View File

@ -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) { };
@ -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);

View File

@ -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);
}

View File

@ -37,34 +37,25 @@ mumlib::Audio::~Audio() {
}
}
int mumlib::Audio::decodeAudioPacket(AudioPacketType type,
uint8_t *inputBuffer,
std::pair<int, bool> mumlib::Audio::decodeOpusPayload(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;
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();
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,
@ -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,
@ -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;
}

View File

@ -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);
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(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);
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) {

View File

@ -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;
}
@ -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 {
auto incomingAudioPacket = audio.decodeIncomingAudioPacket(buffer, length);
if (type == AudioPacketType::OPUS) {
int16_t pcmData[5000];
int pcmDataLength = audio.decodeAudioPacket(type, buffer, length, pcmData, 5000);
callback.audio(pcmData, pcmDataLength);
} catch (mumlib::AudioException &exp) {
logger.warn("Audio decode error: %s, calling unsupportedAudio callback.", exp.what());
callback.unsupportedAudio(buffer, length);
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.error("Audio decode error: %s.", exp.what());
}
return true;
}
private: