Utilise new MergeSym feature to no longer overwrite the source .DEF file when buildin...
[openh323.git] / src / h323caps.cxx
blob338fa0d540c43c4120942b6f52acaee20d7d4700
1 /*
2 * h323caps.cxx
4 * H.323 protocol handler
6 * Open H323 Library
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
18 * under the License.
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): ______________________________________.
29 * $Log$
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
66 * Thanks to Dave Parr
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
177 * Fixed GNU warning
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.
187 * Cosmetic changes.
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
298 * under Linux
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.
383 #ifdef __GNUC__
384 #pragma implementation "h323caps.h"
385 #endif
387 #include <ptlib.h>
389 #include "h323caps.h"
390 #include "h323ep.h"
391 #include "h225.h"
392 #include "h245.h"
393 #include "opalplugin.h"
394 #include "mediafmt.h"
396 #include <algorithm>
398 #define DEFINE_G711_CAPABILITY(cls, code, capName) \
399 class cls : public H323_G711Capability { \
400 public: \
401 cls() : H323_G711Capability(code) { } \
402 }; \
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}")
410 #endif
412 #define new PNEW
415 #if PTRACING
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];
431 #endif
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();
451 if (mt < omt)
452 return LessThan;
453 if (mt > omt)
454 return GreaterThan;
456 int st = GetSubType();
457 int ost = other.GetSubType();
458 if (st < ost)
459 return LessThan;
460 if (st > ost)
461 return GreaterThan;
463 return EqualTo;
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);
478 if (cap == NULL)
479 return NULL;
481 return (H323Capability *)cap->Clone();
485 unsigned H323Capability::GetDefaultSessionID() const
487 return 0;
491 void H323Capability::SetTxFramesInPacket(unsigned /*frames*/)
496 unsigned H323Capability::GetTxFramesInPacket() const
498 return 1;
502 unsigned H323Capability::GetRxFramesInPacket() const
504 return 1;
508 BOOL H323Capability::IsNonStandardMatch(const H245_NonStandardParameter &) const
510 return FALSE;
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;
523 break;
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;
531 break;
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;
538 break;
540 case H245_Capability::e_conferenceCapability:
541 case H245_Capability::e_h235SecurityCapability:
542 case H245_Capability::e_maxPendingReplacementFor:
543 capabilityDirection = e_NoDirection;
546 return TRUE;
550 BOOL H323Capability::IsUsable(const H323Connection &) const
552 return TRUE;
556 /////////////////////////////////////////////////////////////////////////////
558 H323RealTimeCapability::H323RealTimeCapability()
560 rtpqos = NULL;
563 H323RealTimeCapability::H323RealTimeCapability(const H323RealTimeCapability & rtc)
564 : H323Capability(rtc)
566 #if P_HAS_QOS
567 if (rtc.rtpqos != NULL)
568 rtpqos = new RTP_QOS(*rtc.rtpqos);
569 else
570 #endif
571 rtpqos = NULL;
574 H323RealTimeCapability::~H323RealTimeCapability()
576 #if P_HAS_QOS
577 delete rtpqos;
578 #endif
581 void H323RealTimeCapability::AttachQoS(RTP_QOS * _rtpqos)
583 #if P_HAS_QOS
584 delete rtpqos;
585 #endif
587 rtpqos = _rtpqos;
590 H323Channel * H323RealTimeCapability::CreateChannel(H323Connection & connection,
591 H323Channel::Directions dir,
592 unsigned sessionID,
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,
603 PINDEX dataSize)
605 t35CountryCode(0),
606 t35Extension(0),
607 manufacturerCode(0),
608 nonStandardData(dataPtr, dataSize == 0 && dataPtr != NULL
609 ? strlen((const char *)dataPtr) : dataSize),
610 comparisonOffset(0),
611 comparisonLength(0),
612 compareFunc(_compareFunc)
616 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(const BYTE * dataPtr,
617 PINDEX dataSize,
618 PINDEX _offset,
619 PINDEX _len)
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),
627 compareFunc(NULL)
632 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(const PString & _oid,
633 const BYTE * dataPtr,
634 PINDEX dataSize,
635 PINDEX _offset,
636 PINDEX _len)
637 : oid(_oid),
638 nonStandardData(dataPtr, dataSize == 0 && dataPtr != NULL
639 ? strlen((const char *)dataPtr) : dataSize),
640 comparisonOffset(_offset),
641 comparisonLength(_len),
642 compareFunc(NULL)
647 H323NonStandardCapabilityInfo::H323NonStandardCapabilityInfo(BYTE country,
648 BYTE extension,
649 WORD maufacturer,
650 const BYTE * dataPtr,
651 PINDEX dataSize,
652 PINDEX _offset,
653 PINDEX _len)
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),
661 compareFunc(NULL)
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;
681 return TRUE;
685 BOOL H323NonStandardCapabilityInfo::OnSendingNonStandardPDU(PASN_Choice & pdu,
686 unsigned nonStandardTag) const
688 PBYTEArray data;
689 if (!OnSendingPDU(data))
690 return FALSE;
692 pdu.SetTag(nonStandardTag);
693 H245_NonStandardParameter & param = (H245_NonStandardParameter &)pdu.GetObject();
695 if (!oid) {
696 param.m_nonStandardIdentifier.SetTag(H245_NonStandardIdentifier::e_object);
697 PASN_ObjectId & nonStandardIdentifier = param.m_nonStandardIdentifier;
698 nonStandardIdentifier = oid;
700 else {
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;
708 param.m_data = data;
709 return data.GetSize() > 0;
713 BOOL H323NonStandardCapabilityInfo::OnReceivedNonStandardPDU(const PASN_Choice & pdu,
714 unsigned nonStandardTag)
716 if (pdu.GetTag() != nonStandardTag)
717 return FALSE;
719 const H245_NonStandardParameter & param = (const H245_NonStandardParameter &)pdu.GetObject();
721 if (CompareParam(param) != PObject::EqualTo)
722 return FALSE;
724 return OnReceivedPDU(param.m_data);
728 PObject::Comparison H323NonStandardCapabilityInfo::CompareParam(const H245_NonStandardParameter & param) const
730 if (compareFunc != NULL) {
732 PluginCodec_H323NonStandardCodecData compareData;
734 PString objectId;
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;
739 } else {
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);
752 if (!oid) {
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)
759 return cmp;
761 else {
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;
793 PString objectId;
794 if (!other.oid.IsEmpty())
795 compareData.objectId = other.oid;
796 else {
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);
808 if (!oid) {
809 if (other.oid.IsEmpty())
810 return PObject::LessThan;
812 PObject::Comparison cmp = oid.Compare(other.oid);
813 if (cmp != PObject::EqualTo)
814 return cmp;
816 else {
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,
853 len);
854 if (cmp < 0)
855 return PObject::LessThan;
856 if (cmp > 0)
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
875 return e_Audio;
879 unsigned H323AudioCapability::GetDefaultSessionID() const
881 return RTP_Session::DefaultAudioSessionID;
885 void H323AudioCapability::SetTxFramesInPacket(unsigned frames)
887 PAssert(frames > 0, PInvalidParameter);
888 if (frames > 256)
889 txFramesInPacket = 256;
890 else
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) {
910 case e_Transmit:
911 cap.SetTag(H245_Capability::e_transmitAudioCapability);
912 break;
913 case e_ReceiveAndTransmit:
914 cap.SetTag(H245_Capability::e_receiveAndTransmitAudioCapability);
915 break;
916 case e_Receive :
917 default:
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;
945 value = packetSize;
946 return TRUE;
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))
979 return FALSE;
981 pdu.SetTag(AudioTable[subType]);
982 return TRUE;
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)
992 return FALSE;
994 unsigned packetSize = txFramesInPacket;
995 if (!OnReceivedPDU((const H245_AudioCapability &)cap, packetSize))
996 return FALSE;
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;
1004 else {
1005 PTRACE(4, "H323\tCapability tx frames left at "
1006 << txFramesInPacket << " as remote allows " << packetSize);
1009 return TRUE;
1013 BOOL H323AudioCapability::OnReceivedPDU(const H245_DataType & dataType, BOOL receiver)
1015 if (dataType.GetTag() != H245_DataType::e_audioData)
1016 return FALSE;
1018 unsigned & xFramesInPacket = receiver ? rxFramesInPacket : txFramesInPacket;
1019 unsigned packetSize = xFramesInPacket;
1020 if (!OnReceivedPDU((const H245_AudioCapability &)dataType, packetSize))
1021 return FALSE;
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;
1029 else {
1030 PTRACE(4, "H323\tCapability " << (receiver ? 'r' : 't') << "x frames left at "
1031 << xFramesInPacket << " as remote allows " << packetSize);
1034 return TRUE;
1038 BOOL H323AudioCapability::OnReceivedPDU(const H245_AudioCapability & pdu,
1039 unsigned & packetSize)
1041 if (pdu.GetTag() != GetSubType())
1042 return FALSE;
1044 const PASN_Integer & value = pdu;
1046 // Get the maximum number of frames
1047 packetSize = value;
1048 return TRUE;
1052 /////////////////////////////////////////////////////////////////////////////
1054 H323NonStandardAudioCapability::H323NonStandardAudioCapability(
1055 unsigned max,
1056 unsigned desired,
1057 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
1058 const BYTE * fixedData,
1059 PINDEX dataSize
1061 : H323AudioCapability(max, desired),
1062 H323NonStandardCapabilityInfo(compareFunc, fixedData, dataSize)
1066 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max,
1067 unsigned desired,
1068 const BYTE * fixedData,
1069 PINDEX dataSize,
1070 PINDEX offset,
1071 PINDEX length)
1072 : H323AudioCapability(max, desired),
1073 H323NonStandardCapabilityInfo(fixedData, dataSize, offset, length)
1077 H323NonStandardAudioCapability::H323NonStandardAudioCapability(
1078 unsigned max,
1079 unsigned desired,
1080 H323EndPoint &,
1081 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
1082 const BYTE * fixedData,
1083 PINDEX dataSize)
1084 : H323AudioCapability(max, desired),
1085 H323NonStandardCapabilityInfo(compareFunc, fixedData, dataSize)
1089 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max,
1090 unsigned desired,
1091 H323EndPoint &,
1092 const BYTE * fixedData,
1093 PINDEX dataSize,
1094 PINDEX offset,
1095 PINDEX length)
1096 : H323AudioCapability(max, desired),
1097 H323NonStandardCapabilityInfo(fixedData, dataSize, offset, length)
1101 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max,
1102 unsigned desired,
1103 const PString & oid,
1104 const BYTE * fixedData,
1105 PINDEX dataSize,
1106 PINDEX offset,
1107 PINDEX length)
1108 : H323AudioCapability(max, desired),
1109 H323NonStandardCapabilityInfo(oid, fixedData, dataSize, offset, length)
1114 H323NonStandardAudioCapability::H323NonStandardAudioCapability(unsigned max,
1115 unsigned desired,
1116 BYTE country,
1117 BYTE extension,
1118 WORD maufacturer,
1119 const BYTE * fixedData,
1120 PINDEX dataSize,
1121 PINDEX offset,
1122 PINDEX length)
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))
1132 return LessThan;
1134 return CompareInfo((const H323NonStandardAudioCapability &)obj);
1138 unsigned H323NonStandardAudioCapability::GetSubType() const
1140 return H245_AudioCapability::e_nonStandard;
1144 BOOL H323NonStandardAudioCapability::OnSendingPDU(H245_AudioCapability & pdu,
1145 unsigned) const
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,
1158 unsigned &)
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,
1175 PINDEX maxBitRate)
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()
1193 delete(capId);
1196 BOOL H323GenericCapabilityInfo::AddIntegerGenericParameter(
1197 BOOL collapsing,
1198 int standardId,
1199 int type, // should be one of opalplugin.h:PluginCodec_H323GenericParameterType
1200 long int value )
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;
1212 list.Append(param);
1214 return TRUE;
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]));
1238 return TRUE;
1241 BOOL H323GenericCapabilityInfo::OnReceivedGenericPDU(const H245_GenericCapability & /*pdu*/)
1243 return TRUE;
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(
1262 unsigned max,
1263 unsigned desired,
1264 const PString &standardId,
1265 PINDEX maxBitRate)
1266 : H323AudioCapability(max, desired),
1267 H323GenericCapabilityInfo(standardId, maxBitRate)
1271 PObject::Comparison H323GenericAudioCapability::Compare(const PObject & obj) const
1273 if (!PIsDescendant(&obj, H323GenericAudioCapability))
1274 return LessThan;
1276 return CompareInfo((const H323GenericAudioCapability &)obj);
1280 unsigned H323GenericAudioCapability::GetSubType() const
1282 return H245_AudioCapability::e_genericAudioCapability;
1286 BOOL H323GenericAudioCapability::OnSendingPDU(H245_AudioCapability & pdu,
1287 unsigned) const
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,
1296 unsigned &)
1298 if( pdu.GetTag() != H245_AudioCapability::e_genericAudioCapability)
1299 return FALSE;
1300 return OnReceivedGenericPDU((const H245_GenericCapability &)pdu);
1304 /////////////////////////////////////////////////////////////////////////////
1306 #ifndef NO_H323_VIDEO
1308 H323VideoCapability::H323VideoCapability()
1312 H323Capability::MainTypes H323VideoCapability::GetMainType() const
1314 return e_Video;
1318 BOOL H323VideoCapability::OnSendingPDU(H245_Capability & cap) const
1320 switch (capabilityDirection) {
1321 case e_Transmit:
1322 cap.SetTag(H245_Capability::e_transmitVideoCapability);
1323 break;
1324 case e_ReceiveAndTransmit:
1325 cap.SetTag(H245_Capability::e_receiveAndTransmitVideoCapability);
1326 break;
1327 case e_Receive :
1328 default:
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)
1355 return FALSE;
1357 return OnReceivedPDU((const H245_VideoCapability &)cap);
1361 BOOL H323VideoCapability::OnReceivedPDU(const H245_DataType & dataType, BOOL)
1363 if (dataType.GetTag() != H245_DataType::e_videoData)
1364 return FALSE;
1366 return OnReceivedPDU((const H245_VideoCapability &)dataType);
1370 unsigned H323VideoCapability::GetDefaultSessionID() const
1372 return RTP_Session::DefaultVideoSessionID;
1376 /////////////////////////////////////////////////////////////////////////////
1378 H323NonStandardVideoCapability::H323NonStandardVideoCapability(const BYTE * fixedData,
1379 PINDEX dataSize,
1380 PINDEX offset,
1381 PINDEX length)
1382 : H323NonStandardCapabilityInfo(fixedData, dataSize, offset, length)
1386 H323NonStandardVideoCapability::H323NonStandardVideoCapability(H323EndPoint &,
1387 const BYTE * fixedData,
1388 PINDEX dataSize,
1389 PINDEX offset,
1390 PINDEX length)
1391 : H323NonStandardCapabilityInfo(fixedData, dataSize, offset, length)
1395 H323NonStandardVideoCapability::H323NonStandardVideoCapability(const PString & oid,
1396 const BYTE * fixedData,
1397 PINDEX dataSize,
1398 PINDEX offset,
1399 PINDEX length)
1400 : H323NonStandardCapabilityInfo(oid, fixedData, dataSize, offset, length)
1405 H323NonStandardVideoCapability::H323NonStandardVideoCapability(BYTE country,
1406 BYTE extension,
1407 WORD maufacturer,
1408 const BYTE * fixedData,
1409 PINDEX dataSize,
1410 PINDEX offset,
1411 PINDEX length)
1412 : H323NonStandardCapabilityInfo(country, extension, maufacturer, fixedData, dataSize, offset, length)
1417 PObject::Comparison H323NonStandardVideoCapability::Compare(const PObject & obj) const
1419 if (!PIsDescendant(&obj, H323NonStandardVideoCapability))
1420 return LessThan;
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,
1459 PINDEX maxBitRate)
1460 : H323VideoCapability(),
1461 H323GenericCapabilityInfo(capabilityId, maxBitRate)
1465 PObject::Comparison H323GenericVideoCapability::Compare(const PObject & obj) const
1467 if (!PIsDescendant(&obj, H323GenericVideoCapability))
1468 return LessThan;
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)
1491 return FALSE;
1492 return OnReceivedGenericPDU((const H245_GenericCapability &)pdu);
1495 BOOL H323GenericVideoCapability::OnSendingPDU(H245_VideoMode & /*pdu*/) const
1497 return TRUE;
1500 #endif // NO_H323_VIDEO
1503 /////////////////////////////////////////////////////////////////////////////
1505 H323DataCapability::H323DataCapability(unsigned rate)
1506 : maxBitRate(rate)
1511 H323Capability::MainTypes H323DataCapability::GetMainType() const
1513 return e_Data;
1517 unsigned H323DataCapability::GetDefaultSessionID() const
1519 return 3;
1523 H323Codec * H323DataCapability::CreateCodec(H323Codec::Direction) const
1525 return NULL;
1529 BOOL H323DataCapability::OnSendingPDU(H245_Capability & cap) const
1531 switch (capabilityDirection) {
1532 case e_Transmit:
1533 cap.SetTag(H245_Capability::e_transmitDataApplicationCapability);
1534 break;
1535 case e_Receive :
1536 cap.SetTag(H245_Capability::e_receiveDataApplicationCapability);
1537 break;
1538 case e_ReceiveAndTransmit:
1539 default:
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)
1572 return FALSE;
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)
1583 return FALSE;
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,
1595 PINDEX dataSize,
1596 PINDEX offset,
1597 PINDEX length)
1598 : H323DataCapability(maxBitRate),
1599 H323NonStandardCapabilityInfo(fixedData, dataSize, offset, length)
1604 H323NonStandardDataCapability::H323NonStandardDataCapability(unsigned maxBitRate,
1605 const PString & oid,
1606 const BYTE * fixedData,
1607 PINDEX dataSize,
1608 PINDEX offset,
1609 PINDEX length)
1610 : H323DataCapability(maxBitRate),
1611 H323NonStandardCapabilityInfo(oid, fixedData, dataSize, offset, length)
1616 H323NonStandardDataCapability::H323NonStandardDataCapability(unsigned maxBitRate,
1617 BYTE country,
1618 BYTE extension,
1619 WORD maufacturer,
1620 const BYTE * fixedData,
1621 PINDEX dataSize,
1622 PINDEX offset,
1623 PINDEX length)
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))
1633 return LessThan;
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
1676 mode = m;
1677 speed = s;
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);
1711 if (mode == muLaw)
1712 return new H323_muLawCodec(direction, speed, packetSize);
1713 else
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",
1728 "UserInput/dtmf",
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
1738 100, // bits/sec
1739 4, // bytes/frame
1740 8*150, // 150 millisecond
1741 OpalMediaFormat::AudioTimeUnits,
1744 H323_UserInputCapability::H323_UserInputCapability(SubTypes _subType)
1746 subType = _subType;
1747 OpalMediaFormat * fmt = OpalMediaFormatFactory::CreateInstance(OpalUserInputRFC2833);
1748 if (fmt != NULL)
1749 rtpPayloadType = fmt->GetPayloadType();
1753 PObject * H323_UserInputCapability::Clone() const
1755 return new H323_UserInputCapability(*this);
1759 H323Capability::MainTypes H323_UserInputCapability::GetMainType() const
1761 return e_UserInput;
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,
1790 unsigned,
1791 const H245_H2250LogicalChannelParameters *) const
1793 PTRACE(1, "Codec\tCannot create UserInputCapability channel");
1794 return NULL;
1798 H323Codec * H323_UserInputCapability::CreateCodec(H323Codec::Direction) const
1800 PTRACE(1, "Codec\tCannot create UserInputCapability codec");
1801 return NULL;
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
1813 else {
1814 pdu.SetTag(H245_Capability::e_receiveUserInputCapability);
1815 H245_UserInputCapability & ui = pdu;
1816 ui.SetTag(UserInputCapabilitySubTypeCodes[subType]);
1818 return TRUE;
1822 BOOL H323_UserInputCapability::OnSendingPDU(H245_DataType &) const
1824 PTRACE(1, "Codec\tCannot have UserInputCapability in DataType");
1825 return FALSE;
1829 BOOL H323_UserInputCapability::OnSendingPDU(H245_ModeElement &) const
1831 PTRACE(1, "Codec\tCannot have UserInputCapability in ModeElement");
1832 return FALSE;
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
1845 return TRUE;
1848 if (pdu.GetTag() != H245_Capability::e_receiveUserInputCapability &&
1849 pdu.GetTag() != H245_Capability::e_receiveAndTransmitUserInputCapability)
1850 return FALSE;
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");
1860 return FALSE;
1864 BOOL H323_UserInputCapability::IsUsable(const H323Connection & connection) const
1866 if (connection.GetControlVersion() >= 7)
1867 return TRUE;
1869 if (connection.GetRemoteApplication().Find("AltiServ-ITG") != P_MAX_INDEX)
1870 return FALSE;
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)
1890 simultaneous = num;
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))
1904 return FALSE;
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);
1913 return TRUE;
1917 BOOL H323CapabilitiesSet::SetSize(PINDEX newSize)
1919 PINDEX oldSize = GetSize();
1921 if (!H323CapabilitiesSetArray::SetSize(newSize))
1922 return FALSE;
1924 while (oldSize < newSize)
1925 SetAt(oldSize++, new H323SimultaneousCapabilities);
1927 return TRUE;
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))
1955 table.Append(copy);
1956 else
1957 delete copy;
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]);
1976 break;
1986 H323Capabilities::H323Capabilities(const H323Capabilities & original)
1988 operator=(original);
1992 H323Capabilities & H323Capabilities::operator=(const H323Capabilities & original)
1994 RemoveAll();
1996 for (PINDEX i = 0; i < original.GetSize(); i++)
1997 Copy(original[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()));
2011 return *this;
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)
2039 return P_MAX_INDEX;
2041 // Make sure capability has been added to table.
2042 Add(capability);
2044 BOOL newDescriptor = descriptorNum == P_MAX_INDEX;
2045 if (newDescriptor)
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)
2065 PINDEX last = 0;
2066 for (PINDEX i = 0; i < wildcard.GetSize(); i++) {
2067 if (wildcard[i].IsEmpty())
2068 last = str.GetLength();
2069 else {
2070 PINDEX next = str.Find(wildcard[i], last);
2071 if (next == P_MAX_INDEX)
2072 return FALSE;
2073 last = next + wildcard[i].GetLength();
2077 return TRUE;
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();
2101 if (found) {
2102 // add the capability
2103 H323Capability * capability = H323Capability::Create(capName);
2104 PINDEX num = SetCapability(descriptorNum, simultaneous, capability);
2105 if (descriptorNum == P_MAX_INDEX) {
2106 reply = num;
2107 descriptorNum = num;
2108 simultaneous = P_MAX_INDEX;
2110 else if (simultaneous == P_MAX_INDEX) {
2111 if (reply == P_MAX_INDEX)
2112 reply = num;
2113 simultaneous = num;
2119 return reply;
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;
2131 PINDEX i = 0;
2132 while (i < table.GetSize()) {
2133 if (table[i].GetCapabilityNumber() != newCapabilityNumber)
2134 i++;
2135 else {
2136 // If it already in use, increment it
2137 newCapabilityNumber++;
2138 i = 0;
2142 return newCapabilityNumber;
2146 void H323Capabilities::Add(H323Capability * capability)
2148 if (capability == NULL)
2149 return;
2151 // See if already added, confuses things if you add the same instance twice
2152 if (table.GetObjectsIndex(capability) != P_MAX_INDEX)
2153 return;
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)
2176 return;
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);
2187 break;
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())
2204 return;
2206 H323Capability * cap = FindCapability(codecName);
2207 while (cap != NULL) {
2208 Remove(cap);
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()
2223 table.RemoveAll();
2224 set.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]);
2235 return &table[i];
2239 return NULL;
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]);
2256 return &table[i];
2260 return NULL;
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]);
2272 return &table[i];
2276 return NULL;
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]);
2287 return &table[i];
2291 return NULL;
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);
2335 default :
2336 break;
2339 return NULL;
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];
2349 BOOL checkExact;
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));
2359 break;
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));
2369 break;
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));
2379 break;
2382 default :
2383 checkExact = FALSE;
2386 if (checkExact) {
2387 H323Capability * compare = (H323Capability *)capability.Clone();
2388 if (compare->OnReceivedPDU(dataType, FALSE) && *compare == capability) {
2389 delete compare;
2390 PTRACE(3, "H323\tFound capability: " << capability);
2391 return &capability;
2393 delete compare;
2397 return NULL;
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);
2472 default :
2473 break;
2476 return NULL;
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;
2487 switch (mainType) {
2488 case H323Capability::e_Audio:
2489 isGenericCapability = (subTypeID == H245_AudioCapability::e_genericAudioCapability);
2490 break;
2492 case H323Capability::e_Video:
2493 isGenericCapability = (subTypeID == H245_VideoCapability::e_genericVideoCapability);
2494 break;
2496 case H323Capability::e_Data:
2497 isGenericCapability = (subTypeID == H245_DataApplicationCapability_application::e_genericDataCapability);
2498 break;
2500 default:
2501 case H323Capability::e_UserInput:
2502 isGenericCapability = FALSE;
2503 break;
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);
2516 return &capability;
2519 return NULL;
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);
2537 return &capability;
2541 return NULL;
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);
2555 return &capability;
2559 return NULL;
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)
2570 return;
2572 // Set the table of capabilities
2573 pdu.IncludeOptionalField(H245_TerminalCapabilitySet::e_capabilityTable);
2575 PINDEX count = 0;
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);
2601 count = 0;
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.
2620 PINDEX i;
2621 for (i = 0; i < newCaps.GetSize(); i++) {
2622 if (FindCapability(newCaps[i]) == NULL)
2623 Copy(newCaps[i]);
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());
2637 if (cap != NULL)
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())
2653 return;
2655 table.DisallowDeleteObjects();
2657 PINDEX preference = 0;
2658 PINDEX base = 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)) {
2665 if (idx != base)
2666 table.InsertAt(base, table.RemoveAt(idx));
2667 base++;
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));
2679 break;
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()) {
2706 return TRUE;
2711 return FALSE;
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.");
2727 return TRUE;
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()) {
2743 return TRUE;
2752 return FALSE;
2756 /////////////////////////////////////////////////////////////////////////////
2758 #ifndef PASN_NOPRINTON
2761 struct msNonStandardCodecDef {
2762 char * name;
2763 BYTE sig[2];
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 } },
2775 { NULL, { 0, 0 } }
2778 void H245_AudioCapability::PrintOn(ostream & strm) const
2780 strm << GetTagName();
2782 // tag 0 is nonstandard
2783 if (tag == 0) {
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";
2799 PINDEX i;
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;
2805 break;
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)
2817 PString name;
2818 if (data.GetSize() > 0)
2819 name = PString((const char *)(const BYTE *)data, data.GetSize());
2820 strm << " [Equivalence " << name << "]";
2823 // Xiph is 181/0/38
2824 else if ((h221.m_t35CountryCode == 181) &&
2825 (h221.m_t35Extension == 0) &&
2826 (h221.m_manufacturerCode == 38)
2828 PString name;
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)
2839 PString name;
2840 if (data.GetSize() > 0)
2841 name = PString((const char *)(const BYTE *)data, data.GetSize());
2842 strm << " [Cisco " << name << "]";
2846 break;
2847 default:
2848 break;
2852 if (choice == NULL)
2853 strm << " (NULL)";
2854 else {
2855 strm << ' ' << *choice;
2858 //PASN_Choice::PrintOn(strm);
2860 #endif