📄 conference.cxx
字号:
goto processAudio;
keyIndex = spokenList.GetSize() - 1;
PStringList & videoPosnList = videoPosnDict[roomID];
if (keyIndex >= videoPosnList.GetSize()) {
PString tokenToWipe = spokenList[keyIndex-videoPosnList.GetSize()];
keyIndex = FindTokensVideoPosn(tokenToWipe,roomID);
}
if(keyIndex != P_MAX_INDEX)
videoPosnList[keyIndex] = thisToken;
}
processAudio:
#endif
PINDEX i;
for (i = 0; i < memberList.GetSize(); i++)
memberList.GetDataAt(i).WriteAudio(source, buffer, amount);
return TRUE;
}
#endif
void Conference::OnMemberJoining(ConferenceMember * member)
{
manager.OnMemberJoining(this, member);
}
void Conference::OnMemberLeaving(ConferenceMember * member)
{
manager.OnMemberLeaving(this, member);
}
///////////////////////////////////////////////////////////////////////////
ConferenceMember::ConferenceMember(void * _id)
: id(_id)
{
conference = NULL;
}
BOOL ConferenceMember::AddToConference(Conference * _conference)
{
if (conference != NULL)
return FALSE;
conference = _conference;
return TRUE;
}
void ConferenceMember::RemoveFromConference()
{
if (conference != NULL) {
if (conference->RemoveMember(this))
conference->GetManager().RemoveConference(conference->GetID());
}
}
void ConferenceMember::AddConnection(ConferenceMember * memberToAdd)
{
void * newID = memberToAdd->GetID();
PTRACE(3, "Conference\tAdding " << newID << " to connection " << id);
if (lock.Wait(TRUE)) {
ConferenceConnection * conn = memberToAdd->CreateConnection();
memberList.insert(std::pair<void *, ConferenceMember *>(newID, memberToAdd));
connectionList.insert(std::pair<void *, ConferenceConnection *>(newID, conn));
lock.Signal(TRUE);
}
}
void ConferenceMember::RemoveConnection(void * idToDelete)
{
PTRACE(3, "Conference\tRemoving member " << idToDelete << " from connection " << id);
if (lock.Wait(TRUE)) {
memberList.erase(idToDelete);
connectionList.erase(idToDelete);
lock.Signal(TRUE);
}
}
void ConferenceMember::SendUserInputIndication(const PString & str)
{
PTRACE(3, "Conference\tConnection " << id << " sending user indication " << str);
if (lock.Wait()) {
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); ++r)
r->second->OnReceivedUserInputIndication(str);
lock.Signal();
}
}
void ConferenceMember::WriteAudio(const void * buffer, PINDEX amount)
{
if (lock.Wait()) {
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); ++r)
r->second->OnExternalAudio(id, (BYTE *)buffer, amount);
lock.Signal();
}
}
void ConferenceMember::ReadAudio(void * buffer, PINDEX amount)
{
// First, set the buffer to empty.
memset(buffer, 0, amount);
if (lock.Wait()) {
// get number of channels to mix
ConnectionList::iterator r;
for (r = connectionList.begin(); r != connectionList.end(); ++r)
r->second->ReadAndMixAudio((BYTE *)buffer, amount, (PINDEX)connectionList.size());
lock.Signal();
}
}
void ConferenceMember::OnExternalAudio(void * source, const void * buffer, PINDEX amount)
{
if (lock.Wait()) {
ConnectionList::iterator r = connectionList.find(source);
if (r != connectionList.end())
r->second->Write((BYTE *)buffer, amount);
lock.Signal();
}
}
#ifndef NO_MCU_VIDEO
virtual BOOL ConferenceMember::OnOutgoingVideo(void * buffer, PINDEX & amount)
{
}
virtual BOOL ConferenceMember::OnIncomingVideo(const void * buffer, PINDEX amount)
{
}
#endif
///////////////////////////////////////////////////////////////////////////
ConferenceConnection::ConferenceConnection(void * _id)
: id(_id), bufferSize(PCM_BUFFER_SIZE)
{
buffer = new BYTE[bufferSize];
bufferStart = bufferLen = 0;
}
ConferenceConnection::~ConferenceConnection()
{
delete[] buffer;
}
void ConferenceConnection::Write(const BYTE * data, PINDEX amount)
{
if (amount == 0)
return;
PWaitAndSignal mutex(audioBufferMutex);
// if there is not enough room for the new data, make room
PINDEX newLen = bufferLen + amount;
if (newLen > bufferSize) {
PINDEX toRemove = newLen - bufferSize;
bufferStart = (bufferStart + toRemove) % bufferSize;
bufferLen -= toRemove;
}
// copy data to the end of the new data, up to the end of the buffer
PINDEX copyStart = (bufferStart + bufferLen) % bufferSize;
if ((copyStart + amount) > bufferSize) {
PINDEX toCopy = bufferSize - copyStart;
memcpy(buffer + copyStart, data, toCopy);
copyStart = 0;
data += toCopy;
amount -= toCopy;
bufferLen += toCopy;
}
// copy the rest of the data
if (amount > 0) {
memcpy(buffer + copyStart, data, amount);
bufferLen += amount;
}
}
void ConferenceConnection::ReadAudio(BYTE * data, PINDEX amount)
{
if (amount == 0)
return;
PWaitAndSignal mutex(audioBufferMutex);
if (bufferLen == 0) {
memset(data, 0, amount); // nothing in the buffer. return silence
return;
}
// fill output data block with silence if audiobuffer is
// almost empty.
if (amount > bufferLen)
memset(data + bufferLen, 0, amount - bufferLen);
// only copy up to the amount of data remaining
PINDEX copyLeft = PMIN(amount, bufferLen);
// if buffer is wrapping, get first part
if ((bufferStart + copyLeft) > bufferSize) {
PINDEX toCopy = bufferSize - bufferStart;
memcpy(data, buffer + bufferStart, toCopy);
data += toCopy;
bufferLen -= toCopy;
copyLeft -= toCopy;
bufferStart = 0;
}
// get the remainder of the buffer
if (copyLeft > 0) {
memcpy(data, buffer + bufferStart, copyLeft);
bufferLen -= copyLeft;
bufferStart = (bufferStart + copyLeft) % bufferSize;
}
}
void ConferenceConnection::ReadAndMixAudio(BYTE * data, PINDEX amount, PINDEX channels)
{
if (amount == 0) {
PTRACE(3, "Mixer\tNo data to read");
return;
}
PWaitAndSignal mutex(audioBufferMutex);
if (bufferLen == 0) {
// nothing in the buffer to mix.
return;
}
// only mix up to the amount of data remaining
PINDEX copyLeft = PMIN(amount, bufferLen);
// if buffer is wrapping, get first part
if ((bufferStart + copyLeft) > bufferSize) {
PINDEX toCopy = bufferSize - bufferStart;
Mix(data, buffer + bufferStart, toCopy, channels);
data += toCopy;
bufferLen -= toCopy;
copyLeft -= toCopy;
bufferStart = 0;
}
// get the remainder of the buffer
if (copyLeft > 0) {
Mix(data, buffer + bufferStart, copyLeft, channels);
bufferLen -= copyLeft;
bufferStart = (bufferStart + copyLeft) % bufferSize;
}
}
void ConferenceConnection::Mix(BYTE * dst, const BYTE * src, PINDEX count, PINDEX /*channels*/)
{
#if 0
memcpy(dst, src, count);
#else
PINDEX i;
for (i = 0; i < count; i += 2) {
int srcVal = *(short *)src;
int dstVal = *(short *)dst;
int newVal = dstVal;
#if 0 //The loudest person gains the channel.
#define mix_abs(x) ((x) >= 0 ? (x) : -(x))
if (mix_abs(newVal) > mix_abs(srcVal))
dstVal = newVal;
else
dstVal = srcVal;
#else //Just add up all the channels.
if ((newVal + srcVal) > 0x7fff)
dstVal = 0x7fff;
else
dstVal += srcVal;
#endif
*(short *)dst = (short)dstVal;
dst += 2;
src += 2;
}
#endif
}
///////////////////////////////////////////////////////////////
MCULock::MCULock()
{
closing = FALSE;
count = 0;
}
BOOL MCULock::Wait(BOOL hard)
{
mutex.Wait();
if (hard)
return TRUE;
BOOL ret = TRUE;
if (!closing)
count++;
else
ret = FALSE;
mutex.Signal();
return ret;
}
void MCULock::Signal(BOOL hard)
{
if (hard) {
mutex.Signal();
return;
}
mutex.Wait();
if (count > 0)
count--;
if (closing)
closeSync.Signal();
mutex.Signal();
}
void MCULock::WaitForClose()
{
mutex.Wait();
closing = TRUE;
BOOL wait = count > 0;
mutex.Signal();
while (wait) {
closeSync.Wait();
mutex.Wait();
wait = count > 0;
mutex.Signal();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -