/*
* main.h
*
* A simple H.323 MCU
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* 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 this code were written by Post Increment (http://www.postincrement.com)
* with the assistance of funding from Citron Networks (http://www.citron.com.tw)
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): Derek J Smithies (derek@indranet.co.nz)
*
* $Log: main.h,v $
* Revision 2.5 2005/03/11 00:25:24 csoutheren
* Fixed problems with flags
*
* 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/05/03 13:25:47 rjongbloed
* Converted everything to be codec plug in freindly
* Removed GSM and G.729 as now plug ins are "the way"!
*
* Revision 2.2 2004/03/31 03:36:39 csoutheren
* Fixed problem with user indication messages
* Fixed problems with room listener and unlisten
*
* Revision 2.1 2004/03/11 20:49:44 csoutheren
* Removed warnings
*
* 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
*
* Revision 1.30 2004/02/23 23:18:04 csoutheren
* Fixed iLBC compile problems
* Fixed NO_VIDEO compile problems
*
* Revision 1.29 2003/10/23 01:10:25 dereksmithies
* Add fix from Alex Epshteyn to fix NO_VIDEO compiling problem.
*
* Revision 1.28 2003/08/05 22:47:39 dereksmithies
* Apply code from Martin Andre to give single stream functionality. Thanks!
*
* Revision 1.27 2003/06/17 03:05:24 dereksmithies
* Add H263 codec.
*
* Revision 1.26 2003/06/12 23:20:38 dereksmithies
* Bug fix from Dave, related to delays in VideoEncoding. Thanks!
*
* Revision 1.25 2003/05/01 06:29:59 robertj
* Added propagation of user indications from a connection to all other
* connections in a room.
* Minor API clean up.
*
* Revision 1.24 2003/02/06 02:43:49 rogerh
* There is now a video buffer for each 'room', which stops people in
* different rooms from seeing each other. Bug pointed out by Damien Sandras.
* Will need for fix leaks and delete the video buffer when a room empties.
*
* Revision 1.23 2002/11/21 07:55:12 robertj
* Removed redundent and incorrect function for making outgoing call.
*
* Revision 1.22 2002/06/14 08:05:08 dereks
* Added tweak to support operation behind a NAT that forwards ports
* This will use TranslateTCPAddress to change the address reported
* to connections that occur from outside the 192. subnet. Thanks Sahai.
*
* Revision 1.21 2002/04/18 10:54:34 rogerh
* Fix bug in audio mixing reportde by Bob Lindell <lindell@isi.edu>
* AudioBuffer::Read() had been optimised to do reading and mixing and
* contained memset()'s which were incorrect. Clean up the code with
* a proper Read() method and an optimised ReadAndMix() method.
*
* Revision 1.20 2001/12/02 08:17:57 rogerh
* Change --audio-loopback to take a room name. Only connections to the
* specified room will have audio loopback applied. The remainder of the rooms
* in OpenMCU will work as normal.
* Submitted by Malcolm Caldwell <malcolm.caldwell@ntu.edu.au>
* I hard coded room "loopback" as a loopback room regardless of
* the --audio-loopback parameter.
*
* Revision 1.19 2001/11/22 13:06:38 rogerh
* Add --audio-loopback. Users of OpenMCU can hear their own voice echoed back
* which is very handy for testing purposes.
*
* Revision 1.18 2001/07/23 03:55:13 rogerh
* Seperate out codec names for audio and video
*
* Revision 1.17 2001/07/23 03:28:03 rogerh
* Display the codec name in the statistics page
*
* Revision 1.16 2001/05/31 17:01:52 rogerh
* Fixes from Dan Johansson <djn98006@student.mdh.se> to make video work.
* Go back to using 'closed' for the Video Classes. This is needed as
* the the video classes come from PVideoChannel which does not use os_handle
* in its IsOpen() method. Instead, we must define our own IsOpen() method.
* Also, back out the size of the image change.
* Finally, add a new feature. For the first 4 connections, video from an
* endpoint is displayed immediatly rather than waiting until that ep sends
* some audio. (handy for endpoints with video only and with no talking)
*
* Revision 1.15 2001/05/31 14:29:29 rogerh
* Add --disable-menu to OpenMCU
*
* Revision 1.14 2001/05/08 13:43:11 rogerh
* Connections without a room name will now join the default room (room101)
* Handy for NetMeeting users who cannot specify the room to OpenMCU.
* Add --defaultroom to change the default room name. Add --no-defaultroom to
* prevent use of the default room and to reject calls without a room name.
*
* Revision 1.13 2001/03/18 07:40:45 robertj
* Fixed MSVC compatibility.
*
* Revision 1.12 2001/03/18 06:50:20 robertj
* More changes for multiple conferences from Patrick Koorevaar.
*
* Revision 1.11 2001/03/05 22:36:22 robertj
* Changes for logging and multiple conferences from Patrick Koorevaar.
*
* Revision 1.10 2001/02/09 06:09:42 robertj
* Added fix for crashing on exit problem, thanks Dhomin.
*
* Revision 1.9 2001/02/08 07:06:37 robertj
* Added 'm' command to make call, thanks Paul Zaremba.
* Added ability to send CIF size images, thanks again Paul Zaremba.
*
* Revision 1.8 2001/01/23 02:55:05 dereks
* Add user interface thread to openmcu.
* tidy up the exiting process, but it is still in need of work.
*
* Revision 1.7 2001/01/03 03:59:26 dereks
* Adjusted algorithm for selecting which corners contain which video stream.
* Add gsmframes and g711frames option. Add documentation describing data flows.
*
* Revision 1.6 2000/12/22 08:28:23 dereks
* Optimise video handling, and reduce load on mcu computer
* Include noise detection routine, to determine which images are displayed when > 4 connections.
*
* Revision 1.5 2000/12/19 22:41:44 dereks
* Add video conferencing - limited to 5 connected nodes.
* Use the video channel facility now in openh323 and pwlib modules
* Add simple interface to handle commands entered at the keyboard.
*
* Revision 1.4 2000/11/02 03:33:41 craigs
* Changed to provide some sort of software timeing loop
*
* Revision 1.3 2000/05/25 12:06:20 robertj
* Added PConfigArgs class so can save program arguments to config files.
*
* Revision 1.2 2000/05/10 08:11:57 craigs
* Fixed copyrights and names
*
* Revision 1.1 2000/05/10 05:54:07 craigs
* Initial version
*
*/
#ifndef _OpenMCU_MAIN_H
#define _OpenMCU_MAIN_H
#ifdef _WIN32
#pragma warning(disable:4786)
#endif
#include <ptlib.h>
#include <map>
#include <h323.h>
#include <h323pdu.h>
#include <h245.h>
#include <lid.h>
#include "custom.h"
#include "conference.h"
#include "filemembers.h"
#if P_SSL
#include <ptclib/shttpsvc.h>
typedef PSecureHTTPServiceProcess OpenMCUProcessAncestor;
#else
#include <ptclib/httpsvc.h>
typedef PHTTPServiceProcess OpenMCUProcessAncestor;
#endif
/** *****
Data flow.
***Audio.
At any point in time, there are N nodes connected.
Consequently, there are N copies of OpenMCUH323Connection class, which
I will label connA, connB... connN
Ther is only ever one endpoint class, which is MyH323EndPoint.
There are N*(N-1) instances of audiobuffers
Each connection has a dictionary, containing (N-1) instances of audiobuffers.
connI has audioBuffers, labelled abA, abB, abC... (not abI) ...abM, abN
>> IncomingAudio (audio data arives at the mcu)
a)the audio codecs write to the IncomingAudio channel
b)IncomingAudio sends data to connI
c)connI writes the data to the endpoint.
d)the endpoint copies the data to connA, connB.. (not connI)...connM, connN
e)the connections listed in step d copy the data to the specified audiobuffer.
Thus, audio data from connI is copied into abI for connA,
copied into abI for connB, copied into abI for connC etc.
Thus, audio data from connI is copied (N-1) times.
>> OutgoingAudio (the audio encoder requests audio data to send)
a)the audio codec requests data from the OutgoingAudio channel
b)the OutgoingAudio channel requests data from the connI
c)connI requests data from the endpoint.
d)the endpoint (MyH323EndPoint::ReadAudio) method then finds the connection
associated with audio codec that has requested data. - in this case connI.
e)The OpenMCUH323Connection::ReadAudio method is then called for connI.
f)OpenMCUH323Connection::ReadAudio combines the data in each of its audiobuffers.
which is abA, abB, abC... (not abI) ...abM, abN
You will notice that Outgoing audio has additional work, in that connI
(at step c) could bypass the endpoint and go directly to its own audiobuffers
and read the data. This code is not SMP safe, because then the memberMutex does
not protect access (by outgoing audio code) to the connections.
*****Video is simple.
There is a video buffer in the endpoint class.
When an audio packet arrives, it moves the marker for that connection up a list.
If a particular connection is in the top 4 (it has spoken recently), then when
a video frame arrives, the connection writes the frame to the specified
section of the video buffer (eg, top left corner)
When video is requested, the entire frame of data in the video buffer is copied
and returned to the connection.
**/
class MyConferenceManager : public ConferenceManager
{
public:
void OnMemberJoining(Conference * conf, ConferenceMember *);
void OnMemberLeaving(Conference * conf, ConferenceMember *);
};
class MyH323EndPoint : public H323EndPoint
{
PCLASSINFO(MyH323EndPoint, H323EndPoint);
public:
MyH323EndPoint();
Conference * ConferenceRequest(H323Connection & connection,
const H323SignalPDU & setupPDU,
H323Connection::AnswerCallResponse & response);
// overrides from H323EndPoint
virtual H323Connection * CreateConnection(unsigned callReference);
virtual void TranslateTCPAddress(PIPSocket::Address &localAddr, const PIPSocket::Address &remoteAddr);
BOOL behind_masq;
PIPSocket::Address *masqAddressPtr;
// new functions
void Initialise(PConfig & cfg, PConfigPage * rsrc);
PString GetRoomStatus(const PString & block);
ConferenceManager & GetConferenceManager()
{ return conferenceManager; }
protected:
#ifndef NO_MCU_VIDEO
BOOL videoLarge;
int videoBitRate;
int videoFill;
int videoFramesPS;
int videoTxQuality;
#endif
protected:
MyConferenceManager conferenceManager;
//AudioDelay writeDelay;
#ifndef NO_MCU_VIDEO
BOOL hasVideo;
StringListDict spokenListDict; //Array of 'spoken lists' used to decide the
//4 user images to display (one list room)
VideoBufferDict videoBufferDict; //Array of VideoBuffers,(one for each room)
StringListDict videoPosnDict; //Array of 'position lists' that describe
//where video is displayed in the buffer.
#endif
//PSyncPoint exitFlag;
};
class OpenMCU : public OpenMCUProcessAncestor
{
PCLASSINFO(OpenMCU, OpenMCUProcessAncestor)
public:
OpenMCU();
void Main();
BOOL OnStart();
void OnStop();
void OnControl();
void OnConfigChanged();
BOOL Initialise(const char * initMsg);
static OpenMCU & Current() { return (OpenMCU &)PProcess::Current(); }
PString GetDefaultRoomName() const { return defaultRoomName; }
PString GetNewRoomNumber();
void LogMessage(const PString & str);
MyH323EndPoint & GetEndpoint()
{ return *endpoint; }
PFilePath GetConnectingWAVFile() const
{ return connectingWAVFile; }
PFilePath GetLeavingWAVFile() const
{ return leavingWAVFile; }
PFilePath GetEnteringWAVFile() const
{ return enteringWAVFile; }
protected:
MyH323EndPoint * endpoint;
long GetCodec(const PString & codecname);
OpalLineInterfaceDevice * GetDevice(const PString & device);
PString defaultRoomName;
PFilePath logFilename;
BOOL singleStream;
PString audioLoopbackRoom;
PFilePath connectingWAVFile;
PFilePath enteringWAVFile;
PFilePath leavingWAVFile;
};
////////////////////////////////////////////////////
class OutgoingAudio : public PChannel
{
PCLASSINFO(OutgoingAudio, PChannel);
public:
OutgoingAudio(H323EndPoint & ep, OpenMCUH323Connection & conn);
BOOL Read(void * buffer, PINDEX amount);
BOOL Close();
protected:
void CreateSilence(void * buffer, PINDEX amount);
H323EndPoint & ep;
OpenMCUH323Connection & conn;
AudioDelay delay;
PMutex audioChanMutex;
};
////////////////////////////////////////////////////
class IncomingAudio : public PChannel
{
PCLASSINFO(IncomingAudio, PChannel);
public:
IncomingAudio(H323EndPoint & ep, OpenMCUH323Connection & conn);
BOOL Write(const void * buffer, PINDEX amount);
BOOL Close();
protected:
H323EndPoint & ep;
OpenMCUH323Connection & conn;
PMutex audioChanMutex;
AudioDelay delay;
};
////////////////////////////////////////////////////
class H323Connection_ConferenceMember;
class OpenMCUH323Connection : public H323Connection
{
PCLASSINFO(OpenMCUH323Connection, H323Connection);
public:
OpenMCUH323Connection(MyH323EndPoint &, unsigned);
~OpenMCUH323Connection();
// overrides from H323Connection
BOOL OpenAudioChannel(BOOL, unsigned, H323AudioCodec & codec);
void CleanUpOnCallEnd();
AnswerCallResponse OnAnswerCall(const PString &, const H323SignalPDU &, H323SignalPDU &);
BOOL OnSendSignalSetup( H323SignalPDU & callProceedingPDU );
void OnUserInputString(const PString & value);
// functions called for incoming and outgoing channels.
// These provide a link between the audio/video channels and the endpoint.
BOOL OnIncomingAudio(const void * buffer, PINDEX amount);
BOOL OnOutgoingAudio(void * buffer, PINDEX amount);
// functions called to put data in/out of the buffer array.
BOOL ReadAudio (OpenMCUH323Connection * dest, void * buffer, PINDEX amount);
BOOL WriteAudio(OpenMCUH323Connection * dest, const void * buffer, PINDEX amount);
#ifndef NO_MCU_VIDEO
void EnableVideoReception(BOOL isOK) { hasVideo = isOK; }
BOOL OpenVideoChannel( BOOL isEncoding, H323VideoCodec & codec);
BOOL OnIncomingVideo(const void * buffer, PINDEX amount);
BOOL OnOutgoingVideo(void * buffer, PINDEX & amount);
PString GetVideoTransmitCodecName() const { return videoTransmitCodecName; }
PString GetVideoReceiveCodecName() const { return videoReceiveCodecName; }
#endif
PString GetAudioTransmitCodecName() const { return audioTransmitCodecName; }
PString GetAudioReceiveCodecName() const { return audioReceiveCodecName; }
protected:
void LogCall(const BOOL accepted = TRUE);
MyH323EndPoint & ep;
Conference * conference;
H323Connection_ConferenceMember * conferenceMember;
BOOL sendingAllowed;
BOOL connected;
OpalWAVFile playFile;
PString audioTransmitCodecName;
PString audioReceiveCodecName;
#ifndef NO_MCU_VIDEO
PString videoTransmitCodecName;
PString videoReceiveCodecName;
#endif
IncomingAudio * incomingAudio;
OutgoingAudio * outgoingAudio;
};
////////////////////////////////////////////////////
class H323Connection_ConferenceConnection : public ConferenceConnection
{
PCLASSINFO(H323Connection_ConferenceConnection, ConferenceConnection);
public:
H323Connection_ConferenceConnection(void * id)
: ConferenceConnection(id)
{ conn = (OpenMCUH323Connection *)id; }
virtual PString GetName() const
{ return conn->GetCallToken(); }
protected:
OpenMCUH323Connection * conn;
};
class H323Connection_ConferenceMember : public ConferenceMember
{
PCLASSINFO(H323Connection_ConferenceMember, ConferenceMember);
public:
H323Connection_ConferenceMember(OpenMCUH323Connection * _id)
: ConferenceMember((void *)_id)
{ conn = _id; }
virtual ConferenceConnection * CreateConnection()
{ return new H323Connection_ConferenceConnection(conn); }
virtual PString GetName() const
{ return conn->GetCallToken(); }
void OnReceivedUserInputIndication(const PString & str)
{ conn->SendUserInput(str); }
OpenMCUH323Connection * GetConnection()
{ return conn; }
protected:
OpenMCUH323Connection * conn;
};
#endif
// End of File ///////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1