opalpluginmgr.h

Go to the documentation of this file.
00001 /*
00002  * opalpluginmgr.h
00003  *
00004  * OPAL codec plugins handler
00005  *
00006  * OPAL Library
00007  *
00008  * Copyright (C) 2005-2006 Post Increment
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Open Phone Abstraction Library.
00021  *
00022  * The Initial Developer of the Original Code is Post Increment
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Revision: 22817 $
00027  * $Author: rjongbloed $
00028  * $Date: 2009-06-05 02:37:23 +0000 (Fri, 05 Jun 2009) $
00029  */
00030 
00031 #ifndef OPAL_CODEC_OPALPLUGINMGR_H
00032 #define OPAL_CODEC_OPALPLUGINMGR_H
00033 
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037 
00038 #include <ptlib/object.h>
00039 
00040 #include <opal/buildopts.h>
00041 
00042 #include <ptlib/pluginmgr.h>
00043 #include <ptlib/pfactory.h>
00044 #include <codec/opalplugin.h>
00045 #include <opal/mediafmt.h>
00046 #include <opal/transcoders.h>
00047 
00048 #if OPAL_H323
00049 #include <h323/h323caps.h>
00050 #endif
00051 
00052 #if OPAL_VIDEO
00053 #include <codec/vidcodec.h>
00054 #endif
00055 
00056 
00058 
00059 class H323Capability;
00060 
00061 class H323StaticPluginCodec
00062 {
00063   public:
00064     virtual ~H323StaticPluginCodec() { }
00065     virtual PluginCodec_GetAPIVersionFunction Get_GetAPIFn() = 0;
00066     virtual PluginCodec_GetCodecFunction Get_GetCodecFn() = 0;
00067 };
00068 
00069 typedef PFactory<H323StaticPluginCodec> H323StaticPluginCodecFactory;
00070 
00071 
00073 
00074 class OpalPluginCodecManager;
00075 
00076 class OpalPluginCodecHandler : public PObject
00077 {
00078   PCLASSINFO(OpalPluginCodecHandler, PObject);
00079   public:
00080     OpalPluginCodecHandler();
00081 
00082     virtual OpalMediaFormatInternal * OnCreateAudioFormat(OpalPluginCodecManager & mgr,
00083                                             const PluginCodec_Definition * codecDefn,
00084                                                               const char * rtpEncodingName,
00085                                                                   unsigned frameTime,
00086                                                                   unsigned timeUnits,
00087                                                                     time_t timeStamp);
00088 
00089 #if OPAL_VIDEO
00090     virtual OpalMediaFormatInternal * OnCreateVideoFormat(OpalPluginCodecManager & mgr,
00091                                             const PluginCodec_Definition * codecDefn,
00092                                                               const char * rtpEncodingName,
00093                                                                     time_t timeStamp);
00094     virtual void RegisterVideoTranscoder(const PString & src, const PString & dst, const PluginCodec_Definition * codec, bool v);
00095 #endif
00096 
00097 #if OPAL_T38_CAPABILITY
00098     virtual OpalMediaFormatInternal * OnCreateFaxFormat(OpalPluginCodecManager & mgr,
00099                                           const PluginCodec_Definition * codecDefn,
00100                                                             const char * rtpEncodingName,
00101                                                                 unsigned frameTime,
00102                                                                 unsigned timeUnits,
00103                                                                   time_t timeStamp);
00104 #endif
00105 };
00106 
00107 
00108 class OpalPluginCodecManager : public PPluginModuleManager
00109 {
00110   PCLASSINFO(OpalPluginCodecManager, PPluginModuleManager);
00111   public:
00112     OpalPluginCodecManager(PPluginManager * pluginMgr = NULL);
00113     ~OpalPluginCodecManager();
00114 
00115     void RegisterStaticCodec(const H323StaticPluginCodecFactory::Key_T & name,
00116                              PluginCodec_GetAPIVersionFunction getApiVerFn,
00117                              PluginCodec_GetCodecFunction getCodecFn);
00118 
00119     void OnLoadPlugin(PDynaLink & dll, INT code);
00120 
00121     virtual void OnShutdown();
00122 
00123     static void Bootstrap();
00124 
00125 #if OPAL_H323
00126     H323Capability * CreateCapability(
00127           const PString & _mediaFormat, 
00128           const PString & _baseName,
00129                  unsigned maxFramesPerPacket, 
00130                  unsigned recommendedFramesPerPacket,
00131                  unsigned _pluginSubType);
00132 #endif
00133 
00134   protected:
00135     // Note the below MUST NOT be an OpalMediaFormatList
00136     PList<OpalMediaFormat> mediaFormatsOnHeap;
00137 
00138     void RegisterCodecPlugins  (unsigned int count, const PluginCodec_Definition * codecList, OpalPluginCodecHandler * handler);
00139     void UnregisterCodecPlugins(unsigned int count, const PluginCodec_Definition * codecList, OpalPluginCodecHandler * handler);
00140 
00141 #if OPAL_H323
00142     void RegisterCapability(const PluginCodec_Definition * codecDefn);
00143 #endif
00144 };
00145 
00146 
00148 
00149 class OpalPluginControl
00150 {
00151   public:
00152     OpalPluginControl(const PluginCodec_Definition * def, const char * name);
00153 
00154     bool Exists() const
00155     {
00156       return controlDef != NULL;
00157     }
00158 
00159     int Call(void * parm, unsigned * parmLen, void * context = NULL) const
00160     {
00161       return controlDef != NULL ? (*controlDef->control)(codecDef, context, fnName, parm, parmLen) : -1;
00162     }
00163 
00164     int Call(void * parm, unsigned   parmLen, void * context = NULL) const
00165     {
00166       return Call(parm, &parmLen, context);
00167     }
00168 
00169     const char * GetName() const { return fnName; }
00170 
00171   protected:
00172     const PluginCodec_Definition  * codecDef;
00173     const char                    * fnName;
00174     const PluginCodec_ControlDefn * controlDef;
00175 };
00176 
00177 
00179 
00180 class OpalPluginMediaFormatInternal
00181 {
00182   public:
00183     OpalPluginMediaFormatInternal(const PluginCodec_Definition * defn);
00184 
00185     bool AdjustOptions(OpalMediaFormatInternal & fmt, OpalPluginControl & control) const;
00186     void PopulateOptions(OpalMediaFormatInternal & format);
00187     void SetOldStyleOption(OpalMediaFormatInternal & format, const PString & _key, const PString & _val, const PString & type);
00188     bool IsValidForProtocol(const PString & _protocol) const;
00189 
00190     const PluginCodec_Definition * codecDef;
00191     OpalPluginControl getOptionsControl;
00192     OpalPluginControl freeOptionsControl;
00193     OpalPluginControl validForProtocolControl;
00194     OpalPluginControl toNormalisedControl;
00195     OpalPluginControl toCustomisedControl;
00196 };
00197 
00198 
00199 class OpalPluginMediaFormat : public OpalMediaFormat
00200 {
00201   public:
00202     OpalPluginMediaFormat(OpalMediaFormatInternal * info)
00203       : OpalMediaFormat(info)
00204     {
00205     }
00206 
00207     OpalPluginMediaFormatInternal * GetInfo() const { return dynamic_cast<OpalPluginMediaFormatInternal *>(m_info); }
00208 };
00209 
00210 
00211 class OpalPluginTranscoder
00212 {
00213   public:
00214     OpalPluginTranscoder(const PluginCodec_Definition * defn, bool isEnc);
00215     ~OpalPluginTranscoder();
00216 
00217     bool UpdateOptions(const OpalMediaFormat & fmt);
00218     bool Transcode(const void * from, unsigned * fromLen, void * to, unsigned * toLen, unsigned * flags) const
00219     {
00220       return codecDef != NULL && codecDef->codecFunction != NULL &&
00221             (codecDef->codecFunction)(codecDef, context, from, fromLen, to, toLen, flags) != 0;
00222     }
00223 
00224   protected:
00225     const PluginCodec_Definition * codecDef;
00226     bool   isEncoder;
00227     void * context;
00228 
00229     OpalPluginControl setCodecOptions;
00230     OpalPluginControl getOutputDataSizeControl;
00231 };
00232 
00233 
00235 
00236 class OpalPluginAudioFormatInternal : public OpalAudioFormatInternal, public OpalPluginMediaFormatInternal
00237 {
00238   public:
00239     friend class OpalPluginCodecManager;
00240 
00241     OpalPluginAudioFormatInternal(
00242       const PluginCodec_Definition * codecDefn,
00243       const char * rtpEncodingName, 
00244       unsigned frameTime,           
00245       unsigned /*timeUnits*/,       
00246       time_t timeStamp              
00247     );
00248     virtual PObject * Clone() const;
00249     virtual bool IsValidForProtocol(const PString & protocol) const;
00250     virtual bool ToNormalisedOptions();
00251     virtual bool ToCustomisedOptions();
00252 };
00253 
00254 
00255 class OpalPluginFramedAudioTranscoder : public OpalFramedTranscoder, public OpalPluginTranscoder
00256 {
00257   PCLASSINFO(OpalPluginFramedAudioTranscoder, OpalFramedTranscoder);
00258   public:
00259     OpalPluginFramedAudioTranscoder(const PluginCodec_Definition * codecDefn, bool isEncoder);
00260     bool UpdateMediaFormats(const OpalMediaFormat & input, const OpalMediaFormat & output);
00261     PBoolean ConvertFrame(const BYTE * input, PINDEX & consumed, BYTE * output, PINDEX & created);
00262     virtual PBoolean ConvertSilentFrame(BYTE * buffer);
00263     virtual bool AcceptComfortNoise() const { return comfortNoise; }
00264   protected:
00265     bool comfortNoise;
00266 };
00267 
00268 
00269 class OpalPluginStreamedAudioTranscoder : public OpalStreamedTranscoder, public OpalPluginTranscoder
00270 {
00271   PCLASSINFO(OpalPluginStreamedAudioTranscoder, OpalStreamedTranscoder);
00272   public:
00273     OpalPluginStreamedAudioTranscoder(const PluginCodec_Definition * codec, bool isEncoder);
00274     bool UpdateMediaFormats(const OpalMediaFormat & input, const OpalMediaFormat & output);
00275     virtual bool AcceptComfortNoise() const { return comfortNoise; }
00276     virtual int ConvertOne(int from) const;
00277   protected:
00278     bool comfortNoise;
00279 };
00280 
00281 
00283 
00284 #if OPAL_VIDEO
00285 
00286 class OpalPluginVideoFormatInternal : public OpalVideoFormatInternal, public OpalPluginMediaFormatInternal
00287 {
00288   public:
00289     OpalPluginVideoFormatInternal(
00290       const PluginCodec_Definition * codec,
00291       const char * rtpEncodingName, 
00292       time_t timeStamp              
00293     );
00294     virtual PObject * Clone() const;
00295     virtual bool IsValidForProtocol(const PString & protocol) const;
00296     virtual bool ToNormalisedOptions();
00297     virtual bool ToCustomisedOptions();
00298 };
00299 
00300 
00301 class OpalPluginVideoTranscoder : public OpalVideoTranscoder, public OpalPluginTranscoder
00302 {
00303   PCLASSINFO(OpalPluginVideoTranscoder, OpalVideoTranscoder);
00304   public:
00305     OpalPluginVideoTranscoder(const PluginCodec_Definition * codec, bool isEncoder);
00306     ~OpalPluginVideoTranscoder();
00307 
00308     PBoolean ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dstList);
00309     bool UpdateMediaFormats(const OpalMediaFormat & input, const OpalMediaFormat & output);
00310 
00311   protected:
00312     RTP_DataFrame * m_bufferRTP;
00313     PTimeInterval   m_lastVideoFastUpdate;
00314 
00315 #if PTRACING
00316     unsigned m_consecutiveIntraFrames;
00317 #endif
00318 };
00319 
00320 #endif
00321 
00323 
00324 #if OPAL_T38_CAPABILITY
00325 
00326 class OpalPluginFaxFormatInternal : public OpalMediaFormatInternal, public OpalPluginMediaFormatInternal
00327 {
00328   public:
00329     OpalPluginFaxFormatInternal(
00330       const PluginCodec_Definition * codec,
00331       const char * rtpEncodingName, 
00332       unsigned frameTime,
00333       unsigned /*timeUnits*/,           
00334       time_t timeStamp              
00335     );
00336     virtual PObject * Clone() const;
00337     virtual bool IsValidForProtocol(const PString & protocol) const;
00338 };
00339 
00340 #endif // OPAL_T38_CAPABILITY
00341 
00342 
00344 //
00345 //  this is the base class for codecs accesible via the abstract factory functions
00346 //
00347 
00355 class OpalFactoryCodec : public PObject {
00356   PCLASSINFO(OpalFactoryCodec, PObject)
00357   public:
00359     virtual const struct PluginCodec_Definition * GetDefinition()
00360     { return NULL; }
00361 
00363     virtual PString GetInputFormat() const = 0;
00364 
00366     virtual PString GetOutputFormat() const = 0;
00367 
00369     virtual int Encode(const void * from,      
00370                          unsigned * fromLen,   
00371                              void * to,        
00372                                  unsigned * toLen,     
00373                      unsigned int * flag       
00374                        ) = 0;  
00375 
00377     virtual unsigned int GetSampleRate() const = 0;
00378 
00380     virtual unsigned int GetBitsPerSec() const = 0;
00381 
00383     virtual unsigned int GetFrameTime() const = 0;
00384 
00386     virtual unsigned int GetSamplesPerFrame() const = 0;
00387 
00389     virtual unsigned int GetBytesPerFrame() const = 0;
00390 
00392     virtual unsigned int GetRecommendedFramesPerPacket() const = 0;
00393 
00395     virtual unsigned int GetMaxFramesPerPacket() const = 0;
00396 
00398     virtual BYTE         GetRTPPayload() const = 0;
00399 
00401     virtual PString      GetSDPFormat() const = 0;
00402 };
00403 
00405 
00406 template<class TranscoderClass>
00407 class OpalPluginTranscoderFactory : public OpalTranscoderFactory
00408 {
00409   public:
00410     class Worker : public OpalTranscoderFactory::WorkerBase 
00411     {
00412       public:
00413         Worker(const OpalTranscoderKey & key, const PluginCodec_Definition * codec, bool enc)
00414           : OpalTranscoderFactory::WorkerBase(), codecDefn(codec), isEncoder(enc)
00415         { OpalTranscoderFactory::Register(key, this); }
00416 
00417       protected:
00418         virtual OpalTranscoder * Create(const OpalTranscoderKey &) const
00419         { return new TranscoderClass(codecDefn, isEncoder); }
00420 
00421         const PluginCodec_Definition * codecDefn;
00422         bool isEncoder;
00423     };
00424 };
00425 
00427 //
00428 // Helper class for handling plugin capabilities
00429 //
00430 
00431 class H323PluginCapabilityInfo
00432 {
00433   public:
00434     H323PluginCapabilityInfo(const PluginCodec_Definition * codecDefn);
00435 
00436     H323PluginCapabilityInfo(const PString & _baseName);
00437 
00438     const PString & GetFormatName() const
00439     { return m_capabilityFormatName; }
00440 
00441   protected:
00442     const PluginCodec_Definition * m_codecDefn;
00443     PString                        m_capabilityFormatName;
00444 };
00445 
00446 #if OPAL_H323
00447 
00449 //
00450 // Class for handling most audio plugin capabilities
00451 //
00452 
00453 class H323AudioPluginCapability : public H323AudioCapability,
00454                                   public H323PluginCapabilityInfo
00455 {
00456   PCLASSINFO(H323AudioPluginCapability, H323AudioCapability);
00457   public:
00458     H323AudioPluginCapability(const PluginCodec_Definition * codecDefn,
00459                               unsigned pluginSubType);
00460 
00461     // this constructor is only used when creating a capability without a codec
00462     H323AudioPluginCapability(const PString & _mediaFormat,
00463                               const PString & _baseName,
00464                               unsigned _pluginSubType);
00465 
00466     virtual PObject * Clone() const;
00467 
00468     virtual PString GetFormatName() const;
00469 
00470     virtual unsigned GetSubType() const;
00471 
00472   protected:
00473     unsigned pluginSubType;
00474 };
00475 
00476 #define OPAL_DECLARE_EMPTY_AUDIO_CAPABILITY(fmt, type) \
00477 class fmt##_CapabilityRegisterer { \
00478   public: \
00479     fmt##_CapabilityRegisterer() \
00480     { H323CapabilityFactory::Register(fmt, new H323AudioPluginCapability(fmt, fmt, type)); } \
00481 }; \
00482 
00483 #define OPAL_DEFINE_EMPTY_AUDIO_CAPABILITY(fmt) \
00484 static fmt##_CapabilityRegisterer fmt##_CapabilityRegisterer_instance; \
00485 
00487 //
00488 // Class for handling G.723.1 codecs
00489 //
00490 
00491 class H323PluginG7231Capability : public H323AudioPluginCapability
00492 {
00493   PCLASSINFO(H323PluginG7231Capability, H323AudioPluginCapability);
00494   public:
00495     H323PluginG7231Capability(const PluginCodec_Definition * codecDefn, bool annexA = true);
00496 
00497     // this constructor is used for creating empty codecs
00498     H323PluginG7231Capability(const OpalMediaFormat & fmt, bool annexA = true);
00499 
00500     virtual PObject * Clone() const;
00501     virtual PBoolean OnSendingPDU(H245_AudioCapability & cap, unsigned packetSize) const;
00502     virtual PBoolean OnReceivedPDU(const H245_AudioCapability & cap,  unsigned & packetSize);
00503 
00504   protected:
00505     bool m_annexA;
00506 };
00507 
00508 #define OPAL_DECLARE_EMPTY_G7231_CAPABILITY(fmt, annex) \
00509 class fmt##_CapabilityRegisterer { \
00510   public: \
00511     fmt##_CapabilityRegisterer() \
00512     { H323CapabilityFactory::Register(fmt, new H323PluginG7231Capability(fmt, annex)); } \
00513 }; \
00514 
00515 #define OPAL_DEFINE_EMPTY_G7231_CAPABILITY(fmt) \
00516 static fmt##_CapabilityRegisterer fmt##_CapabilityRegisterer_instance; \
00517 
00519 //
00520 // Class for handling non standard audio capabilities
00521 //
00522 
00523 class H323CodecPluginNonStandardAudioCapability : public H323NonStandardAudioCapability,
00524                                                   public H323PluginCapabilityInfo
00525 {
00526   PCLASSINFO(H323CodecPluginNonStandardAudioCapability, H323NonStandardAudioCapability);
00527   public:
00528     H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * codecDefn,
00529                                               H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
00530                                               const unsigned char * data, unsigned dataLen);
00531 
00532     H323CodecPluginNonStandardAudioCapability(const PluginCodec_Definition * codecDefn,
00533                                               const unsigned char * data, unsigned dataLen);
00534 
00535     virtual PObject * Clone() const;
00536 
00537     virtual PString GetFormatName() const;
00538 };
00539 
00541 //
00542 // Class for handling generic audio capabilities
00543 //
00544 
00545 class H323CodecPluginGenericAudioCapability : public H323GenericAudioCapability,
00546                                               public H323PluginCapabilityInfo
00547 {
00548   PCLASSINFO(H323CodecPluginGenericAudioCapability, H323GenericAudioCapability);
00549   public:
00550     H323CodecPluginGenericAudioCapability(const PluginCodec_Definition * codecDefn,
00551                                           const PluginCodec_H323GenericCodecData * data);
00552 
00553     virtual PObject * Clone() const;
00554     virtual PString GetFormatName() const;
00555 };
00556 
00557 
00558 #if OPAL_VIDEO
00559 
00561 //
00562 // Class for handling most audio plugin capabilities
00563 //
00564 
00565 class H323VideoPluginCapability : public H323VideoCapability,
00566                              public H323PluginCapabilityInfo
00567 {
00568   PCLASSINFO(H323VideoPluginCapability, H323VideoCapability);
00569   public:
00570     H323VideoPluginCapability(const PluginCodec_Definition * codecDefn,
00571                               unsigned _pluginSubType);
00572 
00573     virtual PString GetFormatName() const;
00574 
00575     virtual unsigned GetSubType() const;
00576 
00577     static bool SetOptionsFromMPI(OpalMediaFormat & mediaFormat, int frameWidth, int frameHeight, int frameRate);
00578 
00579     virtual void PrintOn(std::ostream & strm) const;
00580 
00581   protected:
00582     unsigned pluginSubType;
00583     unsigned h323subType;   // only set if using capability without codec
00584 };
00585 
00587 //
00588 // Class for handling non standard video capabilities
00589 //
00590 
00591 class H323CodecPluginNonStandardVideoCapability : public H323NonStandardVideoCapability,
00592                                                   public H323PluginCapabilityInfo
00593 {
00594   PCLASSINFO(H323CodecPluginNonStandardVideoCapability, H323NonStandardVideoCapability);
00595   public:
00596     H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * codecDefn,
00597                                               H323NonStandardCapabilityInfo::CompareFuncType compareFunc,
00598                                               const unsigned char * data, unsigned dataLen);
00599 
00600     H323CodecPluginNonStandardVideoCapability(const PluginCodec_Definition * codecDefn,
00601                                               const unsigned char * data, unsigned dataLen);
00602 
00603     virtual PObject * Clone() const;
00604 
00605     virtual PString GetFormatName() const;
00606 };
00607 
00609 //
00610 // Class for handling generic video capabilities
00611 //
00612 
00613 class H323CodecPluginGenericVideoCapability : public H323GenericVideoCapability,
00614                                               public H323PluginCapabilityInfo
00615 {
00616   PCLASSINFO(H323CodecPluginGenericVideoCapability, H323GenericVideoCapability);
00617   public:
00618     H323CodecPluginGenericVideoCapability(const PluginCodec_Definition * codecDefn,
00619                                           const PluginCodec_H323GenericCodecData * data);
00620 
00621     virtual PObject * Clone() const;
00622 
00623     virtual PString GetFormatName() const;
00624 };
00625 
00627 //
00628 // Class for handling H.261 plugin capabilities
00629 //
00630 
00631 class H323H261PluginCapability : public H323VideoPluginCapability
00632 {
00633   PCLASSINFO(H323H261PluginCapability, H323VideoPluginCapability);
00634   public:
00635     H323H261PluginCapability(const PluginCodec_Definition * codecDefn);
00636 
00637     Comparison Compare(const PObject & obj) const;
00638 
00639     virtual PObject * Clone() const;
00640 
00641     virtual PBoolean OnSendingPDU(
00642       H245_VideoCapability & pdu  
00643     ) const;
00644 
00645     virtual PBoolean OnSendingPDU(
00646       H245_VideoMode & pdu
00647     ) const;
00648 
00649     virtual PBoolean OnReceivedPDU(
00650       const H245_VideoCapability & pdu  
00651     );
00652 };
00653 
00655 //
00656 // Class for handling H.263 plugin capabilities
00657 //
00658 
00659 class H323H263PluginCapability : public H323VideoPluginCapability
00660 {
00661   PCLASSINFO(H323H263PluginCapability, H323VideoPluginCapability);
00662   public:
00663     H323H263PluginCapability(const PluginCodec_Definition * codecDefn);
00664 
00665     Comparison Compare(const PObject & obj) const;
00666 
00667     virtual PObject * Clone() const;
00668 
00669     virtual PBoolean OnSendingPDU(
00670       H245_VideoCapability & pdu  
00671     ) const;
00672 
00673     virtual PBoolean OnSendingPDU(
00674       H245_VideoMode & pdu
00675     ) const;
00676 
00677     virtual PBoolean OnReceivedPDU(
00678       const H245_VideoCapability & pdu  
00679     );
00680     virtual PBoolean IsMatch(const PASN_Choice & subTypePDU) const;
00681 };
00682 
00683 #endif // OPAL_VIDEO
00684 #endif // OPAL_H323
00685 
00686 #endif // OPAL_CODEC_OPALPLUGINMGR_H

Generated on Mon Feb 1 00:25:53 2010 for OPAL by  doxygen 1.5.1