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;
105 unsigned m_headerSize;
106 unsigned m_payloadSize;
110 : m_packet((unsigned char *)packet)
113 , m_payloadSize(size - m_headerSize)
118 __inline
unsigned 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 width = MaxVideoResolutions[index].m_width;
346 height = MaxVideoResolutions[index].m_height;
347 maxFrameSize = MaxVideoResolutions[index].m_macroblocks;
358 if (options != NULL) {
359 for (
const char *
const * option = *options; *option != NULL; option += 2)
360 insert(value_type(option[0], option[1]));
367 const_iterator it = find(key);
379 char ** options = (
char **)calloc(size()*2+1,
sizeof(
char *));
380 if (options == NULL) {
381 PTRACE(1,
"Plugin",
"Could not allocate new option lists.");
385 char ** opt = options;
386 for (const_iterator it = begin(); it != end(); ++it) {
387 *opt++ = strdup(it->first.c_str());
388 *opt++ = strdup(it->second.c_str());
396 template<
typename NAME>
416 const char * formatName,
417 const char * payloadName,
418 const char * description,
419 unsigned maxBandwidth,
460 if (parmLen == NULL || parm == NULL || *parmLen !=
sizeof(
char ***)) {
461 PTRACE(1,
"Plugin",
"Invalid parameters to AdjustOptions.");
465 OptionMap originalOptions((
const char *
const * *)parm);
467 if (!(this->*adjuster)(originalOptions, changedOptions)) {
468 PTRACE(1,
"Plugin",
"Could not normalise/customise options.");
472 return (*(
char ***)parm = changedOptions.
GetOptions()) != NULL;
515 template<
typename NAME>
530 const char * formatName,
531 const char * payloadName,
532 const char * description,
533 unsigned samplesPerFrame,
534 unsigned bytesPerFrame,
537 ) :
Parent(formatName, payloadName, description, bytesPerFrame*8 * samplesPerFrame*1000000/sampleRate, options)
560 template<
typename NAME>
572 const char * formatName,
573 const char * payloadName,
574 const char * description,
575 unsigned maxBandwidth,
577 ) :
Parent(formatName, payloadName, description, maxBandwidth, options)
594 template<
typename NAME>
602 ,
m_frameTime((defn->sampleRate/1000*defn->usPerFrame)/1000)
604 PTRACE(3,
"Plugin",
"Codec created: \"" << defn->
descr
633 virtual bool Transcode(
const void * fromPtr,
637 unsigned & flags) = 0;
679 for (
const char *
const * option = options; *option != NULL; option += 2) {
680 if (!this->
SetOption(option[0], option[1])) {
681 PTRACE(1,
"Plugin",
"Could not set option \"" << option[0] <<
"\" to \"" << option[1] <<
'"');
701 virtual bool SetOption(
const char * optionName,
const char * optionValue)
714 template <
typename T>
715 bool SetOptionUnsigned(T & oldValue,
const char * optionValue,
unsigned minimum,
unsigned maximum = UINT_MAX)
717 unsigned newValue = oldValue;
720 oldValue = (T)newValue;
725 bool SetOptionUnsigned(
unsigned & oldValue,
const char * optionValue,
unsigned minimum,
unsigned maximum = UINT_MAX)
728 unsigned newValue = strtoul(optionValue, &end, 10);
732 if (newValue < minimum)
734 else if (newValue > maximum)
737 if (oldValue != newValue) {
746 template <
typename T>
749 bool opt = oldValue != 0;
760 if ( strcasecmp(optionValue,
"0") == 0 ||
761 strcasecmp(optionValue,
"n") == 0 ||
762 strcasecmp(optionValue,
"f") == 0 ||
763 strcasecmp(optionValue,
"no") == 0 ||
764 strcasecmp(optionValue,
"false") == 0)
766 else if (strcasecmp(optionValue,
"1") == 0 ||
767 strcasecmp(optionValue,
"y") == 0 ||
768 strcasecmp(optionValue,
"t") == 0 ||
769 strcasecmp(optionValue,
"yes") == 0 ||
770 strcasecmp(optionValue,
"true") == 0)
775 if (oldValue != newValue) {
784 bool SetOptionBit(
int & oldValue,
unsigned bit,
const char * optionValue)
786 return this->
SetOptionBit((
unsigned &)oldValue, bit, optionValue);
790 bool SetOptionBit(
unsigned & oldValue,
unsigned bit,
const char * optionValue)
793 if (strcmp(optionValue,
"0") == 0)
795 else if (strcmp(optionValue,
"1") == 0)
800 if (((oldValue&bit) != 0) != newValue) {
814 CodecClass * codec =
new CodecClass(defn);
815 if (codec != NULL && codec->Construct())
818 PTRACE(1,
"Plugin",
"Could not open codec, no context being returned.");
832 const void * fromPtr,
836 unsigned int * flags)
838 if (context != NULL && fromPtr != NULL && fromLen != NULL && toPtr != NULL && toLen != NULL && flags != NULL)
839 return ((
PluginCodec *)context)->Transcode(fromPtr, *fromLen, toPtr, *toLen, *flags);
841 PTRACE(1,
"Plugin",
"Invalid parameter to Transcode.");
848 return context != NULL ? ((
PluginCodec *)context)->GetOutputDataSize() : 0;
867 if (context == NULL || parmLen == NULL || parm == NULL || *parmLen !=
sizeof(
char ***)) {
868 PTRACE(1,
"Plugin",
"Invalid parameters to GetActiveOptions.");
876 return (*(
char ***)parm = activeOptions.
GetOptions()) != NULL;
882 if (parm == NULL || len == NULL || *len !=
sizeof(
char ***))
885 char ** strings = (
char **)parm;
886 for (
char **
string = strings; *
string != NULL;
string++)
907 return len != NULL && *len ==
sizeof(
const char **) && parm != NULL &&
908 codec != NULL && codec->
SetOptions((
const char *
const *)parm);
913 return len != NULL && *len ==
sizeof(
const char *) && parm != NULL && defn->
userData != NULL &&
920 return len != NULL && parm != NULL &&
921 codec != NULL && codec->
SetInstanceID((
const char *)parm, *len);
927 return len != NULL && parm != NULL &&
934 return codec != NULL && codec->
Terminate();
954 return ControlsTable;
968 template<
typename NAME>
990 return width*height*3/2;
997 template<
typename NAME>
1021 virtual bool SetOption(
const char * optionName,
const char * optionValue)
1066 template<
typename NAME>
1100 videoHeader->
width = width;
1101 videoHeader->
height = height;
1119 for (
unsigned y = 0; y <
m_height; ++y) {
1127 virtual unsigned OutputImage(
unsigned char * planes[3],
int raster[3],
1128 unsigned width,
unsigned height,
PluginCodec_RTP & rtp,
unsigned & flags)
1133 size_t ySize = width*height;
1134 size_t uvSize = ySize/4;
1135 if (planes[1] == planes[0]+ySize && planes[2] == planes[1]+uvSize)
1140 { width/2, height/2, raster[1], planes[1], planeInfo[0].
m_destination + ySize },
1141 { width/2, height/2, raster[2], planes[2], planeInfo[1].
m_destination + uvSize }
1144 for (
unsigned plane = 0; plane < 3; ++plane)
1145 planeInfo[plane].Copy();
1156 #define PLUGINCODEC_AUDIO_CODEC_CXX(MediaFormat, \
1160 PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
1161 MediaFormat.GetPayloadName(), \
1162 MediaFormat.GetDescription(), \
1163 MediaFormat.GetSampleRate(), \
1164 MediaFormat.GetMaxBandwidth(), \
1165 MediaFormat.GetFrameTime(), \
1166 MediaFormat.GetSamplesPerFrame(), \
1167 MediaFormat.GetBytesPerFrame(), \
1168 MediaFormat.GetRecommendedFramesPerPacket(), \
1169 MediaFormat.GetMaxFramesPerPacket(), \
1170 MediaFormat.GetPayloadType(), \
1171 MediaFormat.GetH323CapabilityType(), \
1172 MediaFormat.GetH323CapabilityData(), \
1173 EncoderClass::Create_s<EncoderClass>, \
1174 EncoderClass::Destroy_s, \
1175 EncoderClass::Transcode_s, \
1176 DecoderClass::Create_s<DecoderClass>, \
1177 DecoderClass::Destroy_s, \
1178 DecoderClass::Transcode_s, \
1179 DecoderClass::GetControls(), \
1180 MediaFormat.GetFlags(), \
1181 PLUGINCODEC_RAW_AUDIO, \
1185 #define PLUGINCODEC_VIDEO_CODEC_CXX(MediaFormat, \
1189 PLUGINCODEC_CODEC_PAIR(MediaFormat.GetFormatName(), \
1190 MediaFormat.GetPayloadName(), \
1191 MediaFormat.GetDescription(), \
1192 PLUGINCODEC_VIDEO_CLOCK, \
1193 MediaFormat.GetMaxBandwidth(), \
1194 1000000/PLUGINCODEC_MAX_FRAME_RATE, \
1195 MediaFormat.GetMaxWidth(), \
1196 MediaFormat.GetMaxHeight(), \
1197 0,PLUGINCODEC_MAX_FRAME_RATE, \
1198 MediaFormat.GetPayloadType(), \
1199 MediaFormat.GetH323CapabilityType(), \
1200 MediaFormat.GetH323CapabilityData(), \
1201 EncoderClass::Create_s<EncoderClass>, \
1202 EncoderClass::Destroy_s, \
1203 EncoderClass::Transcode_s, \
1204 DecoderClass::Create_s<DecoderClass>, \
1205 DecoderClass::Destroy_s, \
1206 DecoderClass::Transcode_s, \
1207 DecoderClass::GetControls(), \
1208 MediaFormat.GetFlags(), \
1209 PLUGINCODEC_RAW_VIDEO, \
1213 #define PLUGIN_CODEC_IMPLEMENT_CXX(NAME, table) \
1215 PLUGIN_CODEC_IMPLEMENT(NAME) \
1216 PLUGIN_CODEC_DLL_API struct PluginCodec_Definition * PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version) { \
1217 if (version < PLUGIN_CODEC_VERSION_OPTIONS) return NULL; \
1218 *count = sizeof(table)/sizeof(struct PluginCodec_Definition); \
1219 PluginCodec_MediaFormat<NAME>::AdjustAllForVersion(version, table, *count); \
1225 #endif // OPAL_CODEC_OPALPLUGIN_HPP