MumbleCommunicator.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include <cstring>
  2. #include <functional>
  3. #include "MumbleCommunicator.hpp"
  4. void mumble::MumbleCommunicator::receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size) {
  5. int dataPointer = 1;
  6. opus_int16 pcmData[1024];
  7. if (audio_data[0] == 0x80) {
  8. int64_t sessionId;
  9. int64_t sequenceNumber;
  10. int64_t opusDataLength;
  11. bool lastPacket;
  12. dataPointer += mumble_parse_variant(&sessionId, &audio_data[dataPointer]);
  13. dataPointer += mumble_parse_variant(&sequenceNumber, &audio_data[dataPointer]);
  14. dataPointer += mumble_parse_variant(&opusDataLength, &audio_data[dataPointer]);
  15. lastPacket = (opusDataLength & 0x2000) != 0;
  16. opusDataLength = opusDataLength & 0x1fff;
  17. unsigned int iAudioBufferSize;
  18. unsigned int iFrameSize = mumble::SAMPLE_RATE / 100;
  19. iAudioBufferSize = iFrameSize;
  20. iAudioBufferSize *= 12;
  21. int decodedSamples = opus_decode(opusDecoder,
  22. reinterpret_cast<const unsigned char *>(&audio_data[dataPointer]),
  23. opusDataLength,
  24. pcmData,
  25. iAudioBufferSize,
  26. 0);
  27. fileHandle.write(pcmData, decodedSamples);
  28. logger.debug("Received %d bytes of Opus data (seq %ld), decoded to %d bytes. Push it to outputQueue.",
  29. opusDataLength, sequenceNumber, decodedSamples);
  30. samplesBuffer.pushSamples(pcmData, decodedSamples);
  31. } else {
  32. logger.warn("Received %d bytes of non-recognisable audio data.", audio_data_size);
  33. }
  34. }
  35. static void mumble_audio_callback(uint8_t *audio_data, uint32_t audio_data_size, void *userData) {
  36. mumble::MumbleCommunicator *mumbleCommunicator = static_cast<mumble::MumbleCommunicator *>(userData);
  37. mumbleCommunicator->receiveAudioFrameCallback(audio_data, audio_data_size);
  38. }
  39. static void mumble_serversync_callback(char *welcome_text,
  40. int32_t session,
  41. int32_t max_bandwidth,
  42. int64_t permissions,
  43. void *usterData) {
  44. printf("%s\n", welcome_text);
  45. }
  46. void mumble_cryptsetup_callback(uint32_t key_size,
  47. uint8_t *key,
  48. uint32_t client_nonce_size,
  49. uint8_t *client_nonce,
  50. uint32_t server_nonce_size,
  51. uint8_t *server_nonce,
  52. void *userData) {
  53. mumble::MumbleCommunicator *mumbleCommunicator = static_cast<mumble::MumbleCommunicator *>(userData);
  54. printf("received crypto nonce\n");
  55. }
  56. static int verify_cert(uint8_t *, uint32_t) {
  57. // Accept every cert
  58. return 1;
  59. }
  60. mumble::MumbleCommunicator::MumbleCommunicator(
  61. ISamplesBuffer &samplesBuffer,
  62. std::string user,
  63. std::string password,
  64. std::string host,
  65. int port) : samplesBuffer(samplesBuffer),
  66. outgoingAudioSequenceNumber(1),
  67. logger(log4cpp::Category::getInstance("MumbleCommunicator")) {
  68. quit = false;
  69. opusDecoder = opus_decoder_create(SAMPLE_RATE, 1, nullptr); //todo grab error
  70. opusEncoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, nullptr);
  71. opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0));
  72. fileHandle = SndfileHandle("capture_mumble.wav", SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 1, SAMPLE_RATE);
  73. struct mumble_config config;
  74. std::memset(&config, 0, sizeof(config));
  75. config.user_data = this;
  76. config.size = sizeof(config);
  77. config.host = const_cast<char *>(host.c_str());
  78. if (port > 0) {
  79. config.port = const_cast<char *>(std::to_string(port).c_str());
  80. }
  81. config.server_password = const_cast<char *>(password.c_str());
  82. config.username = const_cast<char *>(user.c_str());
  83. config.user_cert_filename = nullptr;
  84. config.user_privkey_filename = nullptr;
  85. config.ssl_verification_callback = verify_cert;
  86. config.audio_callback = mumble_audio_callback;
  87. config.serversync_callback = mumble_serversync_callback;
  88. config.cryptsetup_callback = mumble_cryptsetup_callback;
  89. mumble = mumble_connect(nullptr, &config);
  90. if (mumble == nullptr) {
  91. throw mumble::Exception("couldn't establish mumble connection");
  92. }
  93. }
  94. mumble::MumbleCommunicator::~MumbleCommunicator() {
  95. mumble_close(mumble);
  96. }
  97. void mumble::MumbleCommunicator::loop() {
  98. senderThread.reset(new std::thread(&MumbleCommunicator::senderThreadFunction, this));
  99. while (!quit) {
  100. int status = mumble_tick(mumble);
  101. logger.debug("tick");
  102. if (status < 0) {
  103. throw mumble::Exception("mumble_tick status " + status);
  104. }
  105. //todo Other processing here?
  106. }
  107. }
  108. void mumble::MumbleCommunicator::senderThreadFunction() {
  109. while (!quit) {
  110. opus_int16 pcmData[1024];
  111. unsigned char outputBuffer[1024];
  112. int pcmLength = samplesBuffer.pullSamples(pcmData, 480, true);
  113. logger.debug("Pop %d samples from inputQueue.", pcmLength);
  114. int encodedSamples = opus_encode(opusEncoder, pcmData, pcmLength, outputBuffer, sizeof(outputBuffer));
  115. if (encodedSamples < 1) {
  116. logger.warn("opus_encode returned %d: %s", encodedSamples, opus_strerror(encodedSamples));
  117. } else {
  118. logger.debug("Sending %d bytes of Opus audio data (seq %d).", encodedSamples,
  119. outgoingAudioSequenceNumber);
  120. //todo to powinno dać się bezpiecznie wykonać w osobnym wątku
  121. mumble_send_audio_data(mumble, outgoingAudioSequenceNumber, outputBuffer, encodedSamples);
  122. outgoingAudioSequenceNumber += 1;
  123. }
  124. }
  125. }