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(Callback &callback, io_service &ioService);
|
||||||
|
|
||||||
~Mumlib();
|
virtual ~Mumlib();
|
||||||
|
|
||||||
void connect(string host, int port, string user, string password);
|
void connect(string host, int port, string user, string password);
|
||||||
|
|
||||||
|
@ -17,15 +17,27 @@ namespace mumlib {
|
|||||||
AudioException(string message) : MumlibException(message) { }
|
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 {
|
class Audio : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
Audio();
|
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 pcmBufferSize);
|
int inputLength,
|
||||||
|
int16_t *pcmBuffer,
|
||||||
|
int pcmBufferSize);
|
||||||
|
|
||||||
int encodeAudioPacket(
|
int encodeAudioPacket(
|
||||||
int target,
|
int target,
|
||||||
|
@ -19,10 +19,16 @@ namespace mumlib {
|
|||||||
string os_version) { };
|
string os_version) { };
|
||||||
|
|
||||||
virtual void audio(
|
virtual void audio(
|
||||||
|
int target,
|
||||||
|
int sessionId,
|
||||||
|
int sequenceNumber,
|
||||||
int16_t *pcm_data,
|
int16_t *pcm_data,
|
||||||
uint32_t pcm_data_size) { };
|
uint32_t pcm_data_size) { };
|
||||||
|
|
||||||
virtual void unsupportedAudio(
|
virtual void unsupportedAudio(
|
||||||
|
int target,
|
||||||
|
int sessionId,
|
||||||
|
int sequenceNumber,
|
||||||
uint8_t *encoded_audio_data,
|
uint8_t *encoded_audio_data,
|
||||||
uint32_t encoded_audio_data_size) { };
|
uint32_t encoded_audio_data_size) { };
|
||||||
|
|
||||||
@ -156,10 +162,16 @@ namespace mumlib {
|
|||||||
string os_version);
|
string os_version);
|
||||||
|
|
||||||
virtual void audio(
|
virtual void audio(
|
||||||
|
int target,
|
||||||
|
int sessionId,
|
||||||
|
int sequenceNumber,
|
||||||
int16_t *pcm_data,
|
int16_t *pcm_data,
|
||||||
uint32_t pcm_data_size);
|
uint32_t pcm_data_size);
|
||||||
|
|
||||||
virtual void unsupportedAudio(
|
virtual void unsupportedAudio(
|
||||||
|
int target,
|
||||||
|
int sessionId,
|
||||||
|
int sequenceNumber,
|
||||||
uint8_t *encoded_audio_data,
|
uint8_t *encoded_audio_data,
|
||||||
uint32_t encoded_audio_data_size);
|
uint32_t encoded_audio_data_size);
|
||||||
|
|
||||||
|
@ -8,7 +8,11 @@ class MyCallback : public mumlib::BasicCallback {
|
|||||||
public:
|
public:
|
||||||
mumlib::Mumlib *mum;
|
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);
|
mum->sendAudioData(pcm_data, pcm_data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,34 +37,25 @@ mumlib::Audio::~Audio() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mumlib::Audio::decodeAudioPacket(AudioPacketType type,
|
std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
|
||||||
uint8_t *inputBuffer,
|
int inputLength,
|
||||||
int inputLength,
|
int16_t *pcmBuffer,
|
||||||
int16_t *pcmBuffer,
|
int pcmBufferSize) {
|
||||||
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;
|
int64_t opusDataLength;
|
||||||
|
|
||||||
std::array<int64_t *, 3> varInts = {&sessionId, &sequenceNumber, &opusDataLength};
|
int dataPointer = 0;
|
||||||
|
VarInt varInt(inputBuffer);
|
||||||
int dataPointer = 1;
|
opusDataLength = varInt.getValue();
|
||||||
for (int64_t *val : varInts) {
|
dataPointer += varInt.getEncoded().size();
|
||||||
VarInt varInt(&inputBuffer[dataPointer]);
|
|
||||||
*val = varInt.getValue();
|
|
||||||
dataPointer += varInt.getEncoded().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lastPacket = (opusDataLength & 0x2000) != 0;
|
bool lastPacket = (opusDataLength & 0x2000) != 0;
|
||||||
opusDataLength = opusDataLength & 0x1fff;
|
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,
|
int outputSize = opus_decode(opusDecoder,
|
||||||
reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]),
|
reinterpret_cast<const unsigned char *>(&inputBuffer[dataPointer]),
|
||||||
opusDataLength,
|
opusDataLength,
|
||||||
@ -77,17 +68,10 @@ int mumlib::Audio::decodeAudioPacket(AudioPacketType type,
|
|||||||
opus_strerror(outputSize)).str());
|
opus_strerror(outputSize)).str());
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.debug("%d B of Opus data decoded to %d PCM samples, last packet: %d.",
|
||||||
"Received %d B of OPUS data, decoded to %d B (target: %d, sessionID: %ld, seq num: %ld, last: %d).",
|
opusDataLength, outputSize, lastPacket);
|
||||||
opusDataLength,
|
|
||||||
outputSize,
|
|
||||||
target,
|
|
||||||
sessionId,
|
|
||||||
sequenceNumber,
|
|
||||||
lastPacket);
|
|
||||||
|
|
||||||
|
return std::make_pair(outputSize, lastPacket);
|
||||||
return outputSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int inputLength, uint8_t *outputBuffer,
|
int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int inputLength, uint8_t *outputBuffer,
|
||||||
@ -147,3 +131,38 @@ void mumlib::Audio::resetEncoder() {
|
|||||||
|
|
||||||
outgoingSequenceNumber = 0;
|
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(
|
void mumlib::BasicCallback::audio(
|
||||||
|
int target,
|
||||||
|
int sessionId,
|
||||||
|
int sequenceNumber,
|
||||||
int16_t *pcmData,
|
int16_t *pcmData,
|
||||||
uint32_t pcm_data_size) {
|
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) {
|
void BasicCallback::unsupportedAudio(
|
||||||
impl->logger.debug("unsupportedAudio: received %d bytes of encoded data.", encoded_audio_data_size);
|
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) {
|
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),
|
transport(ioService, boost::bind(&_Mumlib_Private::processIncomingTcpMessage, this, _1, _2, _3),
|
||||||
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3)) { }
|
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3)) { }
|
||||||
|
|
||||||
~_Mumlib_Private() {
|
virtual ~_Mumlib_Private() {
|
||||||
if (not externalIoService) {
|
if (not externalIoService) {
|
||||||
delete &ioService;
|
delete &ioService;
|
||||||
}
|
}
|
||||||
@ -54,13 +54,34 @@ namespace mumlib {
|
|||||||
bool processAudioPacket(AudioPacketType type, uint8_t *buffer, int length) {
|
bool processAudioPacket(AudioPacketType type, uint8_t *buffer, int length) {
|
||||||
logger.info("Got %d B of encoded audio data.", length);
|
logger.info("Got %d B of encoded audio data.", length);
|
||||||
try {
|
try {
|
||||||
int16_t pcmData[5000];
|
auto incomingAudioPacket = audio.decodeIncomingAudioPacket(buffer, length);
|
||||||
int pcmDataLength = audio.decodeAudioPacket(type, buffer, length, pcmData, 5000);
|
|
||||||
callback.audio(pcmData, pcmDataLength);
|
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) {
|
} catch (mumlib::AudioException &exp) {
|
||||||
logger.warn("Audio decode error: %s, calling unsupportedAudio callback.", exp.what());
|
logger.error("Audio decode error: %s.", exp.what());
|
||||||
callback.unsupportedAudio(buffer, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user