📄 conference.cxx
字号:
r = monitorList.begin();
}
}
}
BOOL ConferenceTimeLimitInfo::Perform(Conference & conference)
{
Conference::MemberList & list = conference.GetMemberList();
Conference::MemberList::iterator r;
for (r = list.begin(); r != list.end(); ++r)
r->second->Close();
return TRUE;
}
BOOL ConferenceRepeatingInfo::Perform(Conference & conference)
{
this->timeToPerform = PTime() + repeatTime;
return FALSE;
}
BOOL ConferenceMCUCheckInfo::Perform(Conference & conference)
{
// see if any member of this conference is a not an MCU
Conference::MemberList & list = conference.GetMemberList();
Conference::MemberList::iterator r;
for (r = list.begin(); r != list.end(); ++r)
if (!r->second->IsMCU())
break;
// if there is any non-MCU member, check again later
if (r != list.end())
return ConferenceRepeatingInfo::Perform(conference);
// else shut down the conference
for (r = list.begin(); r != list.end(); ++r)
r->second->Close();
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
Conference::Conference( ConferenceManager & _manager,
const OpalGloballyUniqueID & _guid,
const PString & _number,
const PString & _name,
int _mcuNumber
#if OPENMCU_VIDEO
,MCUVideoMixer * _videoMixer
#endif
)
: manager(_manager), guid(_guid), number(_number), name(_name), mcuNumber(_mcuNumber), mcuMonitorRunning(FALSE)
#if OPENMCU_VIDEO
,videoMixer(_videoMixer)
#endif
{
maxMemberCount = 0;
PTRACE(3, "Conference\tNew conference started: ID=" << guid << ", number = " << number);
}
Conference::~Conference()
{
#if OPENMCU_VIDEO
delete videoMixer;
#endif
}
int Conference::GetVisibleMemberCount() const
{
PWaitAndSignal m(memberListMutex);
int visibleMembers = 0;
std::map<void *, ConferenceMember *>::const_iterator r;
for (r = memberList.begin(); r != memberList.end(); r++) {
if (r->second->IsVisible())
++visibleMembers;
}
return visibleMembers;
}
void Conference::AddMonitorEvent(ConferenceMonitorInfo * info)
{
manager.AddMonitorEvent(info);
}
BOOL Conference::AddMember(ConferenceMember * memberToAdd)
{
PTRACE(3, "Conference\tAbout to add member " << memberToAdd->GetTitle() << " to conference " << guid);
// see if the callback refuses the new member
if (!BeforeMemberJoining(memberToAdd))
return FALSE;
// add the member to the conference
if (!memberToAdd->AddToConference(this))
return FALSE;
{
// lock the member list
PWaitAndSignal m(memberListMutex);
#if OPENMCU_VIDEO
if (UseSameVideoForAllMembers() && memberToAdd->IsVisible()) {
if (!videoMixer->AddVideoSource(memberToAdd->GetID(), *memberToAdd))
return FALSE;
}
#endif
PTRACE(3, "Conference\tAdding member " << memberToAdd->GetTitle() << " to conference " << guid);
// add this member to the conference member list
memberList.insert(MemberList::value_type(memberToAdd->GetID(), memberToAdd));
int tid = terminalNumberMap.GetNumber(memberToAdd->GetID());
memberToAdd->SetTerminalNumber(tid);
// make sure each member has a connection created for the new member
// make sure the new member has a connection created for each existing member
PINDEX visibleMembers = 0;
std::map<void *, ConferenceMember *>::const_iterator r;
for (r = memberList.begin(); r != memberList.end(); r++) {
ConferenceMember * conn = r->second;
if (conn != memberToAdd) {
conn->AddConnection(memberToAdd);
memberToAdd->AddConnection(conn);
#if OPENMCU_VIDEO
if (!UseSameVideoForAllMembers()) {
if (conn->IsVisible())
memberToAdd->AddVideoSource(conn->GetID());
if (memberToAdd->IsVisible())
conn->AddVideoSource(memberToAdd->GetID());
}
#endif
}
if (conn->IsVisible())
++visibleMembers;
}
// update the statistics
if (memberToAdd->IsVisible()) {
maxMemberCount = PMAX(maxMemberCount, visibleMembers);
// trigger H245 thread for join message
new NotifyH245Thread(*this, TRUE, memberToAdd);
}
}
// notify that member is joined
memberToAdd->SetJoined(TRUE);
// call the callback function
OnMemberJoining(memberToAdd);
if (memberToAdd->IsMCU() && !mcuMonitorRunning) {
manager.AddMonitorEvent(new ConferenceMCUCheckInfo(GetID(), 1000));
mcuMonitorRunning = TRUE;
}
return TRUE;
}
BOOL Conference::RemoveMember(ConferenceMember * memberToRemove)
{
if(!memberToRemove->IsJoined())
{
PTRACE(4, "Conference\tNo need to remove call " << memberToRemove->GetTitle() << " from conference " << guid);
return (memberList.size() == 0);
}
PTRACE(3, "Conference\tRemoving call " << memberToRemove->GetTitle() << " from conference " << guid << " with size " << (PINDEX)memberList.size());
cout << memberToRemove->GetTitle() << " leaving conference " << number << "(" << guid << ")" << endl;
BOOL closeConference;
{
PWaitAndSignal m(memberListMutex);
// remove this member from the connection lists for all other members
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); r++) {
ConferenceMember * conn = r->second;
if (conn != memberToRemove) {
r->second->RemoveConnection(memberToRemove->GetID());
#if OPENMCU_VIDEO
if (!UseSameVideoForAllMembers()) {
if (memberToRemove->IsVisible())
conn->RemoveVideoSource(memberToRemove->GetID());
if (conn->IsVisible())
memberToRemove->RemoveVideoSource(conn->GetID());
}
#endif
}
}
#if OPENMCU_VIDEO
if (UseSameVideoForAllMembers() && memberToRemove->IsVisible())
videoMixer->RemoveVideoSource(memberToRemove->GetID(), *memberToRemove);
#endif
// trigger H245 thread for leave message
if (memberToRemove->IsVisible())
new NotifyH245Thread(*this, FALSE, memberToRemove);
terminalNumberMap.RemoveNumber(memberToRemove->GetTerminalNumber());
// remove this connection from the member list
memberList.erase(memberToRemove->GetID());
// return TRUE if conference is empty
closeConference = memberList.size() == 0;
}
// notify that member is not joined anymore
memberToRemove->SetJoined(FALSE);
// call the callback function
if (!closeConference)
OnMemberLeaving(memberToRemove);
return closeConference;
}
void Conference::ReadMemberAudio(ConferenceMember * member, void * buffer, PINDEX amount)
{
// get number of channels to mix
ConferenceMember::ConnectionListType & connectionList = member->GetConnectionList();
ConferenceMember::ConnectionListType::iterator r;
for (r = connectionList.begin(); r != connectionList.end(); ++r)
if (r->second != NULL)
r->second->ReadAndMixAudio((BYTE *)buffer, amount, (PINDEX)connectionList.size());
}
void Conference::WriteMemberAudioLevel(ConferenceMember * member, unsigned audioLevel)
{
#if OPENMCU_VIDEO
if (UseSameVideoForAllMembers()) {
if (videoMixer != NULL)
videoMixer->SetAudioLevel(member->GetID(), audioLevel);
}
else
#endif // OPENMCU_VIDEO
{
PWaitAndSignal m(memberListMutex);
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); r++)
r->second->OnExternalSetAudioLevel(member->GetID(), audioLevel);
}
}
#if OPENMCU_VIDEO
void Conference::ReadMemberVideo(ConferenceMember * member, void * buffer, int width, int height, PINDEX & amount)
{
if (videoMixer == NULL)
return;
if (videoMixer->ReadFrame(*member, buffer, width, height, amount))
return;
// find the other member and copy it's video
PWaitAndSignal m(memberListMutex);
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); r++) {
if ((r->second != member) && r->second->IsVisible()) {
void * frameStore = r->second->OnExternalReadVideo(member->GetID(), width, height, amount);
if (frameStore != NULL) {
memcpy(buffer, frameStore, amount);
r->second->UnlockExternalVideo();
}
}
}
}
BOOL Conference::WriteMemberVideo(ConferenceMember * member, const void * buffer, int width, int height, PINDEX amount)
{
if (UseSameVideoForAllMembers()) {
if (videoMixer != NULL)
return videoMixer->WriteFrame(member->GetID(), buffer, width, height, amount);
}
else {
PWaitAndSignal m(memberListMutex);
MemberList::iterator r;
for (r = memberList.begin(); r != memberList.end(); r++)
r->second->OnExternalSendVideo(member->GetID(), buffer, width, height, amount);
}
return TRUE;
}
#endif
BOOL Conference::BeforeMemberJoining(ConferenceMember * member)
{
return manager.BeforeMemberJoining(this, member);
}
void Conference::OnMemberJoining(ConferenceMember * member)
{
manager.OnMemberJoining(this, member);
}
void Conference::OnMemberLeaving(ConferenceMember * member)
{
manager.OnMemberLeaving(this, member);
}
///////////////////////////////////////////////////////////////////////////
ConferenceMember::ConferenceMember(Conference * _conference, ConferenceMemberId _id, BOOL _isMCU)
: conference(_conference), id(_id), isMCU(_isMCU)
{
audioLevel = 0;
terminalNumber = -1;
memberIsJoined = FALSE;
#if OPENMCU_VIDEO
videoMixer = NULL;
fsConverter = PColourConverter::Create("YUV420P", "YUV420P", CIF_WIDTH, CIF_HEIGHT);
MCUVideoMixer::FillCIFYUVFrame(memberFrameStores.GetFrameStore(CIF_WIDTH, CIF_HEIGHT).data.GetPointer(), 0, 0, 0);
totalVideoFramesReceived = 0;
firstFrameReceiveTime = -1;
totalVideoFramesSent = 0;
firstFrameSendTime = -1;
#endif
}
ConferenceMember::~ConferenceMember()
{
#if OPENMCU_VIDEO
delete videoMixer;
#endif
}
BOOL ConferenceMember::AddToConference(Conference * _conference)
{
//if (conference != NULL)
// return FALSE;
//conference = _conference;
#if OPENMCU_VIDEO
if (!conference->UseSameVideoForAllMembers())
videoMixer = conference->GetVideoMixer()->Clone();
#endif
return TRUE;
}
void ConferenceMember::RemoveFromConference()
{
if (conference != NULL) {
if (conference->RemoveMember(this))
conference->GetManager().RemoveConference(conference->GetID());
}
}
void ConferenceMember::AddConnection(ConferenceMember * memberToAdd)
{
ConferenceMemberId newID = memberToAdd->GetID();
PTRACE(3, "Conference\tAdding " << newID << " to connection " << id);
if (lock.Wait(TRUE)) {
ConferenceConnection * conn = memberToAdd->CreateConnection();
memberList.insert(MemberListType::value_type(newID, memberToAdd));
connectionList.insert(ConnectionListType::value_type(newID, conn));
lock.Signal(TRUE);
}
}
void ConferenceMember::RemoveConnection(ConferenceMemberId 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()) {
MemberListType::iterator r;
for (r = memberList.begin(); r != memberList.end(); ++r)
if (r->second != NULL)
r->second->OnReceivedUserInputIndication(str);
lock.Signal();
}
}
void ConferenceMember::WriteAudio(const void * buffer, PINDEX amount)
{
// calculate average signal level for this member
unsigned signalLevel = 0;
{
int sum = 0;
const short * pcm = (short *)buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -