📄 conference.cxx
字号:
/*
* conference.cxx
*
* Conferencing functions for a simple MCU
*
* Copyright (c) 2000 Equivalence Pty. Ltd.
* Copyright (c) 2004 Post Increment
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions of ths code were written by by Post Increment (http://www.postincrement.com)
* with the assistance of funding from Stonevoice, slc. http://www.stonevoice.com
*
* Portions of this code were written by Post Increment (http://www.postincrement.com)
* with the assistance of funding from Citron Networks (http://www.citron.com.tw)
*
* Contributor(s): Derek J Smithies (derek@indranet.co.nz)
* Craig Southeren (craig@postincrement.com)
*
* $Log: conference.cxx,v $
* Revision 1.1 2007/10/17 19:44:28 shorne
* Initial Commit
*
* Revision 2.12 2006/08/07 06:18:22 csoutheren
* Fix detection of MCU members
* Add auto-removal of conferences only containing MCU members
*
* Revision 2.11 2006/07/21 08:01:40 csoutheren
* Fixed conference member detect
* Re-factored video mixer code slightly
*
* Revision 2.10 2006/07/21 05:52:51 csoutheren
* Add flag to indicate if remote endpoint is an MCU
*
* Revision 2.9 2006/07/21 05:08:03 csoutheren
* Stability fixes and more inline documentation
* Thanks to Paolo Amadini of Stonevoice
*
* Revision 2.8 2006/06/09 04:39:59 csoutheren
* Migrated VideoBranch to main trunk
*
* Revision 2.7.2.18 2006/06/06 08:24:16 csoutheren
* Added support for echo test room
* Fix problem with using high frame rates
*
* Revision 2.7.2.17 2006/05/31 08:48:02 csoutheren
* Fixed crash on second call when entry/exit files do not exist
* Fix crash when Cisco HOLD used. Thanks to Christian Bongiovanni of Stonevoice
*
* Revision 2.7.2.16 2006/05/16 02:20:39 csoutheren
* Fixed problems compiling without video
*
* Revision 1.8 2006/05/16 00:29:18 craigs
* Fixed compilation when video disabled
*
* Revision 1.7 2006/04/26 16:02:21 craigs
* Update to latest public sources
* Added ability to have per-conference timeout and reminders
*
* Revision 2.7.2.15 2006/04/26 15:03:16 csoutheren
* Added better override for creating conferenc
*
* Revision 2.7.2.14 2006/04/26 13:09:08 csoutheren
* Fix problem when connecting file not available
* Add optional time limit for rooms
*
* Revision 2.7.2.13 2006/04/18 03:05:09 csoutheren
* Fix video mix problem with > 3 members
* Add test room
*
* Revision 2.7.2.12 2006/04/12 22:58:16 csoutheren
* Removed return in function returning void
*
* Revision 2.7.2.11 2006/04/12 04:54:18 csoutheren
* Fix more problems with audio-only members
*
* Revision 2.7.2.10 2006/04/11 03:46:46 csoutheren
* Fixed problem with hangup during entering wav file play
*
* Revision 2.7.2.9 2006/04/06 08:20:29 csoutheren
* Retyped conference member identifier to epxlicit type
* Added support for H.245 terminal added and terminal left
*
* Revision 2.7.2.8 2006/04/06 01:11:16 csoutheren
* Latest sources include
* - premedia blanking and optional image display
* - ablity to defer conference join for authentication if required
* - more bulletproofing on conference join
* - new video copy/fill functions
*
* Revision 2.7.2.7 2006/04/06 00:50:28 csoutheren
* Latest changes (more to come)
*
* Revision 2.7.2.6 2006/03/28 05:13:38 csoutheren
* Normalised file headers
* Fixed problem with QCIF video
* Seperated H.323 and MCU process functions into seperate files
*
* Revision 2.7.2.5 2006/03/24 22:49:24 csoutheren
* Video now working
*
* Revision 2.7.2.4 2006/03/21 14:02:49 csoutheren
* More video mixiing.
* Still some crashes in video mixer code when members exit conference
*
* Revision 2.7.2.3 2006/03/17 07:00:24 csoutheren
* More video implementation
* Video mixing now working except copying subimage UV components causes overrun
* Y is OK, which is why the images are grey. Also need to work out flipping requirements
*
* Revision 2.7.2.2 2006/03/14 08:02:50 csoutheren
* More implemenrtation of video
* Video mixing infrastructure implemented but not fully working
*
* Revision 2.7.2.1 2006/03/06 05:45:30 csoutheren
* Start of implementation for video. Still in progress
*
* Revision 2.7 2006/02/08 06:54:44 csoutheren
* Added extra information to monitoring page
*
* Revision 2.6 2006/02/03 07:21:41 csoutheren
* Added INVITE function via web interface
*
* Revision 2.5 2004/09/22 22:39:26 csoutheren
* Fixed race condition, thanks to Neil McCurdy
*
* Revision 2.4 2004/05/26 06:54:31 csoutheren
* Changed to be a PHTTPServiceProcess
* Added ability to play WAV files on member entry and exit
* Added additional documentation on all classes
* Preparation for re-introducing video
*
* Revision 2.3 2004/03/31 03:36:38 csoutheren
* Fixed problem with user indication messages
* Fixed problems with room listener and unlisten
*
* Revision 2.2 2004/03/30 11:27:23 csoutheren
* Reverted to old mixing algorithm
*
* Revision 2.1 2004/03/23 11:40:06 csoutheren
* Fixed problem where deleting map element in-place causes crash at end of call
* Fixed problem where referencing map by iterator rather than ID
* Fixed code formatting problems
*
* Revision 2.0 2004/03/08 02:06:24 csoutheren
* Totally rewritten to use new connection locking mecahnism
* Added ability to monitor conferences
* Added initial support for H.323 MCU messages
* Thanks to Citron Networks for supporting this work
*
*/
#include <ptlib.h>
#include "conference.h"
#include "mcu.h"
#if OPENMCU_VIDEO
#include <ptlib/vconvert.h>
#endif
// size of a PCM data packet, in samples
#define PCM_PACKET_LEN 240
// size of a PCM data buffer, in bytes
#define PCM_BUFFER_LEN (PCM_PACKET_LEN * 2)
// number of PCM buffers to keep
#define PCM_BUFFER_COUNT 2
#define PCM_BUFFER_SIZE (PCM_BUFFER_LEN * PCM_BUFFER_COUNT)
////////////////////////////////////////////////////////////////////////////////////
ConferenceManager::ConferenceManager()
{
maxConferenceCount = 0;
monitor = new ConferenceMonitor(*this);
}
ConferenceManager::~ConferenceManager()
{
monitor->running = FALSE;
monitor->WaitForTermination();
delete monitor;
}
Conference * ConferenceManager::MakeAndLockConference(const PString & roomToCreate, const PString & name)
{
PWaitAndSignal m(conferenceListMutex);
OpalGloballyUniqueID conferenceID;
ConferenceListType::const_iterator r;
for (r = conferenceList.begin(); r != conferenceList.end(); ++r) {
if (roomToCreate == r->second->GetNumber()) {
conferenceID = r->second->GetID();
break;
}
}
return MakeAndLockConference(conferenceID, roomToCreate, name);
}
Conference * ConferenceManager::MakeAndLockConference(const OpalGloballyUniqueID & conferenceID,
const PString & roomToCreate,
const PString & name)
{
conferenceListMutex.Wait();
Conference * conference = NULL;
BOOL newConference = FALSE;
ConferenceListType::const_iterator r = conferenceList.find(conferenceID);
if (r != conferenceList.end())
conference = r->second;
else {
// create the conference
conference = CreateConference(conferenceID, roomToCreate, name, mcuNumberMap.GetNumber(conferenceID));
// insert conference into the map
conferenceList.insert(ConferenceListType::value_type(conferenceID, conference));
// set the conference count
maxConferenceCount = PMAX(maxConferenceCount, (PINDEX)conferenceList.size());
newConference = TRUE;
}
if (newConference)
OnCreateConference(conference);
return conference;
}
void ConferenceManager::OnCreateConference(Conference * conference)
{
// set time limit, if there is one
int timeLimit = OpenMCU::Current().GetRoomTimeLimit();
if (timeLimit > 0)
monitor->AddMonitorEvent(new ConferenceTimeLimitInfo(conference->GetID(), PTime() + timeLimit*1000));
}
Conference * ConferenceManager::CreateConference(const OpalGloballyUniqueID & _guid,
const PString & _number,
const PString & _name,
int _mcuNumber)
{
#if OPENMCU_VIDEO
#if ENABLE_ECHO_MIXER
if (_number *= "echo")
return new Conference(*this, _guid, _guid.AsString(), _name, _mcuNumber, new EchoVideoMixer());
#endif
#if ENABLE_TEST_ROOMS
if (_number.Left(8) == "testroom") {
int count = _number.Mid(8).AsInteger();
if (count > 0)
return new Conference(*this, _guid, _number, _name, _mcuNumber, new TestVideoMixer(count));
}
#endif
#endif
return new Conference(*this, _guid, _number, _name, _mcuNumber
#if OPENMCU_VIDEO
,OpenMCU::Current().CreateVideoMixer()
#endif
);
}
BOOL ConferenceManager::HasConference(const OpalGloballyUniqueID & conferenceID, PString & number)
{
PWaitAndSignal m(conferenceListMutex);
ConferenceListType::const_iterator r = conferenceList.find(conferenceID);
if (r == conferenceList.end())
return FALSE;
number = r->second->GetNumber();
return TRUE;
}
BOOL ConferenceManager::HasConference(const PString & number, OpalGloballyUniqueID & conferenceID)
{
PWaitAndSignal m(conferenceListMutex);
ConferenceListType::const_iterator r;
for (r = conferenceList.begin(); r != conferenceList.end(); ++r) {
if (r->second->GetNumber() == number) {
conferenceID = r->second->GetID();
return TRUE;
}
}
return FALSE;
}
void ConferenceManager::RemoveConference(const OpalGloballyUniqueID & confId)
{
PWaitAndSignal m(conferenceListMutex);
ConferenceListType::iterator r = conferenceList.find(confId);
if (r != conferenceList.end()) {
Conference * conf = r->second;
OnDestroyConference(conf);
conferenceList.erase(confId);
mcuNumberMap.RemoveNumber(conf->GetMCUNumber());
monitor->RemoveForConference(conf->GetID());
delete conf;
}
}
void ConferenceManager::RemoveMember(const OpalGloballyUniqueID & confId, ConferenceMember * toRemove)
{
PWaitAndSignal m(conferenceListMutex);
Conference * conf = toRemove->GetConference();
OpalGloballyUniqueID id = conf->GetID(); // make a copy of the ID because it may be about to disappear
BOOL removeConf = conf->RemoveMember(toRemove);
delete toRemove;
if (removeConf)
RemoveConference(id);
}
void ConferenceManager::AddMonitorEvent(ConferenceMonitorInfo * info)
{
monitor->AddMonitorEvent(info);
}
///////////////////////////////////////////////////////////////
void ConferenceMonitor::Main()
{
running = TRUE;
for (;;) {
if (!running)
break;
Sleep(1000);
if (!running)
break;
PWaitAndSignal m(mutex);
PTime now;
MonitorInfoList::iterator r = monitorList.begin();
while (r != monitorList.end()) {
ConferenceMonitorInfo & info = **r;
if (now < info.timeToPerform)
++r;
else {
BOOL deleteAfterPerform = TRUE;
{
PWaitAndSignal m2(manager.GetConferenceListMutex());
ConferenceListType & confList = manager.GetConferenceList();
ConferenceListType::iterator s = confList.find(info.guid);
if (s != confList.end())
deleteAfterPerform = info.Perform(*s->second);
}
if (!deleteAfterPerform)
++r;
else {
delete *r;
monitorList.erase(r);
r = monitorList.begin();
}
}
}
}
}
void ConferenceMonitor::AddMonitorEvent(ConferenceMonitorInfo * info)
{
PWaitAndSignal m(mutex);
monitorList.push_back(info);
}
void ConferenceMonitor::RemoveForConference(const OpalGloballyUniqueID & guid)
{
PWaitAndSignal m(mutex);
MonitorInfoList::iterator r = monitorList.begin();
while (r != monitorList.end()) {
ConferenceMonitorInfo & info = **r;
if (info.guid != guid)
++r;
else {
delete *r;
monitorList.erase(r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -