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