Replace libmumble with mumlib library.

This commit is contained in:
Michał Słomkowski 2015-10-30 13:43:06 +01:00
parent e50e6d278a
commit 87842318be
6 changed files with 51 additions and 167 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
*.iml *.iml
.idea/ .idea/
config.ini config.ini
build/

0
.gitmodules vendored
View File

View File

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

View File

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

View File

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

View File

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