Also bad boy Craig for leaving debugging in the code. :-)
[opal.git] / src / codec / opalpluginmgr.cxx
blob5d674ea70ca8bee1818a6dcf6f2cf682867ff02e
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.50 2007/08/16 00:47:04 rjongbloed
29 * Also bad boy Craig for leaving debugging in the code. :-)
31 * Revision 2.49 2007/08/16 00:22:43 csoutheren
32 * Fixed cut and paste error. Thanks to Matthias Schneider for noticing the
33 * problem, and Robert Jongbloed for providing the fix. Bad boy Craig for making it
35 * Revision 2.48 2007/08/13 06:08:08 csoutheren
36 * Expose more functions
38 * Revision 2.47 2007/08/09 08:21:25 csoutheren
39 * Add missing braces
41 * Revision 2.46 2007/08/08 17:35:16 csoutheren
42 * Final plugin manager changes
44 * Revision 2.45 2007/08/08 11:18:47 csoutheren
45 * Fixed Linux compile errors
47 * Revision 2.44 2007/08/08 08:59:30 csoutheren
48 * More plugin manager changes, as the last approach dead-ended :(
50 * Revision 2.43 2007/08/08 07:13:01 csoutheren
51 * #ifdef out unused code - to be removed later if nobody complains :)
53 * Revision 2.42 2007/08/07 09:04:25 csoutheren
54 * Export more functions
56 * Revision 2.41 2007/08/07 08:25:36 csoutheren
57 * Expose plugin media format classes
59 * Revision 2.40 2007/08/07 00:13:57 csoutheren
60 * Fix compile error on Windows
62 * Revision 2.39 2007/08/06 15:05:43 csoutheren
63 * Fix problem with media format settings not being applied to plugin
64 * video transcoders on startup
66 * Revision 2.38 2007/08/06 07:14:23 csoutheren
67 * Fix logging
68 * Correct matching of H.263 capabilities
70 * Revision 2.37 2007/08/03 08:23:22 csoutheren
71 * Cleanups
73 * Revision 2.36 2007/08/03 08:05:16 csoutheren
74 * Add PrintOn for plugin video caps
76 * Revision 2.35 2007/08/03 07:20:33 csoutheren
77 * Add extra constructor initialisations for plugin capabilities with multiple ancestors
79 * Revision 2.34 2007/08/03 03:41:59 csoutheren
80 * Fixed usage of tolower in codec control parsing
81 * Ensure plugin media options can override existing values
82 * Add extra logging
84 * Revision 2.33 2007/07/24 12:59:44 rjongbloed
85 * Fixed G.723.1 plug in capability matching, should not include Annex A option.
86 * Made sure all integer OpalMediaOptions are unsigned so is compatible with H.245 generic capabilities.
88 * Revision 2.32 2007/07/20 05:45:45 rjongbloed
89 * Fixed incorrect maxBitRate field in Generic Audio Capabilities
91 * Revision 2.31 2007/07/02 18:53:47 csoutheren
92 * Exposed classes
94 * Revision 2.30 2007/06/27 18:19:49 csoutheren
95 * Fix compile when video disabled
97 * Revision 2.29 2007/06/27 12:29:45 rjongbloed
98 * Add new OpalMediaOption for octet strings (simple block of bytes).
100 * Revision 2.28 2007/06/25 04:04:38 rjongbloed
101 * Fixed compile after change to anonymous structure in header (for GCC).
103 * Revision 2.27 2007/06/22 06:29:14 rjongbloed
104 * Fixed GCC warnings.
106 * Revision 2.26 2007/06/22 05:48:09 rjongbloed
107 * Major codec API update:
108 * Automatically map OpalMediaOptions to SIP/SDP FMTP parameters.
109 * Automatically map OpalMediaOptions to H.245 Generic Capability parameters.
110 * Largely removed need to distinguish between SIP and H.323 codecs.
111 * New mechanism for setting OpalMediaOptions from within a plug in.
112 * Fixed setting of output RTP payload types on plug in video codecs.
114 * Revision 2.25 2007/06/16 21:37:01 dsandras
115 * Added H.264 support thanks to Matthias Schneider <ma30002000 yahoo de>.
116 * Thanks a lot !
118 * Baseline Profile:
119 * no B-frames
120 * We make use of the baseline profile (which is the designated profile for interactive vide) ,
121 * that means:
122 * no B-Frames (too much latency in interactive video)
123 * CBR (we want to get the max. quality making use of all the bitrate that is available)
124 * We allow one exeption: configuring a bitrate of > 786 kbit/s
126 * This plugin implements
127 * - Single Time Aggregation Packets A
128 * - Single NAL units
129 * - Fragmentation Units
130 * like described in RFC3984
132 * It requires x264 and ffmpeg.
134 * Revision 2.24 2007/05/12 03:57:34 rjongbloed
135 * Fixed transcoder from plug in not being created correctly due to media format not yet being registered.
137 * Revision 2.23 2007/05/10 05:34:23 csoutheren
138 * Ensure fax transmission works with reasonable size audio blocks
140 * Revision 2.22 2007/04/19 06:34:12 csoutheren
141 * Applied 1703206 - OpalVideoFastUpdatePicture over SIP
142 * Thanks to Josh Mahonin
144 * Revision 2.21 2007/04/10 05:15:54 rjongbloed
145 * Fixed issue with use of static C string variables in DLL environment,
146 * must use functional interface for correct initialisation.
148 * Revision 2.20 2007/04/04 02:12:00 rjongbloed
149 * Reviewed and adjusted PTRACE log levels
150 * Now follows 1=error,2=warn,3=info,4+=debug
152 * Revision 2.19 2007/04/02 05:51:33 rjongbloed
153 * Tidied some trace logs to assure all have a category (bit before a tab character) set.
155 * Revision 2.18 2007/03/29 05:20:17 csoutheren
156 * Implement T.38 and fax
158 * Revision 2.17 2006/12/08 07:33:13 csoutheren
159 * Fix problem with wideband audio plugins and sound channel
161 * Revision 2.16 2006/11/29 06:28:58 csoutheren
162 * Add ability call codec control functions on all transcoders
164 * Revision 2.15 2006/10/17 23:55:07 csoutheren
165 * Changed to match new enum in opalplugin.h
167 * Revision 2.14 2006/10/17 15:36:58 shorne
168 * Missed line removal in last commit
170 * Revision 2.13 2006/10/17 04:10:12 shorne
171 * Corrected h245 generic parameter identifiers
173 * Revision 2.12 2006/10/10 07:18:18 csoutheren
174 * Allow compilation with and without various options
176 * Revision 2.11 2006/10/02 13:30:51 rjongbloed
177 * Added LID plug ins
179 * Revision 2.10 2006/09/28 07:42:17 csoutheren
180 * Merge of useful SRTP implementation
182 * Revision 2.9 2006/09/11 04:48:55 csoutheren
183 * Fixed problem with cloning plugin media formats
185 * Revision 2.8 2006/09/07 09:05:44 csoutheren
186 * Fix case significance in IsValidForProtocol
188 * Revision 2.7 2006/09/06 22:36:11 csoutheren
189 * Fix problem with IsValidForProtocol on video codecs
191 * Revision 2.6 2006/08/22 03:08:42 csoutheren
192 * Fixed compile error on gcc 4.1
194 * Revision 2.5 2006/08/20 03:56:57 csoutheren
195 * Add OpalMediaFormat::IsValidForProtocol to allow plugin codecs to be enabled only for certain protocols
196 * rather than relying on the presence of the IANA rtp encoding name field
198 * Revision 2.4 2006/08/15 23:52:55 csoutheren
199 * Ensure codecs with same name but different clock rate get different payload types
201 * Revision 2.3 2006/08/11 07:52:01 csoutheren
202 * Fix problem with media format factory in VC 2005
203 * Fixing problems with Speex codec
204 * Remove non-portable usages of PFactory code
206 * Revision 2.2 2006/08/10 06:05:32 csoutheren
207 * Fix problem with key type in plugin factory
209 * Revision 2.1 2006/07/24 14:03:39 csoutheren
210 * Merged in audio and video plugins from CVS branch PluginBranch
212 * Revision 1.1.2.15 2006/05/16 07:03:09 csoutheren
213 * Fixed Linux compile system
215 * Revision 1.1.2.14 2006/04/26 08:03:58 csoutheren
216 * H.263 encoding and decoding now working from plugin for both SIP and H.323
218 * Revision 1.1.2.13 2006/04/26 05:05:59 csoutheren
219 * H.263 decoding working via codec plugin
221 * Revision 1.1.2.12 2006/04/25 01:14:54 csoutheren
222 * Added H.263 capabilities
224 * Revision 1.1.2.11 2006/04/24 09:09:13 csoutheren
225 * Added H.263 codec definitions
227 * Revision 1.1.2.10 2006/04/21 05:42:52 csoutheren
228 * Checked in forgotten changes to fix iFrame requests
230 * Revision 1.1.2.9 2006/04/19 07:52:30 csoutheren
231 * Add ability to have SIP-only and H.323-only codecs, and implement for H.261
233 * Revision 1.1.2.8 2006/04/19 04:58:56 csoutheren
234 * Debugging and testing of new video plugins
235 * H.261 working in both CIF and QCIF modes in H.323
237 * Revision 1.1.2.7 2006/04/11 08:40:22 csoutheren
238 * Modified H.261 plugin handling to use new media formats
240 * Revision 1.1.2.6 2006/04/10 08:53:39 csoutheren
241 * Fix problem with audio code parameters
243 * Revision 1.1.2.5 2006/04/06 05:48:08 csoutheren
244 * Fixed last minute edits to allow compilation
246 * Revision 1.1.2.4 2006/04/06 01:21:18 csoutheren
247 * More implementation of video codec plugins
249 * Revision 1.1.2.3 2006/03/23 07:55:18 csoutheren
250 * Audio plugin H.323 capability merging completed.
251 * GSM, LBC, G.711 working. Speex and LPC-10 are not
253 * Revision 1.1.2.2 2006/03/20 05:03:23 csoutheren
254 * Changes to make audio plugins work with SIP
256 * Revision 1.1.2.1 2006/03/16 07:06:00 csoutheren
257 * Initial support for audio plugins
259 * Created from OpenH323 h323pluginmgr.cxx
260 * Revision 1.58 2005/08/05 17:11:03 csoutheren
264 #ifdef __GNUC__
265 #pragma implementation "opalpluginmgr.h"
266 #endif
268 #include <ptlib.h>
270 #include <opal/buildopts.h>
272 #include <opal/transcoders.h>
273 #include <codec/opalpluginmgr.h>
274 #include <codec/opalplugin.h>
275 #include <h323/h323caps.h>
276 #include <asn/h245.h>
278 #if OPAL_VIDEO
279 #include <codec/vidcodec.h>
280 #endif
282 #if OPAL_T38FAX
283 #include <t38/t38proto.h>
284 #endif
286 // G.711 is *always* available
287 #include <codec/g711codec.h>
288 OPAL_REGISTER_G711();
291 #define H323CAP_TAG_PREFIX "h323"
292 static const char GET_CODEC_OPTIONS_CONTROL[] = "get_codec_options";
293 static const char FREE_CODEC_OPTIONS_CONTROL[] = "free_codec_options";
294 static const char GET_OUTPUT_DATA_SIZE_CONTROL[] = "get_output_data_size";
295 static const char SET_CODEC_OPTIONS_CONTROL[] = "set_codec_options";
298 #if OPAL_VIDEO
300 #define CIF_WIDTH 352
301 #define CIF_HEIGHT 288
303 #define CIF4_WIDTH (CIF_WIDTH*2)
304 #define CIF4_HEIGHT (CIF_HEIGHT*2)
306 #define CIF16_WIDTH (CIF_WIDTH*4)
307 #define CIF16_HEIGHT (CIF_HEIGHT*4)
309 #define QCIF_WIDTH (CIF_WIDTH/2)
310 #define QCIF_HEIGHT (CIF_HEIGHT/2)
312 #define SQCIF_WIDTH 128
313 #define SQCIF_HEIGHT 96
315 static const char * sqcifMPI_tag = "SQCIF MPI";
316 static const char * qcifMPI_tag = "QCIF MPI";
317 static const char * cifMPI_tag = "CIF MPI";
318 static const char * cif4MPI_tag = "CIF4 MPI";
319 static const char * cif16MPI_tag = "CIF16 MPI";
321 #if OPAL_H323
323 // H.261 only
324 static const char * h323_stillImageTransmission_tag = H323CAP_TAG_PREFIX "_stillImageTransmission";
326 // H.261/H.263 tags
327 static const char * h323_qcifMPI_tag = H323CAP_TAG_PREFIX "_qcifMPI";
328 static const char * h323_cifMPI_tag = H323CAP_TAG_PREFIX "_cifMPI";
330 // H.263 only
331 static const char * h323_sqcifMPI_tag = H323CAP_TAG_PREFIX "_sqcifMPI";
332 static const char * h323_cif4MPI_tag = H323CAP_TAG_PREFIX "_cif4MPI";
333 static const char * h323_cif16MPI_tag = H323CAP_TAG_PREFIX "_cif16MPI";
334 static const char * h323_temporalSpatialTradeOffCapability_tag = H323CAP_TAG_PREFIX "_temporalSpatialTradeOffCapability";
335 static const char * h323_unrestrictedVector_tag = H323CAP_TAG_PREFIX "_unrestrictedVector";
336 static const char * h323_arithmeticCoding_tag = H323CAP_TAG_PREFIX "_arithmeticCoding";
337 static const char * h323_advancedPrediction_tag = H323CAP_TAG_PREFIX "_advancedPrediction";
338 static const char * h323_pbFrames_tag = H323CAP_TAG_PREFIX "_pbFrames";
339 static const char * h323_hrdB_tag = H323CAP_TAG_PREFIX "_hrdB";
340 static const char * h323_bppMaxKb_tag = H323CAP_TAG_PREFIX "_bppMaxKb";
341 static const char * h323_errorCompensation_tag = H323CAP_TAG_PREFIX "_errorCompensation";
343 #endif // OPAL_H323
344 #endif // OPAL_VIDEO
348 //////////////////////////////////////////////////////////////////////////////
350 // Helper functions for codec control operators
353 BOOL OpalPluginTranscoder::CallCodecControl(const PluginCodec_Definition * codec,
354 void * context,
355 const char * name,
356 void * parm,
357 unsigned int * parmLen,
358 int & retVal)
360 PluginCodec_ControlDefn * codecControls = codec->codecControls;
361 if (codecControls == NULL)
362 return FALSE;
364 // look for explicit named control
365 while (codecControls->name != NULL) {
366 if (strcasecmp(codecControls->name, name) == 0) {
367 retVal = (*codecControls->control)(codec, context, name, parm, parmLen);
368 return TRUE;
370 codecControls++;
373 return FALSE;
376 BOOL OpalPluginTranscoder::HasCodecControl(const PluginCodec_Definition * codec, const char * name)
378 PluginCodec_ControlDefn * codecControls = codec->codecControls;
379 if (codecControls == NULL)
380 return 0;
382 while (codecControls->name != NULL) {
383 if (strcmp(codecControls->name, name) == 0)
384 return TRUE;
385 codecControls++;
388 return FALSE;
391 PluginCodec_ControlDefn * OpalPluginTranscoder::GetCodecControl(const PluginCodec_Definition * codec, const char * name)
393 PluginCodec_ControlDefn * codecControls = codec->codecControls;
394 if (codecControls == NULL)
395 return NULL;
397 while (codecControls->name != NULL) {
398 if (strcasecmp(codecControls->name, name) == 0)
399 return codecControls;
400 codecControls++;
403 return NULL;
406 /////////////////////////////////////////////////////////////////////////////
408 template <typename CodecClass>
409 class OpalFixedCodecFactory : public PFactory<OpalFactoryCodec>
411 public:
412 class Worker : public PFactory<OpalFactoryCodec>::WorkerBase
414 public:
415 Worker(const PString & key)
416 : PFactory<OpalFactoryCodec>::WorkerBase()
417 { PFactory<OpalFactoryCodec>::Register(key, this); }
419 protected:
420 virtual OpalFactoryCodec * Create(const PString &) const
421 { return new CodecClass(); }
426 static PString CreateCodecName(const PluginCodec_Definition * codec)
428 return codec->destFormat != NULL ? codec->destFormat : codec->descr;
431 BOOL OpalPluginMediaFormat::CallCodecControl(const PluginCodec_Definition * codec,
432 const char * name,
433 void * parm,
434 unsigned int * parmLen,
435 int & retVal)
437 return OpalPluginTranscoder::CallCodecControl(codec, NULL, name, parm, parmLen, retVal);
441 void OpalPluginMediaFormat::PopulateMediaFormatOptions(const PluginCodec_Definition * _encoderCodec, OpalMediaFormat & format)
443 void ** _options = NULL;
444 unsigned int optionsLen = sizeof(_options);
445 int retVal;
446 if (CallCodecControl(_encoderCodec, GET_CODEC_OPTIONS_CONTROL, &_options, &optionsLen, retVal) && (_options != NULL)) {
447 if (_encoderCodec->version < PLUGIN_CODEC_VERSION_OPTIONS) {
448 PTRACE(3, "OpalPlugin\tAdding options to OpalMediaFormat " << format << " using old style method");
449 // Old scheme
450 char const * const * options = (char **)_options;
451 while (options[0] != NULL && options[1] != NULL && options[2] != NULL) {
452 SetOldStyleFormatOption(format, options[0], options[1], options[2]);
453 options += 3;
456 else {
457 // New scheme
458 struct PluginCodec_Option const * const * options = (struct PluginCodec_Option const * const *)_options;
459 PTRACE_IF(5, options != NULL, "Adding options to OpalMediaFormat " << format << " using new style method");
460 while (*options != NULL) {
461 struct PluginCodec_Option const * option = *options++;
462 OpalMediaOption * newOption;
463 switch (option->m_type) {
464 case PluginCodec_StringOption :
465 newOption = new OpalMediaOptionString(option->m_name,
466 option->m_readOnly != 0,
467 option->m_value);
468 break;
469 case PluginCodec_BoolOption :
470 newOption = new OpalMediaOptionBoolean(option->m_name,
471 option->m_readOnly != 0,
472 (OpalMediaOption::MergeType)option->m_merge,
473 option->m_value != NULL && *option->m_value == 'T');
474 break;
475 case PluginCodec_IntegerOption :
476 newOption = new OpalMediaOptionUnsigned(option->m_name,
477 option->m_readOnly != 0,
478 (OpalMediaOption::MergeType)option->m_merge,
479 PString(option->m_value).AsInteger(),
480 PString(option->m_minimum).AsInteger(),
481 PString(option->m_maximum).AsInteger());
482 break;
483 case PluginCodec_RealOption :
484 newOption = new OpalMediaOptionReal(option->m_name,
485 option->m_readOnly != 0,
486 (OpalMediaOption::MergeType)option->m_merge,
487 PString(option->m_value).AsReal(),
488 PString(option->m_minimum).AsReal(),
489 PString(option->m_maximum).AsReal());
490 break;
491 case PluginCodec_EnumOption :
493 PStringArray valueTokens = PString(option->m_minimum).Tokenise(':');
494 char ** enumValues = valueTokens.ToCharArray();
495 newOption = new OpalMediaOptionEnum(option->m_name,
496 option->m_readOnly != 0,
497 enumValues,
498 valueTokens.GetSize(),
499 (OpalMediaOption::MergeType)option->m_merge,
500 valueTokens.GetStringsIndex(option->m_value));
501 free(enumValues);
503 break;
504 case PluginCodec_OctetsOption :
505 newOption = new OpalMediaOptionOctets(option->m_name, option->m_readOnly != 0, option->m_minimum != NULL); // Use minimum to indicate Base64
506 newOption->FromString(option->m_value);
507 break;
508 default : // Huh?
509 continue;
512 newOption->SetFMTPName(option->m_FMTPName);
513 newOption->SetFMTPDefault(option->m_FMTPDefault);
515 OpalMediaOption::H245GenericInfo genericInfo;
516 genericInfo.ordinal = option->m_H245Generic&PluginCodec_H245_OrdinalMask;
517 if (option->m_H245Generic&PluginCodec_H245_Collapsing)
518 genericInfo.mode = OpalMediaOption::H245GenericInfo::Collapsing;
519 else if (option->m_H245Generic&PluginCodec_H245_NonCollapsing)
520 genericInfo.mode = OpalMediaOption::H245GenericInfo::NonCollapsing;
521 else
522 genericInfo.mode = OpalMediaOption::H245GenericInfo::None;
523 if (option->m_H245Generic&PluginCodec_H245_Unsigned32)
524 genericInfo.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
525 else if (option->m_H245Generic&PluginCodec_H245_BooleanArray)
526 genericInfo.integerType = OpalMediaOption::H245GenericInfo::BooleanArray;
527 else
528 genericInfo.integerType = OpalMediaOption::H245GenericInfo::UnsignedInt;
529 genericInfo.excludeTCS = (option->m_H245Generic&PluginCodec_H245_TCS) == 0;
530 genericInfo.excludeOLC = (option->m_H245Generic&PluginCodec_H245_OLC) == 0;
531 genericInfo.excludeReqMode = (option->m_H245Generic&PluginCodec_H245_ReqMode) == 0;
532 newOption->SetH245Generic(genericInfo);
534 format.AddOption(newOption, TRUE);
537 CallCodecControl(_encoderCodec, FREE_CODEC_OPTIONS_CONTROL, _options, &optionsLen, retVal);
540 // PStringStream str; format.PrintOptions(str);
541 // PTRACE(5, "OpalPlugin\tOpalMediaFormat " << format << " has options\n" << str);
544 void OpalPluginMediaFormat::SetOldStyleFormatOption(OpalMediaFormat & format, const PString & _key, const PString & _val, const PString & type)
546 PString key(_key);
547 const char * val = _val;
549 #if OPAL_VIDEO
550 // Backward compatibility tests
551 if (strcasecmp(key, h323_qcifMPI_tag) == 0)
552 key = qcifMPI_tag;
553 else if (strcasecmp(key, h323_cifMPI_tag) == 0)
554 key = cifMPI_tag;
555 else if (strcasecmp(key, h323_sqcifMPI_tag) == 0)
556 key = sqcifMPI_tag;
557 else if (strcasecmp(key, h323_cif4MPI_tag) == 0)
558 key = cif4MPI_tag;
559 else if (strcasecmp(key, h323_cif16MPI_tag) == 0)
560 key = cif16MPI_tag;
561 #endif
563 OpalMediaOption::MergeType op = OpalMediaOption::NoMerge;
564 if (val[0] != '\0' && val[1] != '\0') {
565 switch (val[0]) {
566 case '<':
567 op = OpalMediaOption::MinMerge;
568 ++val;
569 break;
570 case '>':
571 op = OpalMediaOption::MaxMerge;
572 ++val;
573 break;
574 case '=':
575 op = OpalMediaOption::EqualMerge;
576 ++val;
577 break;
578 case '!':
579 op = OpalMediaOption::NotEqualMerge;
580 ++val;
581 break;
582 case '*':
583 op = OpalMediaOption::AlwaysMerge;
584 ++val;
585 break;
586 default:
587 break;
591 if (type[0] != '\0') {
592 PStringArray tokens = PString(val+1).Tokenise(':', FALSE);
593 char ** array = tokens.ToCharArray();
594 switch (toupper(type[0])) {
595 case 'E':
596 PTRACE(5, "OpalPlugin\tAdding enum option '" << key << "' " << tokens.GetSize() << " options");
597 format.AddOption(new OpalMediaOptionEnum(key, false, array, tokens.GetSize(), op, tokens.GetStringsIndex(val)), TRUE);
598 break;
599 case 'B':
600 PTRACE(5, "OpalPlugin\tAdding boolean option '" << key << "'=" << val);
601 format.AddOption(new OpalMediaOptionBoolean(key, false, op, (val[0] == '1') || (toupper(val[0]) == 'T')), TRUE);
602 break;
603 case 'R':
604 PTRACE(5, "OpalPlugin\tAdding real option '" << key << "'=" << val);
605 if (tokens.GetSize() < 2)
606 format.AddOption(new OpalMediaOptionReal(key, false, op, PString(val).AsReal()));
607 else
608 format.AddOption(new OpalMediaOptionReal(key, false, op, PString(val).AsReal(), tokens[0].AsReal(), tokens[1].AsReal()), TRUE);
609 break;
610 case 'I':
611 PTRACE(5, "OpalPlugin\tAdding integer option '" << key << "'=" << val);
612 if (tokens.GetSize() < 2)
613 format.AddOption(new OpalMediaOptionUnsigned(key, false, op, PString(val).AsUnsigned()), TRUE);
614 else
615 format.AddOption(new OpalMediaOptionUnsigned(key, false, op, PString(val).AsUnsigned(), tokens[0].AsUnsigned(), tokens[1].AsUnsigned()), TRUE);
616 break;
617 case 'S':
618 default:
619 PTRACE(5, "OpalPlugin\tAdding string option '" << key << "'=" << val);
620 format.AddOption(new OpalMediaOptionString(key, false, val), TRUE);
621 break;
623 free(array);
628 static void PopulateMediaFormatFromGenericData(OpalMediaFormat & mediaFormat, const PluginCodec_H323GenericCodecData * genericData)
630 const PluginCodec_H323GenericParameterDefinition *ptr = genericData->params;
631 for (unsigned i = 0; i < genericData->nParameters; i++, ptr++) {
632 OpalMediaOption::H245GenericInfo generic;
633 generic.ordinal = ptr->id;
634 generic.mode = ptr->collapsing ? OpalMediaOption::H245GenericInfo::Collapsing : OpalMediaOption::H245GenericInfo::NonCollapsing;
635 generic.excludeTCS = ptr->excludeTCS;
636 generic.excludeOLC = ptr->excludeOLC;
637 generic.excludeReqMode = ptr->excludeReqMode;
638 generic.integerType = OpalMediaOption::H245GenericInfo::UnsignedInt;
640 PString name(PString::Printf, "Generic Parameter %u", ptr->id);
642 OpalMediaOption * mediaOption;
643 switch (ptr->type) {
644 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_logical :
645 mediaOption = new OpalMediaOptionBoolean(name, ptr->readOnly, OpalMediaOption::NoMerge, ptr->value.integer != 0);
646 break;
648 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_booleanArray :
649 generic.integerType = OpalMediaOption::H245GenericInfo::BooleanArray;
650 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::AndMerge, ptr->value.integer, 0, 255);
651 break;
653 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsigned32Min :
654 generic.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
655 // Do next case
657 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsignedMin :
658 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::MinMerge, ptr->value.integer);
659 break;
661 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsigned32Max :
662 generic.integerType = OpalMediaOption::H245GenericInfo::Unsigned32;
663 // Do next case
665 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_unsignedMax :
666 mediaOption = new OpalMediaOptionUnsigned(name, ptr->readOnly, OpalMediaOption::MaxMerge, ptr->value.integer);
667 break;
669 case PluginCodec_H323GenericParameterDefinition::PluginCodec_GenericParameter_octetString :
670 mediaOption = new OpalMediaOptionString(name, ptr->readOnly, ptr->value.octetstring);
671 break;
673 default :
674 mediaOption = NULL;
677 if (mediaOption != NULL) {
678 mediaOption->SetH245Generic(generic);
679 mediaFormat.AddOption(mediaOption);
685 bool OpalPluginMediaFormat::IsValidForProtocol(const PluginCodec_Definition * encoderCodec, const PString & _protocol)
687 PString protocol(_protocol.ToLower());
688 int retVal;
689 unsigned int parmLen = sizeof(const char *);
690 if (CallCodecControl(encoderCodec, "valid_for_protocol", (void *)(const char *)protocol, &parmLen, retVal))
691 return retVal != 0;
692 if (protocol == "h.323" || protocol == "h323")
693 return (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_undefined) &&
694 (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_NoH323);
695 if (protocol == "sip")
696 return encoderCodec->sdpFormat != NULL;
697 return FALSE;
700 #if OPAL_AUDIO
702 OpalPluginAudioMediaFormat::OpalPluginAudioMediaFormat(const PluginCodec_Definition * _encoderCodec,
703 const char * rtpEncodingName, /// rtp encoding name
704 unsigned frameTime, /// Time for frame in RTP units (if applicable)
705 unsigned /*timeUnits*/, /// RTP units for frameTime (if applicable)
706 time_t timeStamp /// timestamp (for versioning)
708 : OpalAudioFormat(CreateCodecName(_encoderCodec),
709 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
710 rtpEncodingName,
711 _encoderCodec->parm.audio.bytesPerFrame,
712 frameTime,
713 _encoderCodec->parm.audio.recommendedFramesPerPacket,
714 _encoderCodec->parm.audio.recommendedFramesPerPacket,
715 _encoderCodec->parm.audio.maxFramesPerPacket,
716 _encoderCodec->sampleRate,
717 timeStamp
719 , encoderCodec(_encoderCodec)
721 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
723 // Override calculated value if we have an explicit bit rate
724 if (_encoderCodec->bitsPerSec > 0)
725 SetOptionInteger(MaxBitRateOption(), _encoderCodec->bitsPerSec);
727 // manually register the new singleton type, as we do not have a concrete type
728 OpalMediaFormatFactory::Register(*this, this);
731 OpalPluginAudioMediaFormat::~OpalPluginAudioMediaFormat()
733 OpalMediaFormatFactory::Unregister(*this);
736 bool OpalPluginAudioMediaFormat::IsValidForProtocol(const PString & protocol) const
738 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
741 PObject * OpalPluginAudioMediaFormat::Clone() const
742 { return new OpalPluginAudioMediaFormat(*this); }
744 #if OPAL_H323
746 static H323Capability * CreateG7231Cap(
747 const PluginCodec_Definition * encoderCodec,
748 const PluginCodec_Definition * decoderCodec,
749 int subType
752 static H323Capability * CreateGenericAudioCap(
753 const PluginCodec_Definition * encoderCodec,
754 const PluginCodec_Definition * decoderCodec,
755 int subType
758 static H323Capability * CreateNonStandardAudioCap(
759 const PluginCodec_Definition * encoderCodec,
760 const PluginCodec_Definition * decoderCodec,
761 int subType
764 static H323Capability * CreateGSMCap(
765 const PluginCodec_Definition * encoderCodec,
766 const PluginCodec_Definition * decoderCodec,
767 int subType
770 #endif // OPAL_H323
772 #endif // OPAL_AUDIO
774 #if OPAL_VIDEO
776 OpalPluginVideoMediaFormat::OpalPluginVideoMediaFormat(
777 const PluginCodec_Definition * _encoderCodec,
778 const char * rtpEncodingName, /// rtp encoding name
779 time_t timeStamp /// timestamp (for versioning)
781 : OpalVideoFormat(
782 CreateCodecName(_encoderCodec),
783 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
784 rtpEncodingName,
785 _encoderCodec->parm.video.maxFrameWidth,
786 _encoderCodec->parm.video.maxFrameHeight,
787 _encoderCodec->parm.video.maxFrameRate,
788 _encoderCodec->bitsPerSec,
789 timeStamp
791 , encoderCodec(_encoderCodec)
793 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
795 // manually register the new singleton type, as we do not have a concrete type
796 OpalMediaFormatFactory::Register(*this, this);
799 OpalPluginVideoMediaFormat::~OpalPluginVideoMediaFormat()
801 OpalMediaFormatFactory::Unregister(*this);
804 PObject * OpalPluginVideoMediaFormat::Clone() const
806 return new OpalPluginVideoMediaFormat(*this);
809 bool OpalPluginVideoMediaFormat::IsValidForProtocol(const PString & protocol) const
811 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
814 #if OPAL_H323
816 static H323Capability * CreateNonStandardVideoCap(
817 const PluginCodec_Definition * encoderCodec,
818 const PluginCodec_Definition * decoderCodec,
819 int subType
822 static H323Capability * CreateGenericVideoCap(
823 const PluginCodec_Definition * encoderCodec,
824 const PluginCodec_Definition * decoderCodec,
825 int subType
828 static H323Capability * CreateH261Cap(
829 const PluginCodec_Definition * encoderCodec,
830 const PluginCodec_Definition * decoderCodec,
831 int subType
834 static H323Capability * CreateH263Cap(
835 const PluginCodec_Definition * encoderCodec,
836 const PluginCodec_Definition * decoderCodec,
837 int subType
840 #endif // OPAL_H323
842 #endif // OPAL_VIDEO
844 ////////////////////////////////////////////////////////////////////
846 #if OPAL_H323
848 class H323CodecPluginCapabilityMapEntry {
849 public:
850 int pluginCapType;
851 int h323SubType;
852 H323Capability * (* createFunc)(const PluginCodec_Definition * encoderCodec, const PluginCodec_Definition * decoderCodec, int subType);
855 #if OPAL_AUDIO
857 static H323CodecPluginCapabilityMapEntry audioMaps[] = {
858 { PluginCodec_H323Codec_nonStandard, H245_AudioCapability::e_nonStandard, &CreateNonStandardAudioCap },
859 { PluginCodec_H323AudioCodec_gsmFullRate, H245_AudioCapability::e_gsmFullRate, &CreateGSMCap },
860 { PluginCodec_H323AudioCodec_gsmHalfRate, H245_AudioCapability::e_gsmHalfRate, &CreateGSMCap },
861 { PluginCodec_H323AudioCodec_gsmEnhancedFullRate, H245_AudioCapability::e_gsmEnhancedFullRate, &CreateGSMCap },
862 { PluginCodec_H323AudioCodec_g711Alaw_64k, H245_AudioCapability::e_g711Alaw64k },
863 { PluginCodec_H323AudioCodec_g711Alaw_56k, H245_AudioCapability::e_g711Alaw56k },
864 { PluginCodec_H323AudioCodec_g711Ulaw_64k, H245_AudioCapability::e_g711Ulaw64k },
865 { PluginCodec_H323AudioCodec_g711Ulaw_56k, H245_AudioCapability::e_g711Ulaw56k },
866 { PluginCodec_H323AudioCodec_g7231, H245_AudioCapability::e_g7231, &CreateG7231Cap },
867 { PluginCodec_H323AudioCodec_g729, H245_AudioCapability::e_g729 },
868 { PluginCodec_H323AudioCodec_g729AnnexA, H245_AudioCapability::e_g729AnnexA },
869 { PluginCodec_H323AudioCodec_g728, H245_AudioCapability::e_g728 },
870 { PluginCodec_H323AudioCodec_g722_64k, H245_AudioCapability::e_g722_64k },
871 { PluginCodec_H323AudioCodec_g722_56k, H245_AudioCapability::e_g722_56k },
872 { PluginCodec_H323AudioCodec_g722_48k, H245_AudioCapability::e_g722_48k },
873 { PluginCodec_H323AudioCodec_g729wAnnexB, H245_AudioCapability::e_g729wAnnexB },
874 { PluginCodec_H323AudioCodec_g729AnnexAwAnnexB, H245_AudioCapability::e_g729AnnexAwAnnexB },
875 { PluginCodec_H323Codec_generic, H245_AudioCapability::e_genericAudioCapability, &CreateGenericAudioCap },
877 // not implemented
878 //{ PluginCodec_H323AudioCodec_g729Extensions, H245_AudioCapability::e_g729Extensions, 0 },
879 //{ PluginCodec_H323AudioCodec_g7231AnnexC, H245_AudioCapability::e_g7231AnnexCMode 0 },
880 //{ PluginCodec_H323AudioCodec_is11172, H245_AudioCapability::e_is11172AudioMode, 0 },
881 //{ PluginCodec_H323AudioCodec_is13818Audio, H245_AudioCapability::e_is13818AudioMode, 0 },
883 { -1 }
886 #endif // OPAL_AUDIO
888 #if OPAL_VIDEO
890 static H323CodecPluginCapabilityMapEntry videoMaps[] = {
891 // video codecs
892 { PluginCodec_H323Codec_nonStandard, H245_VideoCapability::e_nonStandard, &CreateNonStandardVideoCap },
893 { PluginCodec_H323VideoCodec_h261, H245_VideoCapability::e_h261VideoCapability, &CreateH261Cap },
894 { PluginCodec_H323VideoCodec_h263, H245_VideoCapability::e_h263VideoCapability, &CreateH263Cap },
895 { PluginCodec_H323Codec_generic, H245_VideoCapability::e_genericVideoCapability, &CreateGenericVideoCap },
897 PluginCodec_H323VideoCodec_h262, // not yet implemented
898 PluginCodec_H323VideoCodec_is11172, // not yet implemented
901 { -1 }
904 #endif // OPAL_VIDEO
906 #endif // OPAL_H323
908 //////////////////////////////////////////////////////////////////////////////
910 #if OPAL_T38FAX
912 OpalPluginFaxMediaFormat::OpalPluginFaxMediaFormat(
913 const PluginCodec_Definition * _encoderCodec,
914 const char * rtpEncodingName, /// rtp encoding name
915 unsigned frameTime,
916 unsigned /*timeUnits*/, /// RTP units for frameTime (if applicable)
917 time_t timeStamp /// timestamp (for versioning)
919 : OpalMediaFormat(CreateCodecName(_encoderCodec),
920 OpalMediaFormat::DefaultDataSessionID,
921 (RTP_DataFrame::PayloadTypes)(((_encoderCodec->flags & PluginCodec_RTPTypeMask) == PluginCodec_RTPTypeDynamic) ? RTP_DataFrame::DynamicBase : _encoderCodec->rtpPayload),
922 rtpEncodingName,
923 FALSE, // need jitter
924 8*_encoderCodec->parm.audio.bytesPerFrame*AudioClockRate/frameTime, // bandwidth
925 _encoderCodec->parm.audio.bytesPerFrame, // size of frame in bytes
926 frameTime, // time for frame
927 _encoderCodec->sampleRate, // clock rate
928 (unsigned int)timeStamp // timestamp
930 , encoderCodec(_encoderCodec)
932 OpalPluginMediaFormat::PopulateMediaFormatOptions(_encoderCodec, *this);
934 // manually register the new singleton type, as we do not have a concrete type
935 OpalMediaFormatFactory::Register(*this, this);
937 OpalPluginFaxMediaFormat::~OpalPluginFaxMediaFormat()
939 OpalMediaFormatFactory::Unregister(*this);
942 PObject * OpalPluginFaxMediaFormat::Clone() const
943 { return new OpalPluginFaxMediaFormat(*this); }
945 bool OpalPluginFaxMediaFormat::IsValidForProtocol(const PString & protocol) const
947 return OpalPluginMediaFormat::IsValidForProtocol(encoderCodec, protocol);
950 #endif // OPAL_T38FAX
952 //////////////////////////////////////////////////////////////////////////////
954 // Plugin framed audio codec classes
957 #if OPAL_AUDIO
958 class OpalPluginFramedAudioTranscoder : public OpalFramedTranscoder, public OpalPluginTranscoder
960 PCLASSINFO(OpalPluginFramedAudioTranscoder, OpalFramedTranscoder);
961 public:
962 OpalPluginFramedAudioTranscoder(PluginCodec_Definition * _codec, BOOL _isEncoder, const char * rawFormat = OpalPCM16)
963 : OpalFramedTranscoder( (strcmp(_codec->sourceFormat, "L16") == 0) ? rawFormat : _codec->sourceFormat,
964 (strcmp(_codec->destFormat, "L16") == 0) ? rawFormat : _codec->destFormat,
965 _isEncoder ? _codec->parm.audio.samplesPerFrame*2 : _codec->parm.audio.bytesPerFrame,
966 _isEncoder ? _codec->parm.audio.bytesPerFrame : _codec->parm.audio.samplesPerFrame*2),
967 codec(_codec), isEncoder(_isEncoder)
969 if (codec->createCodec != NULL)
970 context = (*codec->createCodec)(codec);
971 else
972 context = NULL;
973 inputIsRTP = (codec->flags & PluginCodec_InputTypeMask) == PluginCodec_InputTypeRTP;
974 outputIsRTP = (codec->flags & PluginCodec_OutputTypeMask) == PluginCodec_OutputTypeRTP;
977 ~OpalPluginFramedAudioTranscoder()
979 if (codec->destroyCodec != NULL)
980 (*codec->destroyCodec)(codec, context);
983 BOOL ConvertFrame(
984 const BYTE * input, ///< Input data
985 PINDEX & consumed, ///< number of input bytes consumed
986 BYTE * output, ///< Output data
987 PINDEX & created ///< number of output bytes created
990 if (codec == NULL || codec->codecFunction == NULL)
991 return FALSE;
993 unsigned int fromLen = consumed;
994 unsigned int toLen = created;
995 unsigned flags = 0;
997 BOOL stat = (codec->codecFunction)(codec, context,
998 (const unsigned char *)input, &fromLen,
999 output, &toLen,
1000 &flags) != 0;
1001 consumed = fromLen;
1002 created = toLen;
1004 return stat;
1007 virtual BOOL ConvertSilentFrame(BYTE * buffer)
1009 if (codec == NULL)
1010 return FALSE;
1012 // for a decoder, this mean that we need to create a silence frame
1013 // which is easy - ask the decoder, or just create silence
1014 if (!isEncoder) {
1015 unsigned int length = codec->parm.audio.samplesPerFrame*2;
1016 if ((codec->flags & PluginCodec_DecodeSilence) == 0)
1017 memset(buffer, 0, length);
1018 else {
1019 unsigned flags = PluginCodec_CoderSilenceFrame;
1020 (codec->codecFunction)(codec, context,
1021 NULL, NULL,
1022 buffer, &length,
1023 &flags);
1027 // for an encoder, we encode silence but set the flag so it can do something special if need be
1028 else {
1029 unsigned int length = codec->parm.audio.bytesPerFrame;
1030 if ((codec->flags & PluginCodec_EncodeSilence) == 0) {
1031 PShortArray silence(codec->parm.audio.samplesPerFrame);
1032 memset(silence.GetPointer(), 0, codec->parm.audio.samplesPerFrame*sizeof(short));
1033 unsigned silenceLen = codec->parm.audio.samplesPerFrame * sizeof(short);
1034 unsigned flags = 0;
1035 (codec->codecFunction)(codec, context,
1036 silence, &silenceLen,
1037 buffer, &length,
1038 &flags);
1040 else {
1041 unsigned flags = PluginCodec_CoderSilenceFrame;
1042 (codec->codecFunction)(codec, context,
1043 NULL, NULL,
1044 buffer, &length,
1045 &flags);
1049 return TRUE;
1052 BOOL HasCodecControl(const char * name)
1053 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1055 BOOL CallCodecControl(const char * name,
1056 void * parm,
1057 unsigned int * parmLen,
1058 int & retVal)
1059 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1061 protected:
1062 void * context;
1063 PluginCodec_Definition * codec;
1064 BOOL isEncoder;
1067 //////////////////////////////////////////////////////////////////////////////
1069 // Plugin streamed audio codec classes
1072 class OpalPluginStreamedAudioTranscoder : public OpalStreamedTranscoder, public OpalPluginTranscoder
1074 PCLASSINFO(OpalPluginStreamedAudioTranscoder, OpalStreamedTranscoder);
1075 public:
1076 OpalPluginStreamedAudioTranscoder(PluginCodec_Definition * _codec, unsigned inputBits, unsigned outputBits, PINDEX optimalBits)
1077 : OpalStreamedTranscoder((strcmp(_codec->sourceFormat, "L16") == 0) ? OpalPCM16 : _codec->sourceFormat,
1078 (strcmp(_codec->destFormat, "L16") == 0) ? OpalPCM16 : _codec->destFormat,
1079 inputBits, outputBits, optimalBits),
1080 codec(_codec)
1082 if (codec == NULL || codec->createCodec == NULL)
1083 context = NULL;
1084 else {
1085 context = (*codec->createCodec)(codec);
1089 ~OpalPluginStreamedAudioTranscoder()
1091 if (codec != NULL && codec->destroyCodec != NULL)
1092 (*codec->destroyCodec)(codec, context);
1095 BOOL HasCodecControl(const char * name)
1096 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1098 BOOL CallCodecControl(const char * name,
1099 void * parm,
1100 unsigned int * parmLen,
1101 int & retVal)
1102 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1104 protected:
1105 void * context;
1106 PluginCodec_Definition * codec;
1109 class OpalPluginStreamedAudioEncoder : public OpalPluginStreamedAudioTranscoder
1111 PCLASSINFO(OpalPluginStreamedAudioEncoder, OpalPluginStreamedAudioTranscoder);
1112 public:
1113 OpalPluginStreamedAudioEncoder(PluginCodec_Definition * _codec, BOOL)
1114 : OpalPluginStreamedAudioTranscoder(_codec, 16, (_codec->flags & PluginCodec_BitsPerSampleMask) >> PluginCodec_BitsPerSamplePos, _codec->parm.audio.recommendedFramesPerPacket)
1118 int ConvertOne(int _sample) const
1120 if (codec == NULL || codec->codecFunction == NULL)
1121 return 0;
1123 short sample = (short)_sample;
1124 unsigned int fromLen = sizeof(sample);
1125 int to;
1126 unsigned toLen = sizeof(to);
1127 unsigned flags = 0;
1128 (codec->codecFunction)(codec, context,
1129 (const unsigned char *)&sample, &fromLen,
1130 (unsigned char *)&to, &toLen,
1131 &flags);
1132 return to;
1136 class OpalPluginStreamedAudioDecoder : public OpalPluginStreamedAudioTranscoder
1138 PCLASSINFO(OpalPluginStreamedAudioDecoder, OpalPluginStreamedAudioTranscoder);
1139 public:
1140 OpalPluginStreamedAudioDecoder(PluginCodec_Definition * _codec, BOOL)
1141 : OpalPluginStreamedAudioTranscoder(_codec, (_codec->flags & PluginCodec_BitsPerSampleMask) >> PluginCodec_BitsPerSamplePos, 16, _codec->parm.audio.recommendedFramesPerPacket)
1145 int ConvertOne(int codedSample) const
1147 if (codec == NULL || codec->codecFunction == NULL)
1148 return 0;
1150 unsigned int fromLen = sizeof(codedSample);
1151 short to;
1152 unsigned toLen = sizeof(to);
1153 unsigned flags = 0;
1154 (codec->codecFunction)(codec, context,
1155 (const unsigned char *)&codedSample, &fromLen,
1156 (unsigned char *)&to, &toLen,
1157 &flags);
1158 return to;
1164 #endif // OPAL_AUDIO
1166 #if OPAL_VIDEO
1168 /////////////////////////////////////////////////////////////////////////////
1170 #if 0
1171 class OpalPluginVideoTranscoder : public OpalVideoTranscoder
1173 PCLASSINFO(OpalPluginVideoTranscoder, OpalVideoTranscoder);
1174 public:
1175 OpalPluginVideoTranscoder(const PluginCodec_Definition * _codec, BOOL _isEncoder);
1176 ~OpalPluginVideoTranscoder();
1178 BOOL HasCodecControl(const char * name)
1179 { return ::HasCodecControl(codec, name); }
1181 BOOL CallCodecControl(const char * name,
1182 void * parm,
1183 unsigned int * parmLen,
1184 int & retVal)
1185 { return ::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1187 BOOL ExecuteCommand(const OpalMediaCommand & /*command*/);
1188 PINDEX GetOptimalDataFrameSize(BOOL input) const;
1189 BOOL ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList);
1190 BOOL UpdateOutputMediaFormat(const OpalMediaFormat & fmt);
1192 protected:
1193 void * context;
1194 const PluginCodec_Definition * codec;
1195 BOOL isEncoder;
1196 RTP_DataFrame * bufferRTP;
1198 #endif
1200 OpalPluginVideoTranscoder::OpalPluginVideoTranscoder(const PluginCodec_Definition * _codec, BOOL _isEncoder)
1201 : OpalVideoTranscoder(_codec->sourceFormat, _codec->destFormat),
1202 codec(_codec), isEncoder(_isEncoder)
1204 if (codec == NULL || codec->createCodec == NULL)
1205 context = NULL;
1206 else
1207 context = (*codec->createCodec)(codec);
1209 bufferRTP = NULL;
1212 BOOL OpalPluginVideoTranscoder::CallCodecControl(const char * name,
1213 void * parm,
1214 unsigned int * parmLen,
1215 int & retVal)
1216 { return OpalPluginTranscoder::CallCodecControl(codec, context, name, parm, parmLen, retVal); }
1218 BOOL OpalPluginVideoTranscoder::HasCodecControl(const char * name)
1219 { return OpalPluginTranscoder::HasCodecControl(codec, name); }
1221 BOOL OpalPluginVideoTranscoder::UpdateOutputMediaFormat(const OpalMediaFormat & fmt)
1223 PluginCodec_ControlDefn * ctl = GetCodecControl(codec, SET_CODEC_OPTIONS_CONTROL);
1224 if (ctl != NULL) {
1225 PStringArray list;
1226 for (PINDEX i = 0; i < fmt.GetOptionCount(); i++) {
1227 const OpalMediaOption & option = fmt.GetOption(i);
1228 list += option.GetName();
1229 list += option.AsString();
1230 PTRACE(5, "OpalPlugin\tSetting codec control '" << option.GetName() << "'=" << option.AsString());
1232 char ** _options = list.ToCharArray();
1233 unsigned int optionsLen = sizeof(_options);
1234 (*ctl->control)(codec, context, SET_CODEC_OPTIONS_CONTROL, _options, &optionsLen);
1235 free(_options);
1238 return TRUE;
1242 OpalPluginVideoTranscoder::~OpalPluginVideoTranscoder()
1244 if (bufferRTP == NULL)
1245 delete bufferRTP;
1247 if (codec != NULL && codec->destroyCodec != NULL)
1248 (*codec->destroyCodec)(codec, context);
1251 BOOL OpalPluginVideoTranscoder::ExecuteCommand(const OpalMediaCommand & command)
1253 if (PIsDescendant(&command, OpalVideoUpdatePicture)) {
1254 ++updatePictureCount;
1255 return TRUE;
1258 return OpalTranscoder::ExecuteCommand(command);
1261 PINDEX OpalPluginVideoTranscoder::GetOptimalDataFrameSize(BOOL /*input*/) const
1263 return (frameWidth * frameHeight * 12) / 8;
1266 BOOL OpalPluginVideoTranscoder::ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList)
1268 if (codec == NULL || codec->codecFunction == NULL)
1269 return FALSE;
1271 dstList.RemoveAll();
1273 // get the size of the output buffer
1274 int outputDataSize;
1275 if (!CallCodecControl(GET_OUTPUT_DATA_SIZE_CONTROL, NULL, NULL, outputDataSize))
1276 outputDataSize = 1500;
1278 unsigned flags;
1280 if (isEncoder) {
1282 do {
1284 // create the output buffer
1285 RTP_DataFrame * dst = new RTP_DataFrame(outputDataSize);
1286 dst->SetPayloadType(GetPayloadType(FALSE));
1288 // call the codec function
1289 unsigned int fromLen = src.GetSize();
1290 unsigned int toLen = dst->GetSize();
1291 BOOL forceIFrame = updatePictureCount > 0;
1292 flags = forceIFrame ? PluginCodec_CoderForceIFrame : 0;
1294 if (!(codec->codecFunction)(codec, context,
1295 (const BYTE *)src, &fromLen,
1296 dst->GetPointer(), &toLen,
1297 &flags)) {
1298 delete dst;
1299 return FALSE;
1303 if (forceIFrame && ((flags & PluginCodec_ReturnCoderIFrame) != 0))
1304 --updatePictureCount;
1306 if (toLen > 0) {
1307 dst->SetPayloadSize(toLen - dst->GetHeaderSize());
1308 dstList.Append(dst);
1311 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1314 else {
1316 if (bufferRTP == NULL)
1317 bufferRTP = new RTP_DataFrame(outputDataSize);
1318 else
1319 bufferRTP->SetPayloadSize(outputDataSize);
1320 bufferRTP->SetPayloadType(GetPayloadType(FALSE));
1322 // call the codec function
1323 unsigned int fromLen = src.GetHeaderSize() + src.GetPayloadSize();
1324 unsigned int toLen = bufferRTP->GetSize();
1325 flags = 0;
1327 if (!(codec->codecFunction)(codec, context,
1328 (const BYTE *)src, &fromLen,
1329 bufferRTP->GetPointer(), &toLen,
1330 &flags))
1331 return FALSE;
1333 if ((flags & PluginCodec_ReturnCoderRequestIFrame) != 0) {
1334 if (commandNotifier != PNotifier()) {
1335 OpalVideoUpdatePicture updatePictureCommand;
1336 commandNotifier(updatePictureCommand, 0);
1337 PTRACE (3, "Video\t Could not decode frame, sending VideoUpdatePicture in hope of an I-Frame.");
1341 if (toLen > (unsigned)bufferRTP->GetHeaderSize() && (flags & PluginCodec_ReturnCoderLastFrame) != 0) {
1342 bufferRTP->SetPayloadSize(toLen - bufferRTP->GetHeaderSize());
1343 dstList.Append(bufferRTP);
1344 bufferRTP = NULL;
1348 return TRUE;
1352 #endif // OPAL_VIDEO
1356 //////////////////////////////////////////////////////////////////////////////
1358 // Fax transcoder classes
1361 #if OPAL_T38FAX
1363 class OpalFaxAudioTranscoder : public OpalPluginFramedAudioTranscoder
1365 PCLASSINFO(OpalFaxAudioTranscoder, OpalPluginFramedAudioTranscoder);
1366 public:
1367 OpalFaxAudioTranscoder(PluginCodec_Definition * _codec, BOOL _isEncoder)
1368 : OpalPluginFramedAudioTranscoder(_codec, _isEncoder, "PCM-16-Fax")
1370 bufferRTP = NULL;
1373 ~OpalFaxAudioTranscoder()
1377 BOOL ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList);
1379 protected:
1380 RTP_DataFrame * bufferRTP;
1383 BOOL OpalFaxAudioTranscoder::ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList)
1385 if (codec == NULL || codec->codecFunction == NULL)
1386 return FALSE;
1388 dstList.RemoveAll();
1390 // get the size of the output buffer
1391 int outputDataSize = 400;
1392 //if (!CallCodecControl(GET_OUTPUT_DATA_SIZE_CONTROL, NULL, NULL, outputDataSize))
1393 // return FALSE;
1395 unsigned flags = 0;
1397 if (isEncoder) {
1399 do {
1401 // create the output buffer
1402 RTP_DataFrame * dst = new RTP_DataFrame(outputDataSize);
1403 dst->SetPayloadType(GetPayloadType(FALSE));
1405 // call the codec function
1406 unsigned int fromLen = src.GetSize();
1407 unsigned int toLen = dst->GetSize();
1409 BOOL stat = (codec->codecFunction)(codec, context,
1410 (const BYTE *)src, &fromLen,
1411 dst->GetPointer(), &toLen,
1412 &flags) != 0;
1414 if (!stat) {
1415 delete dst;
1416 return FALSE;
1419 if (toLen > 0) {
1420 dst->SetPayloadSize(toLen - dst->GetHeaderSize());
1421 dstList.Append(dst);
1424 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1427 else {
1429 unsigned int fromLen = src.GetHeaderSize() + src.GetPayloadSize();
1431 do {
1432 if (bufferRTP == NULL)
1433 bufferRTP = new RTP_DataFrame(outputDataSize);
1434 else
1435 bufferRTP->SetPayloadSize(outputDataSize);
1436 bufferRTP->SetPayloadType(GetPayloadType(FALSE));
1438 // call the codec function
1439 unsigned int toLen = bufferRTP->GetSize();
1440 flags = 0;
1441 BOOL stat = (codec->codecFunction)(codec, context,
1442 (const BYTE *)src, &fromLen,
1443 bufferRTP->GetPointer(), &toLen,
1444 &flags) != 0;
1445 if (!stat)
1446 return FALSE;
1448 if (toLen > (unsigned)bufferRTP->GetHeaderSize()) {
1449 bufferRTP->SetPayloadSize(toLen - bufferRTP->GetHeaderSize());
1450 dstList.Append(bufferRTP);
1451 bufferRTP = NULL;
1454 fromLen = 0;
1456 } while ((flags & PluginCodec_ReturnCoderLastFrame) == 0);
1459 return TRUE;
1462 #endif // OPAL_T38FAX
1464 //////////////////////////////////////////////////////////////////////////////
1466 #if OPAL_H323
1468 #if OPAL_AUDIO
1470 //////////////////////////////////////////////////////////////////////////////
1472 // Class for handling most audio plugin capabilities
1475 H323AudioPluginCapability::H323AudioPluginCapability(const PluginCodec_Definition * _encoderCodec,
1476 const PluginCodec_Definition * _decoderCodec,
1477 unsigned _pluginSubType)
1478 : H323AudioCapability(), H323PluginCapabilityInfo(_encoderCodec, _decoderCodec),
1479 pluginSubType(_pluginSubType)
1481 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
1484 // this constructor is only used when creating a capability without a codec
1485 H323AudioPluginCapability::H323AudioPluginCapability(const PString & _mediaFormat,
1486 const PString & _baseName,
1487 unsigned maxFramesPerPacket,
1488 unsigned /*recommendedFramesPerPacket*/,
1489 unsigned _pluginSubType)
1490 : H323AudioCapability(), H323PluginCapabilityInfo(_baseName),
1491 pluginSubType(_pluginSubType)
1493 for (PINDEX i = 0; audioMaps[i].pluginCapType >= 0; i++) {
1494 if (audioMaps[i].pluginCapType == (int)_pluginSubType) {
1495 h323subType = audioMaps[i].h323SubType;
1496 break;
1499 rtpPayloadType = OpalMediaFormat(_mediaFormat).GetPayloadType();
1500 SetTxFramesInPacket(maxFramesPerPacket);
1501 // recommendedFramesPerPacket
1504 PObject * H323AudioPluginCapability::Clone() const
1505 { return new H323AudioPluginCapability(*this); }
1507 PString H323AudioPluginCapability::GetFormatName() const
1508 { return H323PluginCapabilityInfo::GetFormatName();}
1510 unsigned H323AudioPluginCapability::GetSubType() const
1511 { return pluginSubType; }
1513 //////////////////////////////////////////////////////////////////////////////
1515 // Class for handling G.723.1 codecs
1518 class H323PluginG7231Capability : public H323AudioPluginCapability
1520 PCLASSINFO(H323PluginG7231Capability, H323AudioPluginCapability);
1521 public:
1522 H323PluginG7231Capability(const PluginCodec_Definition * _encoderCodec,
1523 const PluginCodec_Definition * _decoderCodec,
1524 BOOL _annexA = TRUE)
1525 : H323AudioPluginCapability(_encoderCodec, _decoderCodec, H245_AudioCapability::e_g7231),
1526 annexA(_annexA)
1529 virtual PObject * Clone() const
1530 { return new H323PluginG7231Capability(*this); }
1532 virtual BOOL OnSendingPDU(H245_AudioCapability & cap, unsigned packetSize) const
1534 cap.SetTag(H245_AudioCapability::e_g7231);
1535 H245_AudioCapability_g7231 & g7231 = cap;
1536 g7231.m_maxAl_sduAudioFrames = packetSize;
1537 g7231.m_silenceSuppression = annexA;
1538 return TRUE;
1541 virtual BOOL OnReceivedPDU(const H245_AudioCapability & cap, unsigned & packetSize)
1543 if (cap.GetTag() != H245_AudioCapability::e_g7231)
1544 return FALSE;
1545 const H245_AudioCapability_g7231 & g7231 = cap;
1546 packetSize = g7231.m_maxAl_sduAudioFrames;
1547 annexA = g7231.m_silenceSuppression;
1548 return TRUE;
1551 protected:
1552 BOOL annexA;
1555 //////////////////////////////////////////////////////////////////////////////
1557 // Class for handling GSM plugin capabilities
1560 class H323GSMPluginCapability : public H323AudioPluginCapability
1562 PCLASSINFO(H323GSMPluginCapability, H323AudioPluginCapability);
1563 public:
1564 H323GSMPluginCapability(const PluginCodec_Definition * _encoderCodec,
1565 const PluginCodec_Definition * _decoderCodec,
1566 int _pluginSubType, int _comfortNoise, int _scrambled)
1567 : H323AudioPluginCapability(_encoderCodec, _decoderCodec, _pluginSubType),
1568 comfortNoise(_comfortNoise), scrambled(_scrambled)
1571 Comparison Compare(const PObject & obj) const;
1573 virtual PObject * Clone() const
1574 { return new H323GSMPluginCapability(*this); }
1576 virtual BOOL OnSendingPDU(
1577 H245_AudioCapability & pdu, /// PDU to set information on
1578 unsigned packetSize /// Packet size to use in capability
1579 ) const;
1581 virtual BOOL OnReceivedPDU(
1582 const H245_AudioCapability & pdu, /// PDU to get information from
1583 unsigned & packetSize /// Packet size to use in capability
1585 protected:
1586 int comfortNoise;
1587 int scrambled;
1590 #endif // OPAL_H323
1592 #endif // OPAL_H323
1594 /////////////////////////////////////////////////////////////////////////////
1596 PMutex & OpalPluginCodecManager::GetMediaFormatMutex()
1598 static PMutex mutex;
1599 return mutex;
1602 OpalPluginCodecManager::OpalPluginCodecManager(PPluginManager * _pluginMgr)
1603 : PPluginModuleManager(PLUGIN_CODEC_GET_CODEC_FN_STR, _pluginMgr)
1605 // instantiate all of the media formats
1607 OpalMediaFormatFactory::KeyList_T keyList = OpalMediaFormatFactory::GetKeyList();
1608 OpalMediaFormatFactory::KeyList_T::const_iterator r;
1609 for (r = keyList.begin(); r != keyList.end(); ++r) {
1610 OpalMediaFormat * instance = OpalMediaFormatFactory::CreateInstance(*r);
1611 if (instance == NULL) {
1612 PTRACE(4, "OpalPlugin\tCannot instantiate opal media format " << *r);
1613 } else {
1614 PTRACE(4, "OpalPlugin\tCreating media format " << *r);
1619 // instantiate all of the static codecs
1621 H323StaticPluginCodecFactory::KeyList_T keyList = H323StaticPluginCodecFactory::GetKeyList();
1622 H323StaticPluginCodecFactory::KeyList_T::const_iterator r;
1623 for (r = keyList.begin(); r != keyList.end(); ++r) {
1624 H323StaticPluginCodec * instance = PFactory<H323StaticPluginCodec>::CreateInstance(*r);
1625 if (instance == NULL) {
1626 PTRACE(4, "OpalPlugin\tCannot instantiate static codec plugin " << *r);
1627 } else {
1628 PTRACE(4, "OpalPlugin\tLoading static codec plugin " << *r);
1629 RegisterStaticCodec(*r, instance->Get_GetAPIFn(), instance->Get_GetCodecFn());
1634 // cause the plugin manager to load all dynamic plugins
1635 pluginMgr->AddNotifier(PCREATE_NOTIFIER(OnLoadModule), TRUE);
1637 #if OPAL_H323
1638 // register the capabilities
1639 while (capabilityCreateList.size() > 0) {
1640 CapabilityCreateListType::iterator r = capabilityCreateList.begin();
1641 RegisterCapability(r->encoderCodec, r->decoderCodec);
1642 capabilityCreateList.erase(r);
1644 #endif
1647 OpalPluginCodecManager::~OpalPluginCodecManager()
1651 void OpalPluginCodecManager::OnShutdown()
1653 // unregister the plugin media formats
1654 OpalMediaFormatFactory::UnregisterAll();
1656 #if 0 // OPAL_H323
1657 // unregister the plugin capabilities
1658 H323CapabilityFactory::UnregisterAll();
1659 #endif
1662 void OpalPluginCodecManager::OnLoadPlugin(PDynaLink & dll, INT code)
1664 PluginCodec_GetCodecFunction getCodecs;
1665 if (!dll.GetFunction(PString(signatureFunctionName), (PDynaLink::Function &)getCodecs)) {
1666 PTRACE(2, "OpalPlugin\tPlugin Codec DLL " << dll.GetName() << " is not a plugin codec");
1667 return;
1670 unsigned int count;
1671 PluginCodec_Definition * codecs = (*getCodecs)(&count, PLUGIN_CODEC_VERSION_OPTIONS);
1672 if (codecs == NULL || count == 0) {
1673 PTRACE(1, "OpalPlugin\tPlugin Codec DLL " << dll.GetName() << " contains no codec definitions");
1674 return;
1677 // get handler for this plugin type
1678 PString name = dll.GetName();
1679 PFactory<OpalPluginCodecHandler>::KeyList_T keys = PFactory<OpalPluginCodecHandler>::GetKeyList();
1680 PFactory<OpalPluginCodecHandler>::KeyList_T::const_iterator r;
1681 OpalPluginCodecHandler * handler = NULL;
1682 for (r = keys.begin(); r != keys.end(); ++r) {
1683 if (name.Right(r->length()) *= *r) {
1684 PTRACE(3, "OpalPlugin\tUsing customer handler for codec " << name);
1685 handler = PFactory<OpalPluginCodecHandler>::CreateInstance(*r);
1686 break;
1690 if (handler == NULL) {
1691 PTRACE(3, "OpalPlugin\tUsing default handler for plugin codec " << name);
1692 handler = new OpalPluginCodecHandler;
1695 switch (code) {
1697 // plugin loaded
1698 case 0:
1699 RegisterCodecPlugins(count, codecs, handler);
1700 break;
1702 // plugin unloaded
1703 case 1:
1704 UnregisterCodecPlugins(count, codecs, handler);
1705 break;
1707 default:
1708 break;
1711 delete handler;
1714 void OpalPluginCodecManager::RegisterStaticCodec(
1715 const H323StaticPluginCodecFactory::Key_T & PTRACE_PARAM(name),
1716 PluginCodec_GetAPIVersionFunction /*getApiVerFn*/,
1717 PluginCodec_GetCodecFunction getCodecFn)
1719 unsigned int count;
1720 PluginCodec_Definition * codecs = (*getCodecFn)(&count, PLUGIN_CODEC_VERSION_OPTIONS);
1721 if (codecs == NULL || count == 0) {
1722 PTRACE(1, "OpalPlugin\tStatic codec " << name << " contains no codec definitions");
1723 return;
1726 OpalPluginCodecHandler * handler = new OpalPluginCodecHandler;
1727 RegisterCodecPlugins(count, codecs, handler);
1728 delete handler;
1731 void OpalPluginCodecManager::RegisterCodecPlugins(unsigned int count, PluginCodec_Definition * codecList, OpalPluginCodecHandler * handler)
1733 // make sure all non-timestamped codecs have the same concept of "now"
1734 static time_t codecNow = ::time(NULL);
1736 unsigned i, j ;
1737 for (i = 0; i < count; i++) {
1739 PluginCodec_Definition & encoder = codecList[i];
1741 BOOL videoSupported = encoder.version >= PLUGIN_CODEC_VERSION_VIDEO;
1742 BOOL faxSupported = encoder.version >= PLUGIN_CODEC_VERSION_FAX;
1744 // for every encoder, we need a decoder
1745 BOOL found = FALSE;
1746 BOOL isEncoder = FALSE;
1747 if (encoder.h323CapabilityType != PluginCodec_H323Codec_undefined &&
1749 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeAudio) &&
1750 strcmp(encoder.sourceFormat, "L16") == 0
1751 ) ||
1753 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeAudioStreamed) &&
1754 strcmp(encoder.sourceFormat, "L16") == 0
1755 ) ||
1757 videoSupported &&
1758 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeVideo) &&
1759 strcmp(encoder.sourceFormat, "YUV420P") == 0
1760 ) ||
1762 faxSupported &&
1763 ((encoder.flags & PluginCodec_MediaTypeMask) == PluginCodec_MediaTypeFax) &&
1764 strcmp(encoder.sourceFormat, "L16") == 0
1767 isEncoder = TRUE;
1768 for (j = 0; j < count; j++) {
1770 PluginCodec_Definition & decoder = codecList[j];
1771 if (
1772 (decoder.h323CapabilityType == encoder.h323CapabilityType) &&
1773 ((decoder.flags & PluginCodec_MediaTypeMask) == (encoder.flags & PluginCodec_MediaTypeMask)) &&
1774 (strcmp(decoder.sourceFormat, encoder.destFormat) == 0) &&
1775 (strcmp(decoder.destFormat, encoder.sourceFormat) == 0)
1779 // deal with codec having no info, or timestamp in future
1780 time_t timeStamp = codecList[i].info == NULL ? codecNow : codecList[i].info->timestamp;
1781 if (timeStamp > codecNow)
1782 timeStamp = codecNow;
1784 // create the media format, transcoder and capability associated with this plugin
1785 RegisterPluginPair(&encoder, &decoder, handler);
1786 found = TRUE;
1788 PTRACE(3, "OpalPlugin\tPlugin codec " << encoder.descr << " defined");
1789 break;
1793 if (!found && isEncoder) {
1794 PTRACE(2, "OpalPlugin\tCannot find decoder for plugin encoder " << encoder.descr);
1799 void OpalPluginCodecManager::UnregisterCodecPlugins(unsigned int, PluginCodec_Definition *, OpalPluginCodecHandler * )
1803 OpalMediaFormatList & OpalPluginCodecManager::GetMediaFormatList()
1805 static OpalMediaFormatList mediaFormatList;
1806 return mediaFormatList;
1809 OpalMediaFormatList OpalPluginCodecManager::GetMediaFormats()
1811 PWaitAndSignal m(GetMediaFormatMutex());
1812 return GetMediaFormatList();
1815 void OpalPluginCodecManager::RegisterPluginPair(
1816 PluginCodec_Definition * encoderCodec,
1817 PluginCodec_Definition * decoderCodec,
1818 OpalPluginCodecHandler * handler
1821 // make sure all non-timestamped codecs have the same concept of "now"
1822 static time_t mediaNow = time(NULL);
1824 // deal with codec having no info, or timestamp in future
1825 time_t timeStamp = encoderCodec->info == NULL ? mediaNow : encoderCodec->info->timestamp;
1826 if (timeStamp > mediaNow)
1827 timeStamp = mediaNow;
1829 unsigned defaultSessionID = 0;
1830 unsigned frameTime = 0;
1831 unsigned clockRate = 0;
1832 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1833 #if OPAL_VIDEO
1834 case PluginCodec_MediaTypeVideo:
1835 defaultSessionID = OpalMediaFormat::DefaultVideoSessionID;
1836 break;
1837 #endif
1838 #if OPAL_AUDIO
1839 case PluginCodec_MediaTypeAudio:
1840 case PluginCodec_MediaTypeAudioStreamed:
1841 defaultSessionID = OpalMediaFormat::DefaultAudioSessionID;
1842 frameTime = (8 * encoderCodec->usPerFrame) / 1000;
1843 clockRate = encoderCodec->sampleRate;
1844 break;
1845 #endif
1846 #if OPAL_T38FAX
1847 case PluginCodec_MediaTypeFax:
1848 defaultSessionID = OpalMediaFormat::DefaultDataSessionID;
1849 frameTime = (8 * encoderCodec->usPerFrame) / 1000;
1850 clockRate = encoderCodec->sampleRate;
1851 break;
1852 #endif
1853 default:
1854 break;
1857 // add the media format
1858 if (defaultSessionID == 0) {
1859 PTRACE(1, "OpalPlugin\tCodec DLL provides unknown media format " << (int)(encoderCodec->flags & PluginCodec_MediaTypeMask));
1860 } else {
1861 PString fmtName = CreateCodecName(encoderCodec);
1862 OpalMediaFormat existingFormat(fmtName);
1863 if (existingFormat.IsValid() && existingFormat.GetCodecBaseTime() >= timeStamp) {
1864 PTRACE(2, "OpalPlugin\tNewer media format " << fmtName << " already exists");
1865 //AddFormat(existingFormat);
1866 } else {
1867 if (existingFormat.IsValid()) {
1868 PWaitAndSignal m(GetMediaFormatMutex());
1869 GetMediaFormatList() -= existingFormat;
1872 PTRACE(3, "OpalPlugin\tCreating new media format " << fmtName);
1874 OpalMediaFormat * mediaFormat = NULL;
1876 // manually register the new singleton type, as we do not have a concrete type
1877 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1878 #if OPAL_VIDEO
1879 case PluginCodec_MediaTypeVideo:
1880 mediaFormat = handler->OnCreateVideoFormat(*this, encoderCodec, encoderCodec->sdpFormat, timeStamp);
1881 break;
1882 #endif
1883 #if OPAL_AUDIO
1884 case PluginCodec_MediaTypeAudio:
1885 case PluginCodec_MediaTypeAudioStreamed:
1886 mediaFormat = handler->OnCreateAudioFormat(*this, encoderCodec, encoderCodec->sdpFormat, frameTime, clockRate, timeStamp);
1887 break;
1888 #endif
1889 #if OPAL_T38FAX
1890 case PluginCodec_MediaTypeFax:
1891 mediaFormat = handler->OnCreateFaxFormat(*this, encoderCodec, encoderCodec->sdpFormat, frameTime, clockRate, timeStamp);
1892 break;
1893 #endif
1894 default:
1895 break;
1897 // if the codec has been flagged to use a shared RTP payload type, then find a codec with the same SDP name
1898 // and clock rate and use that RTP code rather than creating a new one. That prevents codecs (like Speex) from
1899 // consuming dozens of dynamic RTP types
1900 if ((encoderCodec->flags & PluginCodec_RTPTypeShared) != 0 && (encoderCodec->sdpFormat != NULL)) {
1901 PWaitAndSignal m(OpalPluginCodecManager::GetMediaFormatMutex());
1902 OpalMediaFormatList & list = OpalPluginCodecManager::GetMediaFormatList();
1903 for (PINDEX i = 0; i < list.GetSize(); i++) {
1904 OpalMediaFormat * opalFmt = &list[i];
1905 #if OPAL_AUDIO
1907 OpalPluginAudioMediaFormat * fmt = dynamic_cast<OpalPluginAudioMediaFormat *>(opalFmt);
1908 if (
1909 (fmt != NULL) &&
1910 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1911 (fmt->encoderCodec->sdpFormat != NULL) &&
1912 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1914 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1915 break;
1918 #endif
1919 #if OPAL_VIDEO
1921 OpalPluginVideoMediaFormat * fmt = dynamic_cast<OpalPluginVideoMediaFormat *>(opalFmt);
1922 if (
1923 (fmt != NULL) &&
1924 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1925 (fmt->encoderCodec->sdpFormat != NULL) &&
1926 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1928 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1929 break;
1932 #endif
1933 #if OPAL_T38FAX
1935 OpalPluginFaxMediaFormat * fmt = dynamic_cast<OpalPluginFaxMediaFormat *>(opalFmt);
1936 if (
1937 (fmt != NULL) &&
1938 (encoderCodec->sampleRate == fmt->encoderCodec->sampleRate) &&
1939 (fmt->encoderCodec->sdpFormat != NULL) &&
1940 (strcasecmp(encoderCodec->sdpFormat, fmt->encoderCodec->sdpFormat) == 0)
1942 mediaFormat->rtpPayloadType = fmt->GetPayloadType();
1943 break;
1946 #endif
1950 // save the format
1951 AddFormat(*mediaFormat);
1953 // this looks like a memory leak, but it isn't
1954 //delete mediaFormat;
1958 // Create transcoder factories for the codecs
1959 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
1960 #if OPAL_VIDEO
1961 case PluginCodec_MediaTypeVideo:
1962 handler->CreateVideoTranscoder(OpalYUV420P, encoderCodec->destFormat, encoderCodec, TRUE);
1963 handler->CreateVideoTranscoder(encoderCodec->destFormat, OpalYUV420P, decoderCodec, FALSE);
1964 //new OpalPluginTranscoderFactory<OpalPluginVideoTranscoder>::Worker(OpalMediaFormatPair(OpalYUV420P, encoderCodec->destFormat), encoderCodec, TRUE);
1965 //new OpalPluginTranscoderFactory<OpalPluginVideoTranscoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, OpalYUV420P), decoderCodec, FALSE);
1966 break;
1967 #endif
1968 #if OPAL_AUDIO
1969 case PluginCodec_MediaTypeAudio:
1970 if (encoderCodec->sampleRate == 8000) {
1971 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalMediaFormatPair(OpalPCM16, encoderCodec->destFormat), encoderCodec, TRUE);
1972 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, OpalPCM16), decoderCodec, FALSE);
1974 else if (encoderCodec->sampleRate == 16000)
1976 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalMediaFormatPair(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, TRUE);
1977 new OpalPluginTranscoderFactory<OpalPluginFramedAudioTranscoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, FALSE);
1979 else
1981 PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate);
1983 break;
1984 case PluginCodec_MediaTypeAudioStreamed:
1985 if (encoderCodec->sampleRate == 8000) {
1986 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioEncoder>::Worker(OpalMediaFormatPair(OpalPCM16, encoderCodec->destFormat), encoderCodec, TRUE);
1987 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioDecoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, OpalPCM16), decoderCodec, FALSE);
1989 else if (encoderCodec->sampleRate == 16000)
1991 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioEncoder>::Worker(OpalMediaFormatPair(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, TRUE);
1992 new OpalPluginTranscoderFactory<OpalPluginStreamedAudioDecoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, FALSE);
1994 else
1996 PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate);
1998 break;
1999 #endif
2000 #if OPAL_T38FAX
2001 case PluginCodec_MediaTypeFax:
2002 new OpalPluginTranscoderFactory<OpalFaxAudioTranscoder>::Worker(OpalMediaFormatPair(GetOpalPCM16Fax(), encoderCodec->destFormat), encoderCodec, TRUE);
2003 new OpalPluginTranscoderFactory<OpalFaxAudioTranscoder>::Worker(OpalMediaFormatPair(encoderCodec->destFormat, GetOpalPCM16Fax()), decoderCodec, FALSE);
2004 break;
2005 #endif
2006 default:
2007 break;
2010 int retVal;
2011 unsigned int parmLen = sizeof(const char *);
2012 BOOL hasCodecControl = OpalPluginMediaFormat::CallCodecControl(encoderCodec, "valid_for_protocol", (void *)"h323", &parmLen, retVal);
2013 if (encoderCodec->h323CapabilityType == PluginCodec_H323Codec_NoH323 ||
2014 (hasCodecControl && (retVal == 0))
2016 PTRACE(2, "OpalPlugin\tNot adding H.323 capability for plugin codec " << encoderCodec->destFormat << " as this has been specifically disabled");
2017 return;
2020 #if OPAL_H323
2021 PTRACE(4, "OpalPlugin\tDeferring creation of H.323 capability for plugin codec " << encoderCodec->destFormat);
2022 capabilityCreateList.push_back(CapabilityListCreateEntry(encoderCodec, decoderCodec));
2023 #endif
2026 #if OPAL_H323
2028 void OpalPluginCodecManager::RegisterCapability(PluginCodec_Definition * encoderCodec, PluginCodec_Definition * decoderCodec)
2030 // add the capability
2031 H323CodecPluginCapabilityMapEntry * map = NULL;
2033 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
2034 #if OPAL_AUDIO
2035 case PluginCodec_MediaTypeAudio:
2036 case PluginCodec_MediaTypeAudioStreamed:
2037 map = audioMaps;
2038 break;
2039 #endif // OPAL_AUDIO
2041 #if OPAL_VIDEO
2042 case PluginCodec_MediaTypeVideo:
2043 map = videoMaps;
2044 break;
2045 #endif // OPAL_VIDEO
2047 default:
2048 break;
2051 if (map == NULL) {
2052 PTRACE(1, "OpalPlugin\tCannot create capability for unknown plugin codec media format " << (int)(encoderCodec->flags & PluginCodec_MediaTypeMask));
2054 else if (encoderCodec->h323CapabilityType != PluginCodec_H323Codec_undefined) {
2055 for (PINDEX i = 0; map[i].pluginCapType >= 0; i++) {
2056 if (map[i].pluginCapType == encoderCodec->h323CapabilityType) {
2057 H323Capability * cap = NULL;
2058 if (map[i].createFunc != NULL)
2059 cap = (*map[i].createFunc)(encoderCodec, decoderCodec, map[i].h323SubType);
2060 else {
2061 switch (encoderCodec->flags & PluginCodec_MediaTypeMask) {
2062 #if OPAL_AUDIO
2063 case PluginCodec_MediaTypeAudio:
2064 case PluginCodec_MediaTypeAudioStreamed:
2065 cap = new H323AudioPluginCapability(encoderCodec, decoderCodec, map[i].h323SubType);
2066 break;
2067 #endif // OPAL_AUDIO
2069 #if OPAL_VIDEO
2070 case PluginCodec_MediaTypeVideo:
2071 PTRACE(4, "OpalPlugin\tWarning - no capability creation function for " << CreateCodecName(encoderCodec));
2072 // all video caps are created using the create functions
2073 break;
2074 #endif // OPAL_VIDEO
2076 default:
2077 break;
2081 // manually register the new singleton type, as we do not have a concrete type
2082 if (cap != NULL)
2083 H323CapabilityFactory::Register(CreateCodecName(encoderCodec), cap);
2084 break;
2089 #endif // OPAL_H323
2091 void OpalPluginCodecManager::AddFormat(const OpalMediaFormat & fmt)
2093 OpalMediaFormat::SetRegisteredMediaFormat(fmt);
2095 PWaitAndSignal m(GetMediaFormatMutex());
2096 GetMediaFormatList() += fmt;
2100 /////////////////////////////////////////////////////////////////////////////
2102 OpalPluginCodecHandler::OpalPluginCodecHandler()
2106 #if OPAL_AUDIO
2107 OpalMediaFormat * OpalPluginCodecHandler::OnCreateAudioFormat(OpalPluginCodecManager & /*mgr*/,
2108 const PluginCodec_Definition * encoderCodec,
2109 const char * rtpEncodingName,
2110 unsigned frameTime,
2111 unsigned timeUnits,
2112 time_t timeStamp)
2114 return new OpalPluginAudioMediaFormat(encoderCodec, rtpEncodingName, frameTime, timeUnits, timeStamp);
2116 #endif
2118 #if OPAL_VIDEO
2119 OpalMediaFormat * OpalPluginCodecHandler::OnCreateVideoFormat(OpalPluginCodecManager & /*mgr*/,
2120 const PluginCodec_Definition * encoderCodec,
2121 const char * rtpEncodingName,
2122 time_t timeStamp)
2124 return new OpalPluginVideoMediaFormat(encoderCodec, rtpEncodingName, timeStamp);
2127 void OpalPluginCodecHandler::CreateVideoTranscoder(const OpalMediaFormat & src, const OpalMediaFormat & dst, PluginCodec_Definition * codec, BOOL v)
2129 new OpalPluginTranscoderFactory<OpalPluginVideoTranscoder>::Worker(OpalMediaFormatPair(src, dst), codec, v);
2132 #endif
2134 #if OPAL_T38FAX
2135 OpalMediaFormat * OpalPluginCodecHandler::OnCreateFaxFormat(OpalPluginCodecManager & /*mgr*/,
2136 const PluginCodec_Definition * encoderCodec,
2137 const char * rtpEncodingName,
2138 unsigned frameTime,
2139 unsigned timeUnits,
2140 time_t timeStamp)
2142 return new OpalPluginFaxMediaFormat(encoderCodec, rtpEncodingName, frameTime, timeUnits, timeStamp);
2144 #endif
2146 /////////////////////////////////////////////////////////////////////////////
2148 #if OPAL_H323
2150 #if OPAL_AUDIO
2152 H323Capability * CreateNonStandardAudioCap(const PluginCodec_Definition * encoderCodec,
2153 const PluginCodec_Definition * decoderCodec,
2154 int /*subType*/)
2156 PluginCodec_H323NonStandardCodecData * pluginData = (PluginCodec_H323NonStandardCodecData *)encoderCodec->h323CapabilityData;
2157 if (pluginData == NULL) {
2158 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2159 decoderCodec,
2160 (const unsigned char *)encoderCodec->descr,
2161 strlen(encoderCodec->descr));
2164 else if (pluginData->capabilityMatchFunction != NULL)
2165 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2166 decoderCodec,
2167 (H323NonStandardCapabilityInfo::CompareFuncType)pluginData->capabilityMatchFunction,
2168 pluginData->data,
2169 pluginData->dataLength);
2170 else
2171 return new H323CodecPluginNonStandardAudioCapability(encoderCodec,
2172 decoderCodec,
2173 pluginData->data,
2174 pluginData->dataLength);
2177 H323Capability *CreateGenericAudioCap(const PluginCodec_Definition * encoderCodec,
2178 const PluginCodec_Definition * decoderCodec,
2179 int /*subType*/)
2181 PluginCodec_H323GenericCodecData * pluginData = (PluginCodec_H323GenericCodecData *)encoderCodec->h323CapabilityData;
2182 if (pluginData != NULL )
2183 return new H323CodecPluginGenericAudioCapability(encoderCodec, decoderCodec, pluginData);
2185 PTRACE(1, "OpalPlugin\tGeneric codec information for codec '"<<encoderCodec->descr<<"' has NULL data field");
2186 return NULL;
2189 H323Capability * CreateG7231Cap(const PluginCodec_Definition * encoderCodec,
2190 const PluginCodec_Definition * decoderCodec,
2191 int /*subType*/)
2193 return new H323PluginG7231Capability(encoderCodec, decoderCodec, decoderCodec->h323CapabilityData != 0);
2197 H323Capability * CreateGSMCap(const PluginCodec_Definition * encoderCodec,
2198 const PluginCodec_Definition * decoderCodec,
2199 int subType)
2201 PluginCodec_H323AudioGSMData * pluginData = (PluginCodec_H323AudioGSMData *)encoderCodec->h323CapabilityData;
2202 return new H323GSMPluginCapability(encoderCodec, decoderCodec, subType, pluginData->comfortNoise, pluginData->scrambled);
2205 #endif // OPAL_AUDIO
2207 #if OPAL_VIDEO
2209 H323Capability * CreateNonStandardVideoCap(const PluginCodec_Definition * encoderCodec,
2210 const PluginCodec_Definition * decoderCodec,
2211 int /*subType*/)
2213 PluginCodec_H323NonStandardCodecData * pluginData = (PluginCodec_H323NonStandardCodecData *)encoderCodec->h323CapabilityData;
2214 if (pluginData == NULL) {
2215 return new H323CodecPluginNonStandardVideoCapability(
2216 encoderCodec, decoderCodec,
2217 (const unsigned char *)encoderCodec->descr,
2218 strlen(encoderCodec->descr));
2221 else if (pluginData->capabilityMatchFunction != NULL)
2222 return new H323CodecPluginNonStandardVideoCapability(encoderCodec, decoderCodec,
2223 (H323NonStandardCapabilityInfo::CompareFuncType)pluginData->capabilityMatchFunction,
2224 pluginData->data, pluginData->dataLength);
2225 else
2226 return new H323CodecPluginNonStandardVideoCapability(
2227 encoderCodec, decoderCodec,
2228 pluginData->data, pluginData->dataLength);
2231 H323Capability *CreateGenericVideoCap(const PluginCodec_Definition * encoderCodec,
2232 const PluginCodec_Definition * decoderCodec,
2233 int /*subType*/)
2235 PluginCodec_H323GenericCodecData * pluginData = (PluginCodec_H323GenericCodecData *)encoderCodec->h323CapabilityData;
2236 if (pluginData != NULL )
2237 return new H323CodecPluginGenericVideoCapability(encoderCodec, decoderCodec, pluginData);
2239 PTRACE(1, "OpalPlugin\tGeneric codec information for codec '"<<encoderCodec->descr<<"' has NULL data field");
2240 return NULL;
2244 H323Capability * CreateH261Cap(const PluginCodec_Definition * encoderCodec,
2245 const PluginCodec_Definition * decoderCodec,
2246 int /*subType*/)
2248 PTRACE(4, "OpalPlugin\tCreating H.261 plugin capability");
2249 return new H323H261PluginCapability(encoderCodec, decoderCodec);
2252 H323Capability * CreateH263Cap(const PluginCodec_Definition * encoderCodec,
2253 const PluginCodec_Definition * decoderCodec,
2254 int /*subType*/)
2256 PTRACE(4, "OpalPlugin\tCreating H.263 plugin capability");
2257 return new H323H263PluginCapability(encoderCodec, decoderCodec);
2260 #endif // OPAL_VIDEO
2262 /////////////////////////////////////////////////////////////////////////////
2264 H323PluginCapabilityInfo::H323PluginCapabilityInfo(const PluginCodec_Definition * _encoderCodec,
2265 const PluginCodec_Definition * _decoderCodec)
2266 : encoderCodec(_encoderCodec),
2267 decoderCodec(_decoderCodec),
2268 capabilityFormatName(CreateCodecName(_encoderCodec))
2272 H323PluginCapabilityInfo::H323PluginCapabilityInfo(const PString & _baseName)
2273 : encoderCodec(NULL),
2274 decoderCodec(NULL),
2275 capabilityFormatName(_baseName)
2279 #if OPAL_AUDIO
2281 /////////////////////////////////////////////////////////////////////////////
2283 H323CodecPluginNonStandardAudioCapability::H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * _encoderCodec,
2284 const PluginCodec_Definition * _decoderCodec,
2285 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
2286 const unsigned char * data, unsigned dataLen)
2287 : H323NonStandardAudioCapability(compareFunc,data, dataLen),
2288 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2290 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2292 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2293 if (nonStdData->objectId != NULL) {
2294 oid = PString(nonStdData->objectId);
2295 } else {
2296 t35CountryCode = nonStdData->t35CountryCode;
2297 t35Extension = nonStdData->t35Extension;
2298 manufacturerCode = nonStdData->manufacturerCode;
2302 H323CodecPluginNonStandardAudioCapability::H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * _encoderCodec,
2303 const PluginCodec_Definition * _decoderCodec,
2304 const unsigned char * data, unsigned dataLen)
2305 : H323NonStandardAudioCapability(data, dataLen),
2306 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2308 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2309 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2310 if (nonStdData->objectId != NULL) {
2311 oid = PString(nonStdData->objectId);
2312 } else {
2313 t35CountryCode = nonStdData->t35CountryCode;
2314 t35Extension = nonStdData->t35Extension;
2315 manufacturerCode = nonStdData->manufacturerCode;
2319 PObject * H323CodecPluginNonStandardAudioCapability::Clone() const
2320 { return new H323CodecPluginNonStandardAudioCapability(*this); }
2322 PString H323CodecPluginNonStandardAudioCapability::GetFormatName() const
2323 { return H323PluginCapabilityInfo::GetFormatName();}
2325 /////////////////////////////////////////////////////////////////////////////
2327 H323CodecPluginGenericAudioCapability::H323CodecPluginGenericAudioCapability(const PluginCodec_Definition * _encoderCodec,
2328 const PluginCodec_Definition * _decoderCodec,
2329 const PluginCodec_H323GenericCodecData *data )
2330 : H323GenericAudioCapability(data->standardIdentifier, data->maxBitRate ? data->maxBitRate : 0),
2331 H323PluginCapabilityInfo((PluginCodec_Definition *)_encoderCodec, (PluginCodec_Definition *) _decoderCodec)
2333 SetTxFramesInPacket(_decoderCodec->parm.audio.maxFramesPerPacket);
2335 PopulateMediaFormatFromGenericData(GetWritableMediaFormat(), data);
2338 PObject * H323CodecPluginGenericAudioCapability::Clone() const
2339 { return new H323CodecPluginGenericAudioCapability(*this); }
2341 PString H323CodecPluginGenericAudioCapability::GetFormatName() const
2342 { return H323PluginCapabilityInfo::GetFormatName();}
2344 /////////////////////////////////////////////////////////////////////////////
2346 PObject::Comparison H323GSMPluginCapability::Compare(const PObject & obj) const
2348 if (!PIsDescendant(&obj, H323GSMPluginCapability))
2349 return LessThan;
2351 Comparison result = H323AudioCapability::Compare(obj);
2352 if (result != EqualTo)
2353 return result;
2355 const H323GSMPluginCapability& other = (const H323GSMPluginCapability&)obj;
2356 if (scrambled < other.scrambled)
2357 return LessThan;
2358 if (comfortNoise < other.comfortNoise)
2359 return LessThan;
2360 return EqualTo;
2364 BOOL H323GSMPluginCapability::OnSendingPDU(H245_AudioCapability & cap, unsigned packetSize) const
2366 cap.SetTag(pluginSubType);
2367 H245_GSMAudioCapability & gsm = cap;
2368 gsm.m_audioUnitSize = packetSize * encoderCodec->parm.audio.bytesPerFrame;
2369 gsm.m_comfortNoise = comfortNoise;
2370 gsm.m_scrambled = scrambled;
2372 return TRUE;
2376 BOOL H323GSMPluginCapability::OnReceivedPDU(const H245_AudioCapability & cap, unsigned & packetSize)
2378 const H245_GSMAudioCapability & gsm = cap;
2379 packetSize = gsm.m_audioUnitSize / encoderCodec->parm.audio.bytesPerFrame;
2380 if (packetSize == 0)
2381 packetSize = 1;
2383 scrambled = gsm.m_scrambled;
2384 comfortNoise = gsm.m_comfortNoise;
2386 return TRUE;
2389 /////////////////////////////////////////////////////////////////////////////
2391 #endif // OPAL_AUDIO
2393 #if OPAL_VIDEO
2395 //////////////////////////////////////////////////////////////////////////////
2397 // Class for handling most videoplugin capabilities
2400 H323VideoPluginCapability::H323VideoPluginCapability(const PluginCodec_Definition * _encoderCodec,
2401 const PluginCodec_Definition * _decoderCodec,
2402 unsigned _pluginSubType)
2403 : H323VideoCapability(), H323PluginCapabilityInfo(_encoderCodec, _decoderCodec),
2404 pluginSubType(_pluginSubType)
2408 PString H323VideoPluginCapability::GetFormatName() const
2409 { return H323PluginCapabilityInfo::GetFormatName();}
2411 unsigned H323VideoPluginCapability::GetSubType() const
2412 { return pluginSubType; }
2414 BOOL H323VideoPluginCapability::SetCommonOptions(OpalMediaFormat & mediaFormat, int frameWidth, int frameHeight, int frameRate)
2416 if (!mediaFormat.SetOptionInteger(OpalVideoFormat::FrameWidthOption(), frameWidth))
2417 return FALSE;
2419 if (!mediaFormat.SetOptionInteger(OpalVideoFormat::FrameHeightOption(), frameHeight))
2420 return FALSE;
2422 if (!mediaFormat.SetOptionInteger(OpalMediaFormat::FrameTimeOption(), OpalMediaFormat::VideoClockRate * 100 * frameRate / 2997))
2423 return FALSE;
2425 return TRUE;
2428 void H323VideoPluginCapability::PrintOn(std::ostream & strm) const
2430 H323VideoCapability::PrintOn(strm);
2433 /////////////////////////////////////////////////////////////////////////////
2435 H323H261PluginCapability::H323H261PluginCapability(const PluginCodec_Definition * _encoderCodec,
2436 const PluginCodec_Definition * _decoderCodec)
2437 : H323VideoPluginCapability(_encoderCodec, _decoderCodec, H245_VideoCapability::e_h261VideoCapability)
2439 const OpalMediaFormat & fmt = GetMediaFormat();
2440 if (!fmt.HasOption(qcifMPI_tag) && !fmt.HasOption(cifMPI_tag))
2441 GetWritableMediaFormat().AddOption(new OpalMediaOptionUnsigned(cifMPI_tag, false, OpalMediaOption::MinMerge, 4));
2444 PObject::Comparison H323H261PluginCapability::Compare(const PObject & obj) const
2446 if (!PIsDescendant(&obj, H323H261PluginCapability))
2447 return LessThan;
2449 Comparison result = H323Capability::Compare(obj);
2450 if (result != EqualTo)
2451 return result;
2453 const H323H261PluginCapability & other = (const H323H261PluginCapability &)obj;
2455 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2457 int qcifMPI = mediaFormat.HasOption(qcifMPI_tag) ? mediaFormat.GetOptionInteger(qcifMPI_tag) : mediaFormat.GetOptionInteger("QCIF MPI");
2458 int cifMPI = mediaFormat.HasOption(cifMPI_tag) ? mediaFormat.GetOptionInteger(cifMPI_tag) : mediaFormat.GetOptionInteger("CIF MPI");
2460 int other_qcifMPI = other.GetMediaFormat().GetOptionInteger(qcifMPI_tag);
2461 int other_cifMPI = other.GetMediaFormat().GetOptionInteger(cifMPI_tag);
2463 if (((qcifMPI > 0) && (other_qcifMPI > 0)) ||
2464 ((cifMPI > 0) && (other_cifMPI > 0)))
2465 return EqualTo;
2467 if (qcifMPI > 0)
2468 return LessThan;
2470 return GreaterThan;
2473 PObject * H323H261PluginCapability::Clone() const
2475 return new H323H261PluginCapability(*this);
2478 BOOL H323H261PluginCapability::OnSendingPDU(H245_VideoCapability & cap) const
2480 cap.SetTag(H245_VideoCapability::e_h261VideoCapability);
2482 H245_H261VideoCapability & h261 = cap;
2484 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2487 #if PTRACING
2488 ostream & traceStream = PTrace::Begin(4, __FILE__, __LINE__);
2489 traceStream << "H.261 extracting options from\n";
2490 for (PINDEX i = 0; i < mediaFormat.GetOptionCount(); i++) {
2491 const OpalMediaOption & option = mediaFormat.GetOption(i);
2492 traceStream << " " << option.GetName() << " = " << option.AsString() << '\n';
2494 traceStream << PTrace::End;
2495 #endif
2498 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag, 0);
2499 if (qcifMPI > 0) {
2500 h261.IncludeOptionalField(H245_H261VideoCapability::e_qcifMPI);
2501 h261.m_qcifMPI = qcifMPI;
2503 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2504 if (cifMPI > 0 || qcifMPI == 0) {
2505 h261.IncludeOptionalField(H245_H261VideoCapability::e_cifMPI);
2506 h261.m_cifMPI = cifMPI;
2509 h261.m_temporalSpatialTradeOffCapability = mediaFormat.GetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, FALSE);
2510 h261.m_maxBitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 621700)+50)/100;
2511 h261.m_stillImageTransmission = mediaFormat.GetOptionBoolean(h323_stillImageTransmission_tag, FALSE);
2513 return TRUE;
2517 BOOL H323H261PluginCapability::OnSendingPDU(H245_VideoMode & pdu) const
2519 pdu.SetTag(H245_VideoMode::e_h261VideoMode);
2520 H245_H261VideoMode & mode = pdu;
2522 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2524 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2526 mode.m_resolution.SetTag(qcifMPI > 0 ? H245_H261VideoMode_resolution::e_qcif
2527 : H245_H261VideoMode_resolution::e_cif);
2529 mode.m_bitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 621700) + 50) / 1000;
2530 mode.m_stillImageTransmission = mediaFormat.GetOptionBoolean(h323_stillImageTransmission_tag, FALSE);
2532 return TRUE;
2535 BOOL H323H261PluginCapability::OnReceivedPDU(const H245_VideoCapability & cap)
2537 if (cap.GetTag() != H245_VideoCapability::e_h261VideoCapability)
2538 return FALSE;
2540 OpalMediaFormat & mediaFormat = GetWritableMediaFormat();
2542 const H245_H261VideoCapability & h261 = cap;
2543 if (h261.HasOptionalField(H245_H261VideoCapability::e_qcifMPI)) {
2545 if (!mediaFormat.SetOptionInteger(qcifMPI_tag, h261.m_qcifMPI))
2546 return FALSE;
2548 if (!SetCommonOptions(mediaFormat, QCIF_WIDTH, QCIF_HEIGHT, h261.m_qcifMPI))
2549 return FALSE;
2552 if (h261.HasOptionalField(H245_H261VideoCapability::e_cifMPI)) {
2554 if (!mediaFormat.SetOptionInteger(cifMPI_tag, h261.m_cifMPI))
2555 return FALSE;
2557 if (!SetCommonOptions(mediaFormat, QCIF_WIDTH, QCIF_HEIGHT, h261.m_cifMPI))
2558 return FALSE;
2561 mediaFormat.SetOptionInteger(OpalMediaFormat::MaxBitRateOption(), h261.m_maxBitRate*100);
2562 mediaFormat.SetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, h261.m_temporalSpatialTradeOffCapability);
2563 mediaFormat.SetOptionBoolean(h323_stillImageTransmission_tag, h261.m_stillImageTransmission);
2565 return TRUE;
2568 /////////////////////////////////////////////////////////////////////////////
2570 H323H263PluginCapability::H323H263PluginCapability(const PluginCodec_Definition * _encoderCodec,
2571 const PluginCodec_Definition * _decoderCodec)
2572 : H323VideoPluginCapability(_encoderCodec, _decoderCodec, H245_VideoCapability::e_h263VideoCapability)
2576 PObject::Comparison H323H263PluginCapability::Compare(const PObject & obj) const
2578 if (!PIsDescendant(&obj, H323H263PluginCapability))
2579 return LessThan;
2581 Comparison result = H323Capability::Compare(obj);
2582 if (result != EqualTo)
2583 return result;
2585 const H323H263PluginCapability & other = (const H323H263PluginCapability &)obj;
2587 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2589 int sqcifMPI = mediaFormat.GetOptionInteger(sqcifMPI_tag);
2590 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2591 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2592 int cif4MPI = mediaFormat.GetOptionInteger(cif4MPI_tag);
2593 int cif16MPI = mediaFormat.GetOptionInteger(cif16MPI_tag);
2595 int other_sqcifMPI = other.GetMediaFormat().GetOptionInteger(sqcifMPI_tag);
2596 int other_qcifMPI = other.GetMediaFormat().GetOptionInteger(qcifMPI_tag);
2597 int other_cifMPI = other.GetMediaFormat().GetOptionInteger(cifMPI_tag);
2598 int other_cif4MPI = other.GetMediaFormat().GetOptionInteger(cif4MPI_tag);
2599 int other_cif16MPI = other.GetMediaFormat().GetOptionInteger(cif16MPI_tag);
2601 if ((sqcifMPI && other_sqcifMPI) ||
2602 (qcifMPI && other_qcifMPI) ||
2603 (cifMPI && other_cifMPI) ||
2604 (cif4MPI && other_cif4MPI) ||
2605 (cif16MPI && other_cif16MPI)) {
2606 PTRACE(1, "H263: " << *this << " == " << other);
2607 return EqualTo;
2610 if ((!cif16MPI && other_cif16MPI) ||
2611 (!cif4MPI && other_cif4MPI) ||
2612 (!cifMPI && other_cifMPI) ||
2613 (!qcifMPI && other_qcifMPI) ||
2614 (!sqcifMPI && other_sqcifMPI)) {
2615 PTRACE(1, "H263: " << *this << " < " << other);
2616 return LessThan;
2619 PTRACE(1, "H263: " << *this << " > " << other << " are equal");
2620 return GreaterThan;
2623 PObject * H323H263PluginCapability::Clone() const
2624 { return new H323H263PluginCapability(*this); }
2626 static void SetTransmittedCap(const OpalMediaFormat & mediaFormat,
2627 H245_H263VideoCapability & h263,
2628 const char * mpiTag,
2629 int mpiEnum,
2630 PASN_Integer & mpi,
2631 int slowMpiEnum,
2632 PASN_Integer & slowMpi)
2634 int mpiVal = mediaFormat.GetOptionInteger(mpiTag);
2635 if (mpiVal > 0) {
2636 h263.IncludeOptionalField(mpiEnum);
2637 mpi = mpiVal;
2639 else if (mpiVal < 0) {
2640 h263.IncludeOptionalField(slowMpiEnum);
2641 slowMpi = -mpiVal;
2646 BOOL H323H263PluginCapability::OnSendingPDU(H245_VideoCapability & cap) const
2648 cap.SetTag(H245_VideoCapability::e_h263VideoCapability);
2649 H245_H263VideoCapability & h263 = cap;
2651 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2653 //PStringStream str; mediaFormat.PrintOptions(str);
2654 //PTRACE(5, "OpalPlugin\tCreating capability for " << mediaFormat << ", options=\n" << str);
2656 SetTransmittedCap(mediaFormat, cap, sqcifMPI_tag, H245_H263VideoCapability::e_sqcifMPI, h263.m_sqcifMPI, H245_H263VideoCapability::e_slowSqcifMPI, h263.m_slowSqcifMPI);
2657 SetTransmittedCap(mediaFormat, cap, qcifMPI_tag, H245_H263VideoCapability::e_qcifMPI, h263.m_qcifMPI, H245_H263VideoCapability::e_slowQcifMPI, h263.m_slowQcifMPI);
2658 SetTransmittedCap(mediaFormat, cap, cifMPI_tag, H245_H263VideoCapability::e_cifMPI, h263.m_cifMPI, H245_H263VideoCapability::e_slowCifMPI, h263.m_slowCifMPI);
2659 SetTransmittedCap(mediaFormat, cap, cif4MPI_tag, H245_H263VideoCapability::e_cif4MPI, h263.m_cif4MPI, H245_H263VideoCapability::e_slowCif4MPI, h263.m_slowCif4MPI);
2660 SetTransmittedCap(mediaFormat, cap, cif16MPI_tag, H245_H263VideoCapability::e_cif16MPI, h263.m_cif16MPI, H245_H263VideoCapability::e_slowCif16MPI, h263.m_slowCif16MPI);
2662 h263.m_maxBitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 327600) + 50) / 100;
2663 h263.m_temporalSpatialTradeOffCapability = mediaFormat.GetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, FALSE);
2664 h263.m_unrestrictedVector = mediaFormat.GetOptionBoolean(h323_unrestrictedVector_tag, FALSE);
2665 h263.m_arithmeticCoding = mediaFormat.GetOptionBoolean(h323_arithmeticCoding_tag, FALSE);
2666 h263.m_advancedPrediction = mediaFormat.GetOptionBoolean(h323_advancedPrediction_tag, FALSE);
2667 h263.m_pbFrames = mediaFormat.GetOptionBoolean(h323_pbFrames_tag, FALSE);
2668 h263.m_errorCompensation = mediaFormat.GetOptionBoolean(h323_errorCompensation_tag, FALSE);
2671 int hrdB = mediaFormat.GetOptionInteger(h323_hrdB_tag, -1);
2672 if (hrdB >= 0) {
2673 h263.IncludeOptionalField(H245_H263VideoCapability::e_hrd_B);
2674 h263.m_hrd_B = hrdB;
2679 int bppMaxKb = mediaFormat.GetOptionInteger(h323_bppMaxKb_tag, -1);
2680 if (bppMaxKb >= 0) {
2681 h263.IncludeOptionalField(H245_H263VideoCapability::e_bppMaxKb);
2682 h263.m_bppMaxKb = bppMaxKb;
2686 return TRUE;
2690 BOOL H323H263PluginCapability::OnSendingPDU(H245_VideoMode & pdu) const
2692 pdu.SetTag(H245_VideoMode::e_h263VideoMode);
2693 H245_H263VideoMode & mode = pdu;
2695 const OpalMediaFormat & mediaFormat = GetMediaFormat();
2697 int qcifMPI = mediaFormat.GetOptionInteger(qcifMPI_tag);
2698 int cifMPI = mediaFormat.GetOptionInteger(cifMPI_tag);
2699 int cif4MPI = mediaFormat.GetOptionInteger(cif4MPI_tag);
2700 int cif16MPI = mediaFormat.GetOptionInteger(cif16MPI_tag);
2702 mode.m_resolution.SetTag(cif16MPI ? H245_H263VideoMode_resolution::e_cif16
2703 :(cif4MPI ? H245_H263VideoMode_resolution::e_cif4
2704 :(cifMPI ? H245_H263VideoMode_resolution::e_cif
2705 :(qcifMPI ? H245_H263VideoMode_resolution::e_qcif
2706 : H245_H263VideoMode_resolution::e_sqcif))));
2708 mode.m_bitRate = (mediaFormat.GetOptionInteger(OpalMediaFormat::MaxBitRateOption(), 327600) + 50) / 100;
2709 mode.m_unrestrictedVector = mediaFormat.GetOptionBoolean(h323_unrestrictedVector_tag, FALSE);
2710 mode.m_arithmeticCoding = mediaFormat.GetOptionBoolean(h323_arithmeticCoding_tag, FALSE);
2711 mode.m_advancedPrediction = mediaFormat.GetOptionBoolean(h323_advancedPrediction_tag, FALSE);
2712 mode.m_pbFrames = mediaFormat.GetOptionBoolean(h323_pbFrames_tag, FALSE);
2713 mode.m_errorCompensation = mediaFormat.GetOptionBoolean(h323_errorCompensation_tag, FALSE);
2715 return TRUE;
2718 static BOOL SetReceivedH263Cap(OpalMediaFormat & mediaFormat,
2719 const H245_H263VideoCapability & h263,
2720 const char * mpiTag,
2721 int mpiEnum,
2722 const PASN_Integer & mpi,
2723 int slowMpiEnum,
2724 const PASN_Integer & slowMpi,
2725 int frameWidth, int frameHeight,
2726 BOOL & formatDefined)
2728 if (h263.HasOptionalField(mpiEnum)) {
2729 if (!mediaFormat.SetOptionInteger(mpiTag, mpi))
2730 return FALSE;
2731 if (mpi != 0) {
2732 if (!H323VideoPluginCapability::SetCommonOptions(mediaFormat, frameWidth, frameHeight, mpi))
2733 return FALSE;
2734 formatDefined = TRUE;
2737 else if (h263.HasOptionalField(slowMpiEnum)) {
2738 if (!mediaFormat.SetOptionInteger(mpiTag, -(signed)slowMpi))
2739 return FALSE;
2740 if (slowMpi != 0) {
2741 if (!H323VideoPluginCapability::SetCommonOptions(mediaFormat, frameWidth, frameHeight, -(signed)slowMpi))
2742 return FALSE;
2743 formatDefined = TRUE;
2746 else
2747 mediaFormat.SetOptionInteger(mpiTag, 0);
2749 return TRUE;
2752 BOOL H323H263PluginCapability::IsMatch(const PASN_Choice & subTypePDU) const
2754 if (!H323Capability::IsMatch(subTypePDU))
2755 return FALSE;
2757 H245_VideoCapability & video = (H245_VideoCapability &)subTypePDU;
2758 H245_H263VideoCapability & h263 = (H245_H263VideoCapability &)video;
2760 #define COMPARE_MPI(field, slowField) \
2761 if ( \
2762 ((GetMediaFormat().GetOptionInteger(field##_tag) > 0) ? TRUE : FALSE) \
2763 != \
2764 (h263.HasOptionalField(H245_H263VideoCapability::e_##field) ? (h263.m_##field != 0) : FALSE) \
2766 return FALSE; \
2767 if ( \
2768 ((GetMediaFormat().GetOptionInteger(field##_tag) < 0) ? TRUE : FALSE) \
2769 != \
2770 (h263.HasOptionalField(H245_H263VideoCapability::e_##slowField) ? (h263.m_##slowField != 0) : FALSE) \
2772 return FALSE; \
2773 if ( \
2774 ((GetMediaFormat().GetOptionInteger(field##_tag) < 0) ? TRUE : FALSE) \
2775 != \
2776 (h263.HasOptionalField(H245_H263VideoCapability::e_##slowField) ? (h263.m_##slowField != 0) : FALSE) \
2778 return FALSE; \
2780 COMPARE_MPI(sqcifMPI, slowSqcifMPI);
2781 COMPARE_MPI(qcifMPI, slowQcifMPI);
2782 COMPARE_MPI(cifMPI, slowCifMPI);
2783 COMPARE_MPI(cif4MPI, slowCif4MPI);
2784 COMPARE_MPI(cif16MPI, slowCif16MPI);
2787 return TRUE;
2791 BOOL H323H263PluginCapability::OnReceivedPDU(const H245_VideoCapability & cap)
2793 if (cap.GetTag() != H245_VideoCapability::e_h263VideoCapability)
2794 return FALSE;
2796 OpalMediaFormat & mediaFormat = GetWritableMediaFormat();
2798 BOOL formatDefined = FALSE;
2800 const H245_H263VideoCapability & h263 = cap;
2802 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))
2803 return FALSE;
2805 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))
2806 return FALSE;
2808 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))
2809 return FALSE;
2811 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))
2812 return FALSE;
2814 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))
2815 return FALSE;
2817 if (!formatDefined)
2818 return FALSE;
2820 unsigned maxBitRate = h263.m_maxBitRate*100;
2821 if (!mediaFormat.SetOptionInteger(OpalMediaFormat::MaxBitRateOption(), maxBitRate))
2822 return FALSE;
2823 unsigned targetBitRate = mediaFormat.GetOptionInteger(OpalVideoFormat::TargetBitRateOption());
2824 if (targetBitRate > maxBitRate)
2825 mediaFormat.SetOptionInteger(OpalVideoFormat::TargetBitRateOption(), maxBitRate);
2827 mediaFormat.SetOptionBoolean(h323_unrestrictedVector_tag, h263.m_unrestrictedVector);
2828 mediaFormat.SetOptionBoolean(h323_arithmeticCoding_tag, h263.m_arithmeticCoding);
2829 mediaFormat.SetOptionBoolean(h323_advancedPrediction_tag, h263.m_advancedPrediction);
2830 mediaFormat.SetOptionBoolean(h323_pbFrames_tag, h263.m_pbFrames);
2831 mediaFormat.SetOptionBoolean(h323_errorCompensation_tag, h263.m_errorCompensation);
2832 mediaFormat.SetOptionBoolean(h323_temporalSpatialTradeOffCapability_tag, h263.m_temporalSpatialTradeOffCapability);
2834 if (h263.HasOptionalField(H245_H263VideoCapability::e_hrd_B))
2835 mediaFormat.SetOptionInteger(h323_hrdB_tag, h263.m_hrd_B);
2837 if (h263.HasOptionalField(H245_H263VideoCapability::e_bppMaxKb))
2838 mediaFormat.SetOptionInteger(h323_bppMaxKb_tag, h263.m_bppMaxKb);
2840 //PStringStream str; mediaFormat.PrintOptions(str);
2841 //PTRACE(4, "OpalPlugin\tCreated H.263 cap from incoming PDU with format " << mediaFormat << " and options\n" << str);
2843 return TRUE;
2846 /////////////////////////////////////////////////////////////////////////////
2848 H323CodecPluginNonStandardVideoCapability::H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * _encoderCodec,
2849 const PluginCodec_Definition * _decoderCodec,
2850 H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
2851 const unsigned char * data, unsigned dataLen)
2852 : H323NonStandardVideoCapability(compareFunc, data, dataLen),
2853 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2855 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2856 if (nonStdData->objectId != NULL) {
2857 oid = PString(nonStdData->objectId);
2858 } else {
2859 t35CountryCode = nonStdData->t35CountryCode;
2860 t35Extension = nonStdData->t35Extension;
2861 manufacturerCode = nonStdData->manufacturerCode;
2865 H323CodecPluginNonStandardVideoCapability::H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * _encoderCodec,
2866 const PluginCodec_Definition * _decoderCodec,
2867 const unsigned char * data, unsigned dataLen)
2868 : H323NonStandardVideoCapability(data, dataLen),
2869 H323PluginCapabilityInfo(_encoderCodec, _decoderCodec)
2871 PluginCodec_H323NonStandardCodecData * nonStdData = (PluginCodec_H323NonStandardCodecData *)_encoderCodec->h323CapabilityData;
2872 if (nonStdData->objectId != NULL) {
2873 oid = PString(nonStdData->objectId);
2874 } else {
2875 t35CountryCode = nonStdData->t35CountryCode;
2876 t35Extension = nonStdData->t35Extension;
2877 manufacturerCode = nonStdData->manufacturerCode;
2881 PObject * H323CodecPluginNonStandardVideoCapability::Clone() const
2882 { return new H323CodecPluginNonStandardVideoCapability(*this); }
2884 PString H323CodecPluginNonStandardVideoCapability::GetFormatName() const
2885 { return H323PluginCapabilityInfo::GetFormatName();}
2887 /////////////////////////////////////////////////////////////////////////////
2889 H323CodecPluginGenericVideoCapability::H323CodecPluginGenericVideoCapability(const PluginCodec_Definition * _encoderCodec,
2890 const PluginCodec_Definition * _decoderCodec,
2891 const PluginCodec_H323GenericCodecData *data)
2892 : H323GenericVideoCapability(data->standardIdentifier, data->maxBitRate),
2893 H323PluginCapabilityInfo((PluginCodec_Definition *)_encoderCodec, (PluginCodec_Definition *)_decoderCodec)
2895 PopulateMediaFormatFromGenericData(GetWritableMediaFormat(), data);
2898 PObject * H323CodecPluginGenericVideoCapability::Clone() const
2900 return new H323CodecPluginGenericVideoCapability(*this);
2903 PString H323CodecPluginGenericVideoCapability::GetFormatName() const
2905 return H323PluginCapabilityInfo::GetFormatName();
2909 /////////////////////////////////////////////////////////////////////////////
2911 #endif // OPAL_VIDEO
2913 #endif // OPAL_H323
2915 /////////////////////////////////////////////////////////////////////////////
2917 static PAtomicInteger bootStrapCount = 0;
2919 void OpalPluginCodecManager::Bootstrap()
2921 if (++bootStrapCount != 1)
2922 return;
2925 /////////////////////////////////////////////////////////////////////////////
2927 #define INCLUDE_STATIC_CODEC(name) \
2928 extern "C" { \
2929 extern unsigned int Opal_StaticCodec_##name##_GetAPIVersion(); \
2930 extern struct PluginCodec_Definition * Opal_StaticCodec_##name##_GetCodecs(unsigned *,unsigned); \
2931 }; \
2932 class H323StaticPluginCodec_##name : public H323StaticPluginCodec \
2934 public: \
2935 PluginCodec_GetAPIVersionFunction Get_GetAPIFn() \
2936 { return &Opal_StaticCodec_##name##_GetAPIVersion; } \
2937 PluginCodec_GetCodecFunction Get_GetCodecFn() \
2938 { return &Opal_StaticCodec_##name##_GetCodecs; } \
2939 }; \
2940 static H323StaticPluginCodecFactory::Worker<H323StaticPluginCodec_##name > static##name##CodecFactory( #name ); \
2942 #ifdef H323_EMBEDDED_GSM
2944 INCLUDE_STATIC_CODEC(GSM_0610)
2946 #endif