Add sequence and session numbers to audio callbacks. #3
This commit is contained in:
parent
a67dcedf0c
commit
ae1e71fffc
@ -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);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user