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 <string.h>
00038 #include <stdlib.h>
00039 #include <limits.h>
00040
00041 #include <map>
00042 #include <string>
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 protected:
00099 PluginCodec_MediaFormat(OptionsTable options)
00100 : m_options(options)
00101 {
00102 }
00103
00104 public:
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(int & oldValue, const char * optionValue, unsigned minimum, unsigned maximum = UINT_MAX)
00278 {
00279 return SetOptionUnsigned((unsigned &)oldValue, optionValue, minimum, maximum);
00280 }
00281
00282
00283 bool SetOptionUnsigned(unsigned & oldValue, const char * optionValue, unsigned minimum, unsigned maximum = UINT_MAX)
00284 {
00285 char * end;
00286 unsigned newValue = strtoul(optionValue, &end, 10);
00287 if (*end != '\0')
00288 return false;
00289
00290 if (newValue < minimum)
00291 newValue = minimum;
00292 else if (newValue > maximum)
00293 newValue = maximum;
00294
00295 if (oldValue != newValue) {
00296 oldValue = newValue;
00297 m_optionsSame = false;
00298 }
00299
00300 return true;
00301 }
00302
00303
00304 bool SetOptionBoolean(int & oldValue, const char * optionValue)
00305 {
00306 return SetOptionBoolean((unsigned &)oldValue, optionValue);
00307 }
00308
00309
00310 bool SetOptionBoolean(unsigned & oldValue, const char * optionValue)
00311 {
00312 bool opt = oldValue != 0;
00313 if (!SetOptionBoolean(opt, optionValue))
00314 return false;
00315 oldValue = opt;
00316 return true;
00317 }
00318
00319
00320 bool SetOptionBoolean(bool & oldValue, const char * optionValue)
00321 {
00322 bool newValue;
00323 if (strcmp(optionValue, "0") == 0)
00324 newValue = false;
00325 else if (strcmp(optionValue, "1") == 0)
00326 newValue = true;
00327 else
00328 return false;
00329
00330 if (oldValue != newValue) {
00331 oldValue = newValue;
00332 m_optionsSame = false;
00333 }
00334
00335 return true;
00336 }
00337
00338
00339 bool SetOptionBit(int & oldValue, unsigned bit, const char * optionValue)
00340 {
00341 return SetOptionBit((unsigned &)oldValue, bit, optionValue);
00342 }
00343
00344
00345 bool SetOptionBit(unsigned & oldValue, unsigned bit, const char * optionValue)
00346 {
00347 bool newValue;
00348 if (strcmp(optionValue, "0") == 0)
00349 newValue = false;
00350 else if (strcmp(optionValue, "1") == 0)
00351 newValue = true;
00352 else
00353 return false;
00354
00355 if (((oldValue&bit) != 0) != newValue) {
00356 if (newValue)
00357 oldValue |= bit;
00358 else
00359 oldValue &= ~bit;
00360 m_optionsSame = false;
00361 }
00362
00363 return true;
00364 }
00365
00366
00367 template <class CodecClass> static void * Create(const PluginCodec_Definition * defn)
00368 {
00369 CodecClass * codec = new CodecClass(defn);
00370 if (codec != NULL && codec->Construct())
00371 return codec;
00372
00373 PTRACE(1, "Plugin", "Could not open codec, no context being returned.");
00374 delete codec;
00375 return NULL;
00376 }
00377
00378
00379 static void Destroy(const PluginCodec_Definition * , void * context)
00380 {
00381 delete (PluginCodec *)context;
00382 }
00383
00384
00385 static int Transcode(const PluginCodec_Definition * ,
00386 void * context,
00387 const void * fromPtr,
00388 unsigned * fromLen,
00389 void * toPtr,
00390 unsigned * toLen,
00391 unsigned int * flags)
00392 {
00393 if (context != NULL && fromPtr != NULL && fromLen != NULL && toPtr != NULL && toLen != NULL && flags != NULL)
00394 return ((PluginCodec *)context)->Transcode(fromPtr, *fromLen, toPtr, *toLen, *flags);
00395
00396 PTRACE(1, "Plugin", "Invalid parameter to Transcode.");
00397 return false;
00398 }
00399
00400
00401 static int GetOutputDataSize(const PluginCodec_Definition *, void * context, const char *, void *, unsigned *)
00402 {
00403 return context != NULL ? ((PluginCodec *)context)->GetOutputDataSize() : 0;
00404 }
00405
00406
00407 static int ToNormalised(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
00408 {
00409 return defn->userData != NULL ? ((PluginCodec_MediaFormat *)defn->userData)->AdjustOptions(parm, len, &PluginCodec_MediaFormat::ToNormalised) : -1;
00410 }
00411
00412
00413 static int ToCustomised(const PluginCodec_Definition * defn, void *, const char *, void * parm, unsigned * len)
00414 {
00415 return defn->userData != NULL ? ((PluginCodec_MediaFormat *)defn->userData)->AdjustOptions(parm, len, &PluginCodec_MediaFormat::ToCustomised) : -1;
00416 }
00417
00418
00419 static int FreeOptions(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len)
00420 {
00421 if (parm == NULL || len == NULL || *len != sizeof(char ***))
00422 return false;
00423
00424 char ** strings = (char **)parm;
00425 for (char ** string = strings; *string != NULL; string++)
00426 free(*string);
00427 free(strings);
00428 return true;
00429 }
00430
00431
00432 static int GetOptions(const struct PluginCodec_Definition * codec, void *, const char *, void * parm, unsigned * len)
00433 {
00434 if (parm == NULL || len == NULL || *len != sizeof(struct PluginCodec_Option **))
00435 return false;
00436
00437 *(const void **)parm = codec->userData != NULL ? ((PluginCodec_MediaFormat *)codec->userData)->m_options : NULL;
00438 *len = 0;
00439 return true;
00440 }
00441
00442
00443 static int SetOptions(const PluginCodec_Definition *,
00444 void * context,
00445 const char * ,
00446 void * parm,
00447 unsigned * len)
00448 {
00449 PluginCodec * codec = (PluginCodec *)context;
00450 return len != NULL && *len == sizeof(const char **) && parm != NULL &&
00451 codec != NULL && codec->SetOptions((const char * const *)parm);
00452 }
00453
00454 protected:
00455 const PluginCodec_Definition * m_definition;
00456
00457 bool m_optionsSame;
00458 unsigned m_maxBitRate;
00459 unsigned m_frameTime;
00460 };
00461
00462
00463 #define PLUGINCODEC_DEFINE_CONTROL_TABLE(name) \
00464 static PluginCodec_ControlDefn name[] = { \
00465 { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE, PluginCodec::GetOutputDataSize }, \
00466 { PLUGINCODEC_CONTROL_TO_NORMALISED_OPTIONS, PluginCodec::ToNormalised }, \
00467 { PLUGINCODEC_CONTROL_TO_CUSTOMISED_OPTIONS, PluginCodec::ToCustomised }, \
00468 { PLUGINCODEC_CONTROL_FREE_CODEC_OPTIONS, PluginCodec::FreeOptions }, \
00469 { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS, PluginCodec::SetOptions }, \
00470 { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS, PluginCodec::GetOptions }, \
00471 PLUGINCODEC_CONTROL_LOG_FUNCTION \
00472 { NULL } \
00473 }
00474
00475
00476
00477 #endif // OPAL_CODEC_OPALPLUGIN_HPP