summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt')
-rw-r--r--debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt660
1 files changed, 660 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt b/debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt
new file mode 100644
index 00000000..9d8ee9c3
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/docs/tech/module-system-API.txt
@@ -0,0 +1,660 @@
+
+ Module System for Transcode 1.1.0 and later
+ ===========================================
+
+ Francesco Romani <[email protected]>, Andrew Church <[email protected]>
+ -
+ Revision 0.5, 17 August 2006
+
+ Index:
+---------------------------------------------------------------------------
+ 1. Introduction
+ 2. Overview
+ 3. Core API
+ 3.1. What you need to use NMS
+ 3.2. Example code
+ 3.3. The module factory
+ 3.4. Creating and destroying modules
+ 3.5. TCModule
+ 3.6. Using modules
+ 4. Plugin API
+ 4.1. What you need to use NMS (as a plugin writer)
+ 4.2. Example code
+ 4.3. Structure of a NMS plugin
+ 4.4. The registration process
+ 5. Plugin-Writing-HOWTO
+ 6. Internal structure
+ 6.1. Why the factory?
+ 6.2. About multithreading safeness
+ 6.3. On explicit reference counting
+ 6.4. Possibile API and ABI breakage
+ 6.5. init VS configure, fini VS stop
+ 6.6. A bit more about multiplexors and demultiplexors
+ 7. Final notes
+ 8. Appendix A: planned improvements in 1.2.0 and beyond
+
+
+ ***
+
+ 1. Introduction
+---------------------------------------------------------------------------
+
+This document provides basic informations about the new module system
+introduced in transcode 1.1.0. New system has API, ABI and even semantic
+incompatible with old one. This breakage was needed to address the
+recognized problems of old model. We (designers and coders) hope that new
+one will serve better our purposes. Anyway, new model hasn't any claim of
+generality or effectiveness outside transcode use cases: new API was
+designed to be the simplest and cleanest thing that work in transcode
+environment, and it doesn't provide any guarantee outside this field.
+I (Francesco) have chosen to reimplement our module system from scratch,
+despite the fact that well-known libraries such glib provides own ones,
+to lower as much as possible the dependencies count for transcode itself.
+Other developers agrees on the importance of this objective, where it
+is feasible to do (of course we hardly reimplement from scratch some
+Audio/Video codecs!).
+Header and source code files was written trying to achieve readability
+and clarity. Reader is encouraged to take a look at source code and,
+especially, header files to get more informantions and more precise
+documentation about the functions and data structures provided.
+
+Feel free to suggest improvements to API and/or to this documentation.
+PLEASE! report inconsistencies between this documentation and header
+and/or source code files.
+Send suggestions on [email protected] mailing list.
+Help us to make transcode better!
+
+Francesco's notes:
+I'm not a native english speaker. Send me corrections about documentation
+rather than code, and I will apply as soon as is possible :)
+
+Quick terminology overview:
+- NMS:
+ Acronym of (transcode's) New Module System
+- plugin:
+ a shared object (usually) on disk that implements one or more
+ 'module's.
+- module:
+ the central abstract object handled by NMS.
+ A 'module' is a piece of C code that respect some given constraints
+ (see more) and is usable by transcode. Often a 'plugin' implements
+ only a 'module' (or a single 'module' is packed in a single 'plugin'),
+ but there isn't a such constraint, that's only the current practice.
+- module instance:
+ a 'module' specify both the procedures and the data needed to be used
+ properly. We call 'instance' of a module the unshared, private portion
+ of such data. So, if a 'module' is created and runned multiple times,
+ each one has his private context and his private data, so everyone can
+ run independently from each other. Please note that 'modules' _always_
+ have some common, shared (and unmodifiable) data.
+- module class:
+ every module can belong to one or more 'module class'. A 'module class'
+ describe what a given module is supposed to do; this usually means
+ specifyng what functions and/or capabilities a given module supports
+ and/or provides.
+
+
+2. Overview
+---------------------------------------------------------------------------
+
+The new module system (NMS) aims to provide a generic framework for
+module handling through transcode, including external programs and
+helper tools like tcmodinfo.
+NMS aims also to incourage people writing of clean multi-instance plugins,
+avoiding the 'single huge function syndrome' that affects most of filter
+plugins as in transcode < 1.1.0. NMS provide a new and richer capabilities
+support code, supporting a wider range of plugin classes: no more only
+import (demux + decoding), filter and export (encoding + mux).
+
+NMS supports now five module classes, and is a fundamental part of module
+revision process taken starting from transcode 1.1.0.
+Please note that a given module CAN belong to more than one class (this
+means that such module just implements more functions).
+
+- demuxing module:
+ take care of reading stream data and extract audio stream,
+ video stream and so on
+- decoding module:
+ decodes A/V frame to raw data
+- filter module:
+ apply some transformation to A/V raw data
+- encoding module:
+ encodes raw data in a user-defined format
+- muxing module:
+ packs encoded data in a user-defined container
+
+More module classes (notably an input and/or output abstraction)
+can be added in future releases, but class count should not increase
+too much in NMS lifespan.
+
+Exact specification and documentation about such extended module classes
+are partially beyond the purpose of this document; they are further
+examined only for the parts related to NMS.
+
+NMS has quite different usage from old module system.
+A piece of code that want to use a transcode plugin through NMS should
+roughly:
+
+- start a module factory: this will initialize the subsystem; the
+ most important parameter is the module search path, that is no longer
+ hardcoded into code.
+- ask to a module factory to create a given module. This will trasparently
+ load a plugin if needed, resolve needed symbols, initialize it and
+ finally pass back as a reference to client code. In short, module factory
+ does all black magic for you ;)
+- use the module exposed functions as you wish.
+ Above module classes requires roughly the implementation of one module
+ for each one plus some mandatory support methods. For example, filter
+ class requires the implementation of 'filter_video' or 'filter_audio'
+ (or both) operation, (WARNING: as in transcode 1.1.0, this is not
+ enforced, yet) but a given module can implement more than one class
+ simply providing more methods implementation.
+ As an user of a module, just request the operation and check
+ the returned code :)
+ Of course, you can also use the new capabilities system to peek what
+ a loaded module is supposed to do. More on this topic later.
+- when you're set, ask to factory to unload the module. You CAN'T just
+ free your module manually, since factory needs again to do some black
+ magic to handle things nicely.
+- eventually shutdown the module factory itself. Do this only when
+ you have released all modules instances, or factory will complain loudly.
+
+NMS Core API (from module *user* viewpoint) will be covered with greater
+detail into section 3 of this document.
+For interested people, section 6 of this document contains design notes
+and some documentation about the NMS internals.
+
+From module writer viewpoint, some there are major changes too.
+First af all, all new-style modules have a unified entry point with
+following signature (defined in tcmodule-plugin.h):
+
+const TCModuleClass *tc_plugin_setup(void);
+
+If NMS code can't find such symbol defined in your shared object,
+it assumes that given SO *IS NOT* a valid NMS module, and it will go
+ahead.
+NMS entry point is no longer the main entry point for a given module,
+but it's simply the entry point for whole registration process.
+Real execution of module code will happen through some function pointers
+that each module should register into core as initialization stage.
+This registration happen, as well as other needed intialization code,
+into new entry point.
+
+So, NMS requires that each module provides (roughly) a single function
+for each implemented operation. Formerly, this was already a good module
+writing pratice, but was not required by former old module system which
+used a single function interface to do everything.
+
+NMS has also explicit support for module instance data. Each module
+descriptor provide an opaque pointer to module-defined data, which is
+opaque to core and can be used freely by module code.
+
+To summarize, a NMS-compliant module will
+
+- provide a separate function for each implemented operation, plus
+ a few function for support routines (initialization, shutdown,
+ configuration, stop, introspection) which must conform to a
+ give signature.
+ Each method will handle explicitely private (instance) data.
+- provide a single uniform entry point for registration process.
+ core uses module specific methods via some function pointers,
+ so real code can be made static and private; module itself
+ should give back to core valid function pointers to his methods
+ as part of registration process
+- register his capabilities in the exported module initialziation
+ hook. This means registration of methods but also notification
+ of module capabilities. A module can do arbitrary operations
+ other than required ones, even this should never be needed.
+
+NMS Plugin API (from module *writer* viewpoint) will be covered with greater
+detail into section 3 of this document.
+Section 4 of this document will provide some hints for a module writer.
+
+
+3. Core API
+---------------------------------------------------------------------------
+
+The reader of this section is encouraged to take a look of documentation
+of functions and data structures embedded into header files of NMS to
+become confident with the notions exposed here.
+Interesting files:
+
+ libtc/tcmodule-core.h
+ libtc/tcmodule-data.h
+ libtc/tcmodule-info.h
+
+This section will not explore the semantic and the meaning of parameters
+of core API functions, interested reader should be better served just
+reading comments on interesting header files.
+This section will instead explore the semantic of NMS core API and will
+serve to basic usage tutorial.
+
+
+3.1. What you need to use NMS
+-----------------------------
+
+To use transcode's NMS, you need to include some header files on your code:
+
+#include "tcmodule-core.h"
+#include "tcmodule-info.h"
+
+Build system for transcode take care to setup the right include search path.
+Otherwise, you should give explictely to gcc (code isn't tested on
+different compilers due to lack of software):
+
+gcc $YOUR_OPTS -I/path/to/tc/src/libtc/ ...
+
+You also need to link libtc.
+
+Once you have set the gritty details, you are read to start.
+
+
+3.2. Example code
+-----------------
+
+Take a look into tools/tcmodinfo to get maybe the simplest way to use
+the NMS. tcmodinfo will just load a user-requested module and will print
+out it's capabilities. Future releases of this document will perhaps add
+more (pseudo)code examples.
+
+You can also want to look NMS bundled test (in testsuite/ and or libtc/, in
+latter case test is embedded, as a comment in tcmodule.c) to get some more
+examples.
+
+
+3.3. The module factory
+-----------------------
+
+A key element in NMS is the module factory. From the point of view
+of a module user, a factory is represented by a totally opaque handler
+enterely managed by tcmodule code.
+The factory take care of loading plugins (the real shared object holding
+plugin code) if needed, unloading them if no longer need, accounting,
+and create instances. In short, factory does all the dirty work for you.
+
+In order to obtain, and release, a factory handler, you must use the
+tc_new_module_factory and tc_del_module_factory functions.
+Arguments and syntax of this functions is documented on tcmodule-core.h
+header file.
+
+Client code can theorically request an arbitrary number of factories,
+but each factory can handle ONLY modules created by herself. To
+request a factory to do an operation on a module NOT built by herself
+will cause a undefined behaviour (expect crash or some other weird things).
+In a just few words: DON'T DO THIS! :)
+In the common case, "one factory will be enough for everyone".
+
+
+3.4. Creating and destroying modules
+------------------------------------
+
+It's really simple. Just ask to your factory to create a brand new module
+belonging to a given class and from a given name.
+When the module is built, you must configure it passing some options
+packed in a string using the configure function (tc_module_configure).
+some modules can be reconfigured multiple times, some other can
+be reconfigured just the first time; This behaviour is fully
+module-(class-)dependent.
+Options are specific to a module, and there is no way to describe they
+in a general fashion.
+Since a module can be (or must be, for multiplexors) reconfigured
+a run time, the need for inspecting module settings arise.
+NMS provide an explicit operation for inquiry the actual settings of
+a module, the 'inspect' operation. Client code can request to know
+the status each and/or all module configurable parameters using this
+operation.
+
+Please note that NMS *NOT* knows _before_ to loading what every module
+is capable to do, nor the class of a given module. Everything
+is detected after the loading using new capabilities code.
+This means that you can ask to load a given module without to already
+know it's class, nor you ask to load all modules of a given class.
+Both above requests will lead to an error.
+As in transcode 1.1.0, module class and module name are in facts
+tightly bound and can't be handled separately.
+
+Known module classes as in transcode 1.1.0:
+
+ demultiplex,
+ decode,
+ filter,
+ encode,
+ multiplex
+
+Destroying a module is really simple. Just invoke the destruction
+function using your factory and the module, and the latter will be
+destroyed. But remember that real originating plugin will be
+unloaded only with all spawned modules are destroyed.
+In facts, destruction of last module triggers plugin
+unloading. The factory can detect at any time if a given module is
+the last one or not. You should'nt worry about this.
+
+Take care to check the return code of tc_del_module, since it
+triggers plugin unloading it can fail. Some debug messages are
+sent to (real) users using tc_log*().
+Future releases perhaps will add some detailed error codes than
+actual ones, which just carries a "failed/succeeded" information.
+
+
+3.5. TCModule
+-------------
+
+The reader might also take a look at tcmodule-data.h.
+The `TCModule' data structure represent a module instance.
+It is composed by two main components: the module class data,
+comprehending function pointers to real module and capabilities
+information, and the module instance section, private for each module.
+
+You can see the declarations in tcmodule-data.h for more details.
+Most of details are handled by NMS code, so you normally don't need
+to access neither module class or module private instance data.
+In facts, instance data should be accessed only by module code, and
+should be opaque both for NMS and for client code.
+
+It's safe to access (in read-only) the class data, and this is also
+needed to effectively use a module, since function pointers to module
+methods are embedded in class data. For this purpose a few commodities
+macro are provided. Direct access is also possible.
+The only 'critical' field in a class structure is the 'id' one.
+This field is used internally by NMS (see code) and should not be even
+considered by client code.
+
+You can notice that both module instance data and module class data
+have a 'id' field. These two fields are in fact independent, and both
+must be considered opaque by client code.
+
+
+3.6. Using modules
+------------------
+
+Usage of a module, if we want to ignore the internals and the gory details,
+should be really easy and straightforwarded.
+For each possibile module operation, there is a convenience (inline) function
+for easier usage and to avoid clumsy module->operation(module, ... ) syntax.
+
+The list of supported operations follows:
+
+tc_module_configure(module, options, vob)
+ (re)configure a module, changing it's internal settings;
+ modules *requires* to be configure()d _explicitely_
+ before the usage.
+
+tc_module_stop(module)
+ stop a module and prepare it for a new safe (re)configuration.
+ this means flushing all buffers, closing files and so on.
+
+tc_module_inspect(module, param, *value)
+ query about the actual value of a given parameter.
+
+tc_module_encode_video(module, inframe, outframe)
+tc_module_encode_audio(module, inframe, outframe)
+ encode a give video or audio frame and store data in another one.
+
+tc_module_decode_video(module, inframe, outframe)
+tc_module_decode_audio(module, inframe, outframe)
+ decode a give video or audio frame and store data in another one.
+
+tc_module_filter_video(module, vframe)
+tc_module_filter_audio(module, aframe)
+ apply a filter in place to a video or audio frame.
+
+tc_module_multiplex(module, vframe, aframe)
+ pack given encoded audio and video frame (both at once or just one)
+
+tc_module_demultiplex(module, vframe, aframe)
+ unpack encoded audio and video frame (both or just one)
+
+Just use any of above functions in your code. Do not forget to check the
+return code. In the common case, return value of -1 means 'error',
+and 0 means 'succesfull'.
+
+A few special parameters exists for 'inspect':
+
+for 'inspect':
+* "all" option will force the module to return to calling environment
+ a representation of /all/ internal parameters, packed in a single
+ string. This string will be packed in the same format accepted by
+ module option string
+* "help" option will force the module to return a textual, human readable
+ overview of the module, along with an explanation of name, value range
+ and meaning of accepted parameters. Special parameters will not be
+ present in this description.
+
+
+4. Plugin API
+---------------------------------------------------------------------------
+
+The reader of this section is encouraged to take a look of documentation
+of functions and data structures embedded into header files of NMS to
+become familiar with the notions exposed here.
+Interesting files:
+
+ libtc/tcmodule-plugin.h
+ libtc/tcmodule-data.h
+ libtc/tcmodule-info.h
+
+
+4.1. What you need to use NMS (as a plugin writer)
+--------------------------------------------------
+
+Simply include the header file in your plugin source file (or in your main
+plugin source file):
+
+#include "tcmodule-plugin.h"
+
+and you have access to all data structures, constants and functions
+(in fact just one :) ) that you need. Of course, you must design your
+plugin accordingly to NMS structure (covered later on this section and in
+the following section).
+Of course, your plugin must be compiled as shared object.
+
+
+4.2. Example code
+-----------------
+
+You can take a look to filter/filter_null.c multiplex/multiplex_null.c
+or encode/encode_null.c.
+
+Future releases of this document will perhaps add more (pseudo)code
+examples.
+
+
+4.3. Structure of a NMS plugin
+------------------------------
+
+There is quite a few strict constraints about the structure of a NMS
+plugin. Obviously, due to multiple-function-pointers structure, you
+must provide a separate function for each method implemented.
+This is intended to avoid the Single Huge Function Syndrome sometimes
+found on old-style filters ;)
+
+Is recommended to keep the biggest number of symbols on your plugin
+as private (just use 'static' qualifier for functions and reduce
+the usage of global variables, better to avoid it totally if it's
+feasible -and usually it's-).
+NMS has explicit support for module private data, so you should not
+need to use static variables on your plugin.
+Of course you can still use these, but _you_ must take care of
+multi-instances problems and so on.
+
+The only exception for above rule can be the capabilities data for
+a plugin. This data is used only during the registration process
+(see below for some other detail about this process), but is *copied*
+into core in order to avoid dirty tricks. So you can just provide
+a reference to some private variables. This is the preferred way
+since it seems the most simple one.
+
+To see a simple skeleton of a NMS plugin, take a look at
+filter/filter_null.c or multiplex/multiplex_null.c or
+encode/encode_null.c
+
+
+4.4. The registration process
+-----------------------------
+
+The plugin registration process consist simply into a invocation
+of tc_plugin_setup entry point. This function will return a
+TCModuleClass filled by plugin with description informations
+and with valid function pointers to operations implemented
+by plugin.
+
+Core will do some sanity checks on this descriptor returned
+by plugin, and use the given informations to fill it's
+own descriptor. Core WILL NOT change the informations provided
+by a plugin, unless they are detected as incorrect. In this
+case an error will be emitted (via tc_log*()) and more.
+Core will also setup sensible fallback values for all informations,
+or operations, not provided by a given plugin.
+
+Once a plugin is registered, there is no way to change registered
+data, nor to re-register or de-register itself.
+
+
+4.5. The plugin entry point
+---------------------------
+
+(WRITEME)
+
+4.6. Intialization and finalization of a module
+------------------------------------------------
+
+There is a couple of mandatory operations that a module must implement
+still not covered in this document. Those operations are the 'init'
+intialization operation and the 'fini' finalization operation.
+Those operations WILL NOT be exported to client code, and are used
+*only* trasparently by NMS code.
+'init' operation take care of initializing the part of a module that
+isn't changed by configure() operation and sets defaults.
+'fini' operation must cleanup everything and release *all* resources
+acquired by a module. Is the 'one and true' finalization routine, the
+last that is executed during the module life.
+
+
+4.7. Differences between module classes
+---------------------------------------
+
+(WRITEME)
+
+
+5. Plugin-Writing-HOWTO
+---------------------------------------------------------------------------
+
+FIXME: WRITEME
+
+
+6. Internal structure
+---------------------------------------------------------------------------
+
+This section holds sparse design notes about NMS current implementation.
+The reader is encouraged to take a look to source files (libtc/tcmodule*.c)
+to see the gory details.
+
+
+6.1. Why the factory?
+---------------------
+
+The factory descriptor was make explicite for generality and extendability.
+Having explicit factory descriptor make it possible to use more than
+one factory at time, even if this will be unlikely useful.
+There are some use cases for this on actual codebase at time of writing.
+Anyway, it's trivial to force code to use just one factory using something
+like:
+
+/* some_tc_header.h */
+
+extern TCModuleFactory main_factory;
+
+#define tc_load_module(type, name) \
+ tc_new_module(main_factory, type, name)
+#define tc_unload_module(type, name) \
+ tc_del_module(main_factory, mod)
+
+
+6.2. About multithreading safeness
+----------------------------------
+
+Multiple thread CANNOT execute operations concurrently on the same factory
+descriptor.
+It is safe to execute concurrently operations if each module operate on
+it's own descriptor. This means different threads can safely use different
+TCModule, but using one TCModule, or one TCFactory by two or more threads
+won't work.
+
+
+6.3. On explicit reference counting
+-----------------------------------
+
+On linux systems, dlopen() manpage reports that dl code can trasparently
+handle reference count of dlopen()ed modules, so there is no strict need
+of explictely do reference counting and avoid multiple loading on NMS.
+I don't know yet if this behaviour is portable.
+Moreover, I don't still want to drop explicit reference count on NMS,
+since it not complicate things too much and it can helps on accounting
+and debug purposes. This can change in future releases, but this should
+be a change totally transparent to client code.
+
+
+6.4. Possibile API and ABI breakage
+-----------------------------------
+
+Needs a careful review and a bit of discussion on transcode-devel.
+
+
+6.5. init VS configure, fini VS stop
+------------------------------------
+
+This section will higlight and summarize the differences between the
+init/configure and the stop/fini couple.
+
+init: ALWAYS executed BEFORE 'configure'.
+ Runs one and only one time during the life of a module.
+configure: ALWAYS executed AFTER 'init'.
+ Can run one or more times during the life of a module.
+ Modules REQUIRES that configure is runned at least once.
+ It is possible that invokations of configures after the first
+ will be ignored by a given module.
+
+fini: ALWAYS executed AFTER 'stop'.
+ Runs one and only one time during the life of a module.
+ it is possible (and usually happens) that fini invokes 'stop'.
+stop: ALWAYS executed BEFORE 'fini'.
+ Can run zero or more times during the life of a module.
+ Modules REQUIRES that stop is runned before to be re-configure()d.
+ It is possible that this function will do not anything useful.
+
+
+7. Final notes
+---------------------------------------------------------------------------
+
+send any comment to <[email protected]>. Thanks for reading this.
+Corrections about english are welcome.
+
+
+8. Appendix A: planned improvements in 1.2.0 and beyond
+---------------------------------------------------------------------------
+(without a particular order)
+
+1. Generic init/fini functions. Most of them are boilerplate code and
+ there is no need to replicate them every time.
+2. New filter operations with explicit destination argument:
+
+ int (*process_video)(TCModuleInstance self, vframe_list_t *src, vframe_list_t *dst);
+ int (*process_audio)(TCModuleInstance self, aframe_list_t *src, aframe_list_t *dst);
+
+3. Add open/close functions to improve (de)multiplexors:
+
+ int (*open)(TCModuleInstance self, const char *name, uint32_t flags);
+ int (*close)(TCModuleInstance self);
+
+4. Needs careful planning: subdivide modules in separate classes to
+ reduce function bloat.
+5. Make modules arguments explicit and handled by core: that semplifies
+ modules, reduce duplication, adds sanity checks for free.
+6. Related to above: overhaul or get rid of optstr* stuff.
+7. More docs, more sample code.
+8. Make explicit preferred (native?) colorspace for modules (the one for which
+ the module is designed about, so it provide bests results).
+9. Improve (make explicit?) flush API in muxers.
+10. better muxing API (using chunks?).
+
+# EOF