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