4 * H.323 protocol handler
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
27 * Contributor(s): ______________________________________.
30 * Revision 1.105 2006/10/10 04:21:56 csoutheren
31 * Fixed compile problem on Linux with latest PWLib
33 * Revision 1.104 2006/09/05 23:56:57 csoutheren
34 * Convert media format and capability factories to use std::string
36 * Revision 1.103 2006/05/16 11:36:01 shorne
37 * added AEC support and H323VdieoCapability default constructor
39 * Revision 1.102 2005/06/07 07:09:13 csoutheren
40 * Removed compiler warnings on Windows
42 * Revision 1.101 2005/06/07 03:22:24 csoutheren
43 * Added patch 1198741 with support for plugin codecs with generic capabilities
44 * Added patch 1198754 with support for setting quality level on audio codecs
45 * Added patch 1198760 with GSM-AMR codec support
46 * Many thanks to Richard van der Hoff for his work
48 * Revision 1.100 2005/01/03 06:25:55 csoutheren
49 * Added extensive support for disabling code modules at compile time
51 * Revision 1.99 2004/12/08 02:14:26 csoutheren
52 * Guard against NULL capabilities
54 * Revision 1.98 2004/08/26 08:05:04 csoutheren
55 * Codecs now appear in abstract factory system
56 * Fixed Windows factory bootstrap system (again)
58 * Revision 1.97 2004/08/24 14:23:11 csoutheren
59 * Fixed problem with plugin codecs using capability compare functions
61 * Revision 1.96 2004/07/07 03:52:12 csoutheren
62 * Fixed incorrect strings returned by GetFormatName on G.711 codecs
64 * Revision 1.95 2004/07/03 07:05:42 csoutheren
65 * Applied patch 979639 to prevent crash in FindCapability if capability does not exist
68 * Revision 1.94 2004/06/30 12:31:16 rjongbloed
69 * Rewrite of plug in system to use single global variable for all factories to avoid all sorts
70 * of issues with startup orders and Windows DLL multiple instances.
72 * Revision 1.93 2004/06/17 22:40:56 csoutheren
73 * Fixed typo in FindCapability, thanks to Vyacheslav Frolov
75 * Revision 1.92 2004/06/16 07:50:00 csoutheren
76 * Fixed potential crash caused when user indication capabilities are not present. Thanks to Yuri Kiryanov
78 * Revision 1.91 2004/06/08 13:32:18 rjongbloed
79 * Fixed (pre)condition for checking and matching capabilities, thanks Guilhem Tardy
81 * Revision 1.90 2004/06/08 01:20:28 csoutheren
82 * Provide backwards compatibility for applications using old capability API
84 * Revision 1.89 2004/06/03 13:32:00 csoutheren
85 * Renamed INSTANTIATE_FACTORY
87 * Revision 1.88 2004/06/03 12:48:35 csoutheren
88 * Decomposed PFactory declarations to hopefully avoid problems with DLLs
90 * Revision 1.87 2004/06/01 05:48:03 csoutheren
91 * Changed capability table to use abstract factory routines rather than internal linked list
93 * Revision 1.86 2004/05/31 01:32:24 csoutheren
94 * Removed debugging left behind
96 * Revision 1.85 2004/05/26 04:13:21 csoutheren
97 * Safeguard against accidentally removing all capabilities by passing empty string to RemoveCapability
99 * Revision 1.84 2004/05/26 04:00:49 csoutheren
100 * Fixed calling of non-standard capability compare function used primarily for plugin codecs
102 * Revision 1.83 2004/05/20 02:07:29 csoutheren
103 * Use macro to work around MSVC internal compiler errors
105 * Revision 1.82 2004/05/19 23:42:48 csoutheren
106 * Included <algorithm>
108 * Revision 1.81 2004/05/19 13:28:30 csoutheren
109 * Changed H323EndPoint::AddAllCapabilities to only add standard media formats
111 * Revision 1.80 2004/05/19 07:38:23 csoutheren
112 * Changed OpalMediaFormat handling to use abstract factory method functions
114 * Revision 1.79 2004/05/13 12:49:33 rjongbloed
115 * Fixed usage of the compare function in non-standard capabilities.
117 * Revision 1.78 2004/05/10 01:01:25 csoutheren
118 * Guarded against NULL capabilities passed to AddCapability
120 * Revision 1.77 2004/05/06 12:53:09 rjongbloed
121 * Fixed ability to encode rxtx and tx capabilities, thanks Vyacheslav Andrejev.
123 * Revision 1.76 2004/05/04 03:33:33 csoutheren
124 * Added guards against comparing certain kinds of Capabilities
126 * Revision 1.75 2004/04/22 12:38:03 rjongbloed
127 * Removed the RTP QoS class if there is no QoS support in build,
128 * thanks Nick Hoath, ISDN Communications Ltd.
130 * Revision 1.74 2004/04/21 04:58:27 csoutheren
131 * Fixed problem with mode select, thanks to Vamsi K Pottangi
133 * Revision 1.73 2004/04/09 13:28:38 rjongbloed
134 * Fixed conversion of plug ins from OpenH323 to OPAL naming convention.
136 * Revision 1.72 2004/04/03 10:38:25 csoutheren
137 * Added in initial cut at codec plugin code. Branches are for wimps :)
139 * Revision 1.71 2004/04/03 08:28:06 csoutheren
140 * Remove pseudo-RTTI and replaced with real RTTI
142 * Revision 1.70 2004/03/24 01:57:20 csoutheren
143 * Updated for changes in H245v9
145 * Revision 1.69 2004/03/02 11:48:17 rjongbloed
146 * Fixed correct capability table matching when FindCapability with a mode change,
147 * uses different enum so needs translation table.
149 * Revision 1.68 2003/11/08 03:11:29 rjongbloed
150 * Fixed failure to call ancestor in copy ctor, thanks Victor Ivashin.
152 * Revision 1.67 2003/10/27 06:03:39 csoutheren
153 * Added support for QoS
154 * Thanks to Henry Harrison of AliceStreet
156 * Revision 1.66 2003/06/06 02:13:48 rjongbloed
157 * Changed non-standard capability semantics so can use C style strings as
158 * the embedded data block (ie automatically call strlen)
160 * Revision 1.65 2003/05/16 07:30:20 rjongbloed
161 * Fixed correct matching of OLC data types to capabilities, for example CIF
162 * and QCIF video are different and should match exactly.
164 * Revision 1.64 2003/04/28 07:00:09 robertj
165 * Fixed problem with compiler(s) not correctly initialising static globals
167 * Revision 1.63 2003/04/27 23:50:38 craigs
168 * Made list of registered codecs available outside h323caps.cxx
170 * Revision 1.62 2003/03/18 05:11:22 robertj
171 * Fixed OID based non-standard capabilities, thanks Philippe Massicotte
173 * Revision 1.61 2002/12/05 12:29:31 rogerh
174 * Add non standard codec identifier for Xiph.org
176 * Revision 1.60 2002/11/27 11:47:09 robertj
179 * Revision 1.59 2002/11/26 22:48:18 craigs
180 * Changed nonStd codec identification to use a table for MS codecs
182 * Revision 1.58 2002/11/26 13:52:59 craigs
183 * Added PrintOn function for outputting names of nonStandard codecs
185 * Revision 1.57 2002/11/09 04:44:24 robertj
186 * Fixed function to add capabilities to return correct table entry index.
189 * Revision 1.56 2002/08/05 10:03:47 robertj
190 * Cosmetic changes to normalise the usage of pragma interface/implementation.
192 * Revision 1.55 2002/07/18 08:28:52 robertj
193 * Adjusted some trace log levels
195 * Revision 1.54 2002/06/04 07:16:14 robertj
196 * Fixed user indications (DTMF) not working on some endpoints which indicated
197 * receiveAndTransmitUserInputCapability in TCS.
199 * Revision 1.53 2002/05/29 03:55:21 robertj
200 * Added protocol version number checking infrastructure, primarily to improve
201 * interoperability with stacks that are unforgiving of new features.
203 * Revision 1.52 2002/05/14 23:20:03 robertj
204 * Fixed incorrect comparison in non-standard capability, tnanks Vyacheslav Frolov
206 * Revision 1.51 2002/05/10 05:45:41 robertj
207 * Added the max bit rate field to the data channel capability class.
209 * Revision 1.50 2002/03/26 05:51:12 robertj
210 * Forced RFC2833 to payload type 101 as some IOS's go nuts otherwise.
212 * Revision 1.49 2002/03/05 06:18:46 robertj
213 * Fixed problem with some custom local capabilities not being used in getting
214 * remote capability list, especially in things like OpenAM.
216 * Revision 1.48 2002/02/25 04:38:42 robertj
217 * Fixed wildcard lookup with * at end of string.
218 * Fixed being able to create remote capability table before have local table.
219 * Fixed using add all with wildcards adding capability multiple times.
221 * Revision 1.47 2002/02/14 07:15:15 robertj
222 * Fixed problem with creation of remoteCapabilities and the "set" part contianing
223 * pointers to objects that have been deleted. Does not seem to be a practical
224 * problem but certainly needs fixing!
226 * Revision 1.46 2002/01/22 07:08:26 robertj
227 * Added IllegalPayloadType enum as need marker for none set
228 * and MaxPayloadType is a legal value.
230 * Revision 1.45 2002/01/22 06:07:35 robertj
231 * Moved payload type to ancestor so any capability can adjust it on logical channel.
233 * Revision 1.44 2002/01/17 07:05:03 robertj
234 * Added support for RFC2833 embedded DTMF in the RTP stream.
236 * Revision 1.43 2002/01/16 05:38:04 robertj
237 * Added missing mode change functions on non standard capabilities.
239 * Revision 1.42 2002/01/10 05:13:54 robertj
240 * Added support for external RTP stacks, thanks NuMind Software Systems.
242 * Revision 1.41 2002/01/09 00:21:39 robertj
243 * Changes to support outgoing H.245 RequstModeChange.
245 * Revision 1.40 2001/12/22 01:44:30 robertj
246 * Added more support for H.245 RequestMode operation.
248 * Revision 1.39 2001/09/21 02:52:56 robertj
249 * Added default implementation for PDU encode/decode for codecs
250 * that have simple integer as frames per packet.
252 * Revision 1.38 2001/09/11 10:21:42 robertj
253 * Added direction field to capabilities, thanks Nick Hoath.
255 * Revision 1.37 2001/08/06 03:08:56 robertj
256 * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
258 * Revision 1.36 2001/07/19 09:50:30 robertj
259 * Added code for default session ID on data channel being three.
261 * Revision 1.35 2001/07/17 04:44:31 robertj
262 * Partial implementation of T.120 and T.38 logical channels.
264 * Revision 1.34 2001/06/29 04:58:57 robertj
265 * Added wildcard character '*' to capability name string searches.
267 * Revision 1.33 2001/06/15 16:10:19 rogerh
268 * Fix the "capabilities are the same" assertion
270 * Revision 1.32 2001/05/31 06:28:37 robertj
271 * Made sure capability descriptors alternate capability sets are in the same
272 * order as the capability table when doing reorder. This improves compatibility
273 * with endpoints that select the first capability in that list rather than the table.
275 * Revision 1.31 2001/05/14 05:56:28 robertj
276 * Added H323 capability registration system so can add capabilities by
277 * string name instead of having to instantiate explicit classes.
279 * Revision 1.30 2001/05/02 16:22:21 rogerh
280 * Add IsAllow() for a single capability to check if it is in the
281 * capabilities set. This fixes the bug where OpenH323 would accept
282 * incoming H261 video even when told not to accept it.
284 * Revision 1.29 2001/04/12 03:22:44 robertj
285 * Fixed fast start checking of returned OLC frame count to use minimum
286 * of user setting and remotes maximum limitation, Was always just
287 * sending whatever the remote said it could do.
289 * Revision 1.28 2001/03/16 23:00:22 robertj
290 * Improved validation of codec selection against capability set, thanks Chris Purvis.
292 * Revision 1.27 2001/03/06 04:44:47 robertj
293 * Fixed problem where could send capability set twice. This should not be
294 * a problem except when talking to another broken stack, eg Cisco routers.
296 * Revision 1.26 2001/02/09 05:13:55 craigs
297 * Added pragma implementation to (hopefully) reduce the executable image size
300 * Revision 1.25 2001/01/25 07:27:16 robertj
301 * Major changes to add more flexible OpalMediaFormat class to normalise
302 * all information about media types, especially codecs.
304 * Revision 1.24 2001/01/16 03:14:01 craigs
305 * Changed nonstanard capability Compare functions to not assert
306 * if compared to other capability types
308 * Revision 1.23 2001/01/09 23:05:24 robertj
309 * Fixed inability to have 2 non standard codecs in capability table.
311 * Revision 1.22 2001/01/02 07:50:46 robertj
312 * Fixed inclusion of arrays (with bad size) in TCS=0 pdu, thanks Yura Aksyonov.
314 * Revision 1.21 2000/12/19 22:32:26 dereks
315 * Removed MSVC warning about unused parameter
317 * Revision 1.20 2000/11/08 04:50:22 craigs
318 * Changed capability reorder function to reorder all capabilities matching
319 * preferred order, rather than just the first
321 * Revision 1.19 2000/10/16 08:50:08 robertj
322 * Added single function to add all UserInput capability types.
324 * Revision 1.18 2000/10/13 03:43:29 robertj
325 * Added clamping to avoid ever setting incorrect tx frame count.
327 * Revision 1.17 2000/10/13 02:20:32 robertj
328 * Fixed capability clone so gets all fields including those in ancestor.
330 * Revision 1.16 2000/08/23 14:27:04 craigs
331 * Added prototype support for Microsoft GSM codec
333 * Revision 1.15 2000/07/13 12:30:46 robertj
334 * Fixed problems with fast start frames per packet adjustment.
336 * Revision 1.14 2000/07/12 10:25:37 robertj
337 * Renamed all codecs so obvious whether software or hardware.
339 * Revision 1.13 2000/07/10 16:03:02 robertj
340 * Started fixing capability set merging, still more to do.
342 * Revision 1.12 2000/07/04 01:16:49 robertj
343 * Added check for capability allowed in "combinations" set, still needs more done yet.
345 * Revision 1.11 2000/07/02 14:08:43 craigs
346 * Fixed problem with removing capabilities based on wildcard
348 * Revision 1.10 2000/06/03 03:16:39 robertj
349 * Fixed using the wrong capability table (should be connections) for some operations.
351 * Revision 1.9 2000/05/30 06:53:48 robertj
352 * Fixed bug where capability numbers in duplicate table are not identical (should be!).
354 * Revision 1.8 2000/05/23 11:32:37 robertj
355 * Rewrite of capability table to combine 2 structures into one and move functionality into that class
356 * allowing some normalisation of usage across several applications.
357 * Changed H323Connection so gets a copy of capabilities instead of using endponts, allows adjustments
358 * to be done depending on the remote client application.
360 * Revision 1.7 2000/05/10 04:05:34 robertj
361 * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn.
363 * Revision 1.6 2000/05/02 04:32:26 robertj
364 * Fixed copyright notice comment.
366 * Revision 1.5 2000/04/05 19:01:12 robertj
367 * Added function so can change desired transmit packet size.
369 * Revision 1.4 2000/03/22 01:29:43 robertj
370 * Fixed default "frame" size for audio codecs, caused crash using G.711
372 * Revision 1.3 2000/03/21 03:06:50 robertj
373 * Changes to make RTP TX of exact numbers of frames in some codecs.
375 * Revision 1.2 2000/02/16 03:24:27 robertj
376 * Fixed bug in clamping maximum transmit packet size in G.711 capabilities.
378 * Revision 1.1 1999/12/23 23:02:36 robertj
379 * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
384 #pragma implementation "h323caps.h"
389 #include "h323caps.h"
393 #include "opalplugin.h"
394 #include "mediafmt.h"
398 #define DEFINE_G711_CAPABILITY(cls, code, capName) \
399 class cls : public H323_G711Capability { \
401 cls() : H323_G711Capability(code) { } \
403 H323_REGISTER_CAPABILITY(cls, capName) \
405 #ifndef NO_H323_AUDIO_CODECS
407 DEFINE_G711_CAPABILITY(H323_G711ALaw64Capability
, H323_G711Capability::ALaw
, "G.711-ALaw-64k{sw}")
408 DEFINE_G711_CAPABILITY(H323_G711uLaw64Capability
, H323_G711Capability::muLaw
, "G.711-uLaw-64k{sw}")
416 ostream
& operator<<(ostream
& o
, H323Capability::MainTypes t
)
418 const char * const names
[] = {
419 "Audio", "Video", "Data", "UserInput"
421 return o
<< names
[t
];
424 ostream
& operator<<(ostream
& o
, H323Capability::CapabilityDirection d
)
426 const char * const names
[] = {
427 "Unknown", "Receive", "Transmit", "ReceiveAndTransmit", "NoDirection"
429 return o
<< names
[d
];
434 /////////////////////////////////////////////////////////////////////////////
436 H323Capability::H323Capability()
438 assignedCapabilityNumber
= 0; // Unassigned
439 capabilityDirection
= e_Unknown
;
440 rtpPayloadType
= RTP_DataFrame::IllegalPayloadType
;
444 PObject::Comparison
H323Capability::Compare(const PObject
& obj
) const
446 PAssert(PIsDescendant(&obj
, H323Capability
), PInvalidCast
);
447 const H323Capability
& other
= (const H323Capability
&)obj
;
449 int mt
= GetMainType();
450 int omt
= other
.GetMainType();
456 int st
= GetSubType();
457 int ost
= other
.GetSubType();
467 void H323Capability::PrintOn(ostream
& strm
) const
469 strm
<< GetFormatName();
470 if (assignedCapabilityNumber
!= 0)
471 strm
<< " <" << assignedCapabilityNumber
<< '>';
475 H323Capability
* H323Capability::Create(const PString
& name
)
477 H323Capability
* cap
= H323CapabilityFactory::CreateInstance(name
);
481 return (H323Capability
*)cap
->Clone();
485 unsigned H323Capability::GetDefaultSessionID() const
491 void H323Capability::SetTxFramesInPacket(unsigned /*frames*/)
496 unsigned H323Capability::GetTxFramesInPacket() const
502 unsigned H323Capability::GetRxFramesInPacket() const
508 BOOL
H323Capability::IsNonStandardMatch(const H245_NonStandardParameter
&) const
514 BOOL
H323Capability::OnReceivedPDU(const H245_Capability
& cap
)
516 switch (cap
.GetTag()) {
517 case H245_Capability::e_receiveVideoCapability
:
518 case H245_Capability::e_receiveAudioCapability
:
519 case H245_Capability::e_receiveDataApplicationCapability
:
520 case H245_Capability::e_h233EncryptionReceiveCapability
:
521 case H245_Capability::e_receiveUserInputCapability
:
522 capabilityDirection
= e_Receive
;
525 case H245_Capability::e_transmitVideoCapability
:
526 case H245_Capability::e_transmitAudioCapability
:
527 case H245_Capability::e_transmitDataApplicationCapability
:
528 case H245_Capability::e_h233EncryptionTransmitCapability
:
529 case H245_Capability::e_transmitUserInputCapability
:
530 capabilityDirection
= e_Transmit
;
533 case H245_Capability::e_receiveAndTransmitVideoCapability
:
534 case H245_Capability::e_receiveAndTransmitAudioCapability
:
535 case H245_Capability::e_receiveAndTransmitDataApplicationCapability
:
536 case H245_Capability::e_receiveAndTransmitUserInputCapability
:
537 capabilityDirection
= e_ReceiveAndTransmit
;
540 case H245_Capability::e_conferenceCapability
:
541 case H245_Capability::e_h235SecurityCapability
:
542 case H245_Capability::e_maxPendingReplacementFor
:
543 capabilityDirection
= e_NoDirection
;
550 BOOL
H323Capability::IsUsable(const H323Connection
&) const
556 /////////////////////////////////////////////////////////////////////////////
558 H323RealTimeCapability::H323RealTimeCapability()
563 H323RealTimeCapability::H323RealTimeCapability(const H323RealTimeCapability
& rtc
)
564 : H323Capability(rtc
)
567 if (rtc
.rtpqos
!= NULL
)
568 rtpqos
= new RTP_QOS(*rtc
.rtpqos
);
574 H323RealTimeCapability::~H323RealTimeCapability()
581 void H323RealTimeCapability::AttachQoS(RTP_QOS
* _rtpqos
)
590 H323Channel
* H323RealTimeCapability::CreateChannel(H323Connection
& connection
,
591 H323Channel::Directions dir
,
593 const H245_H2250LogicalChannelParameters
* param
) const
595 return connection
.CreateRealTimeLogicalChannel(*this, dir
, sessionID
, param
, rtpqos
);
599 /////////////////////////////////////////////////////////////////////////////
601 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(CompareFuncType _compareFunc
,
602 const BYTE
* dataPtr
,
608 nonStandardData(dataPtr
, dataSize
== 0 && dataPtr
!= NULL
609 ? strlen((const char *)dataPtr
) : dataSize
),
612 compareFunc(_compareFunc
)
616 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(const BYTE
* dataPtr
,
620 : t35CountryCode(H323EndPoint::defaultT35CountryCode
),
621 t35Extension(H323EndPoint::defaultT35Extension
),
622 manufacturerCode(H323EndPoint::defaultManufacturerCode
),
623 nonStandardData(dataPtr
, dataSize
== 0 && dataPtr
!= NULL
624 ? strlen((const char *)dataPtr
) : dataSize
),
625 comparisonOffset(_offset
),
626 comparisonLength(_len
),
632 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(const PString
& _oid
,
633 const BYTE
* dataPtr
,
638 nonStandardData(dataPtr
, dataSize
== 0 && dataPtr
!= NULL
639 ? strlen((const char *)dataPtr
) : dataSize
),
640 comparisonOffset(_offset
),
641 comparisonLength(_len
),
647 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(BYTE country
,
650 const BYTE
* dataPtr
,
654 : t35CountryCode(country
),
655 t35Extension(extension
),
656 manufacturerCode(maufacturer
),
657 nonStandardData(dataPtr
, dataSize
== 0 && dataPtr
!= NULL
658 ? strlen((const char *)dataPtr
) : dataSize
),
659 comparisonOffset(_offset
),
660 comparisonLength(_len
),
666 H323NonStandardCapabilityInfo::~H323NonStandardCapabilityInfo()
671 BOOL
H323NonStandardCapabilityInfo::OnSendingPDU(PBYTEArray
& data
) const
673 data
= nonStandardData
;
674 return data
.GetSize() > 0;
678 BOOL
H323NonStandardCapabilityInfo::OnReceivedPDU(const PBYTEArray
& data
)
680 nonStandardData
= data
;
685 BOOL
H323NonStandardCapabilityInfo::OnSendingNonStandardPDU(PASN_Choice
& pdu
,
686 unsigned nonStandardTag
) const
689 if (!OnSendingPDU(data
))
692 pdu
.SetTag(nonStandardTag
);
693 H245_NonStandardParameter
& param
= (H245_NonStandardParameter
&)pdu
.GetObject();
696 param
.m_nonStandardIdentifier
.SetTag(H245_NonStandardIdentifier::e_object
);
697 PASN_ObjectId
& nonStandardIdentifier
= param
.m_nonStandardIdentifier
;
698 nonStandardIdentifier
= oid
;
701 param
.m_nonStandardIdentifier
.SetTag(H245_NonStandardIdentifier::e_h221NonStandard
);
702 H245_NonStandardIdentifier_h221NonStandard
& h221
= param
.m_nonStandardIdentifier
;
703 h221
.m_t35CountryCode
= (unsigned)t35CountryCode
;
704 h221
.m_t35Extension
= (unsigned)t35Extension
;
705 h221
.m_manufacturerCode
= (unsigned)manufacturerCode
;
709 return data
.GetSize() > 0;
713 BOOL
H323NonStandardCapabilityInfo::OnReceivedNonStandardPDU(const PASN_Choice
& pdu
,
714 unsigned nonStandardTag
)
716 if (pdu
.GetTag() != nonStandardTag
)
719 const H245_NonStandardParameter
& param
= (const H245_NonStandardParameter
&)pdu
.GetObject();
721 if (CompareParam(param
) != PObject::EqualTo
)
724 return OnReceivedPDU(param
.m_data
);
728 PObject::Comparison
H323NonStandardCapabilityInfo::CompareParam(const H245_NonStandardParameter
& param
) const
730 if (compareFunc
!= NULL
) {
732 PluginCodec_H323NonStandardCodecData compareData
;
735 if (param
.m_nonStandardIdentifier
.GetTag() == H245_NonStandardIdentifier::e_object
) {
736 const PASN_ObjectId
& nonStandardIdentifier
= param
.m_nonStandardIdentifier
;
737 objectId
= nonStandardIdentifier
.AsString();
738 compareData
.objectId
= objectId
;
740 const H245_NonStandardIdentifier_h221NonStandard
& h221
= param
.m_nonStandardIdentifier
;
741 compareData
.objectId
= NULL
;
742 compareData
.t35CountryCode
= (unsigned char)h221
.m_t35CountryCode
;
743 compareData
.t35Extension
= (unsigned char)h221
.m_t35Extension
;
744 compareData
.manufacturerCode
= (unsigned short)h221
.m_manufacturerCode
;
746 const PBYTEArray
& data
= param
.m_data
;
747 compareData
.data
= (const unsigned char *)data
;
748 compareData
.dataLength
= data
.GetSize();
749 return (PObject::Comparison
)(*compareFunc
)(&compareData
);
753 if (param
.m_nonStandardIdentifier
.GetTag() != H245_NonStandardIdentifier::e_object
)
754 return PObject::LessThan
;
756 const PASN_ObjectId
& nonStandardIdentifier
= param
.m_nonStandardIdentifier
;
757 PObject::Comparison cmp
= oid
.Compare(nonStandardIdentifier
.AsString());
758 if (cmp
!= PObject::EqualTo
)
762 if (param
.m_nonStandardIdentifier
.GetTag() != H245_NonStandardIdentifier::e_h221NonStandard
)
763 return PObject::LessThan
;
765 const H245_NonStandardIdentifier_h221NonStandard
& h221
= param
.m_nonStandardIdentifier
;
767 if (h221
.m_t35CountryCode
< (unsigned)t35CountryCode
)
768 return PObject::LessThan
;
769 if (h221
.m_t35CountryCode
> (unsigned)t35CountryCode
)
770 return PObject::GreaterThan
;
772 if (h221
.m_t35Extension
< (unsigned)t35Extension
)
773 return PObject::LessThan
;
774 if (h221
.m_t35Extension
> (unsigned)t35Extension
)
775 return PObject::GreaterThan
;
777 if (h221
.m_manufacturerCode
< (unsigned)manufacturerCode
)
778 return PObject::LessThan
;
779 if (h221
.m_manufacturerCode
> (unsigned)manufacturerCode
)
780 return PObject::GreaterThan
;
783 return CompareData(param
.m_data
);
787 PObject::Comparison
H323NonStandardCapabilityInfo::CompareInfo(const H323NonStandardCapabilityInfo
& other
) const
789 if (compareFunc
!= NULL
) {
791 PluginCodec_H323NonStandardCodecData compareData
;
794 if (!other
.oid
.IsEmpty())
795 compareData
.objectId
= other
.oid
;
797 compareData
.objectId
= NULL
;
798 compareData
.t35CountryCode
= other
.t35CountryCode
;
799 compareData
.t35Extension
= other
.t35Extension
;
800 compareData
.manufacturerCode
= other
.manufacturerCode
;
802 compareData
.data
= (const unsigned char *)other
.nonStandardData
;
803 compareData
.dataLength
= other
.nonStandardData
.GetSize();
805 return (*compareFunc
)(&compareData
);
809 if (other
.oid
.IsEmpty())
810 return PObject::LessThan
;
812 PObject::Comparison cmp
= oid
.Compare(other
.oid
);
813 if (cmp
!= PObject::EqualTo
)
817 if (other
.t35CountryCode
< t35CountryCode
)
818 return PObject::LessThan
;
819 if (other
.t35CountryCode
> t35CountryCode
)
820 return PObject::GreaterThan
;
822 if (other
.t35Extension
< t35Extension
)
823 return PObject::LessThan
;
824 if (other
.t35Extension
> t35Extension
)
825 return PObject::GreaterThan
;
827 if (other
.manufacturerCode
< manufacturerCode
)
828 return PObject::LessThan
;
829 if (other
.manufacturerCode
> manufacturerCode
)
830 return PObject::GreaterThan
;
833 return CompareData(other
.nonStandardData
);
837 PObject::Comparison
H323NonStandardCapabilityInfo::CompareData(const PBYTEArray
& data
) const
839 if (comparisonOffset
>= nonStandardData
.GetSize())
840 return PObject::LessThan
;
841 if (comparisonOffset
>= data
.GetSize())
842 return PObject::GreaterThan
;
844 PINDEX len
= comparisonLength
;
845 if (comparisonOffset
+len
> nonStandardData
.GetSize())
846 len
= nonStandardData
.GetSize() - comparisonOffset
;
848 if (comparisonOffset
+len
> data
.GetSize())
849 return PObject::GreaterThan
;
851 int cmp
= memcmp((const BYTE
*)nonStandardData
+ comparisonOffset
,
852 (const BYTE
*)data
+ comparisonOffset
,
855 return PObject::LessThan
;
857 return PObject::GreaterThan
;
858 return PObject::EqualTo
;
862 /////////////////////////////////////////////////////////////////////////////
864 #ifndef NO_H323_AUDIO_CODECS
866 H323AudioCapability::H323AudioCapability(unsigned rx
, unsigned tx
)
868 rxFramesInPacket
= rx
;
869 txFramesInPacket
= tx
;
873 H323Capability::MainTypes
H323AudioCapability::GetMainType() const
879 unsigned H323AudioCapability::GetDefaultSessionID() const
881 return RTP_Session::DefaultAudioSessionID
;
885 void H323AudioCapability::SetTxFramesInPacket(unsigned frames
)
887 PAssert(frames
> 0, PInvalidParameter
);
889 txFramesInPacket
= 256;
891 txFramesInPacket
= frames
;
895 unsigned H323AudioCapability::GetTxFramesInPacket() const
897 return txFramesInPacket
;
901 unsigned H323AudioCapability::GetRxFramesInPacket() const
903 return rxFramesInPacket
;
907 BOOL
H323AudioCapability::OnSendingPDU(H245_Capability
& cap
) const
909 switch (capabilityDirection
) {
911 cap
.SetTag(H245_Capability::e_transmitAudioCapability
);
913 case e_ReceiveAndTransmit
:
914 cap
.SetTag(H245_Capability::e_receiveAndTransmitAudioCapability
);
918 cap
.SetTag(H245_Capability::e_receiveAudioCapability
);
920 return OnSendingPDU((H245_AudioCapability
&)cap
, rxFramesInPacket
);
924 BOOL
H323AudioCapability::OnSendingPDU(H245_DataType
& dataType
) const
926 dataType
.SetTag(H245_DataType::e_audioData
);
927 return OnSendingPDU((H245_AudioCapability
&)dataType
, txFramesInPacket
);
931 BOOL
H323AudioCapability::OnSendingPDU(H245_ModeElement
& mode
) const
933 mode
.m_type
.SetTag(H245_ModeElementType::e_audioMode
);
934 return OnSendingPDU((H245_AudioMode
&)mode
.m_type
);
938 BOOL
H323AudioCapability::OnSendingPDU(H245_AudioCapability
& pdu
,
939 unsigned packetSize
) const
941 pdu
.SetTag(GetSubType());
943 // Set the maximum number of frames
944 PASN_Integer
& value
= pdu
;
950 BOOL
H323AudioCapability::OnSendingPDU(H245_AudioMode
& pdu
) const
952 static const H245_AudioMode::Choices AudioTable
[] = {
953 H245_AudioMode::e_nonStandard
,
954 H245_AudioMode::e_g711Alaw64k
,
955 H245_AudioMode::e_g711Alaw56k
,
956 H245_AudioMode::e_g711Ulaw64k
,
957 H245_AudioMode::e_g711Ulaw56k
,
958 H245_AudioMode::e_g722_64k
,
959 H245_AudioMode::e_g722_56k
,
960 H245_AudioMode::e_g722_48k
,
961 H245_AudioMode::e_g7231
,
962 H245_AudioMode::e_g728
,
963 H245_AudioMode::e_g729
,
964 H245_AudioMode::e_g729AnnexA
,
965 H245_AudioMode::e_is11172AudioMode
,
966 H245_AudioMode::e_is13818AudioMode
,
967 H245_AudioMode::e_g729wAnnexB
,
968 H245_AudioMode::e_g729AnnexAwAnnexB
,
969 H245_AudioMode::e_g7231AnnexCMode
,
970 H245_AudioMode::e_gsmFullRate
,
971 H245_AudioMode::e_gsmHalfRate
,
972 H245_AudioMode::e_gsmEnhancedFullRate
,
973 H245_AudioMode::e_genericAudioMode
,
974 H245_AudioMode::e_g729Extensions
977 unsigned subType
= GetSubType();
978 if (subType
>= PARRAYSIZE(AudioTable
))
981 pdu
.SetTag(AudioTable
[subType
]);
986 BOOL
H323AudioCapability::OnReceivedPDU(const H245_Capability
& cap
)
988 H323Capability::OnReceivedPDU(cap
);
990 if (cap
.GetTag() != H245_Capability::e_receiveAudioCapability
&&
991 cap
.GetTag() != H245_Capability::e_receiveAndTransmitAudioCapability
)
994 unsigned packetSize
= txFramesInPacket
;
995 if (!OnReceivedPDU((const H245_AudioCapability
&)cap
, packetSize
))
998 // Clamp our transmit size to maximum allowed
999 if (txFramesInPacket
> packetSize
) {
1000 PTRACE(4, "H323\tCapability tx frames reduced from "
1001 << txFramesInPacket
<< " to " << packetSize
);
1002 txFramesInPacket
= packetSize
;
1005 PTRACE(4, "H323\tCapability tx frames left at "
1006 << txFramesInPacket
<< " as remote allows " << packetSize
);
1013 BOOL
H323AudioCapability::OnReceivedPDU(const H245_DataType
& dataType
, BOOL receiver
)
1015 if (dataType
.GetTag() != H245_DataType::e_audioData
)
1018 unsigned & xFramesInPacket
= receiver
? rxFramesInPacket
: txFramesInPacket
;
1019 unsigned packetSize
= xFramesInPacket
;
1020 if (!OnReceivedPDU((const H245_AudioCapability
&)dataType
, packetSize
))
1023 // Clamp our transmit size to maximum allowed
1024 if (xFramesInPacket
> packetSize
) {
1025 PTRACE(4, "H323\tCapability " << (receiver
? 'r' : 't') << "x frames reduced from "
1026 << xFramesInPacket
<< " to " << packetSize
);
1027 xFramesInPacket
= packetSize
;
1030 PTRACE(4, "H323\tCapability " << (receiver
? 'r' : 't') << "x frames left at "
1031 << xFramesInPacket
<< " as remote allows " << packetSize
);
1038 BOOL
H323AudioCapability::OnReceivedPDU(const H245_AudioCapability
& pdu
,
1039 unsigned & packetSize
)
1041 if (pdu
.GetTag() != GetSubType())
1044 const PASN_Integer
& value
= pdu
;
1046 // Get the maximum number of frames
1052 /////////////////////////////////////////////////////////////////////////////
1054 H323NonStandardAudioCapability::H323NonStandardAudioCapability(
1057 H323NonStandardCapabilityInfo::CompareFuncType compareFunc
,
1058 const BYTE
* fixedData
,
1061 : H323AudioCapability(max
, desired
),
1062 H323NonStandardCapabilityInfo(compareFunc
, fixedData
, dataSize
)
1066 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max
,
1068 const BYTE
* fixedData
,
1072 : H323AudioCapability(max
, desired
),
1073 H323NonStandardCapabilityInfo(fixedData
, dataSize
, offset
, length
)
1077 H323NonStandardAudioCapability::H323NonStandardAudioCapability(
1081 H323NonStandardCapabilityInfo::CompareFuncType compareFunc
,
1082 const BYTE
* fixedData
,
1084 : H323AudioCapability(max
, desired
),
1085 H323NonStandardCapabilityInfo(compareFunc
, fixedData
, dataSize
)
1089 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max
,
1092 const BYTE
* fixedData
,
1096 : H323AudioCapability(max
, desired
),
1097 H323NonStandardCapabilityInfo(fixedData
, dataSize
, offset
, length
)
1101 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max
,
1103 const PString
& oid
,
1104 const BYTE
* fixedData
,
1108 : H323AudioCapability(max
, desired
),
1109 H323NonStandardCapabilityInfo(oid
, fixedData
, dataSize
, offset
, length
)
1114 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max
,
1119 const BYTE
* fixedData
,
1123 : H323AudioCapability(max
, desired
),
1124 H323NonStandardCapabilityInfo(country
, extension
, maufacturer
, fixedData
, dataSize
, offset
, length
)
1129 PObject::Comparison
H323NonStandardAudioCapability::Compare(const PObject
& obj
) const
1131 if (!PIsDescendant(&obj
, H323NonStandardAudioCapability
))
1134 return CompareInfo((const H323NonStandardAudioCapability
&)obj
);
1138 unsigned H323NonStandardAudioCapability::GetSubType() const
1140 return H245_AudioCapability::e_nonStandard
;
1144 BOOL
H323NonStandardAudioCapability::OnSendingPDU(H245_AudioCapability
& pdu
,
1147 return OnSendingNonStandardPDU(pdu
, H245_AudioCapability::e_nonStandard
);
1151 BOOL
H323NonStandardAudioCapability::OnSendingPDU(H245_AudioMode
& pdu
) const
1153 return OnSendingNonStandardPDU(pdu
, H245_AudioMode::e_nonStandard
);
1157 BOOL
H323NonStandardAudioCapability::OnReceivedPDU(const H245_AudioCapability
& pdu
,
1160 return OnReceivedNonStandardPDU(pdu
, H245_AudioCapability::e_nonStandard
);
1164 BOOL
H323NonStandardAudioCapability::IsNonStandardMatch(const H245_NonStandardParameter
& param
) const
1166 return CompareParam(param
) == EqualTo
;
1169 #endif // NO_H323_AUDIO_CODECS
1172 /////////////////////////////////////////////////////////////////////////////
1174 H323GenericCapabilityInfo::H323GenericCapabilityInfo(const PString
&standardId
,
1176 : maxBitRate(maxBitRate
)
1178 capId
= new H245_CapabilityIdentifier(H245_CapabilityIdentifier::e_standard
);
1179 PASN_ObjectId
&object_id
= *capId
;
1180 object_id
= standardId
;
1183 H323GenericCapabilityInfo::H323GenericCapabilityInfo(const H323GenericCapabilityInfo
&obj
)
1184 : maxBitRate(obj
.maxBitRate
),
1185 collapsingParameters(obj
.collapsingParameters
),
1186 nonCollapsingParameters(obj
.nonCollapsingParameters
)
1188 capId
= new H245_CapabilityIdentifier(*obj
.capId
);
1191 H323GenericCapabilityInfo::~H323GenericCapabilityInfo()
1196 BOOL
H323GenericCapabilityInfo::AddIntegerGenericParameter(
1199 int type
, // should be one of opalplugin.h:PluginCodec_H323GenericParameterType
1202 PList
<H245_GenericParameter
> &list
= collapsing
?collapsingParameters
:nonCollapsingParameters
;
1204 H245_GenericParameter
*param
= new H245_GenericParameter();
1206 param
->m_parameterIdentifier
.SetTag(H245_ParameterIdentifier::e_standard
);
1207 (PASN_Integer
&)param
->m_parameterIdentifier
= standardId
;
1209 param
->m_parameterValue
.SetTag(type
);
1210 (PASN_Integer
&)param
->m_parameterValue
= value
;
1219 BOOL
H323GenericCapabilityInfo::OnSendingGenericPDU(H245_GenericCapability
& pdu
) const
1221 pdu
.m_capabilityIdentifier
= *capId
;
1222 if(maxBitRate
!= 0 ) {
1223 pdu
.IncludeOptionalField(H245_GenericCapability::e_maxBitRate
);
1224 pdu
.m_maxBitRate
= maxBitRate
;
1226 if(collapsingParameters
.GetSize() > 0) {
1227 pdu
.IncludeOptionalField(H245_GenericCapability::e_collapsing
);
1228 for( int i
= 0 ; i
< collapsingParameters
.GetSize(); i
++ )
1229 pdu
.m_collapsing
.Append(new H245_GenericParameter(collapsingParameters
[i
]));
1232 if(nonCollapsingParameters
.GetSize() > 0) {
1233 pdu
.IncludeOptionalField(H245_GenericCapability::e_nonCollapsing
);
1234 for( int i
= 0 ; i
< nonCollapsingParameters
.GetSize(); i
++ )
1235 pdu
.m_nonCollapsing
.Append(new H245_GenericParameter(nonCollapsingParameters
[i
]));
1241 BOOL
H323GenericCapabilityInfo::OnReceivedGenericPDU(const H245_GenericCapability
& /*pdu*/)
1246 PObject::Comparison
H323GenericCapabilityInfo::CompareInfo(const H323GenericCapabilityInfo
& obj
) const
1248 if( *capId
!= *(obj
.capId
) )
1249 return PObject::LessThan
;
1251 return PObject::EqualTo
;
1254 BOOL
H323GenericCapabilityInfo::IsGenericMatch(const H245_GenericCapability
& cap
) const
1256 const H245_CapabilityIdentifier
&otherId
= cap
.m_capabilityIdentifier
;
1257 return otherId
== *capId
;
1261 H323GenericAudioCapability::H323GenericAudioCapability(
1264 const PString
&standardId
,
1266 : H323AudioCapability(max
, desired
),
1267 H323GenericCapabilityInfo(standardId
, maxBitRate
)
1271 PObject::Comparison
H323GenericAudioCapability::Compare(const PObject
& obj
) const
1273 if (!PIsDescendant(&obj
, H323GenericAudioCapability
))
1276 return CompareInfo((const H323GenericAudioCapability
&)obj
);
1280 unsigned H323GenericAudioCapability::GetSubType() const
1282 return H245_AudioCapability::e_genericAudioCapability
;
1286 BOOL
H323GenericAudioCapability::OnSendingPDU(H245_AudioCapability
& pdu
,
1289 pdu
.SetTag(H245_AudioCapability::e_genericAudioCapability
);
1290 H245_GenericCapability
&generic
= (H245_GenericCapability
&)pdu
;
1291 return OnSendingGenericPDU(generic
);
1295 BOOL
H323GenericAudioCapability::OnReceivedPDU(const H245_AudioCapability
& pdu
,
1298 if( pdu
.GetTag() != H245_AudioCapability::e_genericAudioCapability
)
1300 return OnReceivedGenericPDU((const H245_GenericCapability
&)pdu
);
1304 /////////////////////////////////////////////////////////////////////////////
1306 #ifndef NO_H323_VIDEO
1308 H323VideoCapability::H323VideoCapability()
1312 H323Capability::MainTypes
H323VideoCapability::GetMainType() const
1318 BOOL
H323VideoCapability::OnSendingPDU(H245_Capability
& cap
) const
1320 switch (capabilityDirection
) {
1322 cap
.SetTag(H245_Capability::e_transmitVideoCapability
);
1324 case e_ReceiveAndTransmit
:
1325 cap
.SetTag(H245_Capability::e_receiveAndTransmitVideoCapability
);
1329 cap
.SetTag(H245_Capability::e_receiveVideoCapability
);
1331 return OnSendingPDU((H245_VideoCapability
&)cap
);
1335 BOOL
H323VideoCapability::OnSendingPDU(H245_DataType
& dataType
) const
1337 dataType
.SetTag(H245_DataType::e_videoData
);
1338 return OnSendingPDU((H245_VideoCapability
&)dataType
);
1342 BOOL
H323VideoCapability::OnSendingPDU(H245_ModeElement
& mode
) const
1344 mode
.m_type
.SetTag(H245_ModeElementType::e_videoMode
);
1345 return OnSendingPDU((H245_VideoMode
&)mode
.m_type
);
1349 BOOL
H323VideoCapability::OnReceivedPDU(const H245_Capability
& cap
)
1351 H323Capability::OnReceivedPDU(cap
);
1353 if (cap
.GetTag() != H245_Capability::e_receiveVideoCapability
&&
1354 cap
.GetTag() != H245_Capability::e_receiveAndTransmitVideoCapability
)
1357 return OnReceivedPDU((const H245_VideoCapability
&)cap
);
1361 BOOL
H323VideoCapability::OnReceivedPDU(const H245_DataType
& dataType
, BOOL
)
1363 if (dataType
.GetTag() != H245_DataType::e_videoData
)
1366 return OnReceivedPDU((const H245_VideoCapability
&)dataType
);
1370 unsigned H323VideoCapability::GetDefaultSessionID() const
1372 return RTP_Session::DefaultVideoSessionID
;
1376 /////////////////////////////////////////////////////////////////////////////
1378 H323NonStandardVideoCapability::H323NonStandardVideoCapability(const BYTE
* fixedData
,
1382 : H323NonStandardCapabilityInfo(fixedData
, dataSize
, offset
, length
)
1386 H323NonStandardVideoCapability::H323NonStandardVideoCapability(H323EndPoint
&,
1387 const BYTE
* fixedData
,
1391 : H323NonStandardCapabilityInfo(fixedData
, dataSize
, offset
, length
)
1395 H323NonStandardVideoCapability::H323NonStandardVideoCapability(const PString
& oid
,
1396 const BYTE
* fixedData
,
1400 : H323NonStandardCapabilityInfo(oid
, fixedData
, dataSize
, offset
, length
)
1405 H323NonStandardVideoCapability::H323NonStandardVideoCapability(BYTE country
,
1408 const BYTE
* fixedData
,
1412 : H323NonStandardCapabilityInfo(country
, extension
, maufacturer
, fixedData
, dataSize
, offset
, length
)
1417 PObject::Comparison
H323NonStandardVideoCapability::Compare(const PObject
& obj
) const
1419 if (!PIsDescendant(&obj
, H323NonStandardVideoCapability
))
1422 return CompareInfo((const H323NonStandardVideoCapability
&)obj
);
1426 unsigned H323NonStandardVideoCapability::GetSubType() const
1428 return H245_VideoCapability::e_nonStandard
;
1432 BOOL
H323NonStandardVideoCapability::OnSendingPDU(H245_VideoCapability
& pdu
) const
1434 return OnSendingNonStandardPDU(pdu
, H245_VideoCapability::e_nonStandard
);
1438 BOOL
H323NonStandardVideoCapability::OnSendingPDU(H245_VideoMode
& pdu
) const
1440 return OnSendingNonStandardPDU(pdu
, H245_VideoMode::e_nonStandard
);
1444 BOOL
H323NonStandardVideoCapability::OnReceivedPDU(const H245_VideoCapability
& pdu
)
1446 return OnReceivedNonStandardPDU(pdu
, H245_VideoCapability::e_nonStandard
);
1450 BOOL
H323NonStandardVideoCapability::IsNonStandardMatch(const H245_NonStandardParameter
& param
) const
1452 return CompareParam(param
) == EqualTo
;
1455 /////////////////////////////////////////////////////////////////////////////
1457 H323GenericVideoCapability::H323GenericVideoCapability(
1458 const PString
&capabilityId
,
1460 : H323VideoCapability(),
1461 H323GenericCapabilityInfo(capabilityId
, maxBitRate
)
1465 PObject::Comparison
H323GenericVideoCapability::Compare(const PObject
& obj
) const
1467 if (!PIsDescendant(&obj
, H323GenericVideoCapability
))
1470 return CompareInfo((const H323GenericVideoCapability
&)obj
);
1474 unsigned H323GenericVideoCapability::GetSubType() const
1476 return H245_VideoCapability::e_genericVideoCapability
;
1480 BOOL
H323GenericVideoCapability::OnSendingPDU(H245_VideoCapability
& pdu
) const
1482 pdu
.SetTag(H245_VideoCapability::e_genericVideoCapability
);
1483 H245_GenericCapability
&generic
= (H245_GenericCapability
&)pdu
;
1484 return OnSendingGenericPDU(generic
);
1488 BOOL
H323GenericVideoCapability::OnReceivedPDU(const H245_VideoCapability
& pdu
)
1490 if( pdu
.GetTag() != H245_VideoCapability::e_genericVideoCapability
)
1492 return OnReceivedGenericPDU((const H245_GenericCapability
&)pdu
);
1495 BOOL
H323GenericVideoCapability::OnSendingPDU(H245_VideoMode
& /*pdu*/) const
1500 #endif // NO_H323_VIDEO
1503 /////////////////////////////////////////////////////////////////////////////
1505 H323DataCapability::H323DataCapability(unsigned rate
)
1511 H323Capability::MainTypes
H323DataCapability::GetMainType() const
1517 unsigned H323DataCapability::GetDefaultSessionID() const
1523 H323Codec
* H323DataCapability::CreateCodec(H323Codec::Direction
) const
1529 BOOL
H323DataCapability::OnSendingPDU(H245_Capability
& cap
) const
1531 switch (capabilityDirection
) {
1533 cap
.SetTag(H245_Capability::e_transmitDataApplicationCapability
);
1536 cap
.SetTag(H245_Capability::e_receiveDataApplicationCapability
);
1538 case e_ReceiveAndTransmit
:
1540 cap
.SetTag(H245_Capability::e_receiveAndTransmitDataApplicationCapability
);
1542 H245_DataApplicationCapability
& app
= cap
;
1543 app
.m_maxBitRate
= maxBitRate
;
1544 return OnSendingPDU(app
);
1548 BOOL
H323DataCapability::OnSendingPDU(H245_DataType
& dataType
) const
1550 dataType
.SetTag(H245_DataType::e_data
);
1551 H245_DataApplicationCapability
& app
= dataType
;
1552 app
.m_maxBitRate
= maxBitRate
;
1553 return OnSendingPDU(app
);
1557 BOOL
H323DataCapability::OnSendingPDU(H245_ModeElement
& mode
) const
1559 mode
.m_type
.SetTag(H245_ModeElementType::e_dataMode
);
1560 H245_DataMode
& type
= mode
.m_type
;
1561 type
.m_bitRate
= maxBitRate
;
1562 return OnSendingPDU(type
);
1566 BOOL
H323DataCapability::OnReceivedPDU(const H245_Capability
& cap
)
1568 H323Capability::OnReceivedPDU(cap
);
1570 if (cap
.GetTag() != H245_Capability::e_receiveDataApplicationCapability
&&
1571 cap
.GetTag() != H245_Capability::e_receiveAndTransmitDataApplicationCapability
)
1574 const H245_DataApplicationCapability
& app
= cap
;
1575 maxBitRate
= app
.m_maxBitRate
;
1576 return OnReceivedPDU(app
);
1580 BOOL
H323DataCapability::OnReceivedPDU(const H245_DataType
& dataType
, BOOL
)
1582 if (dataType
.GetTag() != H245_DataType::e_data
)
1585 const H245_DataApplicationCapability
& app
= dataType
;
1586 maxBitRate
= app
.m_maxBitRate
;
1587 return OnReceivedPDU(app
);
1591 /////////////////////////////////////////////////////////////////////////////
1593 H323NonStandardDataCapability::H323NonStandardDataCapability(unsigned maxBitRate
,
1594 const BYTE
* fixedData
,
1598 : H323DataCapability(maxBitRate
),
1599 H323NonStandardCapabilityInfo(fixedData
, dataSize
, offset
, length
)
1604 H323NonStandardDataCapability::H323NonStandardDataCapability(unsigned maxBitRate
,
1605 const PString
& oid
,
1606 const BYTE
* fixedData
,
1610 : H323DataCapability(maxBitRate
),
1611 H323NonStandardCapabilityInfo(oid
, fixedData
, dataSize
, offset
, length
)
1616 H323NonStandardDataCapability::H323NonStandardDataCapability(unsigned maxBitRate
,
1620 const BYTE
* fixedData
,
1624 : H323DataCapability(maxBitRate
),
1625 H323NonStandardCapabilityInfo(country
, extension
, maufacturer
, fixedData
, dataSize
, offset
, length
)
1630 PObject::Comparison
H323NonStandardDataCapability::Compare(const PObject
& obj
) const
1632 if (!PIsDescendant(&obj
, H323NonStandardDataCapability
))
1635 return CompareInfo((const H323NonStandardDataCapability
&)obj
);
1639 unsigned H323NonStandardDataCapability::GetSubType() const
1641 return H245_DataApplicationCapability_application::e_nonStandard
;
1645 BOOL
H323NonStandardDataCapability::OnSendingPDU(H245_DataApplicationCapability
& pdu
) const
1647 return OnSendingNonStandardPDU(pdu
.m_application
, H245_DataApplicationCapability_application::e_nonStandard
);
1651 BOOL
H323NonStandardDataCapability::OnSendingPDU(H245_DataMode
& pdu
) const
1653 return OnSendingNonStandardPDU(pdu
.m_application
, H245_DataMode_application::e_nonStandard
);
1657 BOOL
H323NonStandardDataCapability::OnReceivedPDU(const H245_DataApplicationCapability
& pdu
)
1659 return OnReceivedNonStandardPDU(pdu
.m_application
, H245_DataApplicationCapability_application::e_nonStandard
);
1663 BOOL
H323NonStandardDataCapability::IsNonStandardMatch(const H245_NonStandardParameter
& param
) const
1665 return CompareParam(param
) == EqualTo
;
1669 /////////////////////////////////////////////////////////////////////////////
1671 #ifndef NO_H323_AUDIO_CODECS
1673 H323_G711Capability::H323_G711Capability(Mode m
, Speed s
)
1674 : H323AudioCapability(240, 30) // 240ms max, 30ms desired
1681 PObject
* H323_G711Capability::Clone() const
1683 return new H323_G711Capability(*this);
1687 unsigned H323_G711Capability::GetSubType() const
1689 static const unsigned G711SubType
[2][2] = {
1690 { H245_AudioCapability::e_g711Alaw64k
, H245_AudioCapability::e_g711Alaw56k
},
1691 { H245_AudioCapability::e_g711Ulaw64k
, H245_AudioCapability::e_g711Ulaw56k
}
1693 return G711SubType
[mode
][speed
];
1697 PString
H323_G711Capability::GetFormatName() const
1699 static const char * const G711Name
[2][2] = {
1700 { OPAL_G711_ALAW_64K
, OPAL_G711_ALAW_56K
},
1701 { OPAL_G711_ULAW_64K
, OPAL_G711_ULAW_56K
},
1703 return G711Name
[mode
][speed
];
1707 H323Codec
* H323_G711Capability::CreateCodec(H323Codec::Direction direction
) const
1709 unsigned packetSize
= 8*(direction
== H323Codec::Encoder
? txFramesInPacket
: rxFramesInPacket
);
1712 return new H323_muLawCodec(direction
, speed
, packetSize
);
1714 return new H323_ALawCodec(direction
, speed
, packetSize
);
1717 #endif // H323AudioCodec
1720 /////////////////////////////////////////////////////////////////////////////
1722 char OpalUserInputRFC2833
[] = "UserInput/RFC2833";
1724 const char * const H323_UserInputCapability::SubTypeNames
[NumSubTypes
] = {
1725 "UserInput/basicString",
1726 "UserInput/iA5String",
1727 "UserInput/generalString",
1729 "UserInput/hookflash",
1730 OpalUserInputRFC2833
// "UserInput/RFC2833"
1733 OPAL_MEDIA_FORMAT_DECLARE(OpalUserInputRFC2833Format
,
1734 OpalUserInputRFC2833
,
1735 OpalMediaFormat::DefaultAudioSessionID
,
1736 (RTP_DataFrame::PayloadTypes
)101, // Choose this for Cisco IOS compatibility
1737 TRUE
, // Needs jitter
1740 8*150, // 150 millisecond
1741 OpalMediaFormat::AudioTimeUnits
,
1744 H323_UserInputCapability::H323_UserInputCapability(SubTypes _subType
)
1747 OpalMediaFormat
* fmt
= OpalMediaFormatFactory::CreateInstance(OpalUserInputRFC2833
);
1749 rtpPayloadType
= fmt
->GetPayloadType();
1753 PObject
* H323_UserInputCapability::Clone() const
1755 return new H323_UserInputCapability(*this);
1759 H323Capability::MainTypes
H323_UserInputCapability::GetMainType() const
1765 #define SignalToneRFC2833_SubType 10000
1767 static unsigned UserInputCapabilitySubTypeCodes
[] = {
1768 H245_UserInputCapability::e_basicString
,
1769 H245_UserInputCapability::e_iA5String
,
1770 H245_UserInputCapability::e_generalString
,
1771 H245_UserInputCapability::e_dtmf
,
1772 H245_UserInputCapability::e_hookflash
,
1773 SignalToneRFC2833_SubType
1776 unsigned H323_UserInputCapability::GetSubType() const
1778 return UserInputCapabilitySubTypeCodes
[subType
];
1782 PString
H323_UserInputCapability::GetFormatName() const
1784 return SubTypeNames
[subType
];
1788 H323Channel
* H323_UserInputCapability::CreateChannel(H323Connection
&,
1789 H323Channel::Directions
,
1791 const H245_H2250LogicalChannelParameters
*) const
1793 PTRACE(1, "Codec\tCannot create UserInputCapability channel");
1798 H323Codec
* H323_UserInputCapability::CreateCodec(H323Codec::Direction
) const
1800 PTRACE(1, "Codec\tCannot create UserInputCapability codec");
1805 BOOL
H323_UserInputCapability::OnSendingPDU(H245_Capability
& pdu
) const
1807 if (subType
== SignalToneRFC2833
) {
1808 pdu
.SetTag(H245_Capability::e_receiveRTPAudioTelephonyEventCapability
);
1809 H245_AudioTelephonyEventCapability
& atec
= pdu
;
1810 atec
.m_dynamicRTPPayloadType
= rtpPayloadType
;
1811 atec
.m_audioTelephoneEvent
= "0-16"; // Support DTMF 0-9,*,#,A-D & hookflash
1814 pdu
.SetTag(H245_Capability::e_receiveUserInputCapability
);
1815 H245_UserInputCapability
& ui
= pdu
;
1816 ui
.SetTag(UserInputCapabilitySubTypeCodes
[subType
]);
1822 BOOL
H323_UserInputCapability::OnSendingPDU(H245_DataType
&) const
1824 PTRACE(1, "Codec\tCannot have UserInputCapability in DataType");
1829 BOOL
H323_UserInputCapability::OnSendingPDU(H245_ModeElement
&) const
1831 PTRACE(1, "Codec\tCannot have UserInputCapability in ModeElement");
1836 BOOL
H323_UserInputCapability::OnReceivedPDU(const H245_Capability
& pdu
)
1838 H323Capability::OnReceivedPDU(pdu
);
1840 if (pdu
.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability
) {
1841 subType
= SignalToneRFC2833
;
1842 const H245_AudioTelephonyEventCapability
& atec
= pdu
;
1843 rtpPayloadType
= (RTP_DataFrame::PayloadTypes
)(int)atec
.m_dynamicRTPPayloadType
;
1844 // Really should verify atec.m_audioTelephoneEvent here
1848 if (pdu
.GetTag() != H245_Capability::e_receiveUserInputCapability
&&
1849 pdu
.GetTag() != H245_Capability::e_receiveAndTransmitUserInputCapability
)
1852 const H245_UserInputCapability
& ui
= pdu
;
1853 return ui
.GetTag() == UserInputCapabilitySubTypeCodes
[subType
];
1857 BOOL
H323_UserInputCapability::OnReceivedPDU(const H245_DataType
&, BOOL
)
1859 PTRACE(1, "Codec\tCannot have UserInputCapability in DataType");
1864 BOOL
H323_UserInputCapability::IsUsable(const H323Connection
& connection
) const
1866 if (connection
.GetControlVersion() >= 7)
1869 if (connection
.GetRemoteApplication().Find("AltiServ-ITG") != P_MAX_INDEX
)
1872 return subType
!= SignalToneRFC2833
;
1876 void H323_UserInputCapability::AddAllCapabilities(H323Capabilities
& capabilities
,
1877 PINDEX descriptorNum
,
1878 PINDEX simultaneous
)
1880 PINDEX num
= capabilities
.SetCapability(descriptorNum
, simultaneous
, new H323_UserInputCapability(HookFlashH245
));
1881 if (descriptorNum
== P_MAX_INDEX
) {
1882 descriptorNum
= num
;
1883 simultaneous
= P_MAX_INDEX
;
1885 else if (simultaneous
== P_MAX_INDEX
)
1886 simultaneous
= num
+1;
1888 num
= capabilities
.SetCapability(descriptorNum
, simultaneous
, new H323_UserInputCapability(BasicString
));
1889 if (simultaneous
== P_MAX_INDEX
)
1892 capabilities
.SetCapability(descriptorNum
, simultaneous
, new H323_UserInputCapability(SignalToneH245
));
1893 capabilities
.SetCapability(descriptorNum
, simultaneous
, new H323_UserInputCapability(SignalToneRFC2833
));
1897 /////////////////////////////////////////////////////////////////////////////
1899 BOOL
H323SimultaneousCapabilities::SetSize(PINDEX newSize
)
1901 PINDEX oldSize
= GetSize();
1903 if (!H323CapabilitiesListArray::SetSize(newSize
))
1906 while (oldSize
< newSize
) {
1907 H323CapabilitiesList
* list
= new H323CapabilitiesList
;
1908 // The lowest level list should not delete codecs on destruction
1909 list
->DisallowDeleteObjects();
1910 SetAt(oldSize
++, list
);
1917 BOOL
H323CapabilitiesSet::SetSize(PINDEX newSize
)
1919 PINDEX oldSize
= GetSize();
1921 if (!H323CapabilitiesSetArray::SetSize(newSize
))
1924 while (oldSize
< newSize
)
1925 SetAt(oldSize
++, new H323SimultaneousCapabilities
);
1931 H323Capabilities::H323Capabilities()
1936 H323Capabilities::H323Capabilities(const H323Connection
& connection
,
1937 const H245_TerminalCapabilitySet
& pdu
)
1939 H323Capabilities allCapabilities
;
1940 const H323Capabilities
& localCapabilities
= connection
.GetLocalCapabilities();
1941 for (PINDEX c
= 0; c
< localCapabilities
.GetSize(); c
++)
1942 allCapabilities
.Add(allCapabilities
.Copy(localCapabilities
[c
]));
1943 allCapabilities
.AddAllCapabilities(0, 0, "*");
1944 H323_UserInputCapability::AddAllCapabilities(allCapabilities
, P_MAX_INDEX
, P_MAX_INDEX
);
1946 // Decode out of the PDU, the list of known codecs.
1947 if (pdu
.HasOptionalField(H245_TerminalCapabilitySet::e_capabilityTable
)) {
1948 for (PINDEX i
= 0; i
< pdu
.m_capabilityTable
.GetSize(); i
++) {
1949 if (pdu
.m_capabilityTable
[i
].HasOptionalField(H245_CapabilityTableEntry::e_capability
)) {
1950 H323Capability
* capability
= allCapabilities
.FindCapability(pdu
.m_capabilityTable
[i
].m_capability
);
1951 if (capability
!= NULL
) {
1952 H323Capability
* copy
= (H323Capability
*)capability
->Clone();
1953 copy
->SetCapabilityNumber(pdu
.m_capabilityTable
[i
].m_capabilityTableEntryNumber
);
1954 if (copy
->OnReceivedPDU(pdu
.m_capabilityTable
[i
].m_capability
))
1963 PINDEX outerSize
= pdu
.m_capabilityDescriptors
.GetSize();
1964 set
.SetSize(outerSize
);
1965 for (PINDEX outer
= 0; outer
< outerSize
; outer
++) {
1966 H245_CapabilityDescriptor
& desc
= pdu
.m_capabilityDescriptors
[outer
];
1967 if (desc
.HasOptionalField(H245_CapabilityDescriptor::e_simultaneousCapabilities
)) {
1968 PINDEX middleSize
= desc
.m_simultaneousCapabilities
.GetSize();
1969 set
[outer
].SetSize(middleSize
);
1970 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
1971 H245_AlternativeCapabilitySet
& alt
= desc
.m_simultaneousCapabilities
[middle
];
1972 for (PINDEX inner
= 0; inner
< alt
.GetSize(); inner
++) {
1973 for (PINDEX cap
= 0; cap
< table
.GetSize(); cap
++) {
1974 if (table
[cap
].GetCapabilityNumber() == alt
[inner
]) {
1975 set
[outer
][middle
].Append(&table
[cap
]);
1986 H323Capabilities::H323Capabilities(const H323Capabilities
& original
)
1988 operator=(original
);
1992 H323Capabilities
& H323Capabilities::operator=(const H323Capabilities
& original
)
1996 for (PINDEX i
= 0; i
< original
.GetSize(); i
++)
1999 PINDEX outerSize
= original
.set
.GetSize();
2000 set
.SetSize(outerSize
);
2001 for (PINDEX outer
= 0; outer
< outerSize
; outer
++) {
2002 PINDEX middleSize
= original
.set
[outer
].GetSize();
2003 set
[outer
].SetSize(middleSize
);
2004 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
2005 PINDEX innerSize
= original
.set
[outer
][middle
].GetSize();
2006 for (PINDEX inner
= 0; inner
< innerSize
; inner
++)
2007 set
[outer
][middle
].Append(FindCapability(original
.set
[outer
][middle
][inner
].GetCapabilityNumber()));
2015 void H323Capabilities::PrintOn(ostream
& strm
) const
2017 int indent
= strm
.precision()-1;
2018 strm
<< setw(indent
) << " " << "Table:\n";
2019 for (PINDEX i
= 0; i
< table
.GetSize(); i
++)
2020 strm
<< setw(indent
+2) << " " << table
[i
] << '\n';
2022 strm
<< setw(indent
) << " " << "Set:\n";
2023 for (PINDEX outer
= 0; outer
< set
.GetSize(); outer
++) {
2024 strm
<< setw(indent
+2) << " " << outer
<< ":\n";
2025 for (PINDEX middle
= 0; middle
< set
[outer
].GetSize(); middle
++) {
2026 strm
<< setw(indent
+4) << " " << middle
<< ":\n";
2027 for (PINDEX inner
= 0; inner
< set
[outer
][middle
].GetSize(); inner
++)
2028 strm
<< setw(indent
+6) << " " << set
[outer
][middle
][inner
] << '\n';
2034 PINDEX
H323Capabilities::SetCapability(PINDEX descriptorNum
,
2035 PINDEX simultaneousNum
,
2036 H323Capability
* capability
)
2038 if (capability
== NULL
)
2041 // Make sure capability has been added to table.
2044 BOOL newDescriptor
= descriptorNum
== P_MAX_INDEX
;
2046 descriptorNum
= set
.GetSize();
2048 // Make sure the outer array is big enough
2049 set
.SetMinSize(descriptorNum
+1);
2051 if (simultaneousNum
== P_MAX_INDEX
)
2052 simultaneousNum
= set
[descriptorNum
].GetSize();
2054 // Make sure the middle array is big enough
2055 set
[descriptorNum
].SetMinSize(simultaneousNum
+1);
2057 // Now we can put the new entry in.
2058 set
[descriptorNum
][simultaneousNum
].Append(capability
);
2059 return newDescriptor
? descriptorNum
: simultaneousNum
;
2063 static BOOL
MatchWildcard(const PCaselessString
& str
, const PStringArray
& wildcard
)
2066 for (PINDEX i
= 0; i
< wildcard
.GetSize(); i
++) {
2067 if (wildcard
[i
].IsEmpty())
2068 last
= str
.GetLength();
2070 PINDEX next
= str
.Find(wildcard
[i
], last
);
2071 if (next
== P_MAX_INDEX
)
2073 last
= next
+ wildcard
[i
].GetLength();
2081 PINDEX
H323Capabilities::AddAllCapabilities(PINDEX descriptorNum
,
2082 PINDEX simultaneous
,
2083 const PString
& name
)
2085 PINDEX reply
= descriptorNum
== P_MAX_INDEX
? P_MAX_INDEX
: simultaneous
;
2087 PStringArray wildcard
= name
.Tokenise('*', FALSE
);
2089 OpalMediaFormatFactory::KeyList_T stdFormats
= OpalMediaFormatFactory::GetKeyList();
2090 H323CapabilityFactory::KeyList_T stdCaps
= H323CapabilityFactory::GetKeyList();
2091 H323CapabilityFactory::KeyList_T::const_iterator r
;
2093 for (r
= stdCaps
.begin(); r
!= stdCaps
.end(); ++r
) {
2094 PString
capName(*r
);
2095 if (MatchWildcard(capName
, wildcard
) && (FindCapability(capName
) == NULL
)) {
2096 BOOL found
= std::find(stdFormats
.begin(), stdFormats
.end(), std::string((const char *)capName
)) != stdFormats
.end();
2097 if (!found
&& (capName
.Right(4) == "{sw}") && capName
.GetLength() > 4) {
2098 PString
s(capName
.Left(capName
.GetLength()-4));
2099 found
= std::find(stdFormats
.begin(), stdFormats
.end(), std::string((const char *)s
)) != stdFormats
.end();
2102 // add the capability
2103 H323Capability
* capability
= H323Capability::Create(capName
);
2104 PINDEX num
= SetCapability(descriptorNum
, simultaneous
, capability
);
2105 if (descriptorNum
== P_MAX_INDEX
) {
2107 descriptorNum
= num
;
2108 simultaneous
= P_MAX_INDEX
;
2110 else if (simultaneous
== P_MAX_INDEX
) {
2111 if (reply
== P_MAX_INDEX
)
2123 static unsigned MergeCapabilityNumber(const H323CapabilitiesList
& table
,
2124 unsigned newCapabilityNumber
)
2126 // Assign a unique number to the codec, check if the user wants a specific
2127 // value and start with that.
2128 if (newCapabilityNumber
== 0)
2129 newCapabilityNumber
= 1;
2132 while (i
< table
.GetSize()) {
2133 if (table
[i
].GetCapabilityNumber() != newCapabilityNumber
)
2136 // If it already in use, increment it
2137 newCapabilityNumber
++;
2142 return newCapabilityNumber
;
2146 void H323Capabilities::Add(H323Capability
* capability
)
2148 if (capability
== NULL
)
2151 // See if already added, confuses things if you add the same instance twice
2152 if (table
.GetObjectsIndex(capability
) != P_MAX_INDEX
)
2155 capability
->SetCapabilityNumber(MergeCapabilityNumber(table
, 1));
2156 table
.Append(capability
);
2158 PTRACE(3, "H323\tAdded capability: " << *capability
);
2162 H323Capability
* H323Capabilities::Copy(const H323Capability
& capability
)
2164 H323Capability
* newCapability
= (H323Capability
*)capability
.Clone();
2165 newCapability
->SetCapabilityNumber(MergeCapabilityNumber(table
, capability
.GetCapabilityNumber()));
2166 table
.Append(newCapability
);
2168 PTRACE(3, "H323\tAdded capability: " << *newCapability
);
2169 return newCapability
;
2173 void H323Capabilities::Remove(H323Capability
* capability
)
2175 if (capability
== NULL
)
2178 PTRACE(3, "H323\tRemoving capability: " << *capability
);
2180 unsigned capabilityNumber
= capability
->GetCapabilityNumber();
2182 for (PINDEX outer
= 0; outer
< set
.GetSize(); outer
++) {
2183 for (PINDEX middle
= 0; middle
< set
[outer
].GetSize(); middle
++) {
2184 for (PINDEX inner
= 0; inner
< set
[outer
][middle
].GetSize(); inner
++) {
2185 if (set
[outer
][middle
][inner
].GetCapabilityNumber() == capabilityNumber
) {
2186 set
[outer
][middle
].RemoveAt(inner
);
2190 if (set
[outer
][middle
].GetSize() == 0)
2191 set
[outer
].RemoveAt(middle
);
2193 if (set
[outer
].GetSize() == 0)
2194 set
.RemoveAt(outer
);
2197 table
.Remove(capability
);
2201 void H323Capabilities::Remove(const PString
& codecName
)
2203 if (codecName
.IsEmpty())
2206 H323Capability
* cap
= FindCapability(codecName
);
2207 while (cap
!= NULL
) {
2209 cap
= FindCapability(codecName
);
2214 void H323Capabilities::Remove(const PStringArray
& codecNames
)
2216 for (PINDEX i
= 0; i
< codecNames
.GetSize(); i
++)
2217 Remove(codecNames
[i
]);
2221 void H323Capabilities::RemoveAll()
2228 H323Capability
* H323Capabilities::FindCapability(unsigned capabilityNumber
) const
2230 PTRACE(4, "H323\tFindCapability: " << capabilityNumber
);
2232 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2233 if (table
[i
].GetCapabilityNumber() == capabilityNumber
) {
2234 PTRACE(3, "H323\tFound capability: " << table
[i
]);
2243 H323Capability
* H323Capabilities::FindCapability(const PString
& formatName
,
2244 H323Capability::CapabilityDirection direction
) const
2246 PTRACE(4, "H323\tFindCapability: \"" << formatName
<< '"');
2248 PStringArray wildcard
= formatName
.Tokenise('*', FALSE
);
2250 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2251 PCaselessString str
= table
[i
].GetFormatName();
2252 if (MatchWildcard(str
, wildcard
) &&
2253 (direction
== H323Capability::e_Unknown
||
2254 table
[i
].GetCapabilityDirection() == direction
)) {
2255 PTRACE(3, "H323\tFound capability: " << table
[i
]);
2264 H323Capability
* H323Capabilities::FindCapability(
2265 H323Capability::CapabilityDirection direction
) const
2267 PTRACE(4, "H323\tFindCapability: \"" << direction
<< '"');
2269 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2270 if (table
[i
].GetCapabilityDirection() == direction
) {
2271 PTRACE(3, "H323\tFound capability: " << table
[i
]);
2280 H323Capability
* H323Capabilities::FindCapability(const H323Capability
& capability
) const
2282 PTRACE(4, "H323\tFindCapability: " << capability
);
2284 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2285 if (table
[i
] == capability
) {
2286 PTRACE(3, "H323\tFound capability: " << table
[i
]);
2295 H323Capability
* H323Capabilities::FindCapability(const H245_Capability
& cap
) const
2297 PTRACE(4, "H323\tFindCapability: " << cap
.GetTagName());
2299 switch (cap
.GetTag()) {
2300 case H245_Capability::e_receiveAudioCapability
:
2301 case H245_Capability::e_transmitAudioCapability
:
2302 case H245_Capability::e_receiveAndTransmitAudioCapability
:
2304 const H245_AudioCapability
& audio
= cap
;
2305 return FindCapability(H323Capability::e_Audio
, audio
, NULL
);
2308 case H245_Capability::e_receiveVideoCapability
:
2309 case H245_Capability::e_transmitVideoCapability
:
2310 case H245_Capability::e_receiveAndTransmitVideoCapability
:
2312 const H245_VideoCapability
& video
= cap
;
2313 return FindCapability(H323Capability::e_Video
, video
, NULL
);
2316 case H245_Capability::e_receiveDataApplicationCapability
:
2317 case H245_Capability::e_transmitDataApplicationCapability
:
2318 case H245_Capability::e_receiveAndTransmitDataApplicationCapability
:
2320 const H245_DataApplicationCapability
& data
= cap
;
2321 return FindCapability(H323Capability::e_Data
, data
.m_application
, NULL
);
2324 case H245_Capability::e_receiveUserInputCapability
:
2325 case H245_Capability::e_transmitUserInputCapability
:
2326 case H245_Capability::e_receiveAndTransmitUserInputCapability
:
2328 const H245_UserInputCapability
& ui
= cap
;
2329 return FindCapability(H323Capability::e_UserInput
, ui
, NULL
);
2332 case H245_Capability::e_receiveRTPAudioTelephonyEventCapability
:
2333 return FindCapability(H323Capability::e_UserInput
, SignalToneRFC2833_SubType
);
2343 H323Capability
* H323Capabilities::FindCapability(const H245_DataType
& dataType
) const
2345 PTRACE(4, "H323\tFindCapability: " << dataType
.GetTagName());
2347 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2348 H323Capability
& capability
= table
[i
];
2350 switch (dataType
.GetTag()) {
2351 case H245_DataType::e_audioData
:
2353 const H245_AudioCapability
& audio
= dataType
;
2355 checkExact
= capability
.GetMainType() == H323Capability::e_Audio
&&
2356 capability
.GetSubType() == audio
.GetTag() &&
2357 (capability
.GetSubType() != H245_AudioCapability::e_nonStandard
||
2358 capability
.IsNonStandardMatch((const H245_NonStandardParameter
&)audio
));
2362 case H245_DataType::e_videoData
:
2364 const H245_VideoCapability
& video
= dataType
;
2365 checkExact
= capability
.GetMainType() == H323Capability::e_Video
&&
2366 capability
.GetSubType() == video
.GetTag() &&
2367 (capability
.GetSubType() != H245_VideoCapability::e_nonStandard
||
2368 capability
.IsNonStandardMatch((const H245_NonStandardParameter
&)video
));
2372 case H245_DataType::e_data
:
2374 const H245_DataApplicationCapability
& data
= dataType
;
2375 checkExact
= capability
.GetMainType() == H323Capability::e_Data
&&
2376 capability
.GetSubType() == data
.m_application
.GetTag() &&
2377 (capability
.GetSubType() != H245_DataApplicationCapability_application::e_nonStandard
||
2378 capability
.IsNonStandardMatch((const H245_NonStandardParameter
&)data
.m_application
));
2387 H323Capability
* compare
= (H323Capability
*)capability
.Clone();
2388 if (compare
->OnReceivedPDU(dataType
, FALSE
) && *compare
== capability
) {
2390 PTRACE(3, "H323\tFound capability: " << capability
);
2401 H323Capability
* H323Capabilities::FindCapability(const H245_ModeElement
& modeElement
) const
2403 PTRACE(4, "H323\tFindCapability: " << modeElement
.m_type
.GetTagName());
2405 switch (modeElement
.m_type
.GetTag()) {
2406 case H245_ModeElementType::e_audioMode
:
2408 const H245_AudioMode
& audio
= modeElement
.m_type
;
2409 static unsigned const AudioSubTypes
[] = {
2410 H245_AudioCapability::e_nonStandard
,
2411 H245_AudioCapability::e_g711Alaw64k
,
2412 H245_AudioCapability::e_g711Alaw56k
,
2413 H245_AudioCapability::e_g711Ulaw64k
,
2414 H245_AudioCapability::e_g711Ulaw56k
,
2415 H245_AudioCapability::e_g722_64k
,
2416 H245_AudioCapability::e_g722_56k
,
2417 H245_AudioCapability::e_g722_48k
,
2418 H245_AudioCapability::e_g728
,
2419 H245_AudioCapability::e_g729
,
2420 H245_AudioCapability::e_g729AnnexA
,
2421 H245_AudioCapability::e_g7231
,
2422 H245_AudioCapability::e_is11172AudioCapability
,
2423 H245_AudioCapability::e_is13818AudioCapability
,
2424 H245_AudioCapability::e_g729wAnnexB
,
2425 H245_AudioCapability::e_g729AnnexAwAnnexB
,
2426 H245_AudioCapability::e_g7231AnnexCCapability
,
2427 H245_AudioCapability::e_gsmFullRate
,
2428 H245_AudioCapability::e_gsmHalfRate
,
2429 H245_AudioCapability::e_gsmEnhancedFullRate
,
2430 H245_AudioCapability::e_genericAudioCapability
,
2431 H245_AudioCapability::e_g729Extensions
2433 return FindCapability(H323Capability::e_Audio
, audio
, AudioSubTypes
);
2436 case H245_ModeElementType::e_videoMode
:
2438 const H245_VideoMode
& video
= modeElement
.m_type
;
2439 static unsigned const VideoSubTypes
[] = {
2440 H245_VideoCapability::e_nonStandard
,
2441 H245_VideoCapability::e_h261VideoCapability
,
2442 H245_VideoCapability::e_h262VideoCapability
,
2443 H245_VideoCapability::e_h263VideoCapability
,
2444 H245_VideoCapability::e_is11172VideoCapability
,
2445 H245_VideoCapability::e_genericVideoCapability
2447 return FindCapability(H323Capability::e_Video
, video
, VideoSubTypes
);
2450 case H245_ModeElementType::e_dataMode
:
2452 const H245_DataMode
& data
= modeElement
.m_type
;
2453 static unsigned const DataSubTypes
[] = {
2454 H245_DataApplicationCapability_application::e_nonStandard
,
2455 H245_DataApplicationCapability_application::e_t120
,
2456 H245_DataApplicationCapability_application::e_dsm_cc
,
2457 H245_DataApplicationCapability_application::e_userData
,
2458 H245_DataApplicationCapability_application::e_t84
,
2459 H245_DataApplicationCapability_application::e_t434
,
2460 H245_DataApplicationCapability_application::e_h224
,
2461 H245_DataApplicationCapability_application::e_nlpid
,
2462 H245_DataApplicationCapability_application::e_dsvdControl
,
2463 H245_DataApplicationCapability_application::e_h222DataPartitioning
,
2464 H245_DataApplicationCapability_application::e_t30fax
,
2465 H245_DataApplicationCapability_application::e_t140
,
2466 H245_DataApplicationCapability_application::e_t38fax
,
2467 H245_DataApplicationCapability_application::e_genericDataCapability
2469 return FindCapability(H323Capability::e_Data
, data
.m_application
, DataSubTypes
);
2480 H323Capability
* H323Capabilities::FindCapability(H323Capability::MainTypes mainType
,
2481 const PASN_Choice
& subTypePDU
,
2482 const unsigned * translationTable
) const
2484 unsigned int subTypeID
= subTypePDU
.GetTag();
2486 BOOL isGenericCapability
;
2488 case H323Capability::e_Audio
:
2489 isGenericCapability
= (subTypeID
== H245_AudioCapability::e_genericAudioCapability
);
2492 case H323Capability::e_Video
:
2493 isGenericCapability
= (subTypeID
== H245_VideoCapability::e_genericVideoCapability
);
2496 case H323Capability::e_Data
:
2497 isGenericCapability
= (subTypeID
== H245_DataApplicationCapability_application::e_genericDataCapability
);
2501 case H323Capability::e_UserInput
:
2502 isGenericCapability
= FALSE
;
2506 if( isGenericCapability
) {
2507 PTRACE(4, "H323\tFindCapability: " << mainType
<< " generic");
2508 const H245_GenericCapability
&genericPDU
= (const H245_GenericCapability
&)subTypePDU
.GetObject();
2510 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2511 H323Capability
& capability
= table
[i
];
2512 if (capability
.GetMainType() == mainType
&&
2513 capability
.GetSubType() == subTypeID
&&
2514 capability
.IsGenericMatch(genericPDU
)) {
2515 PTRACE(3, "H323\tFound capability: " << capability
);
2523 if (subTypePDU
.GetTag() != 0) {
2524 if (translationTable
!= NULL
)
2525 subTypeID
= translationTable
[subTypeID
];
2526 return FindCapability(mainType
, subTypeID
);
2529 PTRACE(4, "H323\tFindCapability: " << mainType
<< " nonStandard");
2531 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2532 H323Capability
& capability
= table
[i
];
2533 if (capability
.GetMainType() == mainType
&&
2534 capability
.GetSubType() == 0 &&
2535 capability
.IsNonStandardMatch((const H245_NonStandardParameter
&)subTypePDU
.GetObject())) {
2536 PTRACE(3, "H323\tFound capability: " << capability
);
2545 H323Capability
* H323Capabilities::FindCapability(H323Capability::MainTypes mainType
,
2546 unsigned subType
) const
2548 PTRACE(4, "H323\tFindCapability: " << mainType
<< " subtype=" << subType
);
2550 for (PINDEX i
= 0; i
< table
.GetSize(); i
++) {
2551 H323Capability
& capability
= table
[i
];
2552 if (capability
.GetMainType() == mainType
&&
2553 (subType
== UINT_MAX
|| capability
.GetSubType() == subType
)) {
2554 PTRACE(3, "H323\tFound capability: " << capability
);
2563 void H323Capabilities::BuildPDU(const H323Connection
& connection
,
2564 H245_TerminalCapabilitySet
& pdu
) const
2566 PINDEX tableSize
= table
.GetSize();
2567 PINDEX setSize
= set
.GetSize();
2568 //PAssert((tableSize > 0) == (setSize > 0), PLogicError);
2569 if (tableSize
== 0 || setSize
== 0)
2572 // Set the table of capabilities
2573 pdu
.IncludeOptionalField(H245_TerminalCapabilitySet::e_capabilityTable
);
2576 for (PINDEX i
= 0; i
< tableSize
; i
++) {
2577 H323Capability
& capability
= table
[i
];
2578 if (capability
.IsUsable(connection
)) {
2579 pdu
.m_capabilityTable
.SetSize(count
+1);
2580 H245_CapabilityTableEntry
& entry
= pdu
.m_capabilityTable
[count
++];
2581 entry
.m_capabilityTableEntryNumber
= capability
.GetCapabilityNumber();
2582 entry
.IncludeOptionalField(H245_CapabilityTableEntry::e_capability
);
2583 capability
.OnSendingPDU(entry
.m_capability
);
2587 // Set the sets of compatible capabilities
2588 pdu
.IncludeOptionalField(H245_TerminalCapabilitySet::e_capabilityDescriptors
);
2590 pdu
.m_capabilityDescriptors
.SetSize(setSize
);
2591 for (PINDEX outer
= 0; outer
< setSize
; outer
++) {
2592 H245_CapabilityDescriptor
& desc
= pdu
.m_capabilityDescriptors
[outer
];
2593 desc
.m_capabilityDescriptorNumber
= (unsigned)(outer
+ 1);
2594 desc
.IncludeOptionalField(H245_CapabilityDescriptor::e_simultaneousCapabilities
);
2595 PINDEX middleSize
= set
[outer
].GetSize();
2596 desc
.m_simultaneousCapabilities
.SetSize(middleSize
);
2597 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
2598 H245_AlternativeCapabilitySet
& alt
= desc
.m_simultaneousCapabilities
[middle
];
2599 PINDEX innerSize
= set
[outer
][middle
].GetSize();
2600 alt
.SetSize(innerSize
);
2602 for (PINDEX inner
= 0; inner
< innerSize
; inner
++) {
2603 H323Capability
& capability
= set
[outer
][middle
][inner
];
2604 if (capability
.IsUsable(connection
)) {
2605 alt
.SetSize(count
+1);
2606 alt
[count
++] = capability
.GetCapabilityNumber();
2614 BOOL
H323Capabilities::Merge(const H323Capabilities
& newCaps
)
2616 PTRACE_IF(4, !table
.IsEmpty(), "H245\tCapability merge of:\n" << newCaps
2617 << "\nInto:\n" << *this);
2619 // Add any new capabilities not already in set.
2621 for (i
= 0; i
< newCaps
.GetSize(); i
++) {
2622 if (FindCapability(newCaps
[i
]) == NULL
)
2626 // This should merge instead of just adding to it.
2627 PINDEX outerSize
= newCaps
.set
.GetSize();
2628 PINDEX outerBase
= set
.GetSize();
2629 set
.SetSize(outerBase
+outerSize
);
2630 for (PINDEX outer
= 0; outer
< outerSize
; outer
++) {
2631 PINDEX middleSize
= newCaps
.set
[outer
].GetSize();
2632 set
[outerBase
+outer
].SetSize(middleSize
);
2633 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
2634 PINDEX innerSize
= newCaps
.set
[outer
][middle
].GetSize();
2635 for (PINDEX inner
= 0; inner
< innerSize
; inner
++) {
2636 H323Capability
* cap
= FindCapability(newCaps
.set
[outer
][middle
][inner
].GetCapabilityNumber());
2638 set
[outerBase
+outer
][middle
].Append(cap
);
2643 PTRACE_IF(4, !table
.IsEmpty(), "H245\tCapability merge result:\n" << *this);
2644 PTRACE(3, "H245\tReceived capability set, is "
2645 << (table
.IsEmpty() ? "rejected" : "accepted"));
2646 return !table
.IsEmpty();
2650 void H323Capabilities::Reorder(const PStringArray
& preferenceOrder
)
2652 if (preferenceOrder
.IsEmpty())
2655 table
.DisallowDeleteObjects();
2657 PINDEX preference
= 0;
2660 for (preference
= 0; preference
< preferenceOrder
.GetSize(); preference
++) {
2661 PStringArray wildcard
= preferenceOrder
[preference
].Tokenise('*', FALSE
);
2662 for (PINDEX idx
= base
; idx
< table
.GetSize(); idx
++) {
2663 PCaselessString str
= table
[idx
].GetFormatName();
2664 if (MatchWildcard(str
, wildcard
)) {
2666 table
.InsertAt(base
, table
.RemoveAt(idx
));
2672 for (PINDEX outer
= 0; outer
< set
.GetSize(); outer
++) {
2673 for (PINDEX middle
= 0; middle
< set
[outer
].GetSize(); middle
++) {
2674 H323CapabilitiesList
& list
= set
[outer
][middle
];
2675 for (PINDEX idx
= 0; idx
< table
.GetSize(); idx
++) {
2676 for (PINDEX inner
= 0; inner
< list
.GetSize(); inner
++) {
2677 if (&table
[idx
] == &list
[inner
]) {
2678 list
.Append(list
.RemoveAt(inner
));
2686 table
.AllowDeleteObjects();
2690 BOOL
H323Capabilities::IsAllowed(const H323Capability
& capability
)
2692 return IsAllowed(capability
.GetCapabilityNumber());
2696 BOOL
H323Capabilities::IsAllowed(const unsigned a_capno
)
2698 // Check that capno is actually in the set
2699 PINDEX outerSize
= set
.GetSize();
2700 for (PINDEX outer
= 0; outer
< outerSize
; outer
++) {
2701 PINDEX middleSize
= set
[outer
].GetSize();
2702 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
2703 PINDEX innerSize
= set
[outer
][middle
].GetSize();
2704 for (PINDEX inner
= 0; inner
< innerSize
; inner
++) {
2705 if (a_capno
== set
[outer
][middle
][inner
].GetCapabilityNumber()) {
2715 BOOL
H323Capabilities::IsAllowed(const H323Capability
& capability1
,
2716 const H323Capability
& capability2
)
2718 return IsAllowed(capability1
.GetCapabilityNumber(),
2719 capability2
.GetCapabilityNumber());
2723 BOOL
H323Capabilities::IsAllowed(const unsigned a_capno1
, const unsigned a_capno2
)
2725 if (a_capno1
== a_capno2
) {
2726 PTRACE(1, "H323\tH323Capabilities::IsAllowed() capabilities are the same.");
2730 PINDEX outerSize
= set
.GetSize();
2731 for (PINDEX outer
= 0; outer
< outerSize
; outer
++) {
2732 PINDEX middleSize
= set
[outer
].GetSize();
2733 for (PINDEX middle
= 0; middle
< middleSize
; middle
++) {
2734 PINDEX innerSize
= set
[outer
][middle
].GetSize();
2735 for (PINDEX inner
= 0; inner
< innerSize
; inner
++) {
2736 if (a_capno1
== set
[outer
][middle
][inner
].GetCapabilityNumber()) {
2737 /* Now go searching for the other half... */
2738 for (PINDEX middle2
= 0; middle2
< middleSize
; ++middle2
) {
2739 if (middle
!= middle2
) {
2740 PINDEX innerSize2
= set
[outer
][middle2
].GetSize();
2741 for (PINDEX inner2
= 0; inner2
< innerSize2
; ++inner2
) {
2742 if (a_capno2
== set
[outer
][middle2
][inner2
].GetCapabilityNumber()) {
2756 /////////////////////////////////////////////////////////////////////////////
2758 #ifndef PASN_NOPRINTON
2761 struct msNonStandardCodecDef
{
2767 static msNonStandardCodecDef msNonStandardCodec
[] = {
2768 { "L&H CELP 4.8k", { 0x01, 0x11 } },
2769 { "ADPCM", { 0x02, 0x00 } },
2770 { "L&H CELP 8k", { 0x02, 0x11 } },
2771 { "L&H CELP 12k", { 0x03, 0x11 } },
2772 { "L&H CELP 16k", { 0x04, 0x11 } },
2773 { "IMA-ADPCM", { 0x11, 0x00 } },
2774 { "GSM", { 0x31, 0x00 } },
2778 void H245_AudioCapability::PrintOn(ostream
& strm
) const
2780 strm
<< GetTagName();
2782 // tag 0 is nonstandard
2785 H245_NonStandardParameter
& param
= (H245_NonStandardParameter
&)GetObject();
2786 const PBYTEArray
& data
= param
.m_data
;
2788 switch (param
.m_nonStandardIdentifier
.GetTag()) {
2789 case H245_NonStandardIdentifier::e_h221NonStandard
:
2791 H245_NonStandardIdentifier_h221NonStandard
& h221
= param
.m_nonStandardIdentifier
;
2793 // Microsoft is 181/0/21324
2794 if ((h221
.m_t35CountryCode
== 181) &&
2795 (h221
.m_t35Extension
== 0) &&
2796 (h221
.m_manufacturerCode
== 21324)
2798 PString name
= "Unknown";
2800 if (data
.GetSize() >= 21) {
2801 for (i
= 0; msNonStandardCodec
[i
].name
!= NULL
; i
++) {
2802 if ((data
[20] == msNonStandardCodec
[i
].sig
[0]) &&
2803 (data
[21] == msNonStandardCodec
[i
].sig
[1])) {
2804 name
= msNonStandardCodec
[i
].name
;
2809 strm
<< (PString(" [Microsoft") & name
) << "]";
2812 // Equivalence is 9/0/61
2813 else if ((h221
.m_t35CountryCode
== 9) &&
2814 (h221
.m_t35Extension
== 0) &&
2815 (h221
.m_manufacturerCode
== 61)
2818 if (data
.GetSize() > 0)
2819 name
= PString((const char *)(const BYTE
*)data
, data
.GetSize());
2820 strm
<< " [Equivalence " << name
<< "]";
2824 else if ((h221
.m_t35CountryCode
== 181) &&
2825 (h221
.m_t35Extension
== 0) &&
2826 (h221
.m_manufacturerCode
== 38)
2829 if (data
.GetSize() > 0)
2830 name
= PString((const char *)(const BYTE
*)data
, data
.GetSize());
2831 strm
<< " [Xiph " << name
<< "]";
2834 // Cisco is 181/0/18
2835 else if ((h221
.m_t35CountryCode
== 181) &&
2836 (h221
.m_t35Extension
== 0) &&
2837 (h221
.m_manufacturerCode
== 18)
2840 if (data
.GetSize() > 0)
2841 name
= PString((const char *)(const BYTE
*)data
, data
.GetSize());
2842 strm
<< " [Cisco " << name
<< "]";
2855 strm
<< ' ' << *choice
;
2858 //PASN_Choice::PrintOn(strm);