Replace libmumble with mumlib library.
This commit is contained in:
parent
e50e6d278a
commit
87842318be
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +1,6 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
config.ini
|
config.ini
|
||||||
|
|
||||||
|
build/
|
0
.gitmodules
vendored
0
.gitmodules
vendored
@ -7,19 +7,17 @@ INCLUDE(FindPkgConfig)
|
|||||||
find_package(Boost COMPONENTS system unit_test_framework program_options filesystem REQUIRED)
|
find_package(Boost COMPONENTS system unit_test_framework program_options filesystem REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
pkg_check_modules(OPUS "opus")
|
|
||||||
pkg_check_modules(PJSIP "libpjproject")
|
pkg_check_modules(PJSIP "libpjproject")
|
||||||
pkg_check_modules(LOG4CPP "log4cpp")
|
pkg_check_modules(LOG4CPP "log4cpp")
|
||||||
pkg_check_modules(SNDFILE "sndfile")
|
pkg_check_modules(SNDFILE "sndfile")
|
||||||
|
|
||||||
|
|
||||||
include_directories(${OPUS_INCLUDE_DIRS})
|
|
||||||
include_directories(${PJSIP_INCLUDE_DIRS})
|
include_directories(${PJSIP_INCLUDE_DIRS})
|
||||||
include_directories(${LOG4CPP_INCLUDE_DIRS})
|
include_directories(${LOG4CPP_INCLUDE_DIRS})
|
||||||
include_directories(${SNDFILE_INCLUDE_DIRS})
|
include_directories(${SNDFILE_INCLUDE_DIRS})
|
||||||
include_directories(libmumble)
|
include_directories(../mumlib/include)
|
||||||
|
|
||||||
link_directories(libmumble)
|
link_directories(../mumlib/build)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
PjsuaCommunicator.cpp
|
PjsuaCommunicator.cpp
|
||||||
@ -40,7 +38,7 @@ target_link_libraries(mumsi ${PJSIP_LIBRARIES})
|
|||||||
target_link_libraries(mumsi ${LOG4CPP_LIBRARIES})
|
target_link_libraries(mumsi ${LOG4CPP_LIBRARIES})
|
||||||
target_link_libraries(mumsi ${SNDFILE_LIBRARIES})
|
target_link_libraries(mumsi ${SNDFILE_LIBRARIES})
|
||||||
target_link_libraries(mumsi ${Boost_LIBRARIES})
|
target_link_libraries(mumsi ${Boost_LIBRARIES})
|
||||||
target_link_libraries(mumsi mumble)
|
target_link_libraries(mumsi mumlib)
|
||||||
|
|
||||||
#add_executable(mumsi_test ${SOURCE_FILES} ${TEST_SOURCE_FILES} test_main.cpp)
|
#add_executable(mumsi_test ${SOURCE_FILES} ${TEST_SOURCE_FILES} test_main.cpp)
|
||||||
#target_link_libraries(mumsi_test ${OPUS_LIBRARIES})
|
#target_link_libraries(mumsi_test ${OPUS_LIBRARIES})
|
||||||
|
@ -3,163 +3,47 @@
|
|||||||
|
|
||||||
#include "MumbleCommunicator.hpp"
|
#include "MumbleCommunicator.hpp"
|
||||||
|
|
||||||
void mumble::MumbleCommunicator::receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size) {
|
namespace mumble {
|
||||||
int dataPointer = 1;
|
class MumlibCallback : public mumlib::BasicCallback {
|
||||||
opus_int16 pcmData[1024];
|
public:
|
||||||
|
std::shared_ptr<mumlib::Mumlib> mum;
|
||||||
|
MumbleCommunicator *communicator;
|
||||||
|
|
||||||
if (audio_data[0] == 0x80) {
|
virtual void audio(
|
||||||
int64_t sessionId;
|
int16_t *pcm_data,
|
||||||
int64_t sequenceNumber;
|
uint32_t pcm_data_size) {
|
||||||
int64_t opusDataLength;
|
communicator->samplesBuffer.pushSamples(pcm_data, pcm_data_size);
|
||||||
bool lastPacket;
|
}
|
||||||
|
};
|
||||||
dataPointer += mumble_parse_variant(&sessionId, &audio_data[dataPointer]);
|
|
||||||
dataPointer += mumble_parse_variant(&sequenceNumber, &audio_data[dataPointer]);
|
|
||||||
dataPointer += mumble_parse_variant(&opusDataLength, &audio_data[dataPointer]);
|
|
||||||
|
|
||||||
lastPacket = (opusDataLength & 0x2000) != 0;
|
|
||||||
opusDataLength = opusDataLength & 0x1fff;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int iAudioBufferSize;
|
|
||||||
unsigned int iFrameSize = mumble::SAMPLE_RATE / 100;
|
|
||||||
iAudioBufferSize = iFrameSize;
|
|
||||||
iAudioBufferSize *= 12;
|
|
||||||
int decodedSamples = opus_decode(opusDecoder,
|
|
||||||
reinterpret_cast<const unsigned char *>(&audio_data[dataPointer]),
|
|
||||||
opusDataLength,
|
|
||||||
pcmData,
|
|
||||||
iAudioBufferSize,
|
|
||||||
0);
|
|
||||||
|
|
||||||
fileHandle.write(pcmData, decodedSamples);
|
|
||||||
|
|
||||||
logger.debug("Received %d bytes of Opus data (seq %ld), decoded to %d bytes. Push it to outputQueue.",
|
|
||||||
opusDataLength, sequenceNumber, decodedSamples);
|
|
||||||
|
|
||||||
samplesBuffer.pushSamples(pcmData, decodedSamples);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logger.warn("Received %d bytes of non-recognisable audio data.", audio_data_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mumble_audio_callback(uint8_t *audio_data, uint32_t audio_data_size, void *userData) {
|
|
||||||
mumble::MumbleCommunicator *mumbleCommunicator = static_cast<mumble::MumbleCommunicator *>(userData);
|
|
||||||
mumbleCommunicator->receiveAudioFrameCallback(audio_data, audio_data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mumble_serversync_callback(char *welcome_text,
|
|
||||||
int32_t session,
|
|
||||||
int32_t max_bandwidth,
|
|
||||||
int64_t permissions,
|
|
||||||
void *usterData) {
|
|
||||||
printf("%s\n", welcome_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mumble_cryptsetup_callback(uint32_t key_size,
|
|
||||||
uint8_t *key,
|
|
||||||
uint32_t client_nonce_size,
|
|
||||||
uint8_t *client_nonce,
|
|
||||||
uint32_t server_nonce_size,
|
|
||||||
uint8_t *server_nonce,
|
|
||||||
void *userData) {
|
|
||||||
mumble::MumbleCommunicator *mumbleCommunicator = static_cast<mumble::MumbleCommunicator *>(userData);
|
|
||||||
printf("received crypto nonce\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int verify_cert(uint8_t *, uint32_t) {
|
|
||||||
// Accept every cert
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mumble::MumbleCommunicator::MumbleCommunicator(
|
mumble::MumbleCommunicator::MumbleCommunicator(
|
||||||
|
boost::asio::io_service &ioService,
|
||||||
ISamplesBuffer &samplesBuffer,
|
ISamplesBuffer &samplesBuffer,
|
||||||
std::string user,
|
std::string user,
|
||||||
std::string password,
|
std::string password,
|
||||||
std::string host,
|
std::string host,
|
||||||
int port) : samplesBuffer(samplesBuffer),
|
int port) : ioService(ioService),
|
||||||
outgoingAudioSequenceNumber(1),
|
samplesBuffer(samplesBuffer),
|
||||||
logger(log4cpp::Category::getInstance("MumbleCommunicator")) {
|
logger(log4cpp::Category::getInstance("MumbleCommunicator")) {
|
||||||
|
|
||||||
quit = false;
|
quit = false;
|
||||||
|
|
||||||
opusDecoder = opus_decoder_create(SAMPLE_RATE, 1, nullptr); //todo grab error
|
callback.reset(new MumlibCallback());
|
||||||
|
|
||||||
opusEncoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, nullptr);
|
mum.reset(new mumlib::Mumlib(*callback, ioService));
|
||||||
opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0));
|
callback->communicator = this;
|
||||||
|
callback->mum = mum;
|
||||||
|
|
||||||
fileHandle = SndfileHandle("capture_mumble.wav", SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 1, SAMPLE_RATE);
|
mum->connect(host, port, user, password);
|
||||||
|
|
||||||
struct mumble_config config;
|
|
||||||
std::memset(&config, 0, sizeof(config));
|
|
||||||
|
|
||||||
config.user_data = this;
|
|
||||||
|
|
||||||
config.size = sizeof(config);
|
|
||||||
config.host = const_cast<char *>(host.c_str());
|
|
||||||
if (port > 0) {
|
|
||||||
config.port = const_cast<char *>(std::to_string(port).c_str());
|
|
||||||
}
|
|
||||||
config.server_password = const_cast<char *>(password.c_str());
|
|
||||||
config.username = const_cast<char *>(user.c_str());
|
|
||||||
config.user_cert_filename = nullptr;
|
|
||||||
config.user_privkey_filename = nullptr;
|
|
||||||
|
|
||||||
config.ssl_verification_callback = verify_cert;
|
|
||||||
config.audio_callback = mumble_audio_callback;
|
|
||||||
config.serversync_callback = mumble_serversync_callback;
|
|
||||||
config.cryptsetup_callback = mumble_cryptsetup_callback;
|
|
||||||
|
|
||||||
mumble = mumble_connect(nullptr, &config);
|
|
||||||
|
|
||||||
if (mumble == nullptr) {
|
|
||||||
throw mumble::Exception("couldn't establish mumble connection");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mumble::MumbleCommunicator::~MumbleCommunicator() {
|
mumble::MumbleCommunicator::~MumbleCommunicator() {
|
||||||
mumble_close(mumble);
|
mum->disconnect();
|
||||||
}
|
|
||||||
|
|
||||||
void mumble::MumbleCommunicator::loop() {
|
|
||||||
|
|
||||||
senderThread.reset(new std::thread(&MumbleCommunicator::senderThreadFunction, this));
|
|
||||||
|
|
||||||
while (!quit) {
|
|
||||||
int status = mumble_tick(mumble);
|
|
||||||
logger.debug("tick");
|
|
||||||
if (status < 0) {
|
|
||||||
throw mumble::Exception("mumble_tick status " + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo Other processing here?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mumble::MumbleCommunicator::senderThreadFunction() {
|
|
||||||
while (!quit) {
|
|
||||||
opus_int16 pcmData[1024];
|
|
||||||
unsigned char outputBuffer[1024];
|
|
||||||
|
|
||||||
int pcmLength = samplesBuffer.pullSamples(pcmData, 480, true);
|
|
||||||
|
|
||||||
logger.debug("Pop %d samples from inputQueue.", pcmLength);
|
|
||||||
|
|
||||||
int encodedSamples = opus_encode(opusEncoder, pcmData, pcmLength, outputBuffer, sizeof(outputBuffer));
|
|
||||||
|
|
||||||
if (encodedSamples < 1) {
|
|
||||||
logger.warn("opus_encode returned %d: %s", encodedSamples, opus_strerror(encodedSamples));
|
|
||||||
} else {
|
|
||||||
logger.debug("Sending %d bytes of Opus audio data (seq %d).", encodedSamples,
|
|
||||||
outgoingAudioSequenceNumber);
|
|
||||||
|
|
||||||
//todo to powinno dać się bezpiecznie wykonać w osobnym wątku
|
|
||||||
mumble_send_audio_data(mumble, outgoingAudioSequenceNumber, outputBuffer, encodedSamples);
|
|
||||||
|
|
||||||
outgoingAudioSequenceNumber += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//void mumble::MumbleCommunicator::senderThreadFunction() {
|
||||||
|
// while (!quit) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
@ -2,30 +2,27 @@
|
|||||||
#define MUMSI_MUMBLECOMMUNICATOR_HPP
|
#define MUMSI_MUMBLECOMMUNICATOR_HPP
|
||||||
|
|
||||||
#include "ISamplesBuffer.hpp"
|
#include "ISamplesBuffer.hpp"
|
||||||
|
#include <mumlib.hpp>
|
||||||
extern "C" {
|
|
||||||
#include "libmumble.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <opus.h>
|
|
||||||
#include <log4cpp/Category.hh>
|
#include <log4cpp/Category.hh>
|
||||||
#include <sndfile.hh>
|
#include <sndfile.hh>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace mumble {
|
namespace mumble {
|
||||||
|
|
||||||
constexpr unsigned int SAMPLE_RATE = 48000;
|
|
||||||
|
|
||||||
class Exception : public std::runtime_error {
|
class Exception : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
Exception(const char *message) : std::runtime_error(message) { }
|
Exception(const char *message) : std::runtime_error(message) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MumlibCallback;
|
||||||
|
|
||||||
class MumbleCommunicator {
|
class MumbleCommunicator {
|
||||||
public:
|
public:
|
||||||
MumbleCommunicator(
|
MumbleCommunicator(
|
||||||
|
boost::asio::io_service &ioService,
|
||||||
ISamplesBuffer &samplesBuffer,
|
ISamplesBuffer &samplesBuffer,
|
||||||
std::string user,
|
std::string user,
|
||||||
std::string password,
|
std::string password,
|
||||||
@ -34,28 +31,29 @@ namespace mumble {
|
|||||||
|
|
||||||
~MumbleCommunicator();
|
~MumbleCommunicator();
|
||||||
|
|
||||||
void loop();
|
// void senderThreadFunction();
|
||||||
|
|
||||||
void senderThreadFunction();
|
//void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size);
|
||||||
|
|
||||||
void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size);
|
|
||||||
|
|
||||||
private:
|
public:
|
||||||
|
boost::asio::io_service &ioService;
|
||||||
|
|
||||||
log4cpp::Category &logger;
|
log4cpp::Category &logger;
|
||||||
|
|
||||||
ISamplesBuffer &samplesBuffer;
|
ISamplesBuffer &samplesBuffer;
|
||||||
|
|
||||||
|
std::shared_ptr<mumlib::Mumlib> mum;
|
||||||
|
|
||||||
std::unique_ptr<std::thread> senderThread;
|
std::unique_ptr<std::thread> senderThread;
|
||||||
|
|
||||||
mumble_struct *mumble;
|
|
||||||
OpusDecoder *opusDecoder;
|
|
||||||
OpusEncoder *opusEncoder;
|
|
||||||
|
|
||||||
int outgoingAudioSequenceNumber;
|
|
||||||
|
|
||||||
SndfileHandle fileHandle;
|
SndfileHandle fileHandle;
|
||||||
|
|
||||||
|
std::unique_ptr<MumlibCallback> callback;
|
||||||
|
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
||||||
|
friend class MumlibCallback;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
main.cpp
6
main.cpp
@ -22,6 +22,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
config::Configuration conf(argv[1]);
|
config::Configuration conf(argv[1]);
|
||||||
|
|
||||||
|
boost::asio::io_service ioService;
|
||||||
|
|
||||||
sip::PjsuaCommunicator pjsuaCommunicator(
|
sip::PjsuaCommunicator pjsuaCommunicator(
|
||||||
conf.getString("sip.host"),
|
conf.getString("sip.host"),
|
||||||
conf.getString("sip.user"),
|
conf.getString("sip.user"),
|
||||||
@ -29,6 +31,7 @@ int main(int argc, char *argv[]) {
|
|||||||
conf.getInt("sip.port"));
|
conf.getInt("sip.port"));
|
||||||
|
|
||||||
mumble::MumbleCommunicator mumbleCommunicator(
|
mumble::MumbleCommunicator mumbleCommunicator(
|
||||||
|
ioService,
|
||||||
pjsuaCommunicator,
|
pjsuaCommunicator,
|
||||||
conf.getString("mumble.user"),
|
conf.getString("mumble.user"),
|
||||||
conf.getString("mumble.password"),
|
conf.getString("mumble.password"),
|
||||||
@ -37,8 +40,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
logger.info("Application started.");
|
logger.info("Application started.");
|
||||||
|
|
||||||
mumbleCommunicator.loop();
|
ioService.run();
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user