# opalplugin.hpp

Go to the documentation of this file.

    00001 /*
    00002  * opalplugins.hpp
    00003  *
    00004  * OPAL codec plugins handler (C++ version)
    00005  *
    00006  * Open Phone Abstraction Library (OPAL)
    00007  * Formally known as the Open H323 project.
    00008  *
    00009  * Copyright (C) 2010 Vox Lucida
    00010  *
    00011  * Redistribution and use in source and binary forms, with or without
    00012  * modification, are permitted provided that the following conditions
    00013  * are met:
    00014  *
    00015  * - Redistributions of source code must retain the above copyright
    00016  *   notice, this list of conditions and the following disclaimer.
    00017
    00018  * - Redistributions in binary form must reproduce the above copyright
    00019  *   notice, this list of conditions and the following disclaimer in the
    00020  *   documentation and/or other materials provided with the distribution.
    00021  *
    00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00023  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00025  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
    00026  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00033  *
    00034  * $Revision: 29223 $
    00035  * $Author: rjongbloed $
    00036  * $Date: 2013-03-07 18:00:29 -0600 (Thu, 07 Mar 2013) $
    00037  */
    00038
    00039 #ifndef OPAL_CODEC_OPALPLUGIN_HPP
    00040 #define OPAL_CODEC_OPALPLUGIN_HPP
    00041
    00042 #include "opalplugin.h"
    00043
    00044 #include <string.h>
    00045 #include <stdlib.h>
    00046 #include <limits.h>
    00047
    00048 #include <map>
    00049 #include <string>
    00050
    00051
    00053
    00054 #ifndef PLUGINCODEC_TRACING
    00055   #define PLUGINCODEC_TRACING 1
    00056 #endif
    00057
    00058 #if PLUGINCODEC_TRACING
    00059   extern PluginCodec_LogFunction PluginCodec_LogFunctionInstance;
    00060   extern int PluginCodec_SetLogFunction(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len);
    00061
    00062 #define PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF \
    00063   PluginCodec_LogFunction PluginCodec_LogFunctionInstance; \
    00064   int PluginCodec_SetLogFunction(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len) \
    00065   { \
    00066     if (len == NULL || *len != sizeof(PluginCodec_LogFunction)) \
    00067       return false; \
    00068  \
    00069     PluginCodec_LogFunctionInstance = (PluginCodec_LogFunction)parm; \
    00070     if (PluginCodec_LogFunctionInstance != NULL) \
    00071       PluginCodec_LogFunctionInstance(4, __FILE__, __LINE__, "Plugin", "Started logging."); \
    00072  \
    00073     return true; \
    00074   } \
    00075
    00076   #define PLUGINCODEC_CONTROL_LOG_FUNCTION_INC { PLUGINCODEC_CONTROL_SET_LOG_FUNCTION, PluginCodec_SetLogFunction },
    00077 #else
    00078   #define PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF
    00079   #define PLUGINCODEC_CONTROL_LOG_FUNCTION_INC
    00080 #endif
    00081
    00082 #if !defined(PTRACE)
    00083   #if PLUGINCODEC_TRACING
    00084     #include <sstream>
    00085     #define PTRACE_CHECK(level) \
    00086         (PluginCodec_LogFunctionInstance != NULL && PluginCodec_LogFunctionInstance(level, NULL, 0, NULL, NULL))
    00087     #define PTRACE(level, section, args) \
    00088       if (PTRACE_CHECK(level)) { \
    00089         std::ostringstream strm; strm << args; \
    00090         PluginCodec_LogFunctionInstance(level, __FILE__, __LINE__, section, strm.str().c_str()); \
    00091       } else (void)0
    00092   #else
    00093     #define PTRACE_CHECK(level)
    00094     #define PTRACE(level, section, expr)
    00095   #endif
    00096 #endif
    00097
    00098
    00100
    00101 class PluginCodec_RTP
    00102 {
    00103     unsigned char * m_packet;
    00104     unsigned        m_maxSize;
    00105     unsigned        m_headerSize;
    00106     unsigned        m_payloadSize;
    00107
    00108   public:
    00109     PluginCodec_RTP(const void * packet, unsigned size)
    00110       : m_packet((unsigned char *)packet)
    00111       , m_maxSize(size)
    00112       , m_headerSize(PluginCodec_RTP_GetHeaderLength(m_packet))
    00113       , m_payloadSize(size - m_headerSize)
    00114     {
    00115     }
    00116
    00117     __inline unsigned GetMaxSize() const           { return m_maxSize; }
    00118     __inline unsigned GetPacketSize() const        { return m_headerSize+m_payloadSize; }
    00119     __inline unsigned GetHeaderSize() const        { return m_headerSize; }
    00120     __inline unsigned GetPayloadSize() const       { return m_payloadSize; }
    00121     __inline bool     SetPayloadSize(unsigned size)
    00122     {
    00123       if (m_headerSize+size > m_maxSize)
    00124         return false;
    00125       m_payloadSize = size;
    00126       return true;
    00127     }
    00128
    00129     __inline unsigned GetPayloadType() const         { return PluginCodec_RTP_GetPayloadType(m_packet);        }
    00130     __inline void     SetPayloadType(unsigned type)  {        PluginCodec_RTP_SetPayloadType(m_packet, type);  }
    00131     __inline bool     GetMarker() const              { return PluginCodec_RTP_GetMarker(m_packet);             }
    00132     __inline void     SetMarker(bool mark)           {        PluginCodec_RTP_SetMarker(m_packet, mark);       }
    00133     __inline unsigned GetTimestamp() const           { return PluginCodec_RTP_GetTimestamp(m_packet);          }
    00134     __inline void     SetTimestamp(unsigned ts)      {        PluginCodec_RTP_SetTimestamp(m_packet, ts);      }
    00135     __inline unsigned GetSequenceNumber() const      { return PluginCodec_RTP_GetSequenceNumber(m_packet);     }
    00136     __inline void     SetSequenceNumber(unsigned sn) {        PluginCodec_RTP_SetSequenceNumber(m_packet, sn); }
    00137     __inline unsigned GetSSRC() const                { return PluginCodec_RTP_GetSSRC(m_packet);               }
    00138     __inline void     SetSSRC(unsigned ssrc)         {        PluginCodec_RTP_SetSSRC(m_packet, ssrc);         }
    00139
    00140     __inline unsigned char * SetExtended(unsigned id, unsigned len)
    00141     {
    00142       m_packet[0] |= 0x10;
    00143
    00144       unsigned char * ptr = m_packet + PluginCodec_RTP_GetCSRCHdrLength(m_packet);
    00145       switch (id >> 16) {
    00146         case 0 :
    00147           PluginCodec_RTP_SetWORD(ptr, 0, id);
    00148           PluginCodec_RTP_SetWORD(ptr, 2, (len+3)/4);
    00149           ptr += 4;
    00150           break;
    00151
    00152         case 1 :
    00153           *ptr++ = 0xbe;
    00154           *ptr++ = 0xde;
    00155           PluginCodec_RTP_SetWORD(ptr, 0, (len+7)/4); ptr += 2;
    00156           *ptr++ = (unsigned char)(((id&0xf) << 4)|(len-1));
    00157           break;
    00158
    00159         case 2 :
    00160           *ptr++ = 0x10;
    00161           *ptr++ = 0x00;
    00162           PluginCodec_RTP_SetWORD(ptr, 0, (len+8)/4); ptr += 2;
    00163           *ptr++ = (unsigned char)(id&0xff);
    00164           *ptr++ = (unsigned char)(len&0xff);
    00165       }
    00166
    00167       m_headerSize = PluginCodec_RTP_GetHeaderLength(m_packet);
    00168       return ptr;
    00169     }
    00170
    00171     __inline unsigned char * GetExtendedHeader(unsigned & id, size_t & len) const
    00172     {
    00173       if ((m_packet[0]&0x10) == 0)
    00174         return NULL;
    00175
    00176       unsigned char * ptr = m_packet + PluginCodec_RTP_GetCSRCHdrLength(m_packet);
    00177       id = PluginCodec_RTP_GetWORD(ptr, 0);
    00178
    00179       if (id == 0xbede) {
    00180         id = (0x10000|(ptr[4] >> 4));
    00181         len = (ptr[4] & 0xf)+1;
    00182         return ptr + 5;
    00183       }
    00184
    00185       if ((id&0xfff0) == 0x1000) {
    00186         id = 0x20000 | ptr[4];
    00187         len = ptr[5];
    00188         return ptr + 6;
    00189       }
    00190
    00191       len = PluginCodec_RTP_GetWORD(ptr, 2)*4;
    00192       return ptr + 4;
    00193     }
    00194
    00195     __inline unsigned char * GetPayloadPtr() const   { return m_packet + m_headerSize; }
    00196     __inline unsigned char & operator[](size_t offset) { return m_packet[m_headerSize + offset]; }
    00197     __inline unsigned const char & operator[](size_t offset) const { return m_packet[m_headerSize + offset]; }
    00198     __inline bool CopyPayload(const void * data, size_t size, size_t offset = 0)
    00199     {
    00200       if (!SetPayloadSize(offset + size))
    00201         return false;
    00202       memcpy(GetPayloadPtr()+offset, data, size);
    00203       return true;
    00204     }
    00205
    00206     __inline PluginCodec_Video_FrameHeader * GetVideoHeader() const { return (PluginCodec_Video_FrameHeader *)GetPayloadPtr(); }
    00207     __inline unsigned char * GetVideoFrameData() const { return m_packet + m_headerSize + sizeof(PluginCodec_Video_FrameHeader); }
    00208 };
    00209
    00210
    00212
    00213 typedef std::map<std::string, std::string> PluginCodec_OptionMapBase;
    00214
    00215 class PluginCodec_Utilities
    00216 {
    00217   public:
    00218    static unsigned String2Unsigned(const std::string & str)
    00219     {
    00220       return strtoul(str.c_str(), NULL, 10);
    00221     }
    00222
    00223
    00224     static void AppendUnsigned2String(unsigned value, std::string & str)
    00225     {
    00226       // Not very efficient, but really, really simple
    00227       if (value > 9)
    00228         AppendUnsigned2String(value/10, str);
    00229       str += (char)(value%10 + '0');
    00230     }
    00231
    00232
    00233     static void Unsigned2String(unsigned value, std::string & str)
    00234     {
    00235       str.clear();
    00236       AppendUnsigned2String(value,str);
    00237     }
    00238
    00239
    00240     static void Change(const char * value,
    00241                        PluginCodec_OptionMapBase & original,
    00242                        PluginCodec_OptionMapBase & changed,
    00243                        const char * option)
    00244     {
    00245       PluginCodec_OptionMapBase::iterator it = original.find(option);
    00246       if (it != original.end() && it->second != value)
    00247         changed[option] = value;
    00248     }
    00249
    00250
    00251     static void Change(unsigned     value,
    00252                        PluginCodec_OptionMapBase  & original,
    00253                        PluginCodec_OptionMapBase  & changed,
    00254                        const char * option)
    00255     {
    00256       if (String2Unsigned(original[option]) != value)
    00257         Unsigned2String(value, changed[option]);
    00258     }
    00259
    00260
    00261     static void ClampMax(unsigned     maximum,
    00262                          PluginCodec_OptionMapBase  & original,
    00263                          PluginCodec_OptionMapBase  & changed,
    00264                          const char * option,
    00265                          bool forceIfZero = false)
    00266     {
    00267       unsigned value = String2Unsigned(original[option]);
    00268       if (value > maximum || (forceIfZero && value == 0))
    00269         Unsigned2String(maximum, changed[option]);
    00270     }
    00271
    00272
    00273     static void ClampMin(unsigned     minimum,
    00274                          PluginCodec_OptionMapBase  & original,
    00275                          PluginCodec_OptionMapBase  & changed,
    00276                          const char * option)
    00277     {
    00278       unsigned value = String2Unsigned(original[option]);
    00279       if (value < minimum)
    00280         Unsigned2String(minimum, changed[option]);
    00281     }
    00282
    00283
    00284     static unsigned GetMacroBlocks(unsigned width, unsigned height)
    00285     {
    00286       return ((width+15)/16) * ((height+15)/16);
    00287     }
    00288
    00289
    00290     static bool ClampResolution(
    00291       unsigned & width,
    00292       unsigned & height,
    00293       unsigned & maxFrameSize)
    00294     {
    00295       static struct {
    00296         unsigned m_width;
    00297         unsigned m_height;
    00298         unsigned m_macroblocks;
    00299       } MaxVideoResolutions[] = {
    00300         #define OPAL_PLUGIN_CLAMPED_RESOLUTION(width, height) { width, height, ((width+15)/16) * ((height+15)/16) }
    00301         OPAL_PLUGIN_CLAMPED_RESOLUTION(2816, 2304),
    00302         OPAL_PLUGIN_CLAMPED_RESOLUTION(1920, 1080),
    00303         OPAL_PLUGIN_CLAMPED_RESOLUTION(1408, 1152),
    00304         OPAL_PLUGIN_CLAMPED_RESOLUTION(1280,  720),
    00305         OPAL_PLUGIN_CLAMPED_RESOLUTION( 704,  576),
    00306         OPAL_PLUGIN_CLAMPED_RESOLUTION( 640,  480),
    00307         OPAL_PLUGIN_CLAMPED_RESOLUTION( 352,  288),
    00308         OPAL_PLUGIN_CLAMPED_RESOLUTION( 320,  240),
    00309         OPAL_PLUGIN_CLAMPED_RESOLUTION( 176,  144),
    00310         OPAL_PLUGIN_CLAMPED_RESOLUTION( 128,   96)
    00311       };
    00312       static size_t const LastMaxVideoResolutions = sizeof(MaxVideoResolutions)/sizeof(MaxVideoResolutions[0]) - 1;
    00313
    00314       size_t index = 0;
    00315
    00316       if (maxFrameSize > 0) {
    00317         static unsigned const MinWidth = 4*16;  // Four macroblocks wide
    00318         static unsigned const MinHeight = 3*16; // Three macroblocks high
    00319
    00320         unsigned maxWidth  = maxFrameSize*16*16/MinHeight;
    00321         unsigned maxHeight = maxFrameSize*16*16/MinWidth;
    00322
    00323         // Check if total frame size below threshold total of macroblocks.
    00324         unsigned macroBlocks = GetMacroBlocks(width, height);
    00325         if (macroBlocks <= maxFrameSize &&
    00326             width  >= MinWidth  && width  <= maxWidth &&
    00327             height >= MinHeight && height <= maxHeight)
    00328           return false;
    00329
    00330         while (index < LastMaxVideoResolutions &&
    00331                 (MaxVideoResolutions[index].m_macroblocks > maxFrameSize ||
    00332                 MaxVideoResolutions[index].m_width > maxWidth ||
    00333                 MaxVideoResolutions[index].m_height > maxHeight))
    00334           ++index;
    00335       }
    00336
    00337       width = MaxVideoResolutions[index].m_width;
    00338       height = MaxVideoResolutions[index].m_height;
    00339       maxFrameSize = MaxVideoResolutions[index].m_macroblocks;
    00340       return true;
    00341     }
    00342 };
    00343
    00344
    00345 class PluginCodec_OptionMap : public PluginCodec_OptionMapBase, public PluginCodec_Utilities
    00346 {
    00347   public:
    00348     PluginCodec_OptionMap(const char * const * * options = NULL)
    00349     {
    00350       if (options != NULL) {
    00351         for (const char * const * option = *options; *option != NULL; option += 2)
    00352           insert(value_type(option[0], option[1]));
    00353       }
    00354     }
    00355
    00356
    00357     unsigned GetUnsigned(const char * key, unsigned dflt = 0) const
    00358     {
    00359       const_iterator it = find(key);
    00360       return it == end() ? dflt : String2Unsigned(it->second);
    00361     }
    00362
    00363     void SetUnsigned(unsigned value, const char * key)
    00364     {
    00365       Unsigned2String(value, operator[](key));
    00366     }
    00367
    00368
    00369     char ** GetOptions() const
    00370     {
    00371       char ** options = (char **)calloc(size()*2+1, sizeof(char *));
    00372       if (options == NULL) {
    00373         PTRACE(1, "Plugin", "Could not allocate new option lists.");
    00374         return NULL;
    00375       }
    00376
    00377       char ** opt = options;
    00378       for (const_iterator it = begin(); it != end(); ++it) {
    00379         *opt++ = strdup(it->first.c_str());
    00380         *opt++ = strdup(it->second.c_str());
    00381       }
    00382
    00383       return options;
    00384     }
    00385 };
    00386
    00387
    00388 template<typename NAME>
    00389 class PluginCodec_MediaFormat : public PluginCodec_Utilities
    00390 {
    00391   public:
    00392     typedef struct PluginCodec_Option const * const * OptionsTable;
    00393     typedef PluginCodec_OptionMap OptionMap;
    00394
    00395   protected:
    00396     const char * m_formatName;
    00397     const char * m_payloadName;
    00398     unsigned     m_payloadType;
    00399     const char * m_description;
    00400     unsigned     m_maxBandwidth;
    00401     unsigned     m_h323CapabilityType;
    00402     const void * m_h323CapabilityData;
    00403     unsigned     m_flags;
    00404     OptionsTable m_options;
    00405
    00406   protected:
    00407     PluginCodec_MediaFormat(
    00408         const char * formatName,
    00409         const char * payloadName,
    00410         const char * description,
    00411         unsigned     maxBandwidth,
    00412         OptionsTable options)
    00413       : m_formatName(formatName)
    00414       , m_payloadName(payloadName)
    00415       , m_payloadType(0)
    00416       , m_description(description)
    00417       , m_maxBandwidth(maxBandwidth)
    00418       , m_h323CapabilityType(PluginCodec_H323Codec_NoH323)
    00419       , m_h323CapabilityData(NULL)
    00420       , m_flags(PluginCodec_RTPTypeDynamic)
    00421       , m_options(options)
    00422     {
    00423     }
    00424
    00425   public:
    00426     virtual ~PluginCodec_MediaFormat()
    00427     {
    00428     }
    00429
    00430
    00431     __inline const char *  GetFormatName() const   { return this->m_formatName; }
    00432     __inline const char *  GetPayloadName() const  { return this->m_payloadName; }
    00433     __inline unsigned char GetPayloadType() const  { return (unsigned char)this->m_payloadType; }
    00434     __inline const char *  GetDescription() const  { return this->m_description; }
    00435     __inline unsigned      GetMaxBandwidth() const { return this->m_maxBandwidth; }
    00436     __inline unsigned char GetH323CapabilityType() const { return (unsigned char)this->m_h323CapabilityType; }
    00437     __inline const void *  GetH323CapabilityData() const { return this->m_h323CapabilityData; }
    00438     __inline unsigned      GetFlags() const { return this->m_flags; }
    00439     __inline const void *  GetOptionsTable() const { return this->m_options; }
    00440
    00441
    00443     virtual bool IsValidForProtocol(const char * /*protocol*/)
    00444     {
    00445       return true;
    00446     }
    00447
    00448
    00450     bool AdjustOptions(void * parm, unsigned * parmLen, bool (PluginCodec_MediaFormat:: * adjuster)(OptionMap & original, OptionMap & changed))
    00451     {
    00452       if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char ***)) {
    00453         PTRACE(1, "Plugin", "Invalid parameters to AdjustOptions.");
    00454         return false;
    00455       }
    00456
    00457       OptionMap originalOptions((const char * const * *)parm);
    00458       OptionMap changedOptions;
    00459       if (!(this->*adjuster)(originalOptions, changedOptions)) {
    00460         PTRACE(1, "Plugin", "Could not normalise/customise options.");
    00461         return false;
    00462       }
    00463
    00464       return (*(char ***)parm = changedOptions.GetOptions()) != NULL;
    00465     }
    00466
    00467
    00469     virtual bool ToNormalised(OptionMap & /*original*/, OptionMap & /*changed*/)
    00470     {
    00471       return true;
    00472     }
    00473
    00474
    00475     // Adjust codec specific options calculated from normalised options.
    00476     virtual bool ToCustomised(OptionMap & /*original*/, OptionMap & /*changed*/)
    00477     {
    00478       return true;
    00479     }
    00480
    00481
    00482     virtual void AdjustForVersion(unsigned version, const PluginCodec_Definition * /*definition*/)
    00483     {
    00484       if (version < PLUGIN_CODEC_VERSION_INTERSECT) {
    00485         for (PluginCodec_Option ** options = (PluginCodec_Option **)m_options; *options != NULL; ++options) {
    00486           if (strcmp((*options)->m_name, PLUGINCODEC_MEDIA_PACKETIZATIONS) == 0) {
    00487             *options = NULL;
    00488             break;
    00489           }
    00490         }
    00491       }
    00492     }
    00493
    00494
    00495     static void AdjustAllForVersion(unsigned version, const PluginCodec_Definition * definitions, size_t size)
    00496     {
    00497       while (size-- > 0) {
    00498         PluginCodec_MediaFormat * info = (PluginCodec_MediaFormat *)definitions->userData;
    00499         if (info != NULL)
    00500           info->AdjustForVersion(version, definitions);
    00501         ++definitions;
    00502       }
    00503     }
    00504 };
    00505
    00506
    00507 template<typename NAME>
    00508 class PluginCodec_AudioFormat : public PluginCodec_MediaFormat<NAME>
    00509 {
    00510   protected:
    00511     unsigned m_samplesPerFrame;
    00512     unsigned m_bytesPerFrame;
    00513     unsigned m_sampleRate;
    00514     unsigned m_recommendedFramesPerPacket;
    00515     unsigned m_maxFramesPerPacket;
    00516
    00517   public:
    00518     typedef PluginCodec_MediaFormat<NAME> Parent;
    00519     typedef typename Parent::OptionsTable OptionsTable;
    00520
    00521     PluginCodec_AudioFormat(
    00522       const char * formatName,
    00523       const char * payloadName,
    00524       const char * description,
    00525       unsigned     samplesPerFrame,
    00526       unsigned     bytesPerFrame,
    00527       unsigned     sampleRate,
    00528       OptionsTable options
    00529     ) : Parent(formatName, payloadName, description, bytesPerFrame*8 * samplesPerFrame*1000000/sampleRate, options)
    00530       , m_samplesPerFrame(samplesPerFrame)
    00531       , m_bytesPerFrame(bytesPerFrame)
    00532       , m_sampleRate(sampleRate)
    00533       , m_recommendedFramesPerPacket((50*sampleRate)/(1000*samplesPerFrame))
    00534       , m_maxFramesPerPacket((120*sampleRate)/(1000*samplesPerFrame))
    00535     {
    00536       this->m_flags = PluginCodec_MediaTypeAudio /* audio codec */
    00537                     | PluginCodec_InputTypeRaw   /* raw input data */
    00538                     | PluginCodec_OutputTypeRaw; /* raw output data */
    00539
    00540     }
    00541
    00542
    00543     __inline unsigned GetSamplesPerFrame() const { return this->m_samplesPerFrame; }
    00544     __inline unsigned GetBytesPerFrame() const { return this->m_bytesPerFrame; }
    00545     __inline unsigned GetSampleRate() const { return this->m_sampleRate; }
    00546     __inline unsigned GetFrameTime() const { return this->m_samplesPerFrame*1000000/this->m_sampleRate; }
    00547     __inline unsigned GetRecommendedFramesPerPacket() const { return this->m_recommendedFramesPerPacket; }
    00548     __inline unsigned GetMaxFramesPerPacket() const { return this->m_maxFramesPerPacket; }
    00549 };
    00550
    00551
    00552 template<typename NAME>
    00553 class PluginCodec_VideoFormat : public PluginCodec_MediaFormat<NAME>
    00554 {
    00555   protected:
    00556     unsigned m_maxWidth;
    00557     unsigned m_maxHeight;
    00558
    00559   public:
    00560     typedef PluginCodec_MediaFormat<NAME> Parent;
    00561     typedef typename Parent::OptionsTable OptionsTable;
    00562
    00563     PluginCodec_VideoFormat(
    00564       const char * formatName,
    00565       const char * payloadName,
    00566       const char * description,
    00567       unsigned     maxBandwidth,
    00568       OptionsTable options
    00569     ) : Parent(formatName, payloadName, description, maxBandwidth, options)
    00570       , m_maxWidth(1920)
    00571       , m_maxHeight(1200)
    00572     {
    00573       this->m_flags = PluginCodec_MediaTypeVideo /* audio codec */
    00574                     | PluginCodec_InputTypeRTP   /* raw input data */
    00575                     | PluginCodec_OutputTypeRTP; /* raw output data */
    00576     }
    00577
    00578
    00579     __inline unsigned GetMaxWidth() const { return this->m_maxWidth; }
    00580     __inline unsigned GetMaxHeight() const { return this->m_maxHeight; }
    00581 };
    00582
    00583
    00585
    00586 template<typename NAME>
    00587 class PluginCodec : public PluginCodec_Utilities
    00588 {
    00589   protected:
    00590     PluginCodec(const PluginCodec_Definition * defn)
    00591       : m_definition(defn)
    00592       , m_optionsSame(false)
    00593       , m_maxBitRate(defn->bitsPerSec)
    00594       , m_frameTime((defn->sampleRate/1000*defn->usPerFrame)/1000) // Odd way of calculation to avoid 32 bit integer overflow
    00595     {
    00596       PTRACE(3, "Plugin", "Codec created: \"" << defn->descr
    00597              << "\", \"" << defn->sourceFormat << "\" -> \"" << defn->destFormat << '"');
    00598     }
    00599
    00600
    00601   public:
    00602     virtual ~PluginCodec()
    00603     {
    00604     }
    00605
    00606
    00608     virtual bool Construct()
    00609     {
    00610       return true;
    00611     }
    00612
    00613
    00618     static bool Terminate()
    00619     {
    00620       return true;
    00621     }
    00622
    00623
    00625     virtual bool Transcode(const void * fromPtr,
    00626                              unsigned & fromLen,
    00627                                  void * toPtr,
    00628                              unsigned & toLen,
    00629                              unsigned & flags) = 0;
    00630
    00631
    00633     virtual bool GetStatistics(char * /*bufferPtr*/, unsigned /*bufferSize*/)
    00634     {
    00635       return true;
    00636     }
    00637
    00638
    00640     virtual size_t GetOutputDataSize()
    00641     {
    00642       return 576-20-16; // Max safe MTU size (576 bytes as per RFC879) minus IP & UDP headers
    00643     }
    00644
    00645
    00652     virtual bool SetInstanceID(const char * /*idPtr*/, unsigned /*idLen*/)
    00653     {
    00654       return true;
    00655     }
    00656
    00657
    00659     virtual bool GetActiveOptions(PluginCodec_OptionMap & /*options*/)
    00660     {
    00661       return false;
    00662     }
    00663
    00664
    00666     virtual bool SetOptions(const char * const * options)
    00667     {
    00668       this->m_optionsSame = true;
    00669
    00670       // get the media format options after adjustment from protocol negotiation
    00671       for (const char * const * option = options; *option != NULL; option += 2) {
    00672         if (!this->SetOption(option[0], option[1])) {
    00673           PTRACE(1, "Plugin", "Could not set option \"" << option[0] << "\" to \"" << option[1] << '"');
    00674           return false;
    00675         }
    00676       }
    00677
    00678       if (this->m_optionsSame)
    00679         return true;
    00680
    00681       return this->OnChangedOptions();
    00682     }
    00683
    00684
    00686     virtual bool OnChangedOptions()
    00687     {
    00688       return true;
    00689     }
    00690
    00691
    00693     virtual bool SetOption(const char * optionName, const char * optionValue)
    00694     {
    00695       if (strcasecmp(optionName, PLUGINCODEC_OPTION_TARGET_BIT_RATE) == 0)
    00696         return this->SetOptionUnsigned(this->m_maxBitRate, optionValue, 1, this->m_definition->bitsPerSec);
    00697
    00698       if (strcasecmp(optionName, PLUGINCODEC_OPTION_FRAME_TIME) == 0)
    00699         return this->SetOptionUnsigned(this->m_frameTime, optionValue,
    00700                                        this->m_definition->sampleRate/1000, this->m_definition->sampleRate); // 1ms to 1 second
    00701
    00702       return true;
    00703     }
    00704
    00705
    00706     template <typename T>
    00707     bool SetOptionUnsigned(T & oldValue, const char * optionValue, unsigned minimum, unsigned maximum = UINT_MAX)
    00708     {
    00709       unsigned newValue = oldValue;
    00710       if (!this->SetOptionUnsigned(newValue, optionValue, minimum, maximum))
    00711         return false;
    00712       oldValue = (T)newValue;
    00713       return true;
    00714     }
    00715
    00716
    00717     bool SetOptionUnsigned(unsigned & oldValue, const char * optionValue, unsigned minimum, unsigned maximum = UINT_MAX)
    00718     {
    00719       char * end;
    00720       unsigned newValue = strtoul(optionValue, &end, 10);
    00721       if (*end != '\0')
    00722         return false;
    00723
    00724       if (newValue < minimum)
    00725         newValue = minimum;
    00726       else if (newValue > maximum)
    00727         newValue = maximum;
    00728
    00729       if (oldValue != newValue) {
    00730         oldValue = newValue;
    00731         this->m_optionsSame = false;
    00732       }
    00733
    00734       return true;
    00735     }
    00736
    00737
    00738     template <typename T>
    00739     bool SetOptionBoolean(T & oldValue, const char * optionValue)
    00740     {
    00741       bool opt = oldValue != 0;
    00742       if (!this->SetOptionBoolean(opt, optionValue))
    00743         return false;
    00744       oldValue = (T)opt;
    00745       return true;
    00746     }
    00747
    00748
    00749     bool SetOptionBoolean(bool & oldValue, const char * optionValue)
    00750     {
    00751       bool newValue;
    00752       if (     strcasecmp(optionValue, "0") == 0 ||
    00753                strcasecmp(optionValue, "n") == 0 ||
    00754                strcasecmp(optionValue, "f") == 0 ||
    00755                strcasecmp(optionValue, "no") == 0 ||
    00756                strcasecmp(optionValue, "false") == 0)
    00757         newValue = false;
    00758       else if (strcasecmp(optionValue, "1") == 0 ||
    00759                strcasecmp(optionValue, "y") == 0 ||
    00760                strcasecmp(optionValue, "t") == 0 ||
    00761                strcasecmp(optionValue, "yes") == 0 ||
    00762                strcasecmp(optionValue, "true") == 0)
    00763         newValue = true;
    00764       else
    00765         return false;
    00766
    00767       if (oldValue != newValue) {
    00768         oldValue = newValue;
    00769         this->m_optionsSame = false;
    00770       }
    00771
    00772       return true;
    00773     }
    00774
    00775
    00776     bool SetOptionBit(int & oldValue, unsigned bit, const char * optionValue)
    00777     {
    00778       return this->SetOptionBit((unsigned &)oldValue, bit, optionValue);
    00779     }
    00780
    00781
    00782     bool SetOptionBit(unsigned & oldValue, unsigned bit, const char * optionValue)
    00783     {
    00784       bool newValue;
    00785       if (strcmp(optionValue, "0") == 0)
    00786         newValue = false;
    00787       else if (strcmp(optionValue, "1") == 0)
    00788         newValue = true;
    00789       else
    00790         return false;
    00791
    00792       if (((oldValue&bit) != 0) != newValue) {
    00793         if (newValue)
    00794           oldValue |= bit;
    00795         else
    00796           oldValue &= ~bit;
    00797         this->m_optionsSame = false;
    00798       }
    00799
    00800       return true;
    00801     }
    00802
    00803
    00804     template <class CodecClass> static void * Create_s(const PluginCodec_Definition * defn)
    00805     {
    00806       CodecClass * codec = new CodecClass(defn);
    00807       if (codec != NULL && codec->Construct())
    00808         return codec;
    00809
    00810       PTRACE(1, "Plugin", "Could not open codec, no context being returned.");
    00811       delete codec;
    00812       return NULL;
    00813     }
    00814
    00815
    00816     static void Destroy_s(const PluginCodec_Definition * /*defn*/, void * context)
    00817     {
    00818       delete (PluginCodec *)context;
    00819     }
    00820
    00821
    00822     static int Transcode_s(const PluginCodec_Definition * /*defn*/,
    00823                                                    void * context,
    00824                                              const void * fromPtr,
    00825                                                unsigned * fromLen,
    00826                                                    void * toPtr,
    00827                                                unsigned * toLen,
    00828                                            unsigned int * flags)
    00829     {
    00830       if (context != NULL && fromPtr != NULL && fromLen != NULL && toPtr != NULL && toLen != NULL && flags != NULL)
    00831         return ((PluginCodec *)context)->Transcode(fromPtr, *fromLen, toPtr, *toLen, *flags);
    00832
    00833       PTRACE(1, "Plugin", "Invalid parameter to Transcode.");
    00834       return false;
    00835     }
    00836
    00837
    00838     static int GetOutputDataSize_s(const PluginCodec_Definition *, void * context, const char *, void *, unsigned *)
    00839     {
    00840       return context != NULL ? ((PluginCodec *)context)->GetOutputDataSize() : 0;
    00841     }
    00842
    00843     typedef PluginCodec_MediaFormat<NAME> MediaFormat;
    00844
    00845     static int ToNormalised_s(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
    00846     {
    00847       return defn->userData != NULL ? ((MediaFormat *)defn->userData)->AdjustOptions(parm, len, &MediaFormat::ToNormalised) : -1;
    00848     }
    00849
    00850
    00851     static int ToCustomised_s(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
    00852     {
    00853       return defn->userData != NULL ? ((MediaFormat *)defn->userData)->AdjustOptions(parm, len, &MediaFormat::ToCustomised) : -1;
    00854     }
    00855
    00856
    00857     static int GetActiveOptions_s(const PluginCodec_Definition *, void * context, const char *, void * parm, unsigned * parmLen)
    00858     {
    00859       if (context == NULL || parmLen == NULL || parm == NULL || *parmLen != sizeof(char ***)) {
    00860         PTRACE(1, "Plugin", "Invalid parameters to GetActiveOptions.");
    00861         return false;
    00862       }
    00863
    00864       PluginCodec_OptionMap activeOptions;
    00865       if (!((PluginCodec *)context)->GetActiveOptions(activeOptions))
    00866         return false;
    00867
    00868       return (*(char ***)parm = activeOptions.GetOptions()) != NULL;
    00869     }
    00870
    00871
    00872     static int FreeOptions_s(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len)
    00873     {
    00874       if (parm == NULL || len == NULL || *len != sizeof(char ***))
    00875         return false;
    00876
    00877       char ** strings = (char **)parm;
    00878       for (char ** string = strings; *string != NULL; string++)
    00879         free(*string);
    00880       free(strings);
    00881       return true;
    00882     }
    00883
    00884
    00885     static int GetOptions_s(const struct PluginCodec_Definition * codec, void *, const char *, void * parm, unsigned * len)
    00886     {
    00887       if (parm == NULL || len == NULL || *len != sizeof(struct PluginCodec_Option **))
    00888         return false;
    00889
    00890       *(const void **)parm = codec->userData != NULL ? ((MediaFormat *)codec->userData)->GetOptionsTable() : NULL;
    00891       *len = 0;
    00892       return true;
    00893     }
    00894
    00895
    00896     static int SetOptions_s(const PluginCodec_Definition *, void * context, const char *, void * parm, unsigned * len)
    00897     {
    00898       PluginCodec * codec = (PluginCodec *)context;
    00899       return len != NULL && *len == sizeof(const char **) && parm != NULL &&
    00900              codec != NULL && codec->SetOptions((const char * const *)parm);
    00901     }
    00902
    00903     static int ValidForProtocol_s(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
    00904     {
    00905       return len != NULL && *len == sizeof(const char *) && parm != NULL && defn->userData != NULL &&
    00906                               ((MediaFormat *)defn->userData)->IsValidForProtocol((const char *)parm);
    00907     }
    00908
    00909     static int SetInstanceID_s(const PluginCodec_Definition *, void * context, const char *, void * parm, unsigned * len)
    00910     {
    00911       PluginCodec * codec = (PluginCodec *)context;
    00912       return len != NULL && parm != NULL &&
    00913              codec != NULL && codec->SetInstanceID((const char *)parm, *len);
    00914     }
    00915
    00916     static int GetStatistics_s(const PluginCodec_Definition *, void * context, const char *, void * parm, unsigned * len)
    00917     {
    00918       PluginCodec * codec = (PluginCodec *)context;
    00919       return len != NULL && parm != NULL &&
    00920              codec != NULL && codec->GetStatistics((char *)parm, *len);
    00921     }
    00922
    00923     static int Terminate_s(const PluginCodec_Definition *, void * context, const char *, void *, unsigned *)
    00924     {
    00925       PluginCodec * codec = (PluginCodec *)context;
    00926       return codec != NULL && codec->Terminate();
    00927     }
    00928
    00929     static struct PluginCodec_ControlDefn * GetControls()
    00930     {
    00931       static PluginCodec_ControlDefn ControlsTable[] = {
    00932         { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE,  PluginCodec::GetOutputDataSize_s },
    00933         { PLUGINCODEC_CONTROL_TO_NORMALISED_OPTIONS, PluginCodec::ToNormalised_s },
    00934         { PLUGINCODEC_CONTROL_TO_CUSTOMISED_OPTIONS, PluginCodec::ToCustomised_s },
    00935         { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS,     PluginCodec::SetOptions_s },
    00936         { PLUGINCODEC_CONTROL_GET_ACTIVE_OPTIONS,    PluginCodec::GetActiveOptions_s },
    00937         { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS,     PluginCodec::GetOptions_s },
    00938         { PLUGINCODEC_CONTROL_FREE_CODEC_OPTIONS,    PluginCodec::FreeOptions_s },
    00939         { PLUGINCODEC_CONTROL_VALID_FOR_PROTOCOL,    PluginCodec::ValidForProtocol_s },
    00940         { PLUGINCODEC_CONTROL_SET_INSTANCE_ID,       PluginCodec::SetInstanceID_s },
    00941         { PLUGINCODEC_CONTROL_GET_STATISTICS,        PluginCodec::GetStatistics_s },
    00942         { PLUGINCODEC_CONTROL_TERMINATE_CODEC,       PluginCodec::Terminate_s },
    00943         PLUGINCODEC_CONTROL_LOG_FUNCTION_INC
    00944         { NULL }
    00945       };
    00946       return ControlsTable;
    00947     }
    00948
    00949   protected:
    00950     const PluginCodec_Definition * m_definition;
    00951
    00952     bool     m_optionsSame;
    00953     unsigned m_maxBitRate;
    00954     unsigned m_frameTime;
    00955 };
    00956
    00957
    00959
    00960 template<typename NAME>
    00961 class PluginVideoCodec : public PluginCodec<NAME>
    00962 {
    00963     typedef PluginCodec<NAME> BaseClass;
    00964
    00965   public:
    00966     enum {
    00967       DefaultWidth = 352, // CIF size
    00968       DefaultHeight = 288,
    00969       MaxWidth = DefaultWidth*8,
    00970       MaxHeight = DefaultHeight*8
    00971     };
    00972
    00973
    00974     PluginVideoCodec(const PluginCodec_Definition * defn)
    00975       : BaseClass(defn)
    00976     {
    00977     }
    00978
    00979
    00980     virtual size_t GetRawFrameSize(unsigned width, unsigned height)
    00981     {
    00982       return width*height*3/2; // YUV420P
    00983     }
    00984 };
    00985
    00986
    00988
    00989 template<typename NAME>
    00990 class PluginVideoEncoder : public PluginVideoCodec<NAME>
    00991 {
    00992     typedef PluginVideoCodec<NAME> BaseClass;
    00993
    00994   protected:
    00995     unsigned m_width;
    00996     unsigned m_height;
    00997     unsigned m_maxRTPSize;
    00998     unsigned m_tsto;
    00999     unsigned m_keyFramePeriod;
    01000
    01001   public:
    01002     PluginVideoEncoder(const PluginCodec_Definition * defn)
    01003       : BaseClass(defn)
    01004       , m_width(BaseClass::DefaultWidth)
    01005       , m_height(BaseClass::DefaultHeight)
    01006       , m_maxRTPSize(PluginCodec_RTP_MaxPacketSize)
    01007       , m_tsto(31)
    01008       , m_keyFramePeriod(0) // Indicates auto/default
    01009     {
    01010     }
    01011
    01012
    01013     virtual bool SetOption(const char * optionName, const char * optionValue)
    01014     {
    01015       if (strcasecmp(optionName, PLUGINCODEC_OPTION_FRAME_WIDTH) == 0)
    01016         return this->SetOptionUnsigned(this->m_width, optionValue, 16, BaseClass::MaxWidth);
    01017
    01018       if (strcasecmp(optionName, PLUGINCODEC_OPTION_FRAME_HEIGHT) == 0)
    01019         return this->SetOptionUnsigned(this->m_height, optionValue, 16, BaseClass::MaxHeight);
    01020
    01021       if (strcasecmp(optionName, PLUGINCODEC_OPTION_MAX_TX_PACKET_SIZE) == 0)
    01022         return this->SetOptionUnsigned(this->m_maxRTPSize, optionValue, 256, 8192);
    01023
    01024       if (strcasecmp(optionName, PLUGINCODEC_OPTION_TEMPORAL_SPATIAL_TRADE_OFF) == 0)
    01025         return this->SetOptionUnsigned(this->m_tsto, optionValue, 1, 31);
    01026
    01027       if (strcasecmp(optionName, PLUGINCODEC_OPTION_TX_KEY_FRAME_PERIOD) == 0)
    01028         return this->SetOptionUnsigned(this->m_keyFramePeriod, optionValue, 0);
    01029
    01030       // Base class sets bit rate and frame time
    01031       return BaseClass::SetOption(optionName, optionValue);
    01032     }
    01033
    01034
    01036     virtual bool GetActiveOptions(PluginCodec_OptionMap & options)
    01037     {
    01038       options.SetUnsigned(this->m_frameTime, PLUGINCODEC_OPTION_FRAME_TIME);
    01039       return true;
    01040     }
    01041
    01042
    01043     virtual size_t GetPacketSpace(const PluginCodec_RTP & rtp, size_t total)
    01044     {
    01045       size_t space = rtp.GetMaxSize();
    01046       if (space > this->m_maxRTPSize)
    01047         space = this->m_maxRTPSize;
    01048       space -= rtp.GetHeaderSize();
    01049       if (space > total)
    01050         space = total;
    01051       return space;
    01052     }
    01053 };
    01054
    01055
    01057
    01058 template<typename NAME>
    01059 class PluginVideoDecoder : public PluginVideoCodec<NAME>
    01060 {
    01061     typedef PluginVideoCodec<NAME> BaseClass;
    01062
    01063   protected:
    01064     size_t m_outputSize;
    01065
    01066   public:
    01067     PluginVideoDecoder(const PluginCodec_Definition * defn)
    01068       : BaseClass(defn)
    01069       , m_outputSize(BaseClass::DefaultWidth*BaseClass::DefaultHeight*3/2 + sizeof(PluginCodec_Video_FrameHeader) + PluginCodec_RTP_MinHeaderSize)
    01070     {
    01071     }
    01072
    01073
    01074     virtual size_t GetOutputDataSize()
    01075     {
    01076       return this->m_outputSize;
    01077     }
    01078
    01079
    01080     virtual bool CanOutputImage(unsigned width, unsigned height, PluginCodec_RTP & rtp, unsigned & flags)
    01081     {
    01082       size_t newSize = this->GetRawFrameSize(width, height) + sizeof(PluginCodec_Video_FrameHeader) + rtp.GetHeaderSize();
    01083       if (newSize > rtp.GetMaxSize() || !rtp.SetPayloadSize(newSize)) {
    01084         m_outputSize = newSize;
    01085         flags |= PluginCodec_ReturnCoderBufferTooSmall;
    01086         return false;
    01087       }
    01088
    01089       PluginCodec_Video_FrameHeader * videoHeader = rtp.GetVideoHeader();
    01090       videoHeader->x = 0;
    01091       videoHeader->y = 0;
    01092       videoHeader->width = width;
    01093       videoHeader->height = height;
    01094
    01095       flags |= PluginCodec_ReturnCoderLastFrame;
    01096       rtp.SetMarker(true);
    01097       return true;
    01098     }
    01099
    01100
    01101     struct OutputImagePlaneInfo
    01102     {
    01103       unsigned        m_width;
    01104       unsigned        m_height;
    01105       unsigned        m_raster;
    01106       unsigned char * m_source;
    01107       unsigned char * m_destination;
    01108
    01109       void Copy()
    01110       {
    01111         for (unsigned y = 0; y < m_height; ++y) {
    01112           memcpy(m_destination, m_source, m_width);
    01113           this->m_source += m_raster;
    01114           this->m_destination += m_width;
    01115         }
    01116       }
    01117     };
    01118
    01119     virtual unsigned OutputImage(unsigned char * planes[3], int raster[3],
    01120                                  unsigned width, unsigned height, PluginCodec_RTP & rtp, unsigned & flags)
    01121     {
    01122       if (!CanOutputImage(width, height, rtp, flags))
    01123         return 0;
    01124
    01125       size_t ySize = width*height;
    01126       size_t uvSize = ySize/4;
    01127       if (planes[1] == planes[0]+ySize && planes[2] == planes[1]+uvSize)
    01128         memcpy(rtp.GetVideoFrameData(), planes[0], ySize+uvSize*2);
    01129       else {
    01130         OutputImagePlaneInfo planeInfo[3] = {
    01131           { width,   height,   raster[0], planes[0], rtp.GetVideoFrameData()     },
    01132           { width/2, height/2, raster[1], planes[1], planeInfo[0].m_destination + ySize  },
    01133           { width/2, height/2, raster[2], planes[2], planeInfo[1].m_destination + uvSize }
    01134         };
    01135
    01136         for (unsigned plane = 0; plane < 3; ++plane)
    01137           planeInfo[plane].Copy();
    01138       }
    01139
    01140       return rtp.GetPacketSize();
    01141     }
    01142 };
    01143
    01144
    01146
    01148 #define PLUGINCODEC_AUDIO_CODEC_CXX(MediaFormat,      \
    01149                                     EncoderClass,     \
    01150                                     DecoderClass      \
    01151                                     ) \
    01152              PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
    01153                                     MediaFormat.GetPayloadName(), \
    01154                                     MediaFormat.GetDescription(), \
    01155                                     MediaFormat.GetSampleRate(), \
    01156                                     MediaFormat.GetMaxBandwidth(), \
    01157                                     MediaFormat.GetFrameTime(), \
    01158                                     MediaFormat.GetSamplesPerFrame(), \
    01159                                     MediaFormat.GetBytesPerFrame(), \
    01160                                     MediaFormat.GetRecommendedFramesPerPacket(), \
    01161                                     MediaFormat.GetMaxFramesPerPacket(), \
    01162                                     MediaFormat.GetPayloadType(), \
    01163                                     MediaFormat.GetH323CapabilityType(), \
    01164                                     MediaFormat.GetH323CapabilityData(), \
    01165                                     EncoderClass::Create_s<EncoderClass>, \
    01166                                     EncoderClass::Destroy_s, \
    01167                                     EncoderClass::Transcode_s, \
    01168                                     DecoderClass::Create_s<DecoderClass>, \
    01169                                     DecoderClass::Destroy_s, \
    01170                                     DecoderClass::Transcode_s, \
    01171                                     DecoderClass::GetControls(), /* Note doesn't matter if encoder or decoder */ \
    01172                                     MediaFormat.GetFlags(), \
    01173                                     PLUGINCODEC_RAW_AUDIO, \
    01174                                     &MediaFormat)
    01175
    01177 #define PLUGINCODEC_VIDEO_CODEC_CXX(MediaFormat,      \
    01178                                     EncoderClass,     \
    01179                                     DecoderClass      \
    01180                                     ) \
    01181              PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
    01182                                     MediaFormat.GetPayloadName(), \
    01183                                     MediaFormat.GetDescription(), \
    01184                                     PLUGINCODEC_VIDEO_CLOCK, \
    01185                                     MediaFormat.GetMaxBandwidth(), \
    01186                                     1000000/PLUGINCODEC_MAX_FRAME_RATE, \
    01187                                     MediaFormat.GetMaxWidth(), \
    01188                                     MediaFormat.GetMaxHeight(), \
    01189                                     0,PLUGINCODEC_MAX_FRAME_RATE, \
    01190                                     MediaFormat.GetPayloadType(), \
    01191                                     MediaFormat.GetH323CapabilityType(), \
    01192                                     MediaFormat.GetH323CapabilityData(), \
    01193                                     EncoderClass::Create_s<EncoderClass>, \
    01194                                     EncoderClass::Destroy_s, \
    01195                                     EncoderClass::Transcode_s, \
    01196                                     DecoderClass::Create_s<DecoderClass>, \
    01197                                     DecoderClass::Destroy_s, \
    01198                                     DecoderClass::Transcode_s, \
    01199                                     DecoderClass::GetControls(), /* Note doesn't matter if encoder or decoder */ \
    01200                                     MediaFormat.GetFlags(), \
    01201                                     PLUGINCODEC_RAW_VIDEO, \
    01202                                     &MediaFormat)
    01203
    01204
    01205 #define PLUGIN_CODEC_IMPLEMENT_CXX(NAME, table) \
    01206   extern "C" { \
    01207     PLUGIN_CODEC_IMPLEMENT(NAME) \
    01208     PLUGIN_CODEC_DLL_API struct PluginCodec_Definition * PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version) { \
    01209       if (version < PLUGIN_CODEC_VERSION_OPTIONS) return NULL; \
    01210       *count = sizeof(table)/sizeof(struct PluginCodec_Definition); \
    01211       PluginCodec_MediaFormat<NAME>::AdjustAllForVersion(version, table, *count); \
    01212       return table; \
    01213     } \
    01214   }
    01215
    01216
    01217 #endif // OPAL_CODEC_OPALPLUGIN_HPP