Fixed DevStudio 2005 build.
[opal.git] / src / codec / opalpluginmgr.cxx
blob6a66839ce0f4664c870e78cb10516c7c3cd29e99
1 /*
2 * opalplugins.cxx
4 * OPAL codec plugins handler
6 * Open Phone Abstraction Library (OPAL)
7 * Formally known as the Open H323 project.
9 * Copyright (C) 2005-2006 Post Increment
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.0 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18 * the License for the specific language governing rights and limitations
19 * under the License.
21 * The Original Code is Open Phone Abstraction Library.
23 * The Initial Developer of the Original Code is Post Increment
25 * Contributor(s): ______________________________________.
27 * $Log$
28 * Revision 2.52 2007/09/10 03:15:04 rjongbloed
29 * Fixed issues in creating and subsequently using correctly unique
30 * payload types in OpalMediaFormat instances and transcoders.
32 * Revision 2.51 2007/08/22 05:18:09 rjongbloed
33 * Changed size of RTP packet to be slightlysmaller, the true MTU for ethernet.
34 * Also some code clean ups.
36 * Revision 2.50 2007/08/16 00:47:04 rjongbloed
37 * Also bad boy Craig for leaving debugging in the code. :-)
39 * Revision 2.49 2007/08/16 00:22:43 csoutheren
40 * Fixed cut and paste error. Thanks to Matthias Schneider for noticing the
41 * problem, and Robert Jongbloed for providing the fix. Bad boy Craig for making it
43 * Revision 2.48 2007/08/13 06:08:08 csoutheren
44 * Expose more functions
46 * Revision 2.47 2007/08/09 08:21:25 csoutheren
47 * Add missing braces
49 * Revision 2.46 2007/08/08 17:35:16 csoutheren
50 * Final plugin manager changes
52 * Revision 2.45 2007/08/08 11:18:47 csoutheren
53 * Fixed Linux compile errors
55 * Revision 2.44 2007/08/08 08:59:30 csoutheren
56 * More plugin manager changes, as the last approach dead-ended :(
58 * Revision 2.43 2007/08/08 07:13:01 csoutheren
59 * #ifdef out unused code - to be removed later if nobody complains :)
61 * Revision 2.42 2007/08/07 09:04:25 csoutheren
62 * Export more functions
64 * Revision 2.41 2007/08/07 08:25:36 csoutheren
65 * Expose plugin media format classes
67 * Revision 2.40 2007/08/07 00:13:57 csoutheren
68 * Fix compile error on Windows
70 * Revision 2.39 2007/08/06 15:05:43 csoutheren
71 * Fix problem with media format settings not being applied to plugin
72 * video transcoders on startup
74 * Revision 2.38 2007/08/06 07:14:23 csoutheren
75 * Fix logging
76 * Correct matching of H.263 capabilities
78 * Revision 2.37 2007/08/03 08:23:22 csoutheren
79 * Cleanups
81 * Revision 2.36 2007/08/03 08:05:16 csoutheren
82 * Add PrintOn for plugin video caps
84 * Revision 2.35 2007/08/03 07:20:33 csoutheren
85 * Add extra constructor initialisations for plugin capabilities with multiple ancestors
87 * Revision 2.34 2007/08/03 03:41:59 csoutheren
88 * Fixed usage of tolower in codec control parsing
89 * Ensure plugin media options can override existing values
90 * Add extra logging
92 * Revision 2.33 2007/07/24 12:59:44 rjongbloed
93 * Fixed G.723.1 plug in capability matching, should not include Annex A option.
94 * Made sure all integer OpalMediaOptions are unsigned so is compatible with H.245 generic capabilities.
96 * Revision 2.32 2007/07/20 05:45:45 rjongbloed
97 * Fixed incorrect maxBitRate field in Generic Audio Capabilities
99 * Revision 2.31 2007/07/02 18:53:47 csoutheren
100 * Exposed classes
102 * Revision 2.30 2007/06/27 18:19:49 csoutheren
103 * Fix compile when video disabled
105 * Revision 2.29 2007/06/27 12:29:45 rjongbloed
106 * Add new OpalMediaOption for octet strings (simple block of bytes).
108 * Revision 2.28 2007/06/25 04:04:38 rjongbloed
109 * Fixed compile after change to anonymous structure in header (for GCC).
111 * Revision 2.27 2007/06/22 06:29:14 rjongbloed
112 * Fixed GCC warnings.
114 * Revision 2.26 2007/06/22 05:48:09 rjongbloed
115 * Major codec API update:
116 * Automatically map OpalMediaOptions to SIP/SDP FMTP parameters.
117 * Automatically map OpalMediaOptions to H.245 Generic Capability parameters.
118 * Largely removed need to distinguish between SIP and H.323 codecs.
119 * New mechanism for setting OpalMediaOptions from within a plug in.
120 * Fixed setting of output RTP payload types on plug in video codecs.
122 * Revision 2.25 2007/06/16 21:37:01 dsandras
123 * Added H.264 support thanks to Matthias Schneider <ma30002000 yahoo de>.
124 * Thanks a lot !
126 * Baseline Profile:
127 * no B-frames
128 * We make use of the baseline profile (which is the designated profile for interactive vide) ,
129 * that means:
130 * no B-Frames (too much latency in interactive video)
131 * CBR (we want to get the max. quality making use of all the bitrate that is available)
132 * We allow one exeption: configuring a bitrate of > 786 kbit/s
134 * This plugin implements
135 * - Single Time Aggregation Packets A
136 * - Single NAL units
137 * - Fragmentation Units
138 * like described in RFC3984
140 * It requires x264 and ffmpeg.
142 * Revision 2.24 2007/05/12 03:57:34 rjongbloed
143 * Fixed transcoder from plug in not being created correctly due to media format not yet being registered.
145 * Revision 2.23 2007/05/10 05:34:23 csoutheren
146 * Ensure fax transmission works with reasonable size audio blocks
148 * Revision 2.22 2007/04/19 06:34:12 csoutheren
149 * Applied 1703206 - OpalVideoFastUpdatePicture over SIP
150 * Thanks to Josh Mahonin
152 * Revision 2.21 2007/04/10 05:15:54 rjongbloed
153 * Fixed issue with use of static C string variables in DLL environment,
154 * must use functional interface for correct initialisation.
156 * Revision 2.20 2007/04/04 02:12:00 rjongbloed
157 * Reviewed and adjusted PTRACE log levels
158 * Now follows 1=error,2=warn,3=info,4+=debug
160 * Revision 2.19 2007/04/02 05:51:33 rjongbloed
161 * Tidied some trace logs to assure all have a category (bit before a tab character) set.
163 * Revision 2.18 2007/03/29 05:20:17 csoutheren
164 * Implement T.38 and fax
166 * Revision 2.17 2006/12/08 07:33:13 csoutheren
167 * Fix problem with wideband audio plugins and sound channel
169 * Revision 2.16 2006/11/29 06:28:58 csoutheren
170 * Add ability call codec control functions on all transcoders
172 * Revision 2.15 2006/10/17 23:55:07 csoutheren
173 * Changed to match new enum in opalplugin.h
175 * Revision 2.14 2006/10/17 15:36:58 shorne
176 * Missed line removal in last commit
178 * Revision 2.13 2006/10/17 04:10:12 shorne
179 * Corrected h245 generic parameter identifiers
181 * Revision 2.12 2006/10/10 07:18:18 csoutheren
182 * Allow compilation with and without various options
184 * Revision 2.11 2006/10/02 13:30:51 rjongbloed
185 * Added LID plug ins
187 * Revision 2.10 2006/09/28 07:42:17 csoutheren
188 * Merge of useful SRTP implementation
190 * Revision 2.9 2006/09/11 04:48:55 csoutheren
191 * Fixed problem with cloning plugin media formats
193 * Revision 2.8 2006/09/07 09:05:44 csoutheren
194 * Fix case significance in IsValidForProtocol
196 * Revision 2.7 2006/09/06 22:36:11 csoutheren
197 * Fix problem with IsValidForProtocol on video codecs
199 * Revision 2.6 2006/08/22 03:08:42 csoutheren
200 * Fixed compile error on gcc 4.1
202 * Revision 2.5 2006/08/20 03:56:57 csoutheren
203 * Add OpalMediaFormat::IsValidForProtocol to allow plugin codecs to be enabled only for certain protocols
204 * rather than relying on the presence of the IANA rtp encoding name field
206 * Revision 2.4 2006/08/15 23:52:55 csoutheren
207 * Ensure codecs with same name but different clock rate get different payload types
209 * Revision 2.3 2006/08/11 07:52:01 csoutheren
210 * Fix problem with media format factory in VC 2005
211 * Fixing problems with Speex codec
212 * Remove non-portable usages of PFactory code
214 * Revision 2.2 2006/08/10 06:05:32 csoutheren
215 * Fix problem with key type in plugin factory
217 * Revision 2.1 2006/07/24 14:03:39 csoutheren
218 * Merged in audio and video plugins from CVS branch PluginBranch
220 * Revision 1.1.2.15 2006/05/16 07:03:09 csoutheren
221 * Fixed Linux compile system
223 * Revision 1.1.2.14 2006/04/26 08:03:58 csoutheren
224 * H.263 encoding and decoding now working from plugin for both SIP and H.323
226 * Revision 1.1.2.13 2006/04/26 05:05:59 csoutheren
227 * H.263 decoding working via codec plugin
229 * Revision 1.1.2.12 2006/04/25 01:14:54 csoutheren
230 * Added H.263 capabilities
232 * Revision 1.1.2.11 2006/04/24 09:09:13 csoutheren
233 * Added H.263 codec definitions
235 * Revision 1.1.2.10 2006/04/21 05:42:52 csoutheren
236 * Checked in forgotten changes to fix iFrame requests
238 * Revision 1.1.2.9 2006/04/19 07:52:30 csoutheren
239 * Add ability to have SIP-only and H.323-only codecs, and implement for H.261
241 * Revision 1.1.2.8 2006/04/19 04:58:56 csoutheren
242 * Debugging and testing of new video plugins
243 * H.261 working in both CIF and QCIF modes in H.323
245 * Revision 1.1.2.7 2006/04/11 08:40:22 csoutheren
246 * Modified H.261 plugin handling to use new media formats
248 * Revision 1.1.2.6 2006/04/10 08:53:39 csoutheren
249 * Fix problem with audio code parameters
251 * Revision 1.1.2.5 2006/04/06 05:48:08 csoutheren
252 * Fixed last minute edits to allow compilation
254 * Revision 1.1.2.4 2006/04/06 01:21:18 csoutheren
255 * More implementation of video codec plugins
257 * Revision 1.1.2.3 2006/03/23 07:55:18 csoutheren
258 * Audio plugin H.323 capability merging completed.
259 * GSM, LBC, G.711 working. Speex and LPC-10 are not
261 * Revision 1.1.2.2 2006/03/20 05:03:23 csoutheren
262 * Changes to make audio plugins work with SIP
264 * Revision 1.1.2.1 2006/03/16 07:06:00 csoutheren
265 * Initial support for audio plugins
267 * Created from OpenH323 h323pluginmgr.cxx
268 * Revision 1.58 2005/08/05 17:11:03 csoutheren
272 #ifdef __GNUC__
273 #pragma implementation "opalpluginmgr.h"
274 #endif
276 #include <ptlib.h>
278 #include <opal/buildopts.h>
280 #include <opal/transcoders.h>
281 #include <codec/opalpluginmgr.h>
282 #include <codec/opalplugin.h>
283 #include <h323/h323caps.h>
284 #include <asn/h245.h>
286 #if OPAL_VIDEO
287 #include <codec/vidcodec.h>
288 #endif
290 #if OPAL_T38FAX
291 #include <t38/t38proto.h>
292 #endif
294 // G.711 is *always* available
295 #include <codec/g711codec.h>
296 OPAL_REGISTER_G711();
299 #define H323CAP_TAG_PREFIX "h323"
300 static const char GET_CODEC_OPTIONS_CONTROL[] = "get_codec_options";
301 static const char FREE_CODEC_OPTIONS_CONTROL[] = "free_codec_options";
302 static const char GET_OUTPUT_DATA_SIZE_CONTROL[] = "get_output_data_size";
303 static const char SET_CODEC_OPTIONS_CONTROL[] = "set_codec_options";
306 #if OPAL_VIDEO
308 #define CIF_WIDTH 352
309 #define CIF_HEIGHT 288
311 #define CIF4_WIDTH (CIF_WIDTH*2)
312 #define CIF4_HEIGHT (CIF_HEIGHT*2)
314 #define CIF16_WIDTH (CIF_WIDTH*4)
315 #define CIF16_HEIGHT (CIF_HEIGHT*4)
317 #define QCIF_WIDTH (CIF_WIDTH/2)
318 #define QCIF_HEIGHT (CIF_HEIGHT/2)
320 #define SQCIF_WIDTH 128
321 #define SQCIF_HEIGHT 96
323 static const char * sqcifMPI_tag = "SQCIF MPI";
324 static const char * qcifMPI_tag = "QCIF MPI";
325 static const char * cifMPI_tag = "CIF MPI";
326 static const char * cif4MPI_tag = "CIF4 MPI";
327 static const char * cif16MPI_tag = "CIF16 MPI";
329 #if OPAL_H323
331 // H.261 only
332 static const char * h323_stillImageTransmission_tag = H323CAP_TAG_PREFIX "_stillImageTransmission";
334 // H.261/H.263 tags
335 static const char * h323_qcifMPI_tag = H323CAP_TAG_PREFIX "_qcifMPI";
336 static const char * h323_cifMPI_tag = H323CAP_TAG_PREFIX "_cifMPI";
338 // H.263 only
339 static const char * h323_sqcifMPI_tag = H323CAP_TAG_PREFIX "_sqcifMPI";
340 static const char * h323_cif4MPI_tag = H323CAP_TAG_PREFIX "_cif4MPI";
341 static const char * h323_cif16MPI_tag = H323CAP_TAG_PREFIX "_cif16MPI";
342 static const char * h323_temporalSpatialTradeOffCapability_tag = H323CAP_TAG_PREFIX "_temporalSpatialTradeOffCapability";
343 static const char * h323_unrestrictedVector_tag = H323CAP_TAG_PREFIX "_unrestrictedVector";
344 static const char * h323_arithmeticCoding_tag = H323CAP_TAG_PREFIX "_arithmeticCoding";
345 static const char * h323_advancedPrediction_tag = H323CAP_TAG_PREFIX "_advancedPrediction";
346 static const char * h323_pbFrames_tag = H323CAP_TAG_PREFIX "_pbFrames";
347 static const char * h323_hrdB_tag = H323CAP_TAG_PREFIX "_hrdB";
348 static const char * h323_bppMaxKb_tag = H323CAP_TAG_PREFIX "_bppMaxKb";
349 static const char * h323_errorCompensation_tag = H323CAP_TAG_PREFIX "_errorCompensation";
351 #endif // OPAL_H323
352 #endif // OPAL_VIDEO
356 //////////////////////////////////////////////////////////////////////////////
358 // Helper functions for codec control operators
361 BOOL OpalPluginTranscoder::CallCodecControl(const PluginCodec_Definition * codec,
362 void * context,
363 const char * name,
364 void * parm,
365 unsigned int * parmLen,
366 int & retVal)
368 PluginCodec_ControlDefn * codecControls = codec->codecControls;
369 if (codecControls == NULL)
370 return FALSE;
372 // look for explicit named control
373 while (codecControls->name != NULL) {
374 if (strcasecmp(codecControls->name, name) == 0) {
375 retVal = (*codecControls->control)(codec, context, name, parm, parmLen);
376 return TRUE;
378 codecControls++;
381 return FALSE;
384 BOOL OpalPluginTranscoder::HasCodecControl(const PluginCodec_Definition * codec, const char * name)
386 PluginCodec_ControlDefn * codecControls = codec->codecControls;
387 if (codecControls == NULL)
388 return 0;
390 while (codecControls->name != NULL) {
391 if (strcmp(codecControls->name, name) == 0)
392 return TRUE;
393 codecControls++;
396 return FALSE;
399 PluginCodec_ControlDefn * OpalPluginTranscoder::GetCodecControl(const PluginCodec_Definition * codec, const char * name)
401 PluginCodec_ControlDefn * codecControls = codec->codecControls;
402 if (codecControls == NULL)
403 return NULL;
405 while (codecControls->name != NULL) {
406 if (strcasecmp(codecControls->name, name) == 0)
407 return codecControls;
408 codecControls++;
411 return NULL;
414 /////////////////////////////////////////////////////////////////////////////
416 template <typename CodecClass>
417 class OpalFixedCodecFactory : public PFactory<OpalFactoryCodec>
419 public:
420 class Worker : public PFactory<OpalFactoryCodec>::WorkerBase
422 public:
423 Worker(const PString & key)
424 : PFactory<OpalFactoryCodec>::WorkerBase()
425 { PFactory<OpalFactoryCodec>::Register(key, this); }
427 protected:
428 virtual OpalFactoryCodec * Create(const PString &) const
429 { return new CodecClass(); }
434 static PString CreateCodecName(const PluginCodec_Definition * codec)
436 return codec->destFormat != NULL ? codec->destFormat : codec->descr;
439 BOOL OpalPluginMediaFormat::CallCodecControl(const PluginCodec_Definition * codec,
440 const char * name,
441 void * parm,
442 unsigned int * parmLen,
443 int & retVal)
445 return OpalPluginTranscoder::CallCodecControl(codec, NULL, name, parm, parmLen, retVal);
449 void OpalPluginMediaFormat::PopulateMediaFormatOptions(const PluginCodec_Definition * _encoderCodec, OpalMediaFormat & format)
451 void ** _options = NULL;
452 unsigned int optionsLen = sizeof(_options);
453 int retVal;
454 if (CallCodecControl(_encoderCodec, GET_CODEC_OPTIONS_CONTROL, &_options, &optionsLen, retVal) && (_options != NULL)) {
455 if (_encoderCodec->version < PLUGIN_CODEC_VERSION_OPTIONS) {
456 PTRACE(3, "OpalPlugin\tAdding options to OpalMediaFormat " << format << " using old style method");
457 // Old scheme
458 char const * const * options = (char **)_options;
459 while (options[0] != NULL && options[1] != NULL && options[2] != NULL) {
460 SetOldStyleFormatOption(format, options[0], options[1], options[2]);
461 options += 3;
464 else {
465 // New scheme
466 struct PluginCodec_Option const * const * options = (struct PluginCodec_Option const * const *)_options;
467 PTRACE_IF(5, options != NULL, "Adding options to OpalMediaFormat " << format << " using new style method");
468 while (*options != NULL) {
469 struct PluginCodec_Option const * option = *options++;
470 OpalMediaOption * newOption;
471 switch (option->m_type) {
472 case PluginCodec_StringOption :
473 newOption = new OpalMediaOptionString(option->m_name,
474 option->m_readOnly != 0,
475 option->m_value);
476 break;
477 case PluginCodec_BoolOption :
478 newOption = new OpalMediaOptionBoolean(option->m_name,
479 option->m_readOnly != 0,
480 (OpalMediaOption::MergeType)option->m_merge,
481 option->m_value != NULL && *option->m_value == 'T');
482 break;
483 case PluginCodec_IntegerOption :
484 newOption = new OpalMediaOptionUnsigned(option->m_name,
485 option->m_readOnly != 0,
486 (OpalMediaOption::MergeType)option->m_merge,
487 PString(option->m_value).AsInteger(),
488 PString(option->m_minimum).AsInteger(),
489 PString(option->m_maximum).AsInteger());
490 break;
491 case PluginCodec_RealOption :
492 newOption = new OpalMediaOptionReal(option->m_name,
493 option->m_readOnly != 0,
494 (OpalMediaOption::MergeType)option->m_merge,
495 PString(option->m_value).AsReal(),
496 PString(option->m_minimum).AsReal(),
497 PString(option->m_maximum).AsReal());
498 break;
499 case PluginCodec_EnumOption :
501 PStringArray valueTokens = PString(option->m_minimum).Tokenise(':');
502 char ** enumValues = valueTokens.ToCharArray();
503 newOption = new OpalMediaOptionEnum(option->m_name,
504 option->m_readOnly != 0,
505 enumValues,
506 valueTokens.GetSize(),
507 (OpalMediaOption::MergeType)option->m_merge,
508 valueTokens.GetStringsIndex(option->m_value));
509 free(enumValues);
511 break;
512 case PluginCodec_OctetsOption :
513 newOption = new OpalMediaOptionOctets(option->m_name, option->m_readOnly != 0, option->m_minimum != NULL); // Use minimum to indicate Base64
514 newOption->FromString(option->m_value);
515 break;
516 default : // Huh?
517 continue;
520 newOption->SetFMTPName(option->m_FMTPName);
521 newOption->SetFMTPDefault(option->m_FMTPDefault);
523 OpalMediaOption::H245GenericInfo genericInfo;
524 genericInfo.ordinal = option->m_H245Generic&PluginCodec_H245_OrdinalMask;
525 if (option->m_H245Generic&PluginCodec_H245_Collapsing)
526 genericInfo.mode = OpalMediaOption::H245GenericInfo::Collapsing;
527 else if (option->m_H245Generic&PluginCodec_H245_NonCollapsing)
528 genericInfo.mode = OpalMediaOption::H245GenericInfo::NonCollapsing;
529 else
530 genericInfo.mode = OpalMediaOption::H245GenericInfo::None;
531 if (option->m_H245Generic&PluginCodec_H245_Unsigned32)
532 genericInfo.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
533 else if (option->m_H245Generic&PluginCodec_H245_BooleanArray)
534 genericInfo.integerType = OpalMediaOption::H245GenericInfo::BooleanArray;
535 else
536 genericInfo.integerType = OpalMediaOption::H245GenericInfo::UnsignedInt;
537 genericInfo.excludeTCS = (option->m_H245Generic&PluginCodec_H245_TCS) == 0;
538 genericInfo.excludeOLC = (option->m_H245Generic&PluginCodec_H245_OLC) == 0;
539 genericInfo.excludeReqMode = (option->m_H245Generic&PluginCodec_H245_ReqMode) == 0;
540 newOption->SetH245Generic(genericInfo);
542 format.AddOption(newOption, TRUE);
545 CallCodecControl(_encoderCodec, FREE_CODEC_OPTIONS_CONTROL, _options, &optionsLen, retVal);
548 // PStringStream str; format.PrintOptions(str);
549 // PTRACE(5, "OpalPlugin\tOpalMediaFormat " << format << " has options\n" << str);
552 void OpalPluginMediaFormat::SetOldStyleFormatOption(OpalMediaFormat & format, const PString & _key, const PString & _val, const PString & type)
554 PString key(_key);
555 const char * val = _val;
557 #if OPAL_VIDEO
558 // Backward compatibility tests
559 if (strcasecmp(key, h323_qcifMPI_tag) == 0)
560 key = qcifMPI_tag;
561 else if (strcasecmp(key, h323_cifMPI_tag) == 0)
562 key = cifMPI_tag;
563 else if (strcasecmp(key, h323_sqcifMPI_tag) == 0)
564 key = sqcifMPI_tag;
565 else if (strcasecmp(key, h323_cif4MPI_tag) == 0)
566 key = cif4MPI_tag;
567 else if (strcasecmp(key, h323_cif16MPI_tag) == 0)
568 key = cif16MPI_tag;
569 #endif
571 OpalMediaOption::MergeType op = OpalMediaOption::NoMerge;
572 if (val[0] != '\0' && val[1] != '\0') {
573 switch (val[0]) {
574 case '<':
575 op = OpalMediaOption::MinMerge;
576 ++val;
577 break;
578 case '>':
579 op = OpalMediaOption::MaxMerge;
580 ++val;
581 break;
582 case '=':
583 op = OpalMediaOption::EqualMerge;
584 ++val;
585 break;
586 case '!':
587 op = OpalMediaOption::NotEqualMerge;
588 ++val;
589 break;
590 case '*':
591 op = OpalMediaOption::AlwaysMerge;
592 ++val;
593 break;
594 default:
595 break;
599 if (type[0] != '\0') {
600 PStringArray tokens = PString(val+1).Tokenise(':', FALSE);
601 char ** array = tokens.ToCharArray();
602 switch (toupper(type[0])) {
603 case 'E':
604 PTRACE(5, "OpalPlugin\tAdding enum option '" << key << "' " << tokens.GetSize() << " options");
605 format.AddOption(new OpalMediaOptionEnum(key, false, array, tokens.GetSize(), op, tokens.GetStringsIndex(val)), TRUE);
606 break;
607 case 'B':
608 PTRACE(5, "OpalPlugin\tAdding boolean option '" << key << "'=" << val);
609 format.AddOption(new OpalMediaOptionBoolean(key, false, op, (val[0] == '1') || (toupper(val[0]) == 'T')), TRUE);
610 break;
611 case 'R':
612 PTRACE(5, "OpalPlugin\tAdding real option '" << key << "'=" << val);
613 if (tokens.GetSize() < 2)
614 format.AddOption(new OpalMediaOptionReal(key, false, op, PString(val).AsReal()));
615 else
616 format.AddOption(new OpalMediaOptionReal(key, false, op, PString(val).AsReal(), tokens[0].AsReal(), tokens[1].AsReal()), TRUE);
617 break;
618 case 'I':
619 PTRACE(5, "OpalPlugin\tAdding integer option '" << key << "'=" << val);
620 if (tokens.GetSize() < 2)
621 format.AddOption(new OpalMediaOptionUnsigned(key, false, op, PString(val).AsUnsigned()), TRUE);
622 else
623 format.AddOption(new OpalMediaOptionUnsigned(key, false, op, PString(val).AsUnsigned(), tokens[0].AsUnsigned(), tokens[1].AsUnsigned()), TRUE);
624 break;
625 case 'S':
626 default:
627 PTRACE(5, "OpalPlugin\tAdding string option '" << key << "'=" << val);
628 format.AddOption(new OpalMediaOptionString(key, false, val), TRUE);
629 break;
631 free(array);
636 static void PopulateMediaFormatFromGenericData(OpalMediaFormat & mediaFormat, const PluginCodec_H323GenericCodecData * genericData)
638 const PluginCodec_H323GenericParameterDefinition *ptr = genericData->params;
639 for (unsigned i = 0; i < genericData->nParameters; i++, ptr++) {
640 OpalMediaOption::H245GenericInfo generic;
641 generic.ordinal = ptr->id;
642 generic.mode = ptr->collapsing ? OpalMediaOption::H245GenericInfo::Collapsing : OpalMediaOption::H245GenericInfo::NonCollapsing;
643 generic.excludeTCS = ptr->excludeTCS;
644 generic.excludeOLC = ptr->excludeOLC;
645 generic.excludeReqMode = ptr->excludeReqMode;
646 generic.integerType = OpalMediaOption::H245GenericInfo::UnsignedInt;
648 PString name(PString::Printf, "Generic Parameter %u", ptr->id);
650 OpalMediaOption * mediaOption;
651 switch (ptr->type) {
652 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_logical :
653 mediaOption = new OpalMediaOptionBoolean(name, ptr->readOnly, OpalMediaOption::NoMerge, ptr->value.integer != 0);
654 break;
656 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_booleanArray :
657 generic.integerType = OpalMediaOption::H245GenericInfo::BooleanArray;
658 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::AndMerge, ptr->value.integer, 0, 255);
659 break;
661 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsigned32Min :
662 generic.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
663 // Do next case
665 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsignedMin :
666 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::MinMerge, ptr->value.integer);
667 break;
669 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsigned32Max :
670 generic.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
671 // Do next case
673 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsignedMax :
674 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::MaxMerge, ptr->value.integer);
675 break;
677 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_octetString :
678 mediaOption = new OpalMediaOptionString(name, ptr->readOnly, ptr->value.octetstring);
679 break;
681 default :
682 mediaOption = NULL;
685 if (mediaOption != NULL) {
686 mediaOption->SetH245Generic(generic);
687 mediaFormat.AddOption(mediaOption);
693 bool OpalPluginMediaFormat::IsValidForProtocol(const PluginCodec_Definition * encoderCodec, const PString & _protocol)
695 PString protocol(_protocol.ToLower());
696 int retVal;
697 unsigned int parmLen = sizeof(const char *);
698 if (CallCodecControl(encoderCodec, "valid_for_protocol", (void *)(const char *)protocol, &parmLen, retVal))
699 return retVal != 0;
700 if (protocol == "h.323" || protocol == "h323")
701 return (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_undefined) &&
702 (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_NoH323);
703 if (protocol == "sip")
704 return encoderCodec->sdpFormat != NULL;
705 return FALSE;
708 #if OPAL_AUDIO
710 OpalPluginAudioMediaFormat::OpalPluginAudioMediaFormat(const PluginCodec_Definition * _encoderCodec,
711 const char * rtpEncodingName, /// rtp encoding name
712 unsigned frameTime, /// Time for frame in RTP units (if applicable)
713 unsigned /*timeUnits*/, /// RTP units for frameTime (if applicable)
714 time_t timeStamp /// timestamp (for versioning)
716 : OpalAudioFormat(CreateCodecName(_encoderCodec),
717 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
718 rtpEncodingName,
719 _encoderCodec->parm.audio.bytesPerFrame,
720 frameTime,
721 _encoderCodec->parm.audio.recommendedFramesPerPacket,
722 _encoderCodec->parm.audio.recommendedFramesPerPacket,
723 _encoderCodec->parm.audio.maxFramesPerPacket,
724 _encoderCodec->sampleRate,
725 timeStamp
727 , encoderCodec(_encoderCodec)
729 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
731 // Override calculated value if we have an explicit bit rate
732 if (_encoderCodec->bitsPerSec > 0)
733 SetOptionInteger(MaxBitRateOption(), _encoderCodec->bitsPerSec);
735 // manually register the new singleton type, as we do not have a concrete type
736 OpalMediaFormatFactory::Register(*this, this);
739 OpalPluginAudioMediaFormat::~OpalPluginAudioMediaFormat()
741 OpalMediaFormatFactory::Unregister(*this);
744 bool OpalPluginAudioMediaFormat::IsValidForProtocol(const PString & protocol) const
746 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
749 PObject * OpalPluginAudioMediaFormat::Clone() const
750 { return new OpalPluginAudioMediaFormat(*this); }
752 #if OPAL_H323
754 static H323Capability * CreateG7231Cap(
755 const PluginCodec_Definition * encoderCodec,
756 const PluginCodec_Definition * decoderCodec,
757 int subType
760 static H323Capability * CreateGenericAudioCap(
761 const PluginCodec_Definition * encoderCodec,
762 const PluginCodec_Definition * decoderCodec,
763 int subType
766 static H323Capability * CreateNonStandardAudioCap(
767 const PluginCodec_Definition * encoderCodec,
768 const PluginCodec_Definition * decoderCodec,
769 int subType
772 static H323Capability * CreateGSMCap(
773 const PluginCodec_Definition * encoderCodec,
774 const PluginCodec_Definition * decoderCodec,
775 int subType
778 #endif // OPAL_H323
780 #endif // OPAL_AUDIO
782 #if OPAL_VIDEO
784 OpalPluginVideoMediaFormat::OpalPluginVideoMediaFormat(
785 const PluginCodec_Definition * _encoderCodec,
786 const char * rtpEncodingName, /// rtp encoding name
787 time_t timeStamp /// timestamp (for versioning)
789 : OpalVideoFormat(
790 CreateCodecName(_encoderCodec),
791 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
792 rtpEncodingName,
793 _encoderCodec->parm.video.maxFrameWidth,
794 _encoderCodec->parm.video.maxFrameHeight,
795 _encoderCodec->parm.video.maxFrameRate,
796 _encoderCodec->bitsPerSec,
797 timeStamp
799 , encoderCodec(_encoderCodec)
801 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
803 // manually register the new singleton type, as we do not have a concrete type
804 OpalMediaFormatFactory::Register(*this, this);
807 OpalPluginVideoMediaFormat::~OpalPluginVideoMediaFormat()
809 OpalMediaFormatFactory::Unregister(*this);
812 PObject * OpalPluginVideoMediaFormat::Clone() const
814 return new OpalPluginVideoMediaFormat(*this);
817 bool OpalPluginVideoMediaFormat::IsValidForProtocol(const PString & protocol) const
819 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
822 #if OPAL_H323
824 static H323Capability * CreateNonStandardVideoCap(
825 const PluginCodec_Definition * encoderCodec,
826 const PluginCodec_Definition * decoderCodec,
827 int subType
830 static H323Capability * CreateGenericVideoCap(
831 const PluginCodec_Definition * encoderCodec,
832 const PluginCodec_Definition * decoderCodec,
833 int subType
836 static H323Capability * CreateH261Cap(
837 const PluginCodec_Definition * encoderCodec,
838 const PluginCodec_Definition * decoderCodec,
839 int subType
842 static H323Capability * CreateH263Cap(
843 const PluginCodec_Definition * encoderCodec,
844 const PluginCodec_Definition * decoderCodec,
845 int subType
848 #endif // OPAL_H323
850 #endif // OPAL_VIDEO
852 ////////////////////////////////////////////////////////////////////
854 #if OPAL_H323
856 class H323CodecPluginCapabilityMapEntry {
857 public:
858 int pluginCapType;
859 int h323SubType;
860 H323Capability * (* createFunc)(const PluginCodec_Definition * encoderCodec, const PluginCodec_Definition * decoderCodec, int subType);
863 #if OPAL_AUDIO
865 static H323CodecPluginCapabilityMapEntry audioMaps[] = {
866 { PluginCodec_H323Codec_nonStandard, H245_AudioCapability::e_nonStandard, &CreateNonStandardAudioCap },
867 { PluginCodec_H323AudioCodec_gsmFullRate, H245_AudioCapability::e_gsmFullRate, &CreateGSMCap },
868 { PluginCodec_H323AudioCodec_gsmHalfRate, H245_AudioCapability::e_gsmHalfRate, &CreateGSMCap },
869 { PluginCodec_H323AudioCodec_gsmEnhancedFullRate, H245_AudioCapability::e_gsmEnhancedFullRate, &CreateGSMCap },
870 { PluginCodec_H323AudioCodec_g711Alaw_64k, H245_AudioCapability::e_g711Alaw64k },
871 { PluginCodec_H323AudioCodec_g711Alaw_56k, H245_AudioCapability::e_g711Alaw56k },
872 { PluginCodec_H323AudioCodec_g711Ulaw_64k, H245_AudioCapability::e_g711Ulaw64k },
873 { PluginCodec_H323AudioCodec_g711Ulaw_56k, H245_AudioCapability::e_g711Ulaw56k },
874 { PluginCodec_H323AudioCodec_g7231, H245_AudioCapability::e_g7231, &CreateG7231Cap },
875 { PluginCodec_H323AudioCodec_g729, H245_AudioCapability::e_g729 },
876 { PluginCodec_H323AudioCodec_g729AnnexA, H245_AudioCapability::e_g729AnnexA },
877 { PluginCodec_H323AudioCodec_g728, H245_AudioCapability::e_g728 },
878 { PluginCodec_H323AudioCodec_g722_64k, H245_AudioCapability::e_g722_64k },
879 { PluginCodec_H323AudioCodec_g722_56k, H245_AudioCapability::e_g722_56k },
880 { PluginCodec_H323AudioCodec_g722_48k, H245_AudioCapability::e_g722_48k },
881 { PluginCodec_H323AudioCodec_g729wAnnexB, H245_AudioCapability::e_g729wAnnexB },
882 { PluginCodec_H323AudioCodec_g729AnnexAwAnnexB, H245_AudioCapability::e_g729AnnexAwAnnexB },
883 { PluginCodec_H323Codec_generic, H245_AudioCapability::e_genericAudioCapability, &CreateGenericAudioCap },
885 // not implemented
886 //{ PluginCodec_H323AudioCodec_g729Extensions, H245_AudioCapability::e_g729Extensions, 0 },
887 //{ PluginCodec_H323AudioCodec_g7231AnnexC, H245_AudioCapability::e_g7231AnnexCMode 0 },
888 //{ PluginCodec_H323AudioCodec_is11172, H245_AudioCapability::e_is11172AudioMode, 0 },
889 //{ PluginCodec_H323AudioCodec_is13818Audio, H245_AudioCapability::e_is13818AudioMode, 0 },
891 { -1 }
894 #endif // OPAL_AUDIO
896 #if OPAL_VIDEO
898 static H323CodecPluginCapabilityMapEntry videoMaps[] = {
899 // video codecs
900 { PluginCodec_H323Codec_nonStandard, H245_VideoCapability::e_nonStandard, &CreateNonStandardVideoCap },
901 { PluginCodec_H323VideoCodec_h261, H245_VideoCapability::e_h261VideoCapability, &CreateH261Cap },
902 { PluginCodec_H323VideoCodec_h263, H245_VideoCapability::e_h263VideoCapability, &CreateH263Cap },
903 { PluginCodec_H323Codec_generic, H245_VideoCapability::e_genericVideoCapability, &CreateGenericVideoCap },
905 PluginCodec_H323VideoCodec_h262, // not yet implemented
906 PluginCodec_H323VideoCodec_is11172, // not yet implemented
909 { -1 }
912 #endif // OPAL_VIDEO
914 #endif // OPAL_H323
916 //////////////////////////////////////////////////////////////////////////////
918 #if OPAL_T38FAX
920 OpalPluginFaxMediaFormat::OpalPluginFaxMediaFormat(
921 const PluginCodec_Definition * _encoderCodec,
922 const char * rtpEncodingName, /// rtp encoding name
923 unsigned frameTime,
924 unsigned /*timeUnits*/, /// RTP units for frameTime (if applicable)
925 time_t timeStamp /// timestamp (for versioning)
927 : OpalMediaFormat(CreateCodecName(_encoderCodec),
928 OpalMediaFormat::DefaultDataSessionID,
929 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
930 rtpEncodingName,
931 FALSE, // need jitter
932 8*_encoderCodec->parm.audio.bytesPerFrame*AudioClockRate/frameTime, // bandwidth
933 _encoderCodec->parm.audio.bytesPerFrame, // size of frame in bytes
934 frameTime, // time for frame
935 _encoderCodec->sampleRate, // clock rate
936 (unsigned int)timeStamp // timestamp
938 , encoderCodec(_encoderCodec)
940 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
942 // manually register the new singleton type, as we do not have a concrete type
943 OpalMediaFormatFactory::Register(*this, this);
945 OpalPluginFaxMediaFormat::~OpalPluginFaxMediaFormat()
947 OpalMediaFormatFactory::Unregister(*this);
950 PObject * OpalPluginFaxMediaFormat::Clone() const
951 { return new OpalPluginFaxMediaFormat(*this); }
953 bool OpalPluginFaxMediaFormat::IsValidForProtocol(const PString & protocol) const
955 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
958 #endif // OPAL_T38FAX
960 //////////////////////////////////////////////////////////////////////////////
962 // Plugin framed audio codec classes
965 #if OPAL_AUDIO
966 class OpalPluginFramedAudioTranscoder : public OpalFramedTranscoder, public OpalPluginTranscoder
968 PCLASSINFO(OpalPluginFramedAudioTranscoder, OpalFramedTranscoder);
969 public:
970 OpalPluginFramedAudioTranscoder(PluginCodec_Definition * _codec, BOOL _isEncoder, const char * rawFormat = OpalPCM16)
971 : OpalFramedTranscoder( (strcmp(_codec->sourceFormat, "L16") == 0) ? rawFormat : _codec->sourceFormat,
972 (strcmp(_codec->destFormat, "L16") == 0) ? rawFormat : _codec->destFormat,
973 _isEncoder ? _codec->parm.audio.samplesPerFrame*2 : _codec->parm.audio.bytesPerFrame,
974 _isEncoder ? _codec->parm.audio.bytesPerFrame : _codec->parm.audio.samplesPerFrame*2),
975 codec(_codec), isEncoder(_isEncoder)
977 if (codec->createCodec != NULL)
978 context = (*codec->createCodec)(codec);
979 else
980 context = NULL;
981 inputIsRTP = (codec->flags & PluginCodec_InputTypeMask) == PluginCodec_InputTypeRTP;
982 outputIsRTP = (codec->flags & PluginCodec_OutputTypeMask) == PluginCodec_OutputTypeRTP;
985 ~OpalPluginFramedAudioTranscoder()
987 if (codec->destroyCodec != NULL)
988 (*codec->destroyCodec)(codec, context);
991 BOOL ConvertFrame(
992 const BYTE * input, ///< Input data
993 PINDEX & consumed, ///< number of input bytes consumed
994 BYTE * output, ///< Output data
995 PINDEX & created ///< number of output bytes created
998 if (codec == NULL || codec->codecFunction == NULL)
999 return FALSE;
1001 unsigned int fromLen = consumed;
1002 unsigned int toLen = created;
1003 unsigned flags = 0;
1005 BOOL stat = (codec->codecFunction)(codec, context,
1006 (const unsigned char *)input, &fromLen,
1007 output, &toLen,
1008 &flags) != 0;
1009 consumed = fromLen;
1010 created = toLen;
1012 return stat;
1015 virtual BOOL ConvertSilentFrame(BYTE * buffer)
1017 if (codec == NULL)
1018 return FALSE;
1020 // for a decoder, this mean that we need to create a silence frame
1021 // which is easy - ask the decoder, or just create silence
1022 if (!isEncoder) {
1023 unsigned int length = codec->parm.audio.samplesPerFrame*2;
1024 if ((codec->flags & PluginCodec_DecodeSilence) == 0)
1025 memset(buffer, 0, length);
1026 else {
1027 unsigned flags = PluginCodec_CoderSilenceFrame;
1028 (codec->codecFunction)(codec, context,
1029 NULL, NULL,
1030 buffer, &length,
1031 &flags);
1035 // for an encoder, we encode silence but set the flag so it can do something special if need be
1036 else {
1037 unsigned int length = codec->parm.audio.bytesPerFrame;
1038 if ((codec->flags & PluginCodec_EncodeSilence) == 0) {
1039 PShortArray silence(codec->parm.audio.samplesPerFrame);
1040 memset(silence.GetPointer(), 0, codec->parm.audio.samplesPerFrame*sizeof(short));
1041 unsigned silenceLen = codec->parm.audio.samplesPerFrame * sizeof(short);
1042 unsigned flags = 0;
1043 (codec->codecFunction)(codec, context,
1044 silence, &silenceLen,
1045 buffer, &length,
1046 &flags);
1048 else {
1049 unsigned flags = PluginCodec_CoderSilenceFrame;
1050 (codec->codecFunction)(codec, context,
1051 NULL, NULL,
1052 buffer, &length,
1053 &flags);
1057 return TRUE;
1060 BOOL HasCodecControl(const char * name)
1061 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1063 BOOL CallCodecControl(const char * name,
1064 void * parm,
1065 unsigned int * parmLen,
1066 int & retVal)
1067 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1069 protected:
1070 void * context;
1071 PluginCodec_Definition * codec;
1072 BOOL isEncoder;
1075 //////////////////////////////////////////////////////////////////////////////
1077 // Plugin streamed audio codec classes
1080 class OpalPluginStreamedAudioTranscoder : public OpalStreamedTranscoder, public OpalPluginTranscoder
1082 PCLASSINFO(OpalPluginStreamedAudioTranscoder, OpalStreamedTranscoder);
1083 public:
1084 OpalPluginStreamedAudioTranscoder(PluginCodec_Definition * _codec, unsigned inputBits, unsigned outputBits, PINDEX optimalBits)
1085 : OpalStreamedTranscoder((strcmp(_codec->sourceFormat, "L16") == 0) ? OpalPCM16 : _codec->sourceFormat,
1086 (strcmp(_codec->destFormat, "L16") == 0) ? OpalPCM16 : _codec->destFormat,
1087 inputBits, outputBits, optimalBits),
1088 codec(_codec)
1090 if (codec == NULL || codec->createCodec == NULL)
1091 context = NULL;
1092 else {
1093 context = (*codec->createCodec)(codec);
1097 ~OpalPluginStreamedAudioTranscoder()
1099 if (codec != NULL && codec->destroyCodec != NULL)
1100 (*codec->destroyCodec)(codec, context);
1103 BOOL HasCodecControl(const char * name)
1104 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1106 BOOL CallCodecControl(const char * name,
1107 void * parm,
1108 unsigned int * parmLen,
1109 int & retVal)
1110 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1112 protected:
1113 void * context;
1114 PluginCodec_Definition * codec;
1117 class OpalPluginStreamedAudioEncoder : public OpalPluginStreamedAudioTranscoder
1119 PCLASSINFO(OpalPluginStreamedAudioEncoder, OpalPluginStreamedAudioTranscoder);
1120 public:
1121 OpalPluginStreamedAudioEncoder(PluginCodec_Definition * _codec, BOOL)
1122 : OpalPluginStreamedAudioTranscoder(_codec, 16, (_codec->flags & PluginCodec_BitsPerSampleMask) >> PluginCodec_BitsPerSamplePos, _codec->parm.audio.recommendedFramesPerPacket)
1126 int ConvertOne(int _sample) const
1128 if (codec == NULL || codec->codecFunction == NULL)
1129 return 0;
1131 short sample = (short)_sample;
1132 unsigned int fromLen = sizeof(sample);
1133 int to;
1134 unsigned toLen = sizeof(to);
1135 unsigned flags = 0;
1136 (codec->codecFunction)(codec, context,
1137 (const unsigned char *)&sample, &fromLen,
1138 (unsigned char *)&to, &toLen,
1139 &flags);
1140 return to;
1144 class OpalPluginStreamedAudioDecoder : public OpalPluginStreamedAudioTranscoder
1146 PCLASSINFO(OpalPluginStreamedAudioDecoder, OpalPluginStreamedAudioTranscoder);
1147 public:
1148 OpalPluginStreamedAudioDecoder(PluginCodec_Definition * _codec, BOOL)
1149 : OpalPluginStreamedAudioTranscoder(_codec, (_codec->flags & PluginCodec_BitsPerSampleMask) >> PluginCodec_BitsPerSamplePos, 16, _codec->parm.audio.recommendedFramesPerPacket)
1153 int ConvertOne(int codedSample) const
1155 if (codec == NULL || codec->codecFunction == NULL)
1156 return 0;
1158 unsigned int fromLen = sizeof(codedSample);
1159 short to;
1160 unsigned toLen = sizeof(to);
1161 unsigned flags = 0;
1162 (codec->codecFunction)(codec, context,
1163 (const unsigned char *)&codedSample, &fromLen,
1164 (unsigned char *)&to, &toLen,
1165 &flags);
1166 return to;
1172 #endif // OPAL_AUDIO
1174 #if OPAL_VIDEO
1176 /////////////////////////////////////////////////////////////////////////////
1178 #if 0
1179 class OpalPluginVideoTranscoder : public OpalVideoTranscoder
1181 PCLASSINFO(OpalPluginVideoTranscoder, OpalVideoTranscoder);
1182 public:
1183 OpalPluginVideoTranscoder(const PluginCodec_Definition * _codec, BOOL _isEncoder);
1184 ~OpalPluginVideoTranscoder();
1186 BOOL HasCodecControl(const char * name)
1187 { return ::HasCodecControl(codec, name); }
1189 BOOL CallCodecControl(const char * name,
1190 void * parm,
1191 unsigned int * parmLen,
1192 int & retVal)
1193 { return ::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1195 BOOL ExecuteCommand(const OpalMediaCommand & /*command*/);
1196 PINDEX GetOptimalDataFrameSize(BOOL input) const;
1197 BOOL ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList);
1198 BOOL UpdateOutputMediaFormat(const OpalMediaFormat & fmt);
1200 protected:
1201 void * context;
1202 const PluginCodec_Definition * codec;
1203 BOOL isEncoder;
1204 RTP_DataFrame * bufferRTP;
1206 #endif
1208 OpalPluginVideoTranscoder::OpalPluginVideoTranscoder(const PluginCodec_Definition * _codec, BOOL _isEncoder)
1209 : OpalVideoTranscoder(_codec->sourceFormat, _codec->destFormat),
1210 codec(_codec), isEncoder(_isEncoder)
1212 if (codec == NULL || codec->createCodec == NULL)
1213 context = NULL;
1214 else
1215 context = (*codec->createCodec)(codec);
1217 bufferRTP = NULL;
1220 BOOL OpalPluginVideoTranscoder::CallCodecControl(const char * name,
1221 void * parm,
1222 unsigned int * parmLen,
1223 int & retVal)
1224 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1226 BOOL OpalPluginVideoTranscoder::HasCodecControl(const char * name)
1227 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1229 BOOL OpalPluginVideoTranscoder::UpdateOutputMediaFormat(const OpalMediaFormat & fmt)
1231 PluginCodec_ControlDefn * ctl = GetCodecControl(codec, SET_CODEC_OPTIONS_CONTROL);
1232 if (ctl != NULL) {
1233 PStringArray list;
1234 for (PINDEX i = 0; i < fmt.GetOptionCount(); i++) {
1235 const OpalMediaOption & option = fmt.GetOption(i);
1236 list += option.GetName();
1237 list += option.AsString();
1238 PTRACE(5, "OpalPlugin\tSetting codec control '" << option.GetName() << "'=" << option.AsString());
1240 char ** _options = list.ToCharArray();
1241 unsigned int optionsLen = sizeof(_options);
1242 (*ctl->control)(codec, context, SET_CODEC_OPTIONS_CONTROL, _options, &optionsLen);
1243 free(_options);
1246 return TRUE;
1250 OpalPluginVideoTranscoder::~OpalPluginVideoTranscoder()
1252 if (bufferRTP == NULL)
1253 delete bufferRTP;
1255 if (codec != NULL && codec->destroyCodec != NULL)
1256 (*codec->destroyCodec)(codec, context);
1259 BOOL OpalPluginVideoTranscoder::ExecuteCommand(const OpalMediaCommand & command)
1261 if (PIsDescendant(&command, OpalVideoUpdatePicture)) {
1262 ++updatePictureCount;
1263 return TRUE;
1266 return OpalTranscoder::ExecuteCommand(command);
1269 PINDEX OpalPluginVideoTranscoder::GetOptimalDataFrameSize(BOOL /*input*/) const
1271 return (frameWidth * frameHeight * 12) / 8;
1274 BOOL OpalPluginVideoTranscoder::ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList)
1276 if (codec == NULL || codec->codecFunction == NULL)
1277 return FALSE;
1279 dstList.RemoveAll();
1281 // get the size of the output buffer
1282 int outputDataSize;
1283 if (!CallCodecControl(GET_OUTPUT_DATA_SIZE_CONTROL, NULL, NULL, outputDataSize))
1284 outputDataSize = 1518-14-4-8-20-16; // Max Ethernet packet (1518 bytes) minus 802.3/CRC, 802.3, IP, UDP headers
1286 unsigned flags;
1288 if (isEncoder) {
1290 do {
1292 // create the output buffer
1293 RTP_DataFrame * dst = new RTP_DataFrame(outputDataSize);
1294 dst->SetPayloadType(GetPayloadType(FALSE));
1296 // call the codec function
1297 unsigned int fromLen = src.GetSize();
1298 unsigned int toLen = dst->GetSize();
1299 BOOL forceIFrame = updatePictureCount > 0;
1300 flags = forceIFrame ? PluginCodec_CoderForceIFrame : 0;
1302 if (!(codec->codecFunction)(codec, context,
1303 (const BYTE *)src, &fromLen,
1304 dst->GetPointer(), &toLen,
1305 &flags)) {
1306 delete dst;
1307 return FALSE;
1311 if (forceIFrame && ((flags & PluginCodec_ReturnCoderIFrame) != 0))
1312 --updatePictureCount;
1314 if (toLen > 0) {
1315 dst->SetPayloadSize(toLen - dst->GetHeaderSize());
1316 dstList.Append(dst);
1319 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1322 else {
1324 if (bufferRTP == NULL)
1325 bufferRTP = new RTP_DataFrame(outputDataSize);
1326 else
1327 bufferRTP->SetPayloadSize(outputDataSize);
1328 bufferRTP->SetPayloadType(GetPayloadType(FALSE));
1330 // call the codec function
1331 unsigned int fromLen = src.GetHeaderSize() + src.GetPayloadSize();
1332 unsigned int toLen = bufferRTP->GetSize();
1333 flags = 0;
1335 if (!(codec->codecFunction)(codec, context,
1336 (const BYTE *)src, &fromLen,
1337 bufferRTP->GetPointer(), &toLen,
1338 &flags))
1339 return FALSE;
1341 if ((flags & PluginCodec_ReturnCoderRequestIFrame) != 0) {
1342 if (commandNotifier != PNotifier()) {
1343 OpalVideoUpdatePicture updatePictureCommand;
1344 commandNotifier(updatePictureCommand, 0);
1345 PTRACE (3, "Video\t Could not decode frame, sending VideoUpdatePicture in hope of an I-Frame.");
1349 if (toLen > (unsigned)bufferRTP->GetHeaderSize() && (flags & PluginCodec_ReturnCoderLastFrame) != 0) {
1350 bufferRTP->SetPayloadSize(toLen - bufferRTP->GetHeaderSize());
1351 dstList.Append(bufferRTP);
1352 bufferRTP = NULL;
1356 return TRUE;
1360 #endif // OPAL_VIDEO
1364 //////////////////////////////////////////////////////////////////////////////
1366 // Fax transcoder classes
1369 #if OPAL_T38FAX
1371 class OpalFaxAudioTranscoder : public OpalPluginFramedAudioTranscoder
1373 PCLASSINFO(OpalFaxAudioTranscoder, OpalPluginFramedAudioTranscoder);
1374 public:
1375 OpalFaxAudioTranscoder(PluginCodec_Definition * _codec, BOOL _isEncoder)
1376 : OpalPluginFramedAudioTranscoder(_codec, _isEncoder, "PCM-16-Fax")
1378 bufferRTP = NULL;
1381 ~OpalFaxAudioTranscoder()
1385 BOOL ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList);
1387 protected:
1388 RTP_DataFrame * bufferRTP;
1391 BOOL OpalFaxAudioTranscoder::ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList)
1393 if (codec == NULL || codec->codecFunction == NULL)
1394 return FALSE;
1396 dstList.RemoveAll();
1398 // get the size of the output buffer
1399 int outputDataSize = 400;
1400 //if (!CallCodecControl(GET_OUTPUT_DATA_SIZE_CONTROL, NULL, NULL, outputDataSize))
1401 // return FALSE;
1403 unsigned flags = 0;
1405 if (isEncoder) {
1407 do {
1409 // create the output buffer
1410 RTP_DataFrame * dst = new RTP_DataFrame(outputDataSize);
1411 dst->SetPayloadType(GetPayloadType(FALSE));
1413 // call the codec function
1414 unsigned int fromLen = src.GetSize();
1415 unsigned int toLen = dst->GetSize();
1417 BOOL stat = (codec->codecFunction)(codec, context,
1418 (const BYTE *)src, &fromLen,
1419 dst->GetPointer(), &toLen,
1420 &flags) != 0;
1422 if (!stat) {
1423 delete dst;
1424 return FALSE;
1427 if (toLen > 0) {
1428 dst->SetPayloadSize(toLen - dst->GetHeaderSize());
1429 dstList.Append(dst);
1432 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1435 else {
1437 unsigned int fromLen = src.GetHeaderSize() + src.GetPayloadSize();
1439 do {
1440 if (bufferRTP == NULL)
1441 bufferRTP = new RTP_DataFrame(outputDataSize);
1442 else
1443 bufferRTP->SetPayloadSize(outputDataSize);
1444 bufferRTP->SetPayloadType(GetPayloadType(FALSE));
1446 // call the codec function
1447 unsigned int toLen = bufferRTP->GetSize();
1448 flags = 0;
1449 BOOL stat = (codec->codecFunction)(codec, context,
1450 (const BYTE *)src, &fromLen,
1451 bufferRTP->GetPointer(), &toLen,
1452 &flags) != 0;
1453 if (!stat)
1454 return FALSE;
1456 if (toLen > (unsigned)bufferRTP->GetHeaderSize()) {
1457 bufferRTP->SetPayloadSize(toLen - bufferRTP->GetHeaderSize());
1458 dstList.Append(bufferRTP);
1459 bufferRTP = NULL;
1462 fromLen = 0;
1464 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1467 return TRUE;
1470 #endif // OPAL_T38FAX
1472 //////////////////////////////////////////////////////////////////////////////
1474 #if OPAL_H323
1476 #if OPAL_AUDIO
1478 //////////////////////////////////////////////////////////////////////////////
1480 // Class for handling most audio plugin capabilities
1483 H323AudioPluginCapability::H323AudioPluginCapability(const PluginCodec_Definition * _encoderCodec,
1484 const PluginCodec_Definition * _decoderCodec,
1485 unsigned _pluginSubType)
1486 : H323AudioCapability(), H323PluginCapabilityInfo(_encoderCodec, _decoderCodec),
1487 pluginSubType(_pluginSubType)
1489 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
1492 // this constructor is only used when creating a capability without a codec
1493 H323AudioPluginCapability::H323AudioPluginCapability(const PString & _mediaFormat,
1494 const PString & _baseName,
1495 unsigned maxFramesPerPacket,
1496 unsigned /*recommendedFramesPerPacket*/,
1497 unsigned _pluginSubType)
1498 : H323AudioCapability(), H323PluginCapabilityInfo(_baseName),
1499 pluginSubType(_pluginSubType)
1501 for (PINDEX i = 0; audioMaps[i].pluginCapType >= 0; i++) {
1502 if (audioMaps[i].pluginCapType == (int)_pluginSubType) {
1503 h323subType = audioMaps[i].h323SubType;
1504 break;
1507 rtpPayloadType = OpalMediaFormat(_mediaFormat).GetPayloadType();
1508 SetTxFramesInPacket(maxFramesPerPacket);
1509 // recommendedFramesPerPacket
1512 PObject * H323AudioPluginCapability::Clone() const
1513 { return new H323AudioPluginCapability(*this); }
1515 PString H323AudioPluginCapability::GetFormatName() const
1516 { return H323PluginCapabilityInfo::GetFormatName();}
1518 unsigned H323AudioPluginCapability::GetSubType() const
1519 { return pluginSubType; }
1521 //////////////////////////////////////////////////////////////////////////////
1523 // Class for handling G.723.1 codecs
1526 class H323PluginG7231Capability : public H323AudioPluginCapability
1528 PCLASSINFO(H323PluginG7231Capability, H323AudioPluginCapability);
1529 public:
1530 H323PluginG7231Capability(const PluginCodec_Definition * _encoderCodec,
1531 const PluginCodec_Definition * _decoderCodec,
1532 BOOL _annexA = TRUE)
1533 : H323AudioPluginCapability(_encoderCodec, _decoderCodec, H245_AudioCapability::e_g7231),
1534 annexA(_annexA)
1537 virtual PObject * Clone() const
1538 { return new H323PluginG7231Capability(*this); }
1540 virtual BOOL OnSendingPDU(H245_AudioCapability & cap, unsigned packetSize) const
1542 cap.SetTag(H245_AudioCapability::e_g7231);
1543 H245_AudioCapability_g7231 & g7231 = cap;
1544 g7231.m_maxAl_sduAudioFrames = packetSize;
1545 g7231.m_silenceSuppression = annexA;
1546 return TRUE;
1549 virtual BOOL OnReceivedPDU(const H245_AudioCapability & cap, unsigned & packetSize)
1551 if (cap.GetTag() != H245_AudioCapability::e_g7231)
1552 return FALSE;
1553 const H245_AudioCapability_g7231 & g7231 = cap;
1554 packetSize = g7231.m_maxAl_sduAudioFrames;
1555 annexA = g7231.m_silenceSuppression;
1556 return TRUE;
1559 protected:
1560 BOOL annexA;
1563 //////////////////////////////////////////////////////////////////////////////
1565 // Class for handling GSM plugin capabilities
1568 class H323GSMPluginCapability : public H323AudioPluginCapability
1570 PCLASSINFO(H323GSMPluginCapability, H323AudioPluginCapability);
1571 public:
1572 H323GSMPluginCapability(const PluginCodec_Definition * _encoderCodec,
1573 const PluginCodec_Definition * _decoderCodec,
1574 int _pluginSubType, int _comfortNoise, int _scrambled)
1575 : H323AudioPluginCapability(_encoderCodec, _decoderCodec, _pluginSubType),
1576 comfortNoise(_comfortNoise), scrambled(_scrambled)
1579 Comparison Compare(const PObject & obj) const;
1581 virtual PObject * Clone() const
1582 { return new H323GSMPluginCapability(*this); }
1584 virtual BOOL OnSendingPDU(
1585 H245_AudioCapability & pdu, /// PDU to set information on
1586 unsigned packetSize /// Packet size to use in capability
1587 ) const;
1589 virtual BOOL OnReceivedPDU(
1590 const H245_AudioCapability & pdu, /// PDU to get information from
1591 unsigned & packetSize /// Packet size to use in capability
1593 protected:
1594 int comfortNoise;
1595 int scrambled;
1598 #endif // OPAL_H323
1600 #endif // OPAL_H323
1602 /////////////////////////////////////////////////////////////////////////////
1604 PMutex & OpalPluginCodecManager::GetMediaFormatMutex()
1606 static PMutex mutex;
1607 return mutex;
1610 OpalPluginCodecManager::OpalPluginCodecManager(PPluginManager * _pluginMgr)
1611 : PPluginModuleManager(PLUGIN_CODEC_GET_CODEC_FN_STR, _pluginMgr)
1613 // instantiate all of the media formats
1615 OpalMediaFormatFactory::KeyList_T keyList = OpalMediaFormatFactory::GetKeyList();
1616 OpalMediaFormatFactory::KeyList_T::const_iterator r;
1617 for (r = keyList.begin(); r != keyList.end(); ++r) {
1618 OpalMediaFormat * instance = OpalMediaFormatFactory::CreateInstance(*r);
1619 if (instance == NULL) {
1620 PTRACE(4, "OpalPlugin\tCannot instantiate opal media format " << *r);
1621 } else {
1622 PTRACE(4, "OpalPlugin\tCreating media format " << *r);
1627 // instantiate all of the static codecs
1629 H323StaticPluginCodecFactory::KeyList_T keyList = H323StaticPluginCodecFactory::GetKeyList();
1630 H323StaticPluginCodecFactory::KeyList_T::const_iterator r;
1631 for (r = keyList.begin(); r != keyList.end(); ++r) {
1632 H323StaticPluginCodec * instance = PFactory<H323StaticPluginCodec>::CreateInstance(*r);
1633 if (instance == NULL) {
1634 PTRACE(4, "OpalPlugin\tCannot instantiate static codec plugin " << *r);
1635 } else {
1636 PTRACE(4, "OpalPlugin\tLoading static codec plugin " << *r);
1637 RegisterStaticCodec(*r, instance->Get_GetAPIFn(), instance->Get_GetCodecFn());
1642 // cause the plugin manager to load all dynamic plugins
1643 pluginMgr->AddNotifier(PCREATE_NOTIFIER(OnLoadModule), TRUE);
1645 #if OPAL_H323
1646 // register the capabilities
1647 while (capabilityCreateList.size() > 0) {
1648 CapabilityCreateListType::iterator r = capabilityCreateList.begin();
1649 RegisterCapability(r->encoderCodec, r->decoderCodec);
1650 capabilityCreateList.erase(r);
1652 #endif
1655 OpalPluginCodecManager::~OpalPluginCodecManager()
1659 void OpalPluginCodecManager::OnShutdown()
1661 // unregister the plugin media formats
1662 OpalMediaFormatFactory::UnregisterAll();
1664 #if 0 // OPAL_H323
1665 // unregister the plugin capabilities
1666 H323CapabilityFactory::UnregisterAll();
1667 #endif
1670 void OpalPluginCodecManager::OnLoadPlugin(PDynaLink & dll, INT code)
1672 PluginCodec_GetCodecFunction getCodecs;
1673 if (!dll.GetFunction(PString(signatureFunctionName), (PDynaLink::Function &)getCodecs)) {
1674 PTRACE(2, "OpalPlugin\tPlugin Codec DLL " << dll.GetName() << " is not a plugin codec");
1675 return;
1678 unsigned int count;
1679 PluginCodec_Definition * codecs = (*getCodecs)(&count, PLUGIN_CODEC_VERSION_OPTIONS);
1680 if (codecs == NULL || count == 0) {
1681 PTRACE(1, "OpalPlugin\tPlugin Codec DLL " << dll.GetName() << " contains no codec definitions");
1682 return;
1685 // get handler for this plugin type
1686 PString name = dll.GetName();
1687 PFactory<OpalPluginCodecHandler>::KeyList_T keys = PFactory<OpalPluginCodecHandler>::GetKeyList();
1688 PFactory<OpalPluginCodecHandler>::KeyList_T::const_iterator r;
1689 OpalPluginCodecHandler * handler = NULL;
1690 for (r = keys.begin(); r != keys.end(); ++r) {
1691 if (name.Right(r->length()) *= *r) {
1692 PTRACE(3, "OpalPlugin\tUsing customer handler for codec " << name);
1693 handler = PFactory<OpalPluginCodecHandler>::CreateInstance(*r);
1694 break;
1698 if (handler == NULL) {
1699 PTRACE(3, "OpalPlugin\tUsing default handler for plugin codec " << name);
1700 handler = new OpalPluginCodecHandler;
1703 switch (code) {
1705 // plugin loaded
1706 case 0:
1707 RegisterCodecPlugins(count, codecs, handler);
1708 break;
1710 // plugin unloaded
1711 case 1:
1712 UnregisterCodecPlugins(count, codecs, handler);
1713 break;
1715 default:
1716 break;
1719 delete handler;
1722 void OpalPluginCodecManager::RegisterStaticCodec(
1723 const H323StaticPluginCodecFactory::Key_T & PTRACE_PARAM(name),
1724 PluginCodec_GetAPIVersionFunction /*getApiVerFn*/,
1725 PluginCodec_GetCodecFunction getCodecFn)
1727 unsigned int count;
1728 PluginCodec_Definition * codecs = (*getCodecFn)(&count, PLUGIN_CODEC_VERSION_OPTIONS);
1729 if (codecs == NULL || count == 0) {
1730 PTRACE(1, "OpalPlugin\tStatic codec " << name << " contains no codec definitions");
1731 return;
1734 OpalPluginCodecHandler * handler = new OpalPluginCodecHandler;
1735 RegisterCodecPlugins(count, codecs, handler);
1736 delete handler;
1739 void OpalPluginCodecManager::RegisterCodecPlugins(unsigned int count, PluginCodec_Definition * codecList, OpalPluginCodecHandler * handler)
1741 // make sure all non-timestamped codecs have the same concept of "now"
1742 static time_t codecNow = ::time(NULL);
1744 unsigned i, j ;
1745 for (i = 0; i < count; i++) {
1747 PluginCodec_Definition & encoder = codecList[i];
1749 BOOL videoSupported = encoder.version >= PLUGIN_CODEC_VERSION_VIDEO;
1750 BOOL faxSupported = encoder.version >= PLUGIN_CODEC_VERSION_FAX;
1752 // for every encoder, we need a decoder
1753 BOOL found = FALSE;
1754 BOOL isEncoder = FALSE;
1755 if (encoder.h323CapabilityType != PluginCodec_H323Codec_undefined &&
1757 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeAudio) &&
1758 strcmp(encoder.sourceFormat, "L16") == 0
1759 ) ||
1761 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeAudioStreamed) &&
1762 strcmp(encoder.sourceFormat, "L16") == 0
1763 ) ||
1765 videoSupported &&
1766 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeVideo) &&
1767 strcmp(encoder.sourceFormat, "YUV420P") == 0
1768 ) ||
1770 faxSupported &&
1771 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeFax) &&
1772 strcmp(encoder.sourceFormat, "L16") == 0
1775 isEncoder = TRUE;
1776 for (j = 0; j < count; j++) {
1778 PluginCodec_Definition & decoder = codecList[j];
1779 if (
1780 (decoder.h323CapabilityType == encoder.h323CapabilityType) &&
1781 ((decoder.flags & PluginCodec_MediaTypeMask) == (encoder.flags & PluginCodec_MediaTypeMask)) &&
1782 (strcmp(decoder.sourceFormat, encoder.destFormat) == 0) &&
1783 (strcmp(decoder.destFormat, encoder.sourceFormat) == 0)
1787 // deal with codec having no info, or timestamp in future
1788 time_t timeStamp = codecList[i].info == NULL ? codecNow : codecList[i].info->timestamp;
1789 if (timeStamp > codecNow)
1790 timeStamp = codecNow;
1792 // create the media format, transcoder and capability associated with this plugin
1793 RegisterPluginPair(&encoder, &decoder, handler);
1794 found = TRUE;
1796 PTRACE(3, "OpalPlugin\tPlugin codec " << encoder.descr << " defined");
1797 break;
1801 if (!found && isEncoder) {
1802 PTRACE(2, "OpalPlugin\tCannot find decoder for plugin encoder " << encoder.descr);
1807 void OpalPluginCodecManager::UnregisterCodecPlugins(unsigned int, PluginCodec_Definition *, OpalPluginCodecHandler * )
1811 OpalMediaFormatList & OpalPluginCodecManager::GetMediaFormatList()
1813 static OpalMediaFormatList mediaFormatList;
1814 return mediaFormatList;
1817 OpalMediaFormatList OpalPluginCodecManager::GetMediaFormats()
1819 PWaitAndSignal m(GetMediaFormatMutex());
1820 return GetMediaFormatList();
1823 void OpalPluginCodecManager::RegisterPluginPair(
1824 PluginCodec_Definition * encoderCodec,
1825 PluginCodec_Definition * decoderCodec,
1826 OpalPluginCodecHandler * handler
1829 // make sure all non-timestamped codecs have the same concept of "now"
1830 static time_t mediaNow = time(NULL);
1832 // deal with codec having no info, or timestamp in future
1833 time_t timeStamp = encoderCodec->info == NULL ? mediaNow : encoderCodec->info->timestamp;
1834 if (timeStamp > mediaNow)
1835 timeStamp = mediaNow;
1837 unsigned defaultSessionID = 0;
1838 unsigned frameTime = 0;
1839 unsigned clockRate = 0;
1840 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1841 #if OPAL_VIDEO
1842 case PluginCodec_MediaTypeVideo:
1843 defaultSessionID = OpalMediaFormat::DefaultVideoSessionID;
1844 break;
1845 #endif
1846 #if OPAL_AUDIO
1847 case PluginCodec_MediaTypeAudio:
1848 case PluginCodec_MediaTypeAudioStreamed:
1849 defaultSessionID = OpalMediaFormat::DefaultAudioSessionID;
1850 frameTime = (8 * encoderCodec->usPerFrame) / 1000;
1851 clockRate = encoderCodec->sampleRate;
1852 break;
1853 #endif
1854 #if OPAL_T38FAX
1855 case PluginCodec_MediaTypeFax:
1856 defaultSessionID = OpalMediaFormat::DefaultDataSessionID;
1857 frameTime = (8 * encoderCodec->usPerFrame) / 1000;
1858 clockRate = encoderCodec->sampleRate;
1859 break;
1860 #endif
1861 default:
1862 break;
1865 // add the media format
1866 if (defaultSessionID == 0) {
1867 PTRACE(1, "OpalPlugin\tCodec DLL provides unknown media format " << (int)(encoderCodec->flags & PluginCodec_MediaTypeMask));
1868 } else {
1869 PString fmtName = CreateCodecName(encoderCodec);
1870 OpalMediaFormat existingFormat(fmtName);
1871 if (existingFormat.IsValid() && existingFormat.GetCodecBaseTime() >= timeStamp) {
1872 PTRACE(2, "OpalPlugin\tNewer media format " << fmtName << " already exists");
1873 //AddFormat(existingFormat);
1874 } else {
1875 if (existingFormat.IsValid()) {
1876 PWaitAndSignal m(GetMediaFormatMutex());
1877 GetMediaFormatList() -= existingFormat;
1880 PTRACE(3, "OpalPlugin\tCreating new media format " << fmtName);
1882 OpalMediaFormat * mediaFormat = NULL;
1884 // manually register the new singleton type, as we do not have a concrete type
1885 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1886 #if OPAL_VIDEO
1887 case PluginCodec_MediaTypeVideo:
1888 mediaFormat = handler->OnCreateVideoFormat(*this, encoderCodec, encoderCodec->sdpFormat, timeStamp);
1889 break;
1890 #endif
1891 #if OPAL_AUDIO
1892 case PluginCodec_MediaTypeAudio:
1893 case PluginCodec_MediaTypeAudioStreamed:
1894 mediaFormat = handler->OnCreateAudioFormat(*this, encoderCodec, encoderCodec->sdpFormat, frameTime, clockRate, timeStamp);
1895 break;
1896 #endif
1897 #if OPAL_T38FAX
1898 case PluginCodec_MediaTypeFax:
1899 mediaFormat = handler->OnCreateFaxFormat(*this, encoderCodec, encoderCodec->sdpFormat, frameTime, clockRate, timeStamp);
1900 break;
1901 #endif
1902 default:
1903 break;
1905 // if the codec has been flagged to use a shared RTP payload type, then find a codec with the same SDP name
1906 // and clock rate and use that RTP code rather than creating a new one. That prevents codecs (like Speex) from
1907 // consuming dozens of dynamic RTP types
1908 if ((encoderCodec->flags & PluginCodec_RTPTypeShared) != 0 && (encoderCodec->sdpFormat != NULL)) {
1909 PWaitAndSignal m(OpalPluginCodecManager::GetMediaFormatMutex());
1910 OpalMediaFormatList & list = OpalPluginCodecManager::GetMediaFormatList();
1911 for (PINDEX i = 0; i < list.GetSize(); i++) {
1912 OpalMediaFormat * opalFmt = &list[i];
1913 #if OPAL_AUDIO
1915 OpalPluginAudioMediaFormat * fmt = dynamic_cast<OpalPluginAudioMediaFormat *>(opalFmt);
1916 if (
1917 (fmt != NULL) &&
1918 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1919 (fmt->encoderCodec->sdpFormat != NULL) &&
1920 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1922 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1923 break;
1926 #endif
1927 #if OPAL_VIDEO
1929 OpalPluginVideoMediaFormat * fmt = dynamic_cast<OpalPluginVideoMediaFormat *>(opalFmt);
1930 if (
1931 (fmt != NULL) &&
1932 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1933 (fmt->encoderCodec->sdpFormat != NULL) &&
1934 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1936 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1937 break;
1940 #endif
1941 #if OPAL_T38FAX
1943 OpalPluginFaxMediaFormat * fmt = dynamic_cast<OpalPluginFaxMediaFormat *>(opalFmt);
1944 if (
1945 (fmt != NULL) &&
1946 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1947 (fmt->encoderCodec->sdpFormat != NULL) &&
1948 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1950 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1951 break;
1954 #endif
1958 // save the format
1959 AddFormat(*mediaFormat);
1961 // this looks like a memory leak, but it isn't
1962 //delete mediaFormat;
1966 // Create transcoder factories for the codecs
1967 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1968 #if OPAL_VIDEO
1969 case PluginCodec_MediaTypeVideo:
1970 handler->CreateVideoTranscoder(OpalYUV420P, encoderCodec->destFormat, encoderCodec, TRUE);
1971 handler->CreateVideoTranscoder(encoderCodec->destFormat, OpalYUV420P, decoderCodec, FALSE);
1972 break;
1973 #endif
1974 #if OPAL_AUDIO
1975 case PluginCodec_MediaTypeAudio:
1976 if (encoderCodec->sampleRate == 8000) {
1977 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalTranscoderKey(OpalPCM16, encoderCodec->destFormat), encoderCodec, TRUE);
1978 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16), decoderCodec, FALSE);
1980 else if (encoderCodec->sampleRate == 16000)
1982 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalTranscoderKey(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, TRUE);
1983 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, FALSE);
1985 else
1987 PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate);
1989 break;
1990 case PluginCodec_MediaTypeAudioStreamed:
1991 if (encoderCodec->sampleRate == 8000) {
1992 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioEncoder>::Worker(OpalTranscoderKey(OpalPCM16, encoderCodec->destFormat), encoderCodec, TRUE);
1993 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioDecoder>::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16), decoderCodec, FALSE);
1995 else if (encoderCodec->sampleRate == 16000)
1997 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioEncoder>::Worker(OpalTranscoderKey(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, TRUE);
1998 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioDecoder>::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, FALSE);
2000 else
2002 PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate);
2004 break;
2005 #endif
2006 #if OPAL_T38FAX
2007 case PluginCodec_MediaTypeFax:
2008 new OpalPluginTranscoderFactory<OpalFaxAudioTranscoder>::Worker(OpalTranscoderKey(GetOpalPCM16Fax(), encoderCodec->destFormat), encoderCodec, TRUE);
2009 new OpalPluginTranscoderFactory<OpalFaxAudioTranscoder>::Worker(OpalTranscoderKey(encoderCodec->destFormat, GetOpalPCM16Fax()), decoderCodec, FALSE);
2010 break;
2011 #endif
2012 default:
2013 break;
2016 int retVal;
2017 unsigned int parmLen = sizeof(const char *);
2018 BOOL hasCodecControl = OpalPluginMediaFormat::CallCodecControl(encoderCodec, "valid_for_protocol", (void *)"h323", &parmLen, retVal);
2019 if (encoderCodec->h323CapabilityType == PluginCodec_H323Codec_NoH323 ||
2020 (hasCodecControl && (retVal == 0))
2022 PTRACE(2, "OpalPlugin\tNot adding H.323 capability for plugin codec " << encoderCodec->destFormat << " as this has been specifically disabled");
2023 return;
2026 #if OPAL_H323
2027 PTRACE(4, "OpalPlugin\tDeferring creation of H.323 capability for plugin codec " << encoderCodec->destFormat);
2028 capabilityCreateList.push_back(CapabilityListCreateEntry(encoderCodec, decoderCodec));
2029 #endif
2032 #if OPAL_H323
2034 void OpalPluginCodecManager::RegisterCapability(PluginCodec_Definition * encoderCodec, PluginCodec_Definition * decoderCodec)
2036 // add the capability
2037 H323CodecPluginCapabilityMapEntry * map = NULL;
2039 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
2040 #if OPAL_AUDIO
2041 case PluginCodec_MediaTypeAudio:
2042 case PluginCodec_MediaTypeAudioStreamed:
2043 map = audioMaps;
2044 break;
2045 #endif // OPAL_AUDIO
2047 #if OPAL_VIDEO
2048 case PluginCodec_MediaTypeVideo:
2049 map = videoMaps;
2050 break;
2051 #endif // OPAL_VIDEO
2053 default:
2054 break;
2057 if (map == NULL) {
2058 PTRACE(1, "OpalPlugin\tCannot create capability for unknown plugin codec media format " << (int)(encoderCodec->flags & PluginCodec_MediaTypeMask));
2060 else if (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_undefined) {
2061 for (PINDEX i = 0; map[i].pluginCapType >= 0; i++) {
2062 if (map[i].pluginCapType == encoderCodec->h323CapabilityType) {
2063 H323Capability * cap = NULL;
2064 if (map[i].createFunc != NULL)
2065 cap = (*map[i].createFunc)(encoderCodec, decoderCodec, map[i].h323SubType);
2066 else {
2067 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
2068 #if OPAL_AUDIO
2069 case PluginCodec_MediaTypeAudio:
2070 case PluginCodec_MediaTypeAudioStreamed:
2071 cap = new H323AudioPluginCapability(encoderCodec, decoderCodec, map[i].h323SubType);
2072 break;
2073 #endif // OPAL_AUDIO
2075 #if OPAL_VIDEO
2076 case PluginCodec_MediaTypeVideo:
2077 PTRACE(4, "OpalPlugin\tWarning - no capability creation function for " << CreateCodecName(encoderCodec));
2078 // all video caps are created using the create functions
2079 break;
2080 #endif // OPAL_VIDEO
2082 default:
2083 break;
2087 // manually register the new singleton type, as we do not have a concrete type
2088 if (cap != NULL)
2089 H323CapabilityFactory::Register(CreateCodecName(encoderCodec), cap);
2090 break;
2095 #endif // OPAL_H323
2097 void OpalPluginCodecManager::AddFormat(const OpalMediaFormat & fmt)
2099 OpalMediaFormat::SetRegisteredMediaFormat(fmt);
2101 PWaitAndSignal m(GetMediaFormatMutex());
2102 GetMediaFormatList() += fmt;
2106 /////////////////////////////////////////////////////////////////////////////
2108 OpalPluginCodecHandler::OpalPluginCodecHandler()
2112 #if OPAL_AUDIO
2113 OpalMediaFormat * OpalPluginCodecHandler::OnCreateAudioFormat(OpalPluginCodecManager & /*mgr*/,
2114 const PluginCodec_Definition * encoderCodec,
2115 const char * rtpEncodingName,
2116 unsigned frameTime,
2117 unsigned timeUnits,
2118 time_t timeStamp)
2120 return new OpalPluginAudioMediaFormat(encoderCodec, rtpEncodingName, frameTime, timeUnits, timeStamp);
2122 #endif
2124 #if OPAL_VIDEO
2125 OpalMediaFormat * OpalPluginCodecHandler::OnCreateVideoFormat(OpalPluginCodecManager & /*mgr*/,
2126 const PluginCodec_Definition * encoderCodec,
2127 const char * rtpEncodingName,
2128 time_t timeStamp)
2130 return new OpalPluginVideoMediaFormat(encoderCodec, rtpEncodingName, timeStamp);
2133 void OpalPluginCodecHandler::CreateVideoTranscoder(const OpalMediaFormat & src, const OpalMediaFormat & dst, PluginCodec_Definition * codec, BOOL v)
2135 new OpalPluginTranscoderFactory<OpalPluginVideoTranscoder>::Worker(OpalTranscoderKey(src, dst), codec, v);
2138 #endif
2140 #if OPAL_T38FAX
2141 OpalMediaFormat * OpalPluginCodecHandler::OnCreateFaxFormat(OpalPluginCodecManager & /*mgr*/,
2142 const PluginCodec_Definition * encoderCodec,
2143 const char * rtpEncodingName,
2144 unsigned frameTime,
2145 unsigned timeUnits,
2146 time_t timeStamp)
2148 return new OpalPluginFaxMediaFormat(encoderCodec, rtpEncodingName, frameTime, timeUnits, timeStamp);
2150 #endif
2152 /////////////////////////////////////////////////////////////////////////////
2154 #if OPAL_H323
2156 #if OPAL_AUDIO
2158 H323Capability * CreateNonStandardAudioCap(const PluginCodec_Definition * encoderCodec,
2159 const PluginCodec_Definition * decoderCodec,
2160 int /*subType*/)
2162 PluginCodec_H323NonStandardCodecData * pluginData = (PluginCodec_H323NonStandardCodecData *)encoderCodec->h323CapabilityData;
2163 if (pluginData == NULL) {
2164 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2165 decoderCodec,
2166 (const unsigned char *)encoderCodec->descr,
2167 strlen(encoderCodec->descr));
2170 else if (pluginData->capabilityMatchFunction != NULL)
2171 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2172 decoderCodec,
2173 (H323NonStandardCapabilityInfo::CompareFuncType)pluginData->capabilityMatchFunction,
2174 pluginData->data,
2175 pluginData->dataLength);
2176 else
2177 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2178 decoderCodec,
2179 pluginData->data,
2180 pluginData->dataLength);
2183 H323Capability *CreateGenericAudioCap(const PluginCodec_Definition * encoderCodec,
2184 const PluginCodec_Definition * decoderCodec,
2185 int /*subType*/)
2187 PluginCodec_H323GenericCodecData * pluginData = (PluginCodec_H323GenericCodecData *)encoderCodec->h323CapabilityData;
2188 if (pluginData != NULL )
2189 return new H323CodecPluginGenericAudioCapability(encoderCodec, decoderCodec, pluginData);
2191 PTRACE(1, "OpalPlugin\tGeneric codec information for codec '"<<encoderCodec->descr<<"' has NULL data field");
2192 return NULL;
2195 H323Capability * CreateG7231Cap(const PluginCodec_Definition * encoderCodec,
2196 const PluginCodec_Definition * decoderCodec,
2197 int /*subType*/)
2199 return new H323PluginG7231Capability(encoderCodec, decoderCodec, decoderCodec->h323CapabilityData != 0);
2203 H323Capability * CreateGSMCap(const PluginCodec_Definition * encoderCodec,
2204 const PluginCodec_Definition * decoderCodec,
2205 int subType)
2207 PluginCodec_H323AudioGSMData * pluginData = (PluginCodec_H323AudioGSMData *)encoderCodec->h323CapabilityData;
2208 return new H323GSMPluginCapability(encoderCodec, decoderCodec, subType, pluginData->comfortNoise, pluginData->scrambled);
2211 #endif // OPAL_AUDIO
2213 #if OPAL_VIDEO
2215 H323Capability * CreateNonStandardVideoCap(const PluginCodec_Definition * encoderCodec,
2216 const PluginCodec_Definition * decoderCodec,
2217 int /*subType*/)
2219 PluginCodec_H323NonStandardCodecData * pluginData = (PluginCodec_H323NonStandardCodecData *)encoderCodec->h323CapabilityData;
2220 if (pluginData == NULL) {
2221 return new H323CodecPluginNonStandardVideoCapability(
2222 encoderCodec, decoderCodec,
2223 (const unsigned char *)encoderCodec->descr,
2224 strlen(encoderCodec->descr));
2227 else if (pluginData->capabilityMatchFunction != NULL)
2228 return new H323CodecPluginNonStandardVideoCapability(encoderCodec, decoderCodec,
2229 (H323NonStandardCapabilityInfo::CompareFuncType)pluginData->capabilityMatchFunction,
2230 pluginData->data, pluginData->dataLength);
2231 else
2232 return new H323CodecPluginNonStandardVideoCapability(
2233 encoderCodec, decoderCodec,
2234 pluginData->data, pluginData->dataLength);
2237 H323Capability *CreateGenericVideoCap(const PluginCodec_Definition * encoderCodec,
2238 const PluginCodec_Definition * decoderCodec,
2239 int /*subType*/)
2241 PluginCodec_H323GenericCodecData * pluginData = (PluginCodec_H323GenericCodecData *)encoderCodec->h323CapabilityData;
2242 if (pluginData != NULL )
2243 return new H323CodecPluginGenericVideoCapability(encoderCodec, decoderCodec, pluginData);
2245 PTRACE(1, "OpalPlugin\tGeneric codec information for codec '"<<encoderCodec->descr<<"' has NULL data field");
2246 return NULL;
2250 H323Capability * CreateH261Cap(const PluginCodec_Definition * encoderCodec,
2251 const PluginCodec_Definition * decoderCodec,
2252 int /*subType*/)
2254 PTRACE(4, "OpalPlugin\tCreating H.261 plugin capability");
2255 return new H323H261PluginCapability(encoderCodec, decoderCodec);
2258 H323Capability * CreateH263Cap(const PluginCodec_Definition * encoderCodec,
2259 const PluginCodec_Definition * decoderCodec,
2260 int /*subType*/)
2262 PTRACE(4, "OpalPlugin\tCreating H.263 plugin capability");
2263 return new H323H263PluginCapability(encoderCodec, decoderCodec);
2266 #endif // OPAL_VIDEO
2268 /////////////////////////////////////////////////////////////////////////////
2270 H323PluginCapabilityInfo::H323PluginCapabilityInfo(const PluginCodec_Definition * _encoderCodec,
2271 const PluginCodec_Definition * _decoderCodec)
2272 : encoderCodec(_encoderCodec),
2273 decoderCodec(_decoderCodec),
2274 capabilityFormatName(CreateCodecName(_encoderCodec))
2278 H323PluginCapabilityInfo::H323PluginCapabilityInfo(const PString & _baseName)
2279 : encoderCodec(NULL),
2280 decoderCodec(NULL),
2281 capabilityFormatName(_baseName)
2285 #if OPAL_AUDIO
2287 /////////////////////////////////////////////////////////////////////////////
2289 H323CodecPluginNonStandardAudioCapability::H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * _encoderCodec,
2290 const PluginCodec_Definition * _decoderCodec,
2291 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
2292 const unsigned char * data, unsigned dataLen)
2293 : H323NonStandardAudioCapability(compareFunc,data, dataLen),
2294 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2296 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2298 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2299 if (nonStdData->objectId != NULL) {
2300 oid = PString(nonStdData->objectId);
2301 } else {
2302 t35CountryCode = nonStdData->t35CountryCode;
2303 t35Extension = nonStdData->t35Extension;
2304 manufacturerCode = nonStdData->manufacturerCode;
2308 H323CodecPluginNonStandardAudioCapability::H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * _encoderCodec,
2309 const PluginCodec_Definition * _decoderCodec,
2310 const unsigned char * data, unsigned dataLen)
2311 : H323NonStandardAudioCapability(data, dataLen),
2312 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2314 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2315 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2316 if (nonStdData->objectId != NULL) {
2317 oid = PString(nonStdData->objectId);
2318 } else {
2319 t35CountryCode = nonStdData->t35CountryCode;
2320 t35Extension = nonStdData->t35Extension;
2321 manufacturerCode = nonStdData->manufacturerCode;
2325 PObject * H323CodecPluginNonStandardAudioCapability::Clone() const
2326 { return new H323CodecPluginNonStandardAudioCapability(*this); }
2328 PString H323CodecPluginNonStandardAudioCapability::GetFormatName() const
2329 { return H323PluginCapabilityInfo::GetFormatName();}
2331 /////////////////////////////////////////////////////////////////////////////
2333 H323CodecPluginGenericAudioCapability::H323CodecPluginGenericAudioCapability(const PluginCodec_Definition * _encoderCodec,
2334 const PluginCodec_Definition * _decoderCodec,
2335 const PluginCodec_H323GenericCodecData *data )
2336 : H323GenericAudioCapability(data->standardIdentifier, data->maxBitRate ? data->maxBitRate : 0),
2337 H323PluginCapabilityInfo((PluginCodec_Definition *)_encoderCodec, (PluginCodec_Definition *) _decoderCodec)
2339 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2341 PopulateMediaFormatFromGenericData(GetWritableMediaFormat(), data);
2344 PObject * H323CodecPluginGenericAudioCapability::Clone() const
2345 { return new H323CodecPluginGenericAudioCapability(*this); }
2347 PString H323CodecPluginGenericAudioCapability::GetFormatName() const
2348 { return H323PluginCapabilityInfo::GetFormatName();}
2350 /////////////////////////////////////////////////////////////////////////////
2352 PObject::Comparison H323GSMPluginCapability::Compare(const PObject & obj) const
2354 if (!PIsDescendant(&obj, H323GSMPluginCapability))
2355 return LessThan;
2357 Comparison result = H323AudioCapability::Compare(obj);
2358 if (result != EqualTo)
2359 return result;
2361 const H323GSMPluginCapability& other = (const H323GSMPluginCapability&)obj;
2362 if (scrambled < other.scrambled)
2363 return LessThan;
2364 if (comfortNoise < other.comfortNoise)
2365 return LessThan;
2366 return EqualTo;
2370 BOOL H323GSMPluginCapability::OnSendingPDU(H245_AudioCapability & cap, unsigned packetSize) const
2372 cap.SetTag(pluginSubType);
2373 H245_GSMAudioCapability & gsm = cap;
2374 gsm.m_audioUnitSize = packetSize * encoderCodec->parm.audio.bytesPerFrame;
2375 gsm.m_comfortNoise = comfortNoise;
2376 gsm.m_scrambled = scrambled;
2378 return TRUE;
2382 BOOL H323GSMPluginCapability::OnReceivedPDU(const H245_AudioCapability & cap, unsigned & packetSize)
2384 const H245_GSMAudioCapability & gsm = cap;
2385 packetSize = gsm.m_audioUnitSize / encoderCodec->parm.audio.bytesPerFrame;
2386 if (packetSize == 0)
2387 packetSize = 1;
2389 scrambled = gsm.m_scrambled;
2390 comfortNoise = gsm.m_comfortNoise;
2392 return TRUE;
2395 /////////////////////////////////////////////////////////////////////////////
2397 #endif // OPAL_AUDIO
2399 #if OPAL_VIDEO
2401 //////////////////////////////////////////////////////////////////////////////
2403 // Class for handling most videoplugin capabilities
2406 H323VideoPluginCapability::H323VideoPluginCapability(const PluginCodec_Definition * _encoderCodec,
2407 const PluginCodec_Definition * _decoderCodec,
2408 unsigned _pluginSubType)
2409 : H323VideoCapability(), H323PluginCapabilityInfo(_encoderCodec, _decoderCodec),
2410 pluginSubType(_pluginSubType)
2414 PString H323VideoPluginCapability::GetFormatName() const
2415 { return H323PluginCapabilityInfo::GetFormatName();}
2417 unsigned H323VideoPluginCapability::GetSubType() const
2418 { return pluginSubType; }
2420 BOOL H323VideoPluginCapability::SetCommonOptions(OpalMediaFormat & mediaFormat, int frameWidth, int frameHeight, int frameRate)
2422 if (!mediaFormat.SetOptionInteger(OpalVideoFormat::FrameWidthOption(), frameWidth))
2423 return FALSE;
2425 if (!mediaFormat.SetOptionInteger(OpalVideoFormat::FrameHeightOption(), frameHeight))
2426 return FALSE;
2428 if (!mediaFormat.SetOptionInteger(OpalMediaFormat::FrameTimeOption(), OpalMediaFormat::VideoClockRate * 100 * frameRate / 2997))
2429 return FALSE;
2431 return TRUE;
2434 void H323VideoPluginCapability::PrintOn(std::ostream & strm) const
2436 H323VideoCapability::PrintOn(strm);
2439 /////////////////////////////////////////////////////////////////////////////
2441 H323H261PluginCapability::H323H261PluginCapability(const PluginCodec_Definition * _encoderCodec,
2442 const PluginCodec_Definition * _decoderCodec)
2443 : H323VideoPluginCapability(_encoderCodec, _decoderCodec, H245_VideoCapability::e_h261VideoCapability)
2445 const OpalMediaFormat & fmt = GetMediaFormat();
2446 if (!fmt.HasOption(qcifMPI_tag) && !fmt.HasOption(cifMPI_tag))
2447 GetWritableMediaFormat().AddOption(new OpalMediaOptionUnsigned(cifMPI_tag, false, OpalMediaOption::MinMerge, 4));
2450 PObject::Comparison H323H261PluginCapability::Compare(const PObject & obj) const
2452 if (!PIsDescendant(&obj, H323H261PluginCapability))
2453 return LessThan;
2455 Comparison result = H323Capability::Compare(obj);
2456 if (result != EqualTo)
2457 return result;
2459 const H323H261PluginCapability & other = (const H323H261PluginCapability &)obj;
2461 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2462 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2463 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2465 const OpalMediaFormat & otherFormat = other.GetMediaFormat();
2466 int other_qcifMPI = otherFormat.GetOptionInteger(qcifMPI_tag);
2467 int other_cifMPI = otherFormat.GetOptionInteger(cifMPI_tag);
2469 if (((qcifMPI > 0) && (other_qcifMPI > 0)) ||
2470 ((cifMPI > 0) && (other_cifMPI > 0)))
2471 return EqualTo;
2473 if (qcifMPI > 0)
2474 return LessThan;
2476 return GreaterThan;
2479 PObject * H323H261PluginCapability::Clone() const
2481 return new H323H261PluginCapability(*this);
2484 BOOL H323H261PluginCapability::OnSendingPDU(H245_VideoCapability & cap) const
2486 cap.SetTag(H245_VideoCapability::e_h261VideoCapability);
2488 H245_H261VideoCapability & h261 = cap;
2490 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2493 #if PTRACING
2494 ostream & traceStream = PTrace::Begin(4, __FILE__, __LINE__);
2495 traceStream << "H.261 extracting options from\n";
2496 for (PINDEX i = 0; i < mediaFormat.GetOptionCount(); i++) {
2497 const OpalMediaOption & option = mediaFormat.GetOption(i);
2498 traceStream << " " << option.GetName() << " = " << option.AsString() << '\n';
2500 traceStream << PTrace::End;
2501 #endif
2504 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag, 0);
2505 if (qcifMPI > 0) {
2506 h261.IncludeOptionalField(H245_H261VideoCapability::e_qcifMPI);
2507 h261.m_qcifMPI = qcifMPI;
2509 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2510 if (cifMPI > 0 || qcifMPI == 0) {
2511 h261.IncludeOptionalField(H245_H261VideoCapability::e_cifMPI);
2512 h261.m_cifMPI = cifMPI;
2515 h261.m_temporalSpatialTradeOffCapability = mediaFormat.GetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, FALSE);
2516 h261.m_maxBitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 621700)+50)/100;
2517 h261.m_stillImageTransmission = mediaFormat.GetOptionBoolean(h323_stillImageTransmission_tag, FALSE);
2519 return TRUE;
2523 BOOL H323H261PluginCapability::OnSendingPDU(H245_VideoMode & pdu) const
2525 pdu.SetTag(H245_VideoMode::e_h261VideoMode);
2526 H245_H261VideoMode & mode = pdu;
2528 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2530 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2532 mode.m_resolution.SetTag(qcifMPI > 0 ? H245_H261VideoMode_resolution::e_qcif
2533 : H245_H261VideoMode_resolution::e_cif);
2535 mode.m_bitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 621700) + 50) / 1000;
2536 mode.m_stillImageTransmission = mediaFormat.GetOptionBoolean(h323_stillImageTransmission_tag, FALSE);
2538 return TRUE;
2541 BOOL H323H261PluginCapability::OnReceivedPDU(const H245_VideoCapability & cap)
2543 if (cap.GetTag() != H245_VideoCapability::e_h261VideoCapability)
2544 return FALSE;
2546 OpalMediaFormat & mediaFormat = GetWritableMediaFormat();
2548 const H245_H261VideoCapability & h261 = cap;
2549 if (h261.HasOptionalField(H245_H261VideoCapability::e_qcifMPI)) {
2551 if (!mediaFormat.SetOptionInteger(qcifMPI_tag, h261.m_qcifMPI))
2552 return FALSE;
2554 if (!SetCommonOptions(mediaFormat, QCIF_WIDTH, QCIF_HEIGHT, h261.m_qcifMPI))
2555 return FALSE;
2558 if (h261.HasOptionalField(H245_H261VideoCapability::e_cifMPI)) {
2560 if (!mediaFormat.SetOptionInteger(cifMPI_tag, h261.m_cifMPI))
2561 return FALSE;
2563 if (!SetCommonOptions(mediaFormat, QCIF_WIDTH, QCIF_HEIGHT, h261.m_cifMPI))
2564 return FALSE;
2567 mediaFormat.SetOptionInteger(OpalMediaFormat::MaxBitRateOption(), h261.m_maxBitRate*100);
2568 mediaFormat.SetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, h261.m_temporalSpatialTradeOffCapability);
2569 mediaFormat.SetOptionBoolean(h323_stillImageTransmission_tag, h261.m_stillImageTransmission);
2571 return TRUE;
2574 /////////////////////////////////////////////////////////////////////////////
2576 H323H263PluginCapability::H323H263PluginCapability(const PluginCodec_Definition * _encoderCodec,
2577 const PluginCodec_Definition * _decoderCodec)
2578 : H323VideoPluginCapability(_encoderCodec, _decoderCodec, H245_VideoCapability::e_h263VideoCapability)
2582 PObject::Comparison H323H263PluginCapability::Compare(const PObject & obj) const
2584 if (!PIsDescendant(&obj, H323H263PluginCapability))
2585 return LessThan;
2587 Comparison result = H323Capability::Compare(obj);
2588 if (result != EqualTo)
2589 return result;
2591 const H323H263PluginCapability & other = (const H323H263PluginCapability &)obj;
2593 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2595 int sqcifMPI = mediaFormat.GetOptionInteger(sqcifMPI_tag);
2596 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2597 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2598 int cif4MPI = mediaFormat.GetOptionInteger(cif4MPI_tag);
2599 int cif16MPI = mediaFormat.GetOptionInteger(cif16MPI_tag);
2601 const OpalMediaFormat & otherFormat = other.GetMediaFormat();
2602 int other_sqcifMPI = otherFormat.GetOptionInteger(sqcifMPI_tag);
2603 int other_qcifMPI = otherFormat.GetOptionInteger(qcifMPI_tag);
2604 int other_cifMPI = otherFormat.GetOptionInteger(cifMPI_tag);
2605 int other_cif4MPI = otherFormat.GetOptionInteger(cif4MPI_tag);
2606 int other_cif16MPI = otherFormat.GetOptionInteger(cif16MPI_tag);
2608 if ((sqcifMPI && other_sqcifMPI) ||
2609 (qcifMPI && other_qcifMPI) ||
2610 (cifMPI && other_cifMPI) ||
2611 (cif4MPI && other_cif4MPI) ||
2612 (cif16MPI && other_cif16MPI)) {
2613 PTRACE(5, "H.263\t" << *this << " == " << other);
2614 return EqualTo;
2617 if ((!cif16MPI && other_cif16MPI) ||
2618 (!cif4MPI && other_cif4MPI) ||
2619 (!cifMPI && other_cifMPI) ||
2620 (!qcifMPI && other_qcifMPI) ||
2621 (!sqcifMPI && other_sqcifMPI)) {
2622 PTRACE(5, "H.263\t" << *this << " < " << other);
2623 return LessThan;
2626 PTRACE(5, "H.263\t" << *this << " > " << other << " are equal");
2627 return GreaterThan;
2630 PObject * H323H263PluginCapability::Clone() const
2631 { return new H323H263PluginCapability(*this); }
2633 static void SetTransmittedCap(const OpalMediaFormat & mediaFormat,
2634 H245_H263VideoCapability & h263,
2635 const char * mpiTag,
2636 int mpiEnum,
2637 PASN_Integer & mpi,
2638 int slowMpiEnum,
2639 PASN_Integer & slowMpi)
2641 int mpiVal = mediaFormat.GetOptionInteger(mpiTag);
2642 if (mpiVal > 0) {
2643 h263.IncludeOptionalField(mpiEnum);
2644 mpi = mpiVal;
2646 else if (mpiVal < 0) {
2647 h263.IncludeOptionalField(slowMpiEnum);
2648 slowMpi = -mpiVal;
2653 BOOL H323H263PluginCapability::OnSendingPDU(H245_VideoCapability & cap) const
2655 cap.SetTag(H245_VideoCapability::e_h263VideoCapability);
2656 H245_H263VideoCapability & h263 = cap;
2658 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2660 //PStringStream str; mediaFormat.PrintOptions(str);
2661 //PTRACE(5, "OpalPlugin\tCreating capability for " << mediaFormat << ", options=\n" << str);
2663 SetTransmittedCap(mediaFormat, cap, sqcifMPI_tag, H245_H263VideoCapability::e_sqcifMPI, h263.m_sqcifMPI, H245_H263VideoCapability::e_slowSqcifMPI, h263.m_slowSqcifMPI);
2664 SetTransmittedCap(mediaFormat, cap, qcifMPI_tag, H245_H263VideoCapability::e_qcifMPI, h263.m_qcifMPI, H245_H263VideoCapability::e_slowQcifMPI, h263.m_slowQcifMPI);
2665 SetTransmittedCap(mediaFormat, cap, cifMPI_tag, H245_H263VideoCapability::e_cifMPI, h263.m_cifMPI, H245_H263VideoCapability::e_slowCifMPI, h263.m_slowCifMPI);
2666 SetTransmittedCap(mediaFormat, cap, cif4MPI_tag, H245_H263VideoCapability::e_cif4MPI, h263.m_cif4MPI, H245_H263VideoCapability::e_slowCif4MPI, h263.m_slowCif4MPI);
2667 SetTransmittedCap(mediaFormat, cap, cif16MPI_tag, H245_H263VideoCapability::e_cif16MPI, h263.m_cif16MPI, H245_H263VideoCapability::e_slowCif16MPI, h263.m_slowCif16MPI);
2669 h263.m_maxBitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 327600) + 50) / 100;
2670 h263.m_temporalSpatialTradeOffCapability = mediaFormat.GetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, FALSE);
2671 h263.m_unrestrictedVector = mediaFormat.GetOptionBoolean(h323_unrestrictedVector_tag, FALSE);
2672 h263.m_arithmeticCoding = mediaFormat.GetOptionBoolean(h323_arithmeticCoding_tag, FALSE);
2673 h263.m_advancedPrediction = mediaFormat.GetOptionBoolean(h323_advancedPrediction_tag, FALSE);
2674 h263.m_pbFrames = mediaFormat.GetOptionBoolean(h323_pbFrames_tag, FALSE);
2675 h263.m_errorCompensation = mediaFormat.GetOptionBoolean(h323_errorCompensation_tag, FALSE);
2678 int hrdB = mediaFormat.GetOptionInteger(h323_hrdB_tag, -1);
2679 if (hrdB >= 0) {
2680 h263.IncludeOptionalField(H245_H263VideoCapability::e_hrd_B);
2681 h263.m_hrd_B = hrdB;
2686 int bppMaxKb = mediaFormat.GetOptionInteger(h323_bppMaxKb_tag, -1);
2687 if (bppMaxKb >= 0) {
2688 h263.IncludeOptionalField(H245_H263VideoCapability::e_bppMaxKb);
2689 h263.m_bppMaxKb = bppMaxKb;
2693 return TRUE;
2697 BOOL H323H263PluginCapability::OnSendingPDU(H245_VideoMode & pdu) const
2699 pdu.SetTag(H245_VideoMode::e_h263VideoMode);
2700 H245_H263VideoMode & mode = pdu;
2702 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2704 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2705 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2706 int cif4MPI = mediaFormat.GetOptionInteger(cif4MPI_tag);
2707 int cif16MPI = mediaFormat.GetOptionInteger(cif16MPI_tag);
2709 mode.m_resolution.SetTag(cif16MPI ? H245_H263VideoMode_resolution::e_cif16
2710 :(cif4MPI ? H245_H263VideoMode_resolution::e_cif4
2711 :(cifMPI ? H245_H263VideoMode_resolution::e_cif
2712 :(qcifMPI ? H245_H263VideoMode_resolution::e_qcif
2713 : H245_H263VideoMode_resolution::e_sqcif))));
2715 mode.m_bitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 327600) + 50) / 100;
2716 mode.m_unrestrictedVector = mediaFormat.GetOptionBoolean(h323_unrestrictedVector_tag, FALSE);
2717 mode.m_arithmeticCoding = mediaFormat.GetOptionBoolean(h323_arithmeticCoding_tag, FALSE);
2718 mode.m_advancedPrediction = mediaFormat.GetOptionBoolean(h323_advancedPrediction_tag, FALSE);
2719 mode.m_pbFrames = mediaFormat.GetOptionBoolean(h323_pbFrames_tag, FALSE);
2720 mode.m_errorCompensation = mediaFormat.GetOptionBoolean(h323_errorCompensation_tag, FALSE);
2722 return TRUE;
2725 static BOOL SetReceivedH263Cap(OpalMediaFormat & mediaFormat,
2726 const H245_H263VideoCapability & h263,
2727 const char * mpiTag,
2728 int mpiEnum,
2729 const PASN_Integer & mpi,
2730 int slowMpiEnum,
2731 const PASN_Integer & slowMpi,
2732 int frameWidth, int frameHeight,
2733 BOOL & formatDefined)
2735 if (h263.HasOptionalField(mpiEnum)) {
2736 if (!mediaFormat.SetOptionInteger(mpiTag, mpi))
2737 return FALSE;
2738 if (mpi != 0) {
2739 if (!H323VideoPluginCapability::SetCommonOptions(mediaFormat, frameWidth, frameHeight, mpi))
2740 return FALSE;
2741 formatDefined = TRUE;
2744 else if (h263.HasOptionalField(slowMpiEnum)) {
2745 if (!mediaFormat.SetOptionInteger(mpiTag, -(signed)slowMpi))
2746 return FALSE;
2747 if (slowMpi != 0) {
2748 if (!H323VideoPluginCapability::SetCommonOptions(mediaFormat, frameWidth, frameHeight, -(signed)slowMpi))
2749 return FALSE;
2750 formatDefined = TRUE;
2753 else
2754 mediaFormat.SetOptionInteger(mpiTag, 0);
2756 return TRUE;
2759 BOOL H323H263PluginCapability::IsMatch(const PASN_Choice & subTypePDU) const
2761 if (!H323Capability::IsMatch(subTypePDU))
2762 return FALSE;
2764 H245_VideoCapability & video = (H245_VideoCapability &)subTypePDU;
2765 H245_H263VideoCapability & h263 = (H245_H263VideoCapability &)video;
2767 #define COMPARE_MPI(field, slowField) \
2768 if ( \
2769 ((GetMediaFormat().GetOptionInteger(field##_tag) > 0) ? TRUE : FALSE) \
2770 != \
2771 (h263.HasOptionalField(H245_H263VideoCapability::e_##field) ? (h263.m_##field != 0) : FALSE) \
2773 return FALSE; \
2774 if ( \
2775 ((GetMediaFormat().GetOptionInteger(field##_tag) < 0) ? TRUE : FALSE) \
2776 != \
2777 (h263.HasOptionalField(H245_H263VideoCapability::e_##slowField) ? (h263.m_##slowField != 0) : FALSE) \
2779 return FALSE; \
2780 if ( \
2781 ((GetMediaFormat().GetOptionInteger(field##_tag) < 0) ? TRUE : FALSE) \
2782 != \
2783 (h263.HasOptionalField(H245_H263VideoCapability::e_##slowField) ? (h263.m_##slowField != 0) : FALSE) \
2785 return FALSE; \
2787 COMPARE_MPI(sqcifMPI, slowSqcifMPI);
2788 COMPARE_MPI(qcifMPI, slowQcifMPI);
2789 COMPARE_MPI(cifMPI, slowCifMPI);
2790 COMPARE_MPI(cif4MPI, slowCif4MPI);
2791 COMPARE_MPI(cif16MPI, slowCif16MPI);
2794 return TRUE;
2798 BOOL H323H263PluginCapability::OnReceivedPDU(const H245_VideoCapability & cap)
2800 if (cap.GetTag() != H245_VideoCapability::e_h263VideoCapability)
2801 return FALSE;
2803 OpalMediaFormat & mediaFormat = GetWritableMediaFormat();
2805 BOOL formatDefined = FALSE;
2807 const H245_H263VideoCapability & h263 = cap;
2809 if (!SetReceivedH263Cap(mediaFormat, cap, sqcifMPI_tag, H245_H263VideoCapability::e_sqcifMPI, h263.m_sqcifMPI, H245_H263VideoCapability::e_slowSqcifMPI, h263.m_slowSqcifMPI, SQCIF_WIDTH, SQCIF_HEIGHT, formatDefined))
2810 return FALSE;
2812 if (!SetReceivedH263Cap(mediaFormat, cap, qcifMPI_tag, H245_H263VideoCapability::e_qcifMPI, h263.m_qcifMPI, H245_H263VideoCapability::e_slowQcifMPI, h263.m_slowQcifMPI, QCIF_WIDTH, QCIF_HEIGHT, formatDefined))
2813 return FALSE;
2815 if (!SetReceivedH263Cap(mediaFormat, cap, cifMPI_tag, H245_H263VideoCapability::e_cifMPI, h263.m_cifMPI, H245_H263VideoCapability::e_slowCifMPI, h263.m_slowCifMPI, CIF_WIDTH, CIF_HEIGHT, formatDefined))
2816 return FALSE;
2818 if (!SetReceivedH263Cap(mediaFormat, cap, cif4MPI_tag, H245_H263VideoCapability::e_cif4MPI, h263.m_cif4MPI, H245_H263VideoCapability::e_slowCif4MPI, h263.m_slowCif4MPI, CIF4_WIDTH, CIF4_HEIGHT, formatDefined))
2819 return FALSE;
2821 if (!SetReceivedH263Cap(mediaFormat, cap, cif16MPI_tag, H245_H263VideoCapability::e_cif16MPI, h263.m_cif16MPI, H245_H263VideoCapability::e_slowCif16MPI, h263.m_slowCif16MPI, CIF16_WIDTH, CIF16_HEIGHT, formatDefined))
2822 return FALSE;
2824 if (!formatDefined)
2825 return FALSE;
2827 unsigned maxBitRate = h263.m_maxBitRate*100;
2828 if (!mediaFormat.SetOptionInteger(OpalMediaFormat::MaxBitRateOption(), maxBitRate))
2829 return FALSE;
2830 unsigned targetBitRate = mediaFormat.GetOptionInteger(OpalVideoFormat::TargetBitRateOption());
2831 if (targetBitRate > maxBitRate)
2832 mediaFormat.SetOptionInteger(OpalVideoFormat::TargetBitRateOption(), maxBitRate);
2834 mediaFormat.SetOptionBoolean(h323_unrestrictedVector_tag, h263.m_unrestrictedVector);
2835 mediaFormat.SetOptionBoolean(h323_arithmeticCoding_tag, h263.m_arithmeticCoding);
2836 mediaFormat.SetOptionBoolean(h323_advancedPrediction_tag, h263.m_advancedPrediction);
2837 mediaFormat.SetOptionBoolean(h323_pbFrames_tag, h263.m_pbFrames);
2838 mediaFormat.SetOptionBoolean(h323_errorCompensation_tag, h263.m_errorCompensation);
2839 mediaFormat.SetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, h263.m_temporalSpatialTradeOffCapability);
2841 if (h263.HasOptionalField(H245_H263VideoCapability::e_hrd_B))
2842 mediaFormat.SetOptionInteger(h323_hrdB_tag, h263.m_hrd_B);
2844 if (h263.HasOptionalField(H245_H263VideoCapability::e_bppMaxKb))
2845 mediaFormat.SetOptionInteger(h323_bppMaxKb_tag, h263.m_bppMaxKb);
2847 //PStringStream str; mediaFormat.PrintOptions(str);
2848 //PTRACE(4, "OpalPlugin\tCreated H.263 cap from incoming PDU with format " << mediaFormat << " and options\n" << str);
2850 return TRUE;
2853 /////////////////////////////////////////////////////////////////////////////
2855 H323CodecPluginNonStandardVideoCapability::H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * _encoderCodec,
2856 const PluginCodec_Definition * _decoderCodec,
2857 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
2858 const unsigned char * data, unsigned dataLen)
2859 : H323NonStandardVideoCapability(compareFunc, data, dataLen),
2860 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2862 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2863 if (nonStdData->objectId != NULL) {
2864 oid = PString(nonStdData->objectId);
2865 } else {
2866 t35CountryCode = nonStdData->t35CountryCode;
2867 t35Extension = nonStdData->t35Extension;
2868 manufacturerCode = nonStdData->manufacturerCode;
2872 H323CodecPluginNonStandardVideoCapability::H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * _encoderCodec,
2873 const PluginCodec_Definition * _decoderCodec,
2874 const unsigned char * data, unsigned dataLen)
2875 : H323NonStandardVideoCapability(data, dataLen),
2876 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2878 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2879 if (nonStdData->objectId != NULL) {
2880 oid = PString(nonStdData->objectId);
2881 } else {
2882 t35CountryCode = nonStdData->t35CountryCode;
2883 t35Extension = nonStdData->t35Extension;
2884 manufacturerCode = nonStdData->manufacturerCode;
2888 PObject * H323CodecPluginNonStandardVideoCapability::Clone() const
2889 { return new H323CodecPluginNonStandardVideoCapability(*this); }
2891 PString H323CodecPluginNonStandardVideoCapability::GetFormatName() const
2892 { return H323PluginCapabilityInfo::GetFormatName();}
2894 /////////////////////////////////////////////////////////////////////////////
2896 H323CodecPluginGenericVideoCapability::H323CodecPluginGenericVideoCapability(const PluginCodec_Definition * _encoderCodec,
2897 const PluginCodec_Definition * _decoderCodec,
2898 const PluginCodec_H323GenericCodecData *data)
2899 : H323GenericVideoCapability(data->standardIdentifier, data->maxBitRate),
2900 H323PluginCapabilityInfo((PluginCodec_Definition *)_encoderCodec, (PluginCodec_Definition *)_decoderCodec)
2902 PopulateMediaFormatFromGenericData(GetWritableMediaFormat(), data);
2905 PObject * H323CodecPluginGenericVideoCapability::Clone() const
2907 return new H323CodecPluginGenericVideoCapability(*this);
2910 PString H323CodecPluginGenericVideoCapability::GetFormatName() const
2912 return H323PluginCapabilityInfo::GetFormatName();
2916 /////////////////////////////////////////////////////////////////////////////
2918 #endif // OPAL_VIDEO
2920 #endif // OPAL_H323
2922 /////////////////////////////////////////////////////////////////////////////
2924 static PAtomicInteger bootStrapCount = 0;
2926 void OpalPluginCodecManager::Bootstrap()
2928 if (++bootStrapCount != 1)
2929 return;
2932 /////////////////////////////////////////////////////////////////////////////
2934 #define INCLUDE_STATIC_CODEC(name) \
2935 extern "C" { \
2936 extern unsigned int Opal_StaticCodec_##name##_GetAPIVersion(); \
2937 extern struct PluginCodec_Definition * Opal_StaticCodec_##name##_GetCodecs(unsigned *,unsigned); \
2938 }; \
2939 class H323StaticPluginCodec_##name : public H323StaticPluginCodec \
2941 public: \
2942 PluginCodec_GetAPIVersionFunction Get_GetAPIFn() \
2943 { return &Opal_StaticCodec_##name##_GetAPIVersion; } \
2944 PluginCodec_GetCodecFunction Get_GetCodecFn() \
2945 { return &Opal_StaticCodec_##name##_GetCodecs; } \
2946 }; \
2947 static H323StaticPluginCodecFactory::Worker<H323StaticPluginCodec_##name > static##name##CodecFactory( #name ); \
2949 #ifdef H323_EMBEDDED_GSM
2951 INCLUDE_STATIC_CODEC(GSM_0610)
2953 #endif