39 #ifndef OPAL_CODEC_OPALPLUGIN_HPP
40 #define OPAL_CODEC_OPALPLUGIN_HPP
54 #ifndef PLUGINCODEC_TRACING
55 #define PLUGINCODEC_TRACING 1
58 #if PLUGINCODEC_TRACING
62 #define PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF \
63 PluginCodec_LogFunction PluginCodec_LogFunctionInstance; \
64 int PluginCodec_SetLogFunction(const PluginCodec_Definition *, void *, const char *, void * parm, unsigned * len) \
66 if (len == NULL || *len != sizeof(PluginCodec_LogFunction)) \
69 PluginCodec_LogFunctionInstance = (PluginCodec_LogFunction)parm; \
70 if (PluginCodec_LogFunctionInstance != NULL) \
71 PluginCodec_LogFunctionInstance(4, __FILE__, __LINE__, "Plugin", "Started logging."); \
76 #define PLUGINCODEC_CONTROL_LOG_FUNCTION_INC { PLUGINCODEC_CONTROL_SET_LOG_FUNCTION, PluginCodec_SetLogFunction },
78 #define PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF
79 #define PLUGINCODEC_CONTROL_LOG_FUNCTION_INC
83 #if PLUGINCODEC_TRACING
85 #define PTRACE_CHECK(level) \
86 (PluginCodec_LogFunctionInstance != NULL && PluginCodec_LogFunctionInstance(level, NULL, 0, NULL, NULL))
87 #define PTRACE(level, section, args) \
88 if (PTRACE_CHECK(level)) { \
89 std::ostringstream strm; strm << args; \
90 PluginCodec_LogFunctionInstance(level, __FILE__, __LINE__, section, strm.str().c_str()); \
93 #define PTRACE_CHECK(level)
94 #define PTRACE(level, section, expr)
103 unsigned char * m_packet;
106 size_t m_payloadSize;
110 : m_packet((unsigned char *)packet)
113 , m_payloadSize(size - m_headerSize)
118 __inline
size_t GetPacketSize()
const {
return m_headerSize+m_payloadSize; }
123 if (m_headerSize+size > m_maxSize)
125 m_payloadSize = size;
156 *ptr++ = (
unsigned char)(((
id&0xf) << 4)|(len-1));
163 *ptr++ = (
unsigned char)(
id&0xff);
164 *ptr++ = (
unsigned char)(len&0xff);
173 if ((m_packet[0]&0x10) == 0)
180 id = (0x10000|(ptr[4] >> 4));
181 len = (ptr[4] & 0xf)+1;
185 if ((
id&0xfff0) == 0x1000) {
186 id = 0x20000 | ptr[4];
195 __inline
unsigned char *
GetPayloadPtr()
const {
return m_packet + m_headerSize; }
196 __inline
unsigned char &
operator[](
size_t offset) {
return m_packet[m_headerSize + offset]; }
197 __inline
unsigned const char &
operator[](
size_t offset)
const {
return m_packet[m_headerSize + offset]; }
198 __inline
bool CopyPayload(
const void * data,
size_t size,
size_t offset = 0)
220 return strtoul(str.c_str(), NULL, 10);
229 str += (char)(value%10 +
'0');
245 PluginCodec_OptionMapBase::iterator it = original.find(option);
246 if (it != original.end() && it->second != value)
247 changed[option] = value;
265 bool forceIfZero =
false)
268 if (value > maximum || (forceIfZero && value == 0))
286 return ((width+15)/16) * ((height+15)/16);
293 unsigned & maxFrameSize)
298 unsigned m_macroblocks;
299 } MaxVideoResolutions[] = {
300 #define OPAL_PLUGIN_CLAMPED_RESOLUTION(width, height) { width, height, ((width+15)/16) * ((height+15)/16) }
320 static size_t const LastMaxVideoResolutions =
sizeof(MaxVideoResolutions)/
sizeof(MaxVideoResolutions[0]) - 1;
324 if (maxFrameSize > 0) {
325 static unsigned const MinWidth = 4*16;
326 static unsigned const MinHeight = 3*16;
328 unsigned maxWidth = maxFrameSize*16*16/MinHeight;
329 unsigned maxHeight = maxFrameSize*16*16/MinWidth;
333 if (macroBlocks <= maxFrameSize &&
334 width >= MinWidth && width <= maxWidth &&
335 height >= MinHeight && height <= maxHeight)
338 while (index < LastMaxVideoResolutions &&
339 (MaxVideoResolutions[index].m_macroblocks > maxFrameSize ||
340 MaxVideoResolutions[index].m_width > maxWidth ||
341 MaxVideoResolutions[index].m_height > maxHeight))
345 PTRACE(4,
"Plugin",
"ClampResolution: idx=" << index <<
' '
346 << width <<
'x' << height <<
" > " << maxFrameSize <<
"mb reduced to "
347 << MaxVideoResolutions[index].m_width <<
'x' << MaxVideoResolutions[index].m_height
348 <<
'=' << MaxVideoResolutions[index].m_macroblocks <<
"mb");
349 width = MaxVideoResolutions[index].m_width;
350 height = MaxVideoResolutions[index].m_height;
351 maxFrameSize = MaxVideoResolutions[index].m_macroblocks;
360 unsigned & maxMacroBlocks,
372 ClampMax(maxWidth, original, changed, widthKey);
373 ClampMax(maxHeight, original, changed, heightKey);
374 ClampMax(maxWidth, original, changed, maxWidthKey);
375 ClampMax(maxHeight, original, changed, maxHeightKey);
376 ClampMax(maxWidth, original, changed, minWidthKey);
377 ClampMax(maxHeight, original, changed, minHeightKey);
388 if (options != NULL) {
389 for (
const char *
const * option = *options; *option != NULL; option += 2)
390 insert(value_type(option[0], option[1]));
397 const_iterator it = find(key);
409 char ** options = (
char **)calloc(size()*2+1,
sizeof(
char *));
410 if (options == NULL) {
411 PTRACE(1,
"Plugin",
"Could not allocate new option lists.");
415 char ** opt = options;
416 for (const_iterator it = begin(); it != end(); ++it) {
417 *opt++ = strdup(it->first.c_str());
418 *opt++ = strdup(it->second.c_str());
426 template<
typename NAME>
447 const char * rawFormat,
448 const char * formatName,
449 const char * payloadName,
450 const char * description,
451 unsigned maxBandwidth,
495 if (parmLen == NULL || parm == NULL || *parmLen !=
sizeof(
char ***)) {
496 PTRACE(1,
"Plugin",
"Invalid parameters to AdjustOptions.");
500 OptionMap originalOptions((
const char *
const * *)parm);
502 if (!(this->*adjuster)(originalOptions, changedOptions)) {
503 PTRACE(1,
"Plugin",
"Could not normalise/customise options.");
507 return (*(
char ***)parm = changedOptions.
GetOptions()) != NULL;
542 template<
typename NAME>
558 const char * formatName,
559 const char * payloadName,
560 const char * description,
561 unsigned samplesPerFrame,
562 unsigned bytesPerFrame,
563 unsigned sampleRate = 8000,
565 ) :
Parent(
PLUGINCODEC_RAW_AUDIO, formatName, payloadName, description, bytesPerFrame*8 * samplesPerFrame*1000000/sampleRate, options)
594 template<
typename NAME>
607 const char * formatName,
608 const char * payloadName,
609 const char * description,
610 unsigned maxBandwidth,
633 template<
typename NAME>
640 ,
m_maxBitRate(defn->bitsPerSec > 0 ? defn->bitsPerSec : 4*1024*1024)
641 ,
m_frameTime((defn->sampleRate/1000*defn->usPerFrame)/1000)
643 PTRACE(3,
"Plugin",
"Codec created: \"" << defn->
descr
672 virtual bool Transcode(
const void * fromPtr,
676 unsigned & flags) = 0;
718 for (
const char *
const * option = options; *option != NULL; option += 2) {
719 if (!this->
SetOption(option[0], option[1])) {
720 PTRACE(1,
"Plugin",
"Could not set option \"" << option[0] <<
"\" to \"" << option[1] <<
'"');
740 virtual bool SetOption(
const char * optionName,
const char * optionValue)
761 template <
typename T>
762 bool SetOptionUnsigned(T & oldValue,
const char * optionValue,
unsigned minimum,
unsigned maximum = UINT_MAX)
764 unsigned newValue = oldValue;
767 oldValue = (T)newValue;
772 bool SetOptionUnsigned(
unsigned & oldValue,
const char * optionValue,
unsigned minimum,
unsigned maximum = UINT_MAX)
775 unsigned newValue = strtoul(optionValue, &end, 10);
779 if (newValue < minimum)
781 else if (newValue > maximum)
784 if (oldValue != newValue) {
793 template <
typename T>
796 bool opt = oldValue != 0;
807 if ( strcasecmp(optionValue,
"0") == 0 ||
808 strcasecmp(optionValue,
"n") == 0 ||
809 strcasecmp(optionValue,
"f") == 0 ||
810 strcasecmp(optionValue,
"no") == 0 ||
811 strcasecmp(optionValue,
"false") == 0)
813 else if (strcasecmp(optionValue,
"1") == 0 ||
814 strcasecmp(optionValue,
"y") == 0 ||
815 strcasecmp(optionValue,
"t") == 0 ||
816 strcasecmp(optionValue,
"yes") == 0 ||
817 strcasecmp(optionValue,
"true") == 0)
822 if (oldValue != newValue) {
831 bool SetOptionBit(
int & oldValue,
unsigned bit,
const char * optionValue)
833 return this->
SetOptionBit((
unsigned &)oldValue, bit, optionValue);
837 bool SetOptionBit(
unsigned & oldValue,
unsigned bit,
const char * optionValue)
840 if (strcmp(optionValue,
"0") == 0)
842 else if (strcmp(optionValue,
"1") == 0)
847 if (((oldValue&bit) != 0) != newValue) {
861 CodecClass * codec =
new CodecClass(defn);
862 if (codec != NULL && codec->Construct())
865 PTRACE(1,
"Plugin",
"Could not open codec, no context being returned.");
879 const void * fromPtr,
883 unsigned int * flags)
885 if (context != NULL && fromPtr != NULL && fromLen != NULL && toPtr != NULL && toLen != NULL && flags != NULL)
886 return ((
PluginCodec *)context)->Transcode(fromPtr, *fromLen, toPtr, *toLen, *flags);
888 PTRACE(1,
"Plugin",
"Invalid parameter to Transcode.");
914 if (context == NULL || parmLen == NULL || parm == NULL || *parmLen !=
sizeof(
char ***)) {
915 PTRACE(1,
"Plugin",
"Invalid parameters to GetActiveOptions.");
923 return (*(
char ***)parm = activeOptions.
GetOptions()) != NULL;
929 if (parm == NULL || len == NULL || *len !=
sizeof(
char ***))
932 char ** strings = (
char **)parm;
933 for (
char **
string = strings; *
string != NULL;
string++)
954 return len != NULL && *len ==
sizeof(
const char **) && parm != NULL &&
955 codec != NULL && codec->
SetOptions((
const char *
const *)parm);
960 return len != NULL && *len ==
sizeof(
const char *) && parm != NULL && defn->
userData != NULL &&
967 return len != NULL && parm != NULL &&
968 codec != NULL && codec->
SetInstanceID((
const char *)parm, *len);
974 return len != NULL && parm != NULL &&
981 return codec != NULL && codec->
Terminate();
1001 return ControlsTable;
1015 template<
typename NAME>
1045 return width*height*3/2;
1058 template<
typename NAME>
1078 virtual bool SetOption(
const char * optionName,
const char * optionValue)
1123 template<
typename NAME>
1139 virtual bool SetOption(
const char * optionName,
const char * optionValue)
1160 if (width == 0 || height == 0)
1173 videoHeader->
width = width;
1174 videoHeader->
height = height;
1192 for (
unsigned y = 0; y <
m_height; ++y) {
1200 virtual unsigned OutputImage(
unsigned char * planes[3],
int raster[3],
1201 unsigned width,
unsigned height,
PluginCodec_RTP & rtp,
unsigned & flags)
1206 size_t ySize = width*height;
1207 size_t uvSize = ySize/4;
1208 if (planes[1] == planes[0]+ySize && planes[2] == planes[1]+uvSize)
1213 { width/2, height/2, raster[1], planes[1], planeInfo[0].
m_destination + ySize },
1214 { width/2, height/2, raster[2], planes[2], planeInfo[1].
m_destination + uvSize }
1217 for (
unsigned plane = 0; plane < 3; ++plane)
1218 planeInfo[plane].Copy();
1229 #define PLUGINCODEC_KNOWN_CODEC_CXX(MediaType, \
1235 PLUGINCODEC_CODEC_PAIR(Name, \
1248 EncoderClass::Create_s<EncoderClass>, \
1249 EncoderClass::Destroy_s, \
1250 EncoderClass::Transcode_s, \
1251 DecoderClass::Create_s<DecoderClass>, \
1252 DecoderClass::Destroy_s, \
1253 DecoderClass::Transcode_s, \
1254 DecoderClass::GetControls(), \
1255 PluginCodec_MediaTypeKnown, \
1256 PLUGINCODEC_RAW_##MediaType, \
1260 #define PLUGINCODEC_AUDIO_CODEC_CXX(MediaFormat, \
1264 PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
1265 MediaFormat.GetPayloadName(), \
1266 MediaFormat.GetDescription(), \
1267 MediaFormat.GetSampleRate(), \
1268 MediaFormat.GetMaxBandwidth(), \
1269 MediaFormat.GetFrameTime(), \
1270 MediaFormat.GetSamplesPerFrame(), \
1271 MediaFormat.GetBytesPerFrame(), \
1272 MediaFormat.GetRecommendedFramesPerPacket(), \
1273 MediaFormat.GetMaxFramesPerPacket(), \
1274 MediaFormat.GetPayloadType(), \
1275 MediaFormat.GetH323CapabilityType(), \
1276 MediaFormat.GetH323CapabilityData(), \
1277 EncoderClass::Create_s<EncoderClass>, \
1278 EncoderClass::Destroy_s, \
1279 EncoderClass::Transcode_s, \
1280 DecoderClass::Create_s<DecoderClass>, \
1281 DecoderClass::Destroy_s, \
1282 DecoderClass::Transcode_s, \
1283 DecoderClass::GetControls(), \
1284 MediaFormat.GetFlags(), \
1285 MediaFormat.GetRawFormat(), \
1289 #define PLUGINCODEC_VIDEO_CODEC_CXX(MediaFormat, \
1293 PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
1294 MediaFormat.GetPayloadName(), \
1295 MediaFormat.GetDescription(), \
1296 PLUGINCODEC_VIDEO_CLOCK, \
1297 MediaFormat.GetMaxBandwidth(), \
1298 1000000/PLUGINCODEC_MAX_FRAME_RATE, \
1299 MediaFormat.GetMaxWidth(), \
1300 MediaFormat.GetMaxHeight(), \
1301 0,PLUGINCODEC_MAX_FRAME_RATE, \
1302 MediaFormat.GetPayloadType(), \
1303 MediaFormat.GetH323CapabilityType(), \
1304 MediaFormat.GetH323CapabilityData(), \
1305 EncoderClass::Create_s<EncoderClass>, \
1306 EncoderClass::Destroy_s, \
1307 EncoderClass::Transcode_s, \
1308 DecoderClass::Create_s<DecoderClass>, \
1309 DecoderClass::Destroy_s, \
1310 DecoderClass::Transcode_s, \
1311 DecoderClass::GetControls(), \
1312 MediaFormat.GetFlags(), \
1313 MediaFormat.GetRawFormat(), \
1317 #define PLUGIN_CODEC_IMPLEMENT_CXX(NAME, table) \
1319 PLUGIN_CODEC_IMPLEMENT(NAME) \
1320 PLUGIN_CODEC_DLL_API struct PluginCodec_Definition * PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version) { \
1321 if (version < PLUGIN_CODEC_VERSION_OPTIONS) return NULL; \
1322 *count = sizeof(table)/sizeof(struct PluginCodec_Definition); \
1323 PluginCodec_MediaFormat<NAME>::AdjustAllForVersion(version, table, *count); \
1329 #endif // OPAL_CODEC_OPALPLUGIN_HPP