|
|
|
@ -32,51 +32,49 @@
@@ -32,51 +32,49 @@
|
|
|
|
|
#include <QtConcurrent/QtConcurrentRun> |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@fn void CoreAV::avInvite(uint32_t friendId, bool video) |
|
|
|
|
@brief Sent when a friend calls us. |
|
|
|
|
@param friendId Id of friend in call list. |
|
|
|
|
@param video False if chat is audio only, true audio and video. |
|
|
|
|
|
|
|
|
|
@fn void CoreAV::avStart(uint32_t friendId, bool video) |
|
|
|
|
@brief Sent when a call we initiated has started. |
|
|
|
|
@param friendId Id of friend in call list. |
|
|
|
|
@param video False if chat is audio only, true audio and video. |
|
|
|
|
|
|
|
|
|
@fn void CoreAV::avEnd(uint32_t friendId) |
|
|
|
|
@brief Sent when a call was ended by the peer. |
|
|
|
|
@param friendId Id of friend in call list. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@var CoreAV::AUDIO_DEFAULT_BITRATE |
|
|
|
|
@brief In kb/s. More than enough for Opus. |
|
|
|
|
|
|
|
|
|
@var CoreAV::VIDEO_DEFAULT_BITRATE |
|
|
|
|
@brief Picked at random by fair dice roll. |
|
|
|
|
*/ |
|
|
|
|
* @fn void CoreAV::avInvite(uint32_t friendId, bool video) |
|
|
|
|
* @brief Sent when a friend calls us. |
|
|
|
|
* @param friendId Id of friend in call list. |
|
|
|
|
* @param video False if chat is audio only, true audio and video. |
|
|
|
|
* |
|
|
|
|
* @fn void CoreAV::avStart(uint32_t friendId, bool video) |
|
|
|
|
* @brief Sent when a call we initiated has started. |
|
|
|
|
* @param friendId Id of friend in call list. |
|
|
|
|
* @param video False if chat is audio only, true audio and video. |
|
|
|
|
* |
|
|
|
|
* @fn void CoreAV::avEnd(uint32_t friendId) |
|
|
|
|
* @brief Sent when a call was ended by the peer. |
|
|
|
|
* @param friendId Id of friend in call list. |
|
|
|
|
* |
|
|
|
|
* @var CoreAV::AUDIO_DEFAULT_BITRATE |
|
|
|
|
* @brief In kb/s. More than enough for Opus. |
|
|
|
|
* |
|
|
|
|
* @var CoreAV::VIDEO_DEFAULT_BITRATE |
|
|
|
|
* @brief Picked at random by fair dice roll. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@var std::atomic_flag CoreAV::threadSwitchLock |
|
|
|
|
@brief This flag is to be acquired before switching in a blocking way between the UI and CoreAV thread. |
|
|
|
|
|
|
|
|
|
The CoreAV thread must have priority for the flag, other threads should back off or release it quickly. |
|
|
|
|
CoreAV needs to interface with three threads, the toxcore/Core thread that fires non-payload |
|
|
|
|
toxav callbacks, the toxav/CoreAV thread that fires AV payload callbacks and manages |
|
|
|
|
most of CoreAV's members, and the UI thread, which calls our [start/answer/cancel]Call functions |
|
|
|
|
and which we call via signals. |
|
|
|
|
When the UI calls us, we switch from the UI thread to the CoreAV thread to do the processing, |
|
|
|
|
when toxcore fires a non-payload av callback, we do the processing in the CoreAV thread and then |
|
|
|
|
switch to the UI thread to send it a signal. Both switches block both threads, so this would deadlock. |
|
|
|
|
*/ |
|
|
|
|
* @var std::atomic_flag CoreAV::threadSwitchLock |
|
|
|
|
* @brief This flag is to be acquired before switching in a blocking way between the UI and CoreAV thread. |
|
|
|
|
* |
|
|
|
|
* The CoreAV thread must have priority for the flag, other threads should back off or release it quickly. |
|
|
|
|
* CoreAV needs to interface with three threads, the toxcore/Core thread that fires non-payload |
|
|
|
|
* toxav callbacks, the toxav/CoreAV thread that fires AV payload callbacks and manages |
|
|
|
|
* most of CoreAV's members, and the UI thread, which calls our [start/answer/cancel]Call functions |
|
|
|
|
* and which we call via signals. |
|
|
|
|
* When the UI calls us, we switch from the UI thread to the CoreAV thread to do the processing, |
|
|
|
|
* when toxcore fires a non-payload av callback, we do the processing in the CoreAV thread and then |
|
|
|
|
* switch to the UI thread to send it a signal. Both switches block both threads, so this would deadlock. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Maps friend IDs to ToxFriendCall. |
|
|
|
|
*/ |
|
|
|
|
* @brief Maps friend IDs to ToxFriendCall. |
|
|
|
|
*/ |
|
|
|
|
IndexedList<ToxFriendCall> CoreAV::calls; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Maps group IDs to ToxGroupCalls. |
|
|
|
|
*/ |
|
|
|
|
* @brief Maps group IDs to ToxGroupCalls. |
|
|
|
|
*/ |
|
|
|
|
IndexedList<ToxGroupCall> CoreAV::groupCalls; |
|
|
|
|
|
|
|
|
|
CoreAV::CoreAV(Tox *tox) |
|
|
|
@ -120,8 +118,8 @@ const ToxAV *CoreAV::getToxAv() const
@@ -120,8 +118,8 @@ const ToxAV *CoreAV::getToxAv() const
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Starts the CoreAV main loop that calls toxav's main loop |
|
|
|
|
*/ |
|
|
|
|
* @brief Starts the CoreAV main loop that calls toxav's main loop |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::start() |
|
|
|
|
{ |
|
|
|
|
// Timers can only be touched from their own thread
|
|
|
|
@ -131,8 +129,8 @@ void CoreAV::start()
@@ -131,8 +129,8 @@ void CoreAV::start()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Stops the main loop |
|
|
|
|
*/ |
|
|
|
|
* @brief Stops the main loop |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::stop() |
|
|
|
|
{ |
|
|
|
|
// Timers can only be touched from their own thread
|
|
|
|
@ -142,8 +140,8 @@ void CoreAV::stop()
@@ -142,8 +140,8 @@ void CoreAV::stop()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Calls itself blocking queued on the coreav thread |
|
|
|
|
*/ |
|
|
|
|
* @brief Calls itself blocking queued on the coreav thread |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::killTimerFromThread() |
|
|
|
|
{ |
|
|
|
|
// Timers can only be touched from their own thread
|
|
|
|
@ -159,10 +157,10 @@ void CoreAV::process()
@@ -159,10 +157,10 @@ void CoreAV::process()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Check, that and calls are active now |
|
|
|
|
@return True is any calls are currently active, False otherwise |
|
|
|
|
@note A call about to start is not yet active |
|
|
|
|
*/ |
|
|
|
|
* @brief Check, that and calls are active now |
|
|
|
|
* @return True is any calls are currently active, False otherwise |
|
|
|
|
* @note A call about to start is not yet active |
|
|
|
|
*/ |
|
|
|
|
bool CoreAV::anyActiveCalls() |
|
|
|
|
{ |
|
|
|
|
return !calls.isEmpty(); |
|
|
|
@ -296,14 +294,14 @@ void CoreAV::timeoutCall(uint32_t friendNum)
@@ -296,14 +294,14 @@ void CoreAV::timeoutCall(uint32_t friendNum)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Send audio frame to a friend |
|
|
|
|
@param callId Id of friend in call list. |
|
|
|
|
@param pcm An array of audio samples (Pulse-code modulation). |
|
|
|
|
@param samples Number of samples in this frame. |
|
|
|
|
@param chans Number of audio channels. |
|
|
|
|
@param rate Audio sampling rate used in this frame. |
|
|
|
|
@return False only on error, but not if there's nothing to send. |
|
|
|
|
*/ |
|
|
|
|
* @brief Send audio frame to a friend |
|
|
|
|
* @param callId Id of friend in call list. |
|
|
|
|
* @param pcm An array of audio samples (Pulse-code modulation). |
|
|
|
|
* @param samples Number of samples in this frame. |
|
|
|
|
* @param chans Number of audio channels. |
|
|
|
|
* @param rate Audio sampling rate used in this frame. |
|
|
|
|
* @return False only on error, but not if there's nothing to send. |
|
|
|
|
*/ |
|
|
|
|
bool CoreAV::sendCallAudio(uint32_t callId, const int16_t *pcm, size_t samples, uint8_t chans, uint32_t rate) |
|
|
|
|
{ |
|
|
|
|
if (!calls.contains(callId)) |
|
|
|
@ -403,17 +401,17 @@ void CoreAV::volMuteToggle(uint32_t callId)
@@ -403,17 +401,17 @@ void CoreAV::volMuteToggle(uint32_t callId)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Called from Tox API when group call receives audio data. |
|
|
|
|
|
|
|
|
|
@param[in] tox the Tox object |
|
|
|
|
@param[in] group the group number |
|
|
|
|
@param[in] peer the peer number |
|
|
|
|
@param[in] data the audio data to playback |
|
|
|
|
@param[in] samples the audio samples |
|
|
|
|
@param[in] channels the audio channels |
|
|
|
|
@param[in] sample_rate the audio sample rate |
|
|
|
|
@param[in] core the qTox Core class |
|
|
|
|
*/ |
|
|
|
|
* @brief Called from Tox API when group call receives audio data. |
|
|
|
|
* |
|
|
|
|
* @param[in] tox the Tox object |
|
|
|
|
* @param[in] group the group number |
|
|
|
|
* @param[in] peer the peer number |
|
|
|
|
* @param[in] data the audio data to playback |
|
|
|
|
* @param[in] samples the audio samples |
|
|
|
|
* @param[in] channels the audio channels |
|
|
|
|
* @param[in] sample_rate the audio sample rate |
|
|
|
|
* @param[in] core the qTox Core class |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::groupCallCallback(void* tox, int group, int peer, |
|
|
|
|
const int16_t* data, unsigned samples, |
|
|
|
|
uint8_t channels, unsigned sample_rate, |
|
|
|
@ -445,10 +443,10 @@ void CoreAV::groupCallCallback(void* tox, int group, int peer,
@@ -445,10 +443,10 @@ void CoreAV::groupCallCallback(void* tox, int group, int peer,
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Get a call's video source. |
|
|
|
|
@param friendNum Id of friend in call list. |
|
|
|
|
@return Video surface to show |
|
|
|
|
*/ |
|
|
|
|
* @brief Get a call's video source. |
|
|
|
|
* @param friendNum Id of friend in call list. |
|
|
|
|
* @return Video surface to show |
|
|
|
|
*/ |
|
|
|
|
VideoSource *CoreAV::getVideoSourceFromCall(int friendNum) |
|
|
|
|
{ |
|
|
|
|
if (!calls.contains(friendNum)) |
|
|
|
@ -461,10 +459,10 @@ VideoSource *CoreAV::getVideoSourceFromCall(int friendNum)
@@ -461,10 +459,10 @@ VideoSource *CoreAV::getVideoSourceFromCall(int friendNum)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Starts a call in an existing AV groupchat. |
|
|
|
|
@note Call from the GUI thread. |
|
|
|
|
@param groupId Id of group to join |
|
|
|
|
*/ |
|
|
|
|
* @brief Starts a call in an existing AV groupchat. |
|
|
|
|
* @note Call from the GUI thread. |
|
|
|
|
* @param groupId Id of group to join |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::joinGroupCall(int groupId) |
|
|
|
|
{ |
|
|
|
|
qDebug() << QString("Joining group call %1").arg(groupId); |
|
|
|
@ -474,10 +472,10 @@ void CoreAV::joinGroupCall(int groupId)
@@ -474,10 +472,10 @@ void CoreAV::joinGroupCall(int groupId)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Will not leave the group, just stop the call. |
|
|
|
|
@note Call from the GUI thread. |
|
|
|
|
@param groupId Id of group to leave |
|
|
|
|
*/ |
|
|
|
|
* @brief Will not leave the group, just stop the call. |
|
|
|
|
* @note Call from the GUI thread. |
|
|
|
|
* @param groupId Id of group to leave |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::leaveGroupCall(int groupId) |
|
|
|
|
{ |
|
|
|
|
qDebug() << QString("Leaving group call %1").arg(groupId); |
|
|
|
@ -532,18 +530,18 @@ bool CoreAV::isGroupCallVolEnabled(int groupId) const
@@ -532,18 +530,18 @@ bool CoreAV::isGroupCallVolEnabled(int groupId) const
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Check, that group has audio or video stream |
|
|
|
|
@param groupId Id of group to check |
|
|
|
|
@return True for AV groups, false for text-only groups |
|
|
|
|
*/ |
|
|
|
|
* @brief Check, that group has audio or video stream |
|
|
|
|
* @param groupId Id of group to check |
|
|
|
|
* @return True for AV groups, false for text-only groups |
|
|
|
|
*/ |
|
|
|
|
bool CoreAV::isGroupAvEnabled(int groupId) const |
|
|
|
|
{ |
|
|
|
|
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Forces to regenerate each call's audio sources. |
|
|
|
|
*/ |
|
|
|
|
* @brief Forces to regenerate each call's audio sources. |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::invalidateCallSources() |
|
|
|
|
{ |
|
|
|
|
for (ToxGroupCall& call : groupCalls) |
|
|
|
@ -558,9 +556,9 @@ void CoreAV::invalidateCallSources()
@@ -558,9 +556,9 @@ void CoreAV::invalidateCallSources()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Signal to all peers that we're not sending video anymore. |
|
|
|
|
@note The next frame sent cancels this. |
|
|
|
|
*/ |
|
|
|
|
* @brief Signal to all peers that we're not sending video anymore. |
|
|
|
|
* @note The next frame sent cancels this. |
|
|
|
|
*/ |
|
|
|
|
void CoreAV::sendNoVideo() |
|
|
|
|
{ |
|
|
|
|
// We don't change the audio bitrate, but we signal that we're not sending video anymore
|
|
|
|
|