📄 main.cxx
字号:
}
if (!endpoint.StartListener(listener)) {
cout << "Could not open H.323 listener port on "
<< listener->GetListenerPort() << endl;
delete listener;
return;
}
cout << "Listening on port " << listener->GetListenerPort() << endl;
if (args.GetOptionString('q').IsEmpty()) {
endpoint.behind_masq = FALSE;
} else {
endpoint.masqAddressPtr = new PIPSocket::Address(args.GetOptionString('q'));
endpoint.behind_masq = TRUE;
cout << "Masquerading as address " << *(endpoint.masqAddressPtr) << endl;
}
#ifndef NO_VIDEO
// If videoLarge was specified
if (args.HasOption("videolarge")) {
endpoint.videoLarge = TRUE;
} else {
endpoint.videoLarge = FALSE;
}
if (args.HasOption('v')) {
//Add capability to allow the reception of video.
// this is the only way I know of at present to transmit
// CIF size video - pez
// Do not allow CIF video if size is medium
if ( endpoint.videoLarge )
endpoint.SetCapability(0, 1, new H323_H261Capability(0, 4, FALSE, FALSE, 6217)); // CIF
endpoint.SetCapability(0, 1, new H323_H261Capability(2, 0, FALSE, FALSE, 6217)); // QCIF
}
endpoint.EnableVideoReception(args.HasOption('v'));
int videoTxQual = 10;
if (args.HasOption("videotxquality"))
videoTxQual = args.GetOptionString("videotxquality").AsInteger();
endpoint.videoTxQuality = PMAX(1, PMIN(31, videoTxQual));
int videoF = 2;
if (args.HasOption("videofill"))
videoF = args.GetOptionString("videofill").AsInteger();
endpoint.videoFill = PMAX(1, PMIN(99, videoF));
int videoFPS = 10;
if (args.HasOption("videotxfps"))
videoFPS = args.GetOptionString("videotxfps").AsInteger();
endpoint.videoFramesPS = PMAX(1,PMIN(30,videoFPS));
#endif
if (args.HasOption('g')) {
PString gkName = args.GetOptionString('g');
if (endpoint.SetGatekeeper(gkName, new H323TransportUDP(endpoint)))
cout << "Gatekeeper set: " << *endpoint.GetGatekeeper() << endl;
else {
cout << "Error registering with gatekeeper at \"" << gkName << '"' << endl;
return;
}
}
else if (!args.HasOption('n')) {
cout << "Searching for gatekeeper..." << flush;
if (endpoint.DiscoverGatekeeper(new H323TransportUDP(endpoint)))
cout << "\nGatekeeper found: " << *endpoint.GetGatekeeper() << endl;
else {
cout << "\nNo gatekeeper found." << endl;
if (args.HasOption("require-gatekeeper"))
return;
}
}
PString roomName = "room101";
if (args.HasOption("defaultroom")) {
roomName = args.GetOptionString("defaultroom");
}
if (args.HasOption("no-defaultroom")) {
roomName = "";
}
endpoint.SetDefaultRoomName(roomName);
if (args.HasOption("disable-menu")) {
endpoint.hasMenu = FALSE;
} else {
endpoint.hasMenu = TRUE;
}
if (args.HasOption("audio-loopback")) {
endpoint.audioLoopbackRoom = args.GetOptionString("audio-loopback");
} else {
endpoint.audioLoopbackRoom = "";
}
cout << "Codecs (in preference order):\n" << setprecision(2) << endpoint.GetCapabilities() << endl << endl;
endpoint.ListenForIncomingCalls();
endpoint.AwaitTermination();
cout << "GoodBye. " << endl;
PThread::Current()->Sleep(2000);
cout << "Finished 2 sec sleep" <<endl;
#if 0 //PTRACING
if (output != NULL)
delete output;
#endif
}
///////////////////////////////////////////////////////////////
MyH323EndPoint::MyH323EndPoint()
{
terminalType = e_MCUWithAudioMP;
#ifndef NO_VIDEO
terminalType = e_MCUWithAVMP;
#endif
}
H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference)
{
return new MyH323Connection(*this, callReference);
}
void MyH323EndPoint::TranslateTCPAddress(PIPSocket::Address &localAddr, const PIPSocket::Address &remoteAddr)
{
if (this->behind_masq &&
(remoteAddr.Byte1() != 192)) {
localAddr = *(this->masqAddressPtr);
}
return;
}
void MyH323EndPoint::ListenForIncomingCalls()
{
cout << "Waiting for incoming calls for \"" << GetLocalUserName() << '"' << endl;
}
void MyH323EndPoint::AwaitTermination()
{
PThread * userInterfaceThread = NULL;
if (hasMenu)
userInterfaceThread = new UserInterfaceThread(*this);
// poll the handset every 100ms looking for state changes
while (!exitFlag.Wait(100)) {
// lock the user interface state whilst we change it
}
if (userInterfaceThread != NULL) {
userInterfaceThread->Terminate();
userInterfaceThread->WaitForTermination();
delete userInterfaceThread;
cout << "User Interface thread has terminated successfully."<<endl;
}
}
void MyH323EndPoint::HandleUserInterface()
{
PConsoleChannel console(PConsoleChannel::StandardInput);
PString user;
PString str;
PINDEX idx;
PTRACE(2, "OpenMCU\tUser interface thread started.");
PStringStream help;
help << "Select:\n"
" ? : Print this help message\n"
#ifndef NO_VIDEO
" v : report connections are at which video corner\n"
#endif
" m : make a call\n"
" x : Exit immediately\n"
" s : Report statistics\n"
" z : Put message in log file (for debugging)\n"
;
for (;;) {
// display the prompt
cout << "Command ? " << flush;
//terminate the menu loop if console finished
char ch = (char)console.peek();
if (console.eof()) {
cerr << "\nConsole gone - menu disabled" << endl;
cerr << "Finishing program"<<endl;
ch = 'x';
} else
console >> ch;
switch (tolower(ch)) {
case '?' :
cout << help << endl;
break;
case 'm' :
console >> user;
if (!MakeCall(user, str))
cerr << "Error making call to \"" << user << '"' << endl;
break;
case 's' :
{
memberMutex.Wait();
PINDEX rooms = memberListDict.GetSize();
if (rooms == 0) {
cout << "No statistics available" << endl;
} else {
for (idx = 0; idx < rooms; idx++) {
PStringList & memberList = memberListDict.GetDataAt(idx);
PString roomID = memberListDict.GetKeyAt(idx);
cout << "Statistics for " << memberList.GetSize() << " connected parties in room "
<< (idx+1) << " of "<< rooms << " with room id "
<< roomID << endl;
for (PINDEX i = 0; i < memberList.GetSize(); i++) {
PString token = memberList[i];
MyH323Connection * conn = (MyH323Connection *)FindConnectionWithLock(token);
if (conn != NULL) {
PTime now;
PTime callStart = conn->GetConnectionStartTime();
cout << "Connected to : " << conn->GetRemotePartyName() << " for "
<< setw(5) << setprecision(0) << (now - callStart) << " mins " <<endl;
RTP_Session * session = conn->GetSession(RTP_Session::DefaultAudioSessionID);
if (session == NULL) {
cout << " : "
<< "Sending audio with "
<< conn->GetAudioTransmitCodecName()
<< endl;
cout << " : "
<< "Receiving audio with "
<< conn->GetAudioReceiveCodecName()
<< endl;
} else {
cout << " : "
<< session->GetPacketsSent() << '/'
<< session->GetOctetsSent()
<< " audio packets/bytes sent ("
<< conn->GetAudioTransmitCodecName()
<< ")" << endl;
cout << " : "
<< session->GetPacketsReceived() << '/'
<< session->GetOctetsReceived()
<< " audio packets/bytes received ("
<< conn->GetAudioReceiveCodecName()
<< ")" << endl;
}
#ifndef NO_VIDEO
cout << " : "
<< "Sending video with "
<< conn->GetVideoTransmitCodecName()
<< endl;
cout << " : "
<< "Receiving video with "
<< conn->GetVideoReceiveCodecName()
<< endl;
#endif
conn->Unlock();
}
}
PStringList & videoPosnList = videoPosnDict[roomID];
for(PINDEX j = 0; j < videoPosnList.GetSize(); j++) {
str = videoPosnList[j];
str.Delete(0,3);
cout << " video for position " << j << " is \""
<< str.Left(str.Find(':')) << '"' << endl;
}
}
}
memberMutex.Signal();
}
break;
#ifndef NO_VIDEO
case 'v' :
cout << " video information now available with option s" << endl;
break;
#endif
case 'z' :
console >> str;
PTRACE(0,"Log message=" << str);
break;
case 'q' :
case 'x' :
cout << "Exiting." << endl;
memberMutex.Wait(); //Stops flow of data into/out of audio buffers.
ClearAllCalls(H323Connection::EndedByLocalUser, FALSE);
/*for (i = 0; i < memberList.GetSize(); i++) {
PString token = memberList[i];
MyH323Connection * conn = (MyH323Connection *)FindConnectionWithLock(token);
if (conn != NULL)
conn->ClearCall();
}*/
cout << "All calls cleared"<<endl;
exitFlag.Signal();
console.ignore(INT_MAX, '\n');
memberMutex.Signal();
return;
default :
cout << "The input character \""<<ch<<"\" is not defined"<<endl;
}
}
}
void MyH323EndPoint::SetDefaultRoomName(PString roomName)
{
defaultRoomName = roomName;
}
PString MyH323EndPoint::GetDefaultRoomName(void)
{
return defaultRoomName;
}
void MyH323EndPoint::AddMember(MyH323Connection * newMember)
{
PWaitAndSignal mutex(memberMutex);
PString newToken = newMember->GetCallToken();
PString newRoomID = newMember->GetRoomID();
BOOL create_new_room = FALSE;
// is this is the first connection to a room?
if (!memberListDict.Contains(newRoomID)) {
create_new_room = TRUE;
}
// if this is the first connection to a room, create the memberList
if (create_new_room) {
memberListDict.SetAt(newRoomID, new PStringList);
}
// add this connection to the member list
PStringList & memberList = memberListDict[newRoomID];
memberList.AppendString(newToken);
#ifndef NO_VIDEO
// if this is the first connection to a room, create the video buffer.
if (create_new_room) {
//cout << "CREATING VIDEO BUFFER FOR "<<newRoomID<<endl;
videoBufferDict.SetAt(newRoomID, new VideoBuffer);
VideoBuffer & videoBuffer = videoBufferDict[newRoomID];
if (videoLarge)
videoBuffer.SetSize(352,288);
// create the spoken list.
spokenListDict.SetAt(newRoomID, new PStringList);
// create the position list.
videoPosnDict.SetAt(newRoomID, new PStringList);
PStringList & videoPosnList = videoPosnDict[newRoomID];
PINDEX i;
for(i=0;i<4;i++) // hard coded to support 4 images
videoPosnList.AppendString("");
}
// Normally we display the video for the "active" users, ie
// people who are currently speaking (based on noise detection)
//
// If there are currently less than 4 members then we can display
// the video right from the start, before they begin talking.
// This is also handy for connections with video, but no audio.
//
// Problem is finding out whether or not an ep sends video.
// That is for a coming version.
AddVideoPosnToken(newToken,newRoomID);
#endif
// add the new member to every other member,
// and add every other member to the new member.
PINDEX i;
for (i = 0; i < memberList.GetSize(); i++) {
PString token = memberList[i];
if (token != newToken) {
cout << "Adding member " << newToken << " to list of " << token << endl;
MyH323Connection * conn = (MyH323Connection *)FindConnectionWithLock(token);
if (conn != NULL) {
conn->AddMember(newToken);
newMember->AddMember(token);
conn->Unlock();
}
} else {
if ((newRoomID == audioLoopbackRoom) || (newRoomID == "loopback")
|| (audioLoopbackRoom == "*") // basic wildcard
) {
cout << "Member " << newToken << " will hear their own voice" << endl;
newMember->AddMember(newToken);
} else {
cout << "Member " << newToken << " will not hear their own voice" << endl;
}
}
}
}
void MyH323EndPoint::RemoveMember(MyH323Connection * oldConn)
{
PWaitAndSignal mutex(memberMutex);
PString oldToken = oldConn->GetCallToken();
PString oldRoomID = oldConn->GetRoomID();
BOOL delete_this_room = FALSE;
// get the list of members of this room
PStringList & memberList = memberListDict[oldRoomID];
PINDEX i;
#ifndef NO_VIDEO
PStringList & spokenList = spokenListDict[oldRoomID];
//remove the connection from the spokenList
PINDEX keyIndex = spokenList.GetStringsIndex(oldToken);
if (keyIndex != P_MAX_INDEX)
spokenList.RemoveAt(keyIndex);
//Clear the corner of the video window that the connection just
//vacated.
VideoBuffer & videoBuffer = videoBufferDict[oldRoomID];
PStringList & videoPosn = videoPosnDict[oldRoomID];
i = FindTokensVideoPosn(oldToken,oldRoomID);
if (i != P_MAX_INDEX) {
videoBuffer.Clear(i);
videoPosn[i] = "";
}
#endif
// remove this member from the audio buffer lists
for (i = 0; i < memberList.GetSize(); i++) {
PString token = memberList[i];
if (token != oldToken) {
MyH323Connection * conn = (MyH323Connection *)FindConnectionWithLock(token);
if (conn != NULL) {
conn->RemoveMember(oldToken);
oldConn->RemoveMember(token);
conn->Unlock();
}
}
}
// remove this connection from the member list
memberList.RemoveAt(memberList.GetStringsIndex(oldToken));
// is the room empty now?
if (memberList.GetSize() == 0) {
delete_this_room = TRUE;
}
// if there are no more members in this room, clean up
if (delete_this_room == TRUE) {
cout << "Room " << oldRoomID << " is now empty" << endl;
memberListDict.RemoveAt(oldRoomID); // Note: memberList is now invalid
#ifndef NO_VIDEO
spokenListDict.RemoveAt(oldRoomID);
videoBufferDict.RemoveAt(oldRoomID);
videoPosnDict.RemoveAt(oldRoomID);
#endif
}
}
#ifndef NO_VIDEO
PINDEX MyH323EndPoint::FindTokensVideoPosn(const PString & thisToken, PString roomID)
{
PStringList & videoPosnList = videoPosnDict[roomID];
PINDEX keyIndex;
for (keyIndex = 0; keyIndex<videoPosnList.GetSize(); keyIndex++)
if (thisToken == videoPosnList[keyIndex] )
return keyIndex;
return P_MAX_INDEX;
}
BOOL MyH323EndPoint::AddVideoPosnToken(const PString & thisToken, PString roomID)
{
PStringList & videoPosnList = videoPosnDict[roomID];
PINDEX keyIndex;
for (keyIndex = 0; keyIndex<videoPosnList.GetSize(); keyIndex++)
if (videoPosnList[keyIndex] == "" ) {
videoPosnList[keyIndex] = thisToken;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -