00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef OPAL_CODEC_OPALPLUGIN_HPP
00033 #define OPAL_CODEC_OPALPLUGIN_HPP
00034
00035 #include "opalplugin.h"
00036
00037 #include <map>
00038 #include <string>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <malloc.h>
00042 #include <limits.h>
00043
00044
00046
00047 #ifndef PLUGINCODEC_TRACING
00048 #define PLUGINCODEC_TRACING 1
00049 #endif
00050
00051 #if PLUGINCODEC_TRACING
00052 static PluginCodec_LogFunction PluginCodec_LogFunctionInstance;
00053
00054 static int PluginCodec_SetLogFunction(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len)
00055 {
00056 if (len == NULL || *len != sizeof(PluginCodec_LogFunction))
00057 return false;
00058
00059 PluginCodec_LogFunctionInstance = (PluginCodec_LogFunction)parm;
00060 if (PluginCodec_LogFunctionInstance != NULL)
00061 PluginCodec_LogFunctionInstance(4, __FILE__, __LINE__, "Plugin", "Started logging.");
00062
00063 return true;
00064 }
00065
00066 #define PLUGINCODEC_CONTROL_LOG_FUNCTION { PLUGINCODEC_CONTROL_SET_LOG_FUNCTION, PluginCodec_SetLogFunction },
00067 #else
00068 #define PLUGINCODEC_CONTROL_LOG_FUNCTION
00069 #endif
00070
00071 #if !defined(PTRACE)
00072 #if PLUGINCODEC_TRACING
00073 #include <sstream>
00074 #define PTRACE(level, section, args) \
00075 if (PluginCodec_LogFunctionInstance != NULL && PluginCodec_LogFunctionInstance(level, NULL, 0, NULL, NULL)) { \
00076 std::ostringstream strm; strm << args; \
00077 PluginCodec_LogFunctionInstance(level, __FILE__, __LINE__, section, strm.str().c_str()); \
00078 } else (void)0
00079 #else
00080 #define PTRACE(level, section, expr)
00081 #endif
00082 #endif
00083
00084
00086
00087 class PluginCodec_MediaFormat
00088 {
00089 friend class PluginCodec;
00090
00091 public:
00092 typedef struct PluginCodec_Option const * const * OptionsTable;
00093 typedef std::map<std::string, std::string> OptionMap;
00094
00095 protected:
00096 OptionsTable m_options;
00097
00098 public:
00099 PluginCodec_MediaFormat(OptionsTable options)
00100 : m_options(options)
00101 {
00102 }
00103
00104
00105 virtual ~PluginCodec_MediaFormat()
00106 {
00107 }
00108
00109
00110 bool AdjustOptions(void * parm, unsigned * parmLen, bool (PluginCodec_MediaFormat:: * adjuster)(OptionMap & original, OptionMap & changed))
00111 {
00112 if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char ***))
00113 return false;
00114
00115 OptionMap originalOptions;
00116 for (const char * const * option = *(const char * const * *)parm; *option != NULL; option += 2)
00117 originalOptions[option[0]] = option[1];
00118
00119 OptionMap changedOptions;
00120 if (!(this->*adjuster)(originalOptions, changedOptions))
00121 return false;
00122
00123 char ** options = (char **)calloc(changedOptions.size()*2+1, sizeof(char *));
00124 *(char ***)parm = options;
00125 if (options == NULL)
00126 return false;
00127
00128 for (OptionMap::iterator i = changedOptions.begin(); i != changedOptions.end(); ++i) {
00129 *options++ = strdup(i->first.c_str());
00130 *options++ = strdup(i->second.c_str());
00131 }
00132
00133 return true;
00134 }
00135
00136
00137 virtual bool ToNormalised(OptionMap & original, OptionMap & changed) = 0;
00138
00139
00140 virtual bool ToCustomised(OptionMap & original, OptionMap & changed) = 0;
00141
00142
00143 static void Change(const char * value,
00144 OptionMap & original,
00145 OptionMap & changed,
00146 const char * option)
00147 {
00148 if (original[option] != value)
00149 changed[option] = value;
00150 }
00151
00152
00153 static unsigned String2Unsigned(const std::string & str)
00154 {
00155 return strtoul(str.c_str(), NULL, 10);
00156 }
00157
00158
00159 static void Unsigned2String(unsigned value, std::string & str)
00160 {
00161
00162 if (value > 9)
00163 Unsigned2String(value/10, str);
00164 str += (char)(value%10 + '0');
00165 }
00166
00167
00168 static void Change(unsigned value,
00169 OptionMap & original,
00170 OptionMap & changed,
00171 const char * option)
00172 {
00173 if (String2Unsigned(original[option]) != value)
00174 Unsigned2String(value, changed[option]);
00175 }
00176
00177
00178 static void ClampMax(unsigned maximum,
00179 OptionMap & original,
00180 OptionMap & changed,
00181 const char * option)
00182 {
00183 unsigned value = String2Unsigned(original[option]);
00184 if (value > maximum)
00185 Unsigned2String(maximum, changed[option]);
00186 }
00187
00188
00189 static void ClampMin(unsigned minimum,
00190 OptionMap & original,
00191 OptionMap & changed,
00192 const char * option)
00193 {
00194 unsigned value = String2Unsigned(original[option]);
00195 if (value < minimum)
00196 Unsigned2String(minimum, changed[option]);
00197 }
00198 };
00199
00200
00202
00203 class PluginCodec
00204 {
00205 protected:
00206 PluginCodec(const PluginCodec_Definition * defn)
00207 : m_definition(defn)
00208 , m_optionsSame(false)
00209 , m_maxBitRate(defn->bitsPerSec)
00210 , m_frameTime((defn->sampleRate/1000*defn->usPerFrame)/1000)
00211 {
00212 PTRACE(3, "Plugin", "Codec created: \"" << defn->descr
00213 << "\", \"" << defn->sourceFormat << "\" -> \"" << defn->destFormat << '"');
00214 }
00215
00216
00217 public:
00218 virtual ~PluginCodec()
00219 {
00220 }
00221
00222
00223 virtual bool Construct()
00224 {
00225 return true;
00226 }
00227
00228
00229 virtual bool Transcode(const void * fromPtr,
00230 unsigned & fromLen,
00231 void * toPtr,
00232 unsigned & toLen,
00233 unsigned & flags) = 0;
00234
00235
00236 virtual size_t GetOutputDataSize()
00237 {
00238 return 576-20-16;
00239 }
00240
00241
00242 virtual bool SetOptions(const char * const * options)
00243 {
00244 m_optionsSame = true;
00245
00246
00247 for (const char * const * option = options; *option != NULL; option += 2) {
00248 if (!SetOption(option[0], option[1]))
00249 return false;
00250 }
00251
00252 if (m_optionsSame)
00253 return true;
00254
00255 return OnChangedOptions();
00256 }
00257
00258
00259 virtual bool OnChangedOptions()
00260 {
00261 return true;
00262 }
00263
00264
00265 virtual bool SetOption(const char * optionName, const char * optionValue)
00266 {
00267 if (strcasecmp(optionName, PLUGINCODEC_OPTION_TARGET_BIT_RATE) == 0)
00268 return SetOptionUnsigned(m_maxBitRate, optionValue, 1, m_definition->bitsPerSec);
00269
00270 if (strcasecmp(optionName, PLUGINCODEC_OPTION_FRAME_TIME) == 0)
00271 return SetOptionUnsigned(m_frameTime, optionValue, m_definition->sampleRate/1000, m_definition->sampleRate);
00272
00273 return true;
00274 }
00275
00276
00277 bool SetOptionUnsigned(unsigned & oldValue, const char * optionValue, unsigned minimum, unsigned maximum = UINT_MAX)
00278 {
00279 char * end;
00280 unsigned newValue = strtoul(optionValue, &end, 10);
00281 if (*end != '\0')
00282 return false;
00283
00284 if (newValue < minimum)
00285 newValue = minimum;
00286 else if (newValue > maximum)
00287 newValue = maximum;
00288
00289 if (oldValue != newValue) {
00290 oldValue = newValue;
00291 m_optionsSame = false;
00292 }
00293
00294 return true;
00295 }
00296
00297
00298 bool SetOptionBoolean(bool & oldValue, const char * optionValue)
00299 {
00300 bool newValue;
00301 if (strcmp(optionValue, "0") == 0)
00302 newValue = false;
00303 else if (strcmp(optionValue, "1") == 0)
00304 newValue = true;
00305 else
00306 return false;
00307
00308 if (oldValue != newValue) {
00309 oldValue = newValue;
00310 m_optionsSame = false;
00311 }
00312
00313 return true;
00314 }
00315
00316
00317 bool SetOptionBit(unsigned & oldValue, unsigned bit, const char * optionValue)
00318 {
00319 bool newValue;
00320 if (strcmp(optionValue, "0") == 0)
00321 newValue = false;
00322 else if (strcmp(optionValue, "1") == 0)
00323 newValue = true;
00324 else
00325 return false;
00326
00327 if (((oldValue&bit) != 0) != newValue) {
00328 if (newValue)
00329 oldValue |= bit;
00330 else
00331 oldValue &= ~bit;
00332 m_optionsSame = false;
00333 }
00334
00335 return true;
00336 }
00337
00338
00339 template <class CodecClass> static void * Create(const PluginCodec_Definition * defn)
00340 {
00341 CodecClass * codec = new CodecClass(defn);
00342 if (codec != NULL && codec->Construct())
00343 return codec;
00344
00345 PTRACE(1, "Plugin", "Could not open codec, no context being returned.");
00346 delete codec;
00347 return NULL;
00348 }
00349
00350
00351 static void Destroy(const PluginCodec_Definition * , void * context)
00352 {
00353 delete (PluginCodec *)context;
00354 }
00355
00356
00357 static int Transcode(const PluginCodec_Definition * ,
00358 void * context,
00359 const void * fromPtr,
00360 unsigned * fromLen,
00361 void * toPtr,
00362 unsigned * toLen,
00363 unsigned int * flags)
00364 {
00365 if (context != NULL && fromPtr != NULL && fromLen != NULL && toPtr != NULL && toLen != NULL && flags != NULL)
00366 return ((PluginCodec *)context)->Transcode(fromPtr, *fromLen, toPtr, *toLen, *flags);
00367
00368 PTRACE(1, "Plugin", "Invalid parameter to Transcode.");
00369 return false;
00370 }
00371
00372
00373 static int GetOutputDataSize(const PluginCodec_Definition *, void * context, const char *, void *, unsigned *)
00374 {
00375 return context != NULL ? ((PluginCodec *)context)->GetOutputDataSize() : 0;
00376 }
00377
00378
00379 static int ToNormalised(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
00380 {
00381 return defn->userData != NULL ? ((PluginCodec_MediaFormat *)defn->userData)->AdjustOptions(parm, len, &PluginCodec_MediaFormat::ToNormalised) : -1;
00382 }
00383
00384
00385 static int ToCustomised(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
00386 {
00387 return defn->userData != NULL ? ((PluginCodec_MediaFormat *)defn->userData)->AdjustOptions(parm, len, &PluginCodec_MediaFormat::ToCustomised) : -1;
00388 }
00389
00390
00391 static int FreeOptions(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len)
00392 {
00393 if (parm == NULL || len == NULL || *len != sizeof(char ***))
00394 return false;
00395
00396 char ** strings = (char **)parm;
00397 for (char ** string = strings; *string != NULL; string++)
00398 free(*string);
00399 free(strings);
00400 return true;
00401 }
00402
00403
00404 static int GetOptions(const struct PluginCodec_Definition * codec, void *, const char *, void * parm, unsigned * len)
00405 {
00406 if (parm == NULL || len == NULL || *len != sizeof(struct PluginCodec_Option **))
00407 return false;
00408
00409 *(const void **)parm = codec->userData != NULL ? ((PluginCodec_MediaFormat *)codec->userData)->m_options : NULL;
00410 *len = 0;
00411 return true;
00412 }
00413
00414
00415 static int SetOptions(const PluginCodec_Definition *,
00416 void * context,
00417 const char * ,
00418 void * parm,
00419 unsigned * len)
00420 {
00421 PluginCodec * codec = (PluginCodec *)context;
00422 return len != NULL && *len == sizeof(const char **) && parm != NULL &&
00423 codec != NULL && codec->SetOptions((const char * const *)parm);
00424 }
00425
00426 protected:
00427 const PluginCodec_Definition * m_definition;
00428
00429 bool m_optionsSame;
00430 unsigned m_maxBitRate;
00431 unsigned m_frameTime;
00432 };
00433
00434
00435 #define PLUGINCODEC_DEFINE_CONTROL_TABLE(name) \
00436 static PluginCodec_ControlDefn name[] = { \
00437 { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE, PluginCodec::GetOutputDataSize }, \
00438 { PLUGINCODEC_CONTROL_TO_NORMALISED_OPTIONS, PluginCodec::ToNormalised }, \
00439 { PLUGINCODEC_CONTROL_TO_CUSTOMISED_OPTIONS, PluginCodec::ToCustomised }, \
00440 { PLUGINCODEC_CONTROL_FREE_CODEC_OPTIONS, PluginCodec::FreeOptions }, \
00441 { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS, PluginCodec::SetOptions }, \
00442 { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS, PluginCodec::GetOptions }, \
00443 PLUGINCODEC_CONTROL_LOG_FUNCTION \
00444 { NULL } \
00445 }
00446
00447
00448
00449 #endif // OPAL_CODEC_OPALPLUGIN_HPP