You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.7 KiB
C

/*
* tcmodule-plugin.h -- transcode module system, take two: plugin parts.
* (C) 2005-2010 - Francesco Romani <fromani -at- gmail -dot- com>
*
* This file is part of transcode, a video stream processing tool.
*
* transcode is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* transcode is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TCMODULE_PLUGIN_H
#define TCMODULE_PLUGIN_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdint.h>
#include "tcmodule-info.h"
#include "tcmodule-data.h"
#define TC_MODULE_SELF_CHECK(self, WHERE) do { \
if ((self) == NULL) { \
tc_log_error(MOD_NAME, WHERE ": " # self " is NULL"); \
return TC_ERROR; /* catch all for filter/encoders/decoders/(de)muxers */ \
} \
} while (0)
#define TC_HAS_FEATURE(flags, feat) \
((flags & (TC_MODULE_FEATURE_ ## feat)) ?1 :0)
#ifdef HAVE_GCC_ATTRIBUTES
__attribute__((unused))
#endif
static int tc_module_av_check(uint32_t flags)
{
int i = 0;
i += TC_HAS_FEATURE(flags, AUDIO);
i += TC_HAS_FEATURE(flags, VIDEO);
i += TC_HAS_FEATURE(flags, EXTRA);
return i;
}
#ifdef HAVE_GCC_ATTRIBUTES
__attribute__((unused))
#endif
static int tc_module_cap_check(uint32_t flags)
{
int i = 0;
i += TC_HAS_FEATURE(flags, DECODE);
i += TC_HAS_FEATURE(flags, FILTER);
i += TC_HAS_FEATURE(flags, ENCODE);
i += TC_HAS_FEATURE(flags, MULTIPLEX);
i += TC_HAS_FEATURE(flags, DEMULTIPLEX);
return i;
}
#undef TC_HAS_FEATURE
#define TC_MODULE_INIT_CHECK(self, FEATURES, feat) do { \
int j = tc_module_cap_check((feat)); \
\
if ((!((FEATURES) & TC_MODULE_FEATURE_MULTIPLEX) \
&& !((FEATURES) & TC_MODULE_FEATURE_DEMULTIPLEX)) \
&& (tc_module_av_check((feat)) > 1)) { \
tc_log_error(MOD_NAME, "unsupported stream types for" \
" this module instance"); \
return TC_ERROR; \
} \
\
if (j != 0 && j != 1) { \
tc_log_error(MOD_NAME, "feature request mismatch for" \
" this module instance (req=%i)", j); \
return TC_ERROR; \
} \
/* is perfectly fine to request to do nothing */ \
if ((feat != 0) && ((FEATURES) & (feat))) { \
(self)->features = (feat); \
} else { \
tc_log_error(MOD_NAME, "this module does not support" \
" requested feature"); \
return TC_ERROR; \
} \
} while (0)
/*
* autogeneration macros for generic init/fini pair
* looks like generic pair is needed often that expected;
* In future module system revision, maybe they will be
* moved into core.
*/
#define TC_MODULE_GENERIC_INIT(MODNAME, MODDATA) \
static int MODNAME ## _init(TCModuleInstance *self, uint32_t features) \
{ \
MODDATA *pd = NULL; \
\
TC_MODULE_SELF_CHECK(self, "init"); \
TC_MODULE_INIT_CHECK(self, MOD_FEATURES, features); \
\
pd = tc_malloc(sizeof(MODDATA)); \
if (pd == NULL) { \
tc_log_error(MOD_NAME, "init: out of memory!"); \
return TC_ERROR; \
} \
\
self->userdata = pd; \
\
if (verbose) { \
tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP); \
} \
\
return TC_OK; \
}
#define TC_MODULE_GENERIC_FINI(MODNAME) \
static int MODNAME ## _fini(TCModuleInstance *self) \
{ \
TC_MODULE_SELF_CHECK(self, "fini"); \
\
tc_free(self->userdata); \
self->userdata = NULL; \
return TC_OK; \
}
/*
* autogeneration macro for TCModuleInfo descriptor
*/
#define TC_MODULE_INFO(PREFIX) \
static const TCModuleInfo PREFIX ## _info = { \
.features = MOD_FEATURES, \
.flags = MOD_FLAGS, \
.name = MOD_NAME, \
.version = MOD_VERSION, \
.description = MOD_CAP, \
.codecs_in = PREFIX ## _codecs_in, \
.codecs_out = PREFIX ## _codecs_out, \
.formats_in = PREFIX ## _formats_in, \
.formats_out = PREFIX ## _formats_out \
}
/* please note the MISSING trailing comma */
#define TC_MODULE_CLASS_HEAD(PREFIX) \
.version = TC_MODULE_VERSION, \
.info = & ( PREFIX ## _info)
/*
* autogeneration for supported codecs/multiplexors
*/
#define TC_MODULE_FILTER_FORMATS(PREFIX) \
static const TCFormatID PREFIX ## _formats_in[] = { TC_FORMAT_ERROR }; \
static const TCFormatID PREFIX ## _formats_out[] = { TC_FORMAT_ERROR }
#define TC_MODULE_CODEC_FORMATS(PREFIX) \
static const TCFormatID PREFIX ## _formats_in[] = { TC_FORMAT_ERROR }; \
static const TCFormatID PREFIX ## _formats_out[] = { TC_FORMAT_ERROR }
#define TC_MODULE_MPLEX_FORMATS_CODECS(PREFIX) \
static const TCCodecID PREFIX ## _codecs_out[] = { TC_CODEC_ERROR }; \
static const TCFormatID PREFIX ## _formats_in[] = { TC_FORMAT_ERROR }
#define TC_MODULE_DEMUX_FORMATS_CODECS(PREFIX) \
static const TCCodecID PREFIX ## _codecs_in = { TC_CODEC_ERROR }; \
static const TCFormatID PREFIX ## _formats_out[] = { TC_FORMAT_ERROR }
/*
* plugin entry point prototype
*/
const TCModuleClass *tc_plugin_setup(void);
#define TC_MODULE_ENTRY_POINT(MODNAME) \
extern const TCModuleClass *tc_plugin_setup(void) \
{ \
return &( MODNAME ## _class); \
}
/* TODO: unify in a proper way OLDINTERFACE and OLDINTERFACE_M */
#define TC_FILTER_OLDINTERFACE(name) \
/* Old-fashioned module interface. */ \
static TCModuleInstance mod; \
\
int tc_filter(frame_list_t *frame, char *options) \
{ \
if (frame->tag & TC_FILTER_INIT) { \
if (name ## _init(&mod, TC_MODULE_FEATURE_FILTER) < 0) { \
return TC_ERROR; \
} \
return name ## _configure(&mod, options, tc_get_vob()); \
\
} else if (frame->tag & TC_FILTER_GET_CONFIG) { \
return name ## _get_config(&mod, options); \
\
} else if (frame->tag & TC_FILTER_CLOSE) { \
if (name ## _stop(&mod) < 0) { \
return TC_ERROR; \
} \
return name ## _fini(&mod); \
} \
\
return name ## _process(&mod, frame); \
}
#define TC_FILTER_OLDINTERFACE_INSTANCES 128
/* FIXME:
* this uses the filter ID as an index--the ID can grow
* arbitrarily large, so this needs to be fixed
*/
#define TC_FILTER_OLDINTERFACE_M(name) \
/* Old-fashioned module interface. */ \
static TCModuleInstance mods[TC_FILTER_OLDINTERFACE_INSTANCES]; \
\
int tc_filter(frame_list_t *frame, char *options) \
{ \
TCModuleInstance *mod = &mods[frame->filter_id]; \
\
if (frame->tag & TC_FILTER_INIT) { \
tc_log_info(MOD_NAME, "instance #%i", frame->filter_id); \
if (name ## _init(mod, TC_MODULE_FEATURE_FILTER) < 0) { \
return TC_ERROR; \
} \
return name ## _configure(mod, options, tc_get_vob()); \
\
} else if (frame->tag & TC_FILTER_GET_CONFIG) { \
return name ## _get_config(mod, options); \
\
} else if (frame->tag & TC_FILTER_CLOSE) { \
if (name ## _stop(mod) < 0) { \
return TC_ERROR; \
} \
return name ## _fini(mod); \
} \
\
return name ## _process(mod, frame); \
}
#endif /* TCMODULE_PLUGIN_H */