EXPERIMENTAL audio reception in calls

As in, some sounds comes out of your speakers
pull/9/head^2
Tux3 / Mlkj / !Lev.uXFMLA 2014-06-27 15:16:39 +02:00
parent 6114cb66c6
commit b8af78be32
3 changed files with 114 additions and 8 deletions

View File

@ -29,16 +29,10 @@
#include "settings.h"
#define GROUPCHAT_MAX_SIZE 32
#define TOX_SAVE_INTERVAL 30*1000
#define TOX_FILE_INTERVAL 20
#define TOX_BOOTSTRAP_INTERVAL 10*1000
#define TOXAV_MAX_CALLS 32
#define TOXAV_RINGING_TIME 15
const QString Core::CONFIG_FILE_NAME = "tox_save";
QList<ToxFile> Core::fileSendQueue;
QList<ToxFile> Core::fileRecvQueue;
ToxCall Core::calls[TOXAV_MAX_CALLS];
Core::Core() :
tox(nullptr)
@ -899,6 +893,8 @@ void Core::onAvStart(int32_t call_index, void* core)
}
qDebug() << QString("Core: AV start from %1").arg(friendId);
prepareCall(friendId, call_index, static_cast<Core*>(core)->toxav);
emit static_cast<Core*>(core)->avStart(friendId, call_index);
}
@ -930,6 +926,8 @@ void Core::onAvEnd(int32_t call_index, void* core)
}
qDebug() << QString("Core: AV end from %1").arg(friendId);
cleanupCall(call_index);
emit static_cast<Core*>(core)->avEnd(friendId, call_index);
}
@ -956,6 +954,8 @@ void Core::onAvStarting(int32_t call_index, void* core)
}
qDebug() << QString("Core: AV starting %1").arg(friendId);
prepareCall(friendId, call_index, static_cast<Core*>(core)->toxav);
emit static_cast<Core*>(core)->avStarting(friendId, call_index);
}
@ -969,6 +969,8 @@ void Core::onAvEnding(int32_t call_index, void* core)
}
qDebug() << QString("Core: AV ending from %1").arg(friendId);
cleanupCall(call_index);
emit static_cast<Core*>(core)->avEnding(friendId, call_index);
}
@ -1019,3 +1021,81 @@ void Core::cancelCall(int callId, int friendId)
qDebug() << QString("Core: Cancelling call with %1").arg(friendId);
toxav_cancel(toxav, callId, friendId, 0);
}
void Core::prepareCall(int friendId, int callId, ToxAv* toxav)
{
qDebug() << QString("Core: preparing call %1").arg(callId);
calls[callId].callId = callId;
calls[callId].friendId = friendId;
calls[callId].audioBuffer.open(QBuffer::ReadWrite);
calls[callId].codecSettings = av_DefaultSettings;
toxav_prepare_transmission(toxav, callId, &calls[callId].codecSettings, false);
QAudioFormat format;
format.setSampleRate(calls[callId].codecSettings.audio_sample_rate);
format.setChannelCount(calls[callId].codecSettings.audio_channels);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
calls[callId].audioOutput = nullptr;
qWarning() << "Core: Raw audio format not supported by backend, cannot play audio.";
return;
}
calls[callId].audioOutput = new QAudioOutput(format);
calls[callId].active = true;
QtConcurrent::run(playCallAudio, callId, toxav);
calls[callId].audioOutput->start(&calls[callId].audioBuffer);
if (calls[callId].audioOutput->state() == QAudio::StoppedState
&& calls[callId].audioOutput->error() == QAudio::OpenError)
qWarning() << "Core: Unable to start audio";
}
void Core::cleanupCall(int callId)
{
qDebug() << QString("Core: cleaning up call %1").arg(callId);
calls[callId].active = false;
if (calls[callId].audioOutput != nullptr)
{
delete calls[callId].audioOutput;
}
calls[callId].audioBuffer.close();
}
void Core::playCallAudio(int callId, ToxAv* toxav)
{
while (calls[callId].active)
{
int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000;
int16_t buf[framesize];
int len = toxav_recv_audio(toxav, callId, framesize, buf);
if (len < 0)
{
qDebug() << "Core::playCallAudio: Error receiving audio";
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2);
continue;
}
if (len == 0)
continue;
qDebug() << QString("Core::playCallAudio: Playing %1 frames/sample").arg(len);
calls[callId].audioBuffer.write((char*)buf, len*2);
calls[callId].audioBuffer.seek(0);
calls[callId].audioOutput->resume();
int error = calls[callId].audioOutput->error();
if (error != QAudio::NoError)
qWarning() << QString("Core::playCallAudio: Error: %1").arg(error);
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2);
}
}
void Core::sendCallAudio(int callId, ToxAv* toxav)
{
while (calls[callId].active)
{
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2);
}
}

26
core.h
View File

@ -30,6 +30,15 @@
#include <QList>
#include <QByteArray>
#include <QFuture>
#include <QBuffer>
#include <QAudioOutput>
#define TOXAV_MAX_CALLS 32
#define GROUPCHAT_MAX_SIZE 32
#define TOX_SAVE_INTERVAL 30*1000
#define TOX_FILE_INTERVAL 20
#define TOX_BOOTSTRAP_INTERVAL 10*1000
#define TOXAV_RINGING_TIME 15
struct DhtServer
{
@ -70,6 +79,17 @@ struct ToxFile
QFuture<void> sendFuture;
};
struct ToxCall
{
public:
QBuffer audioBuffer;
QAudioOutput* audioOutput;
ToxAvCodecSettings codecSettings;
int callId;
int friendId;
bool active;
};
class Core : public QObject
{
Q_OBJECT
@ -208,6 +228,11 @@ private:
static void onAvRequestTimeout(int32_t call_index, void* toxav);
static void onAvPeerTimeout(int32_t call_index, void* toxav);
static void prepareCall(int friendId, int callId, ToxAv *toxav);
static void cleanupCall(int callId);
static void playCallAudio(int callId, ToxAv* toxav); // Blocking, start in a thread
static void sendCallAudio(int callId, ToxAv* toxav); // Blocking, start in a thread
void checkConnection();
void onBootstrapTimer();
@ -227,6 +252,7 @@ private:
QList<DhtServer> dhtServerList;
int dhtServerId;
static QList<ToxFile> fileSendQueue, fileRecvQueue;
static ToxCall calls[TOXAV_MAX_CALLS];
static const QString CONFIG_FILE_NAME;
};

View File

@ -4,7 +4,7 @@
#
#-------------------------------------------------
QT += core gui
QT += core gui multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets