1 /*
2  * tcmodule-core.h -- transcode module system, take two: core components.
3  * (C) 2005-2010 - Francesco Romani <fromani -at- gmail -dot- com>
4  *
5  * This file is part of transcode, a video stream processing tool.
6  *
7  * transcode is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * transcode is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 
23 /*
24  * this header file is intended to be included in components
25  * which want to use the new transcode module system, acting like
26  * clients respect to a plugin.
27  */
28 
29 #ifndef TCMODULE_CORE_H
30 #define TCMODULE_CORE_H
31 
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35 
36 #include <stdint.h>
37 
38 #include "tcmodule-data.h" /* pulls framebuffer.h and transcode.h */
39 
40 /*
41  * this structure will hold all data needed to use a module by client code:
42  * module operations and capabilities (given by module class, so shared
43  * between all modules) and private data.
44  */
45 typedef struct tcmodule_ *TCModule;
46 struct tcmodule_ {
47     const TCModuleClass *klass;
48     /* pointer to class data shared between all instances */
49 
50     TCModuleInstance instance;
51     /* each module has it's private instance data, it's embedded here */
52 };
53 
54 /*************************************************************************
55  * interface helpers, using shortened notation                           *
56  *************************************************************************/
57 
58 #ifdef HAVE_GCC_ATTRIBUTES
59 __attribute__((unused))
60 #endif
tc_module_configure(TCModule handle,const char * options,vob_t * vob)61 static int tc_module_configure(TCModule handle,
62                                const char *options, vob_t *vob)
63 {
64     return handle->klass->configure(&(handle->instance), options, vob);
65 }
66 
67 #ifdef HAVE_GCC_ATTRIBUTES
68 __attribute__((unused))
69 #endif
tc_module_stop(TCModule handle)70 static int tc_module_stop(TCModule handle)
71 {
72     return handle->klass->stop(&(handle->instance));
73 }
74 
75 #ifdef HAVE_GCC_ATTRIBUTES
76 __attribute__((unused))
77 #endif
tc_module_inspect(TCModule handle,const char * param,const char ** value)78 static int tc_module_inspect(TCModule handle,
79                              const char *param, const char **value)
80 {
81     return handle->klass->inspect(&(handle->instance), param, value);
82 }
83 
84 #ifdef HAVE_GCC_ATTRIBUTES
85 __attribute__((unused))
86 #endif
tc_module_encode_video(TCModule handle,vframe_list_t * inframe,vframe_list_t * outframe)87 static int tc_module_encode_video(TCModule handle,
88                                   vframe_list_t *inframe,
89                                   vframe_list_t *outframe)
90 {
91     return handle->klass->encode_video(&(handle->instance),
92                                        inframe, outframe);
93 }
94 
95 #ifdef HAVE_GCC_ATTRIBUTES
96 __attribute__((unused))
97 #endif
tc_module_encode_audio(TCModule handle,aframe_list_t * inframe,aframe_list_t * outframe)98 static int tc_module_encode_audio(TCModule handle,
99                                   aframe_list_t *inframe,
100                                   aframe_list_t *outframe)
101 {
102     return handle->klass->encode_audio(&(handle->instance),
103                                        inframe, outframe);
104 }
105 
106 #ifdef HAVE_GCC_ATTRIBUTES
107 __attribute__((unused))
108 #endif
tc_module_decode_video(TCModule handle,vframe_list_t * inframe,vframe_list_t * outframe)109 static int tc_module_decode_video(TCModule handle,
110                                   vframe_list_t *inframe,
111                                   vframe_list_t *outframe)
112 {
113     return handle->klass->decode_video(&(handle->instance),
114                                        inframe, outframe);
115 }
116 
117 #ifdef HAVE_GCC_ATTRIBUTES
118 __attribute__((unused))
119 #endif
tc_module_decode_audio(TCModule handle,aframe_list_t * inframe,aframe_list_t * outframe)120 static int tc_module_decode_audio(TCModule handle,
121                                   aframe_list_t *inframe,
122                                   aframe_list_t *outframe)
123 {
124     return handle->klass->decode_audio(&(handle->instance),
125                                        inframe, outframe);
126 }
127 
128 #ifdef HAVE_GCC_ATTRIBUTES
129 __attribute__((unused))
130 #endif
tc_module_filter_video(TCModule handle,vframe_list_t * frame)131 static int tc_module_filter_video(TCModule handle,
132                                   vframe_list_t *frame)
133 {
134     return handle->klass->filter_video(&(handle->instance), frame);
135 }
136 
137 #ifdef HAVE_GCC_ATTRIBUTES
138 __attribute__((unused))
139 #endif
tc_module_filter_audio(TCModule handle,aframe_list_t * frame)140 static int tc_module_filter_audio(TCModule handle,
141                                   aframe_list_t *frame)
142 {
143     return handle->klass->filter_audio(&(handle->instance), frame);
144 }
145 
146 #ifdef HAVE_GCC_ATTRIBUTES
147 __attribute__((unused))
148 #endif
tc_module_multiplex(TCModule handle,vframe_list_t * vframe,aframe_list_t * aframe)149 static int tc_module_multiplex(TCModule handle,
150                                vframe_list_t *vframe,
151                                aframe_list_t *aframe)
152 {
153     return handle->klass->multiplex(&(handle->instance), vframe, aframe);
154 }
155 
156 #ifdef HAVE_GCC_ATTRIBUTES
157 __attribute__((unused))
158 #endif
tc_module_demultiplex(TCModule handle,vframe_list_t * vframe,aframe_list_t * aframe)159 static int tc_module_demultiplex(TCModule handle,
160                                  vframe_list_t *vframe,
161                                  aframe_list_t *aframe)
162 {
163     return handle->klass->demultiplex(&(handle->instance), vframe, aframe);
164 }
165 
166 #ifdef HAVE_GCC_ATTRIBUTES
167 __attribute__((unused))
168 #endif
tc_module_get_info(TCModule handle)169 static const TCModuleInfo *tc_module_get_info(TCModule handle)
170 {
171     return handle->klass->info;
172 }
173 
174 #ifdef HAVE_GCC_ATTRIBUTES
175 __attribute__((unused))
176 #endif
tc_module_match(int codec,TCModule handle,TCModule other)177 static int tc_module_match(int codec,
178                            TCModule handle, TCModule other)
179 {
180     return tc_module_info_match(codec,
181                                 handle->klass->info, other->klass->info);
182 }
183 
184 #ifdef HAVE_GCC_ATTRIBUTES
185 __attribute__((unused))
186 #endif
tc_module_show_info(TCModule handle,int verbose)187 static void tc_module_show_info(TCModule handle, int verbose)
188 {
189     tc_module_info_log(handle->klass->info, verbose);
190 }
191 
192 /* FIXME: that's just ugly. */
193 #ifdef HAVE_GCC_ATTRIBUTES
194 __attribute__((unused))
195 #endif
tc_module_pass_extradata(TCModule source,TCModule dest)196 static void tc_module_pass_extradata(TCModule source, TCModule dest)
197 {
198     if (source != NULL && dest != NULL) {
199         /* soft copy */
200         dest->instance.extradata      = source->instance.extradata;
201         dest->instance.extradata_size = source->instance.extradata_size;
202     }
203 }
204 
205 
206 /* factory data type. */
207 typedef struct tcfactory_ *TCFactory;
208 
209 /*************************************************************************
210  * factory methods                                                       *
211  *************************************************************************/
212 
213 /*
214  * tc_new_module_factory:
215  *      initialize a module factory. This function will acquire all
216  *      needed resources and set all things appropriately to make the
217  *      factory ready for create module instances, loading plugins on
218  *      demand if needed.
219  *
220  * Parameters:
221  *    modpath:
222  *        module base directory. The factory will look for
223  *        transcode plugins to load if needed starting from this
224  *        directory.
225  *        Note that this must be a single directory.
226  *    verbose:
227  *        verbosiness level of factory. Control the quantity
228  *        of informative messates to print out.
229  *        Should be one of TC_INFO, TC_DEBUG... value.
230  *
231  * Return Value:
232  *     A valid TCFactory if initialization was done
233  *     succesfully, NULL otherwise. In latter case, a informative
234  *     message is sent through tc_log*().
235  *
236  * Side effects:
237  *     uses tc_log*() internally.
238  *
239  * Preconditions:
240  *     modpath NOT NULL; giving a NULL parameter will cause a
241  *     graceful failure.
242  *
243  * Postconditions:
244  *     factory initialized and ready to create TCModules.
245  */
246 TCFactory tc_new_module_factory(const char *modpath, int verbose);
247 
248 /*
249  * tc_del_module_factory:
250  *     finalize a module factory. Shutdowns the factory completely,
251  *     cleaning up everything and unloading plugins.
252  *     PLEASE NOTE: this function _CAN_ fail, notably if a plugin
253  *     can't be unloaded cleanly (this usually happens because a plugin
254  *     has still some live  instances at finalization time).
255  *     ALWAYS check the return value and take opportune countermeasures.
256  *     At time of writing, a factory can't (and it's unlikely it will
257  *     do) destroy all living instances automatically.
258  *
259  * Parameters:
260  *     factory: factory handle to finalize.
261  *
262  * Return Value:
263  *     0  succesfull.
264  *     -1 an error occurred (notified via tc_log*).
265  *
266  * Side effects:
267  *     uses tc_log*() internally.
268  *
269  * Preconditions:
270  *     given factory was already initialized. Trying to finalize a
271  *     non-initialized factory causes undefined behaviour.
272  *
273  * Postconditions:
274  *     all resources acquired by factory are released; no modules are
275  *     loaded or avalaible, nor module instances are still floating around.
276  */
277 int tc_del_module_factory(TCFactory factory);
278 
279 /*
280  * tc_new_module:
281  *      using given factory, create a new module instance of the given type,
282  *      belonging to given class, and initialize it with reasonnable
283  *      defaults values.
284  *      This function may load a plugin implicitely to fullfill the request,
285  *      since plugins are loaded on demand of client code.
286  *      The returned instance pointer must be released using
287  *      tc_del_module (see below).
288  *      The returned instance is ready to use with above tc_module_* macros,
289  *      or in any way you like.
290  *
291  *      PLEASE NOTE: this function automatically invokes module initialization
292  *      method on given module. You should NOT do by yourself.
293  *
294  * Parameters:
295  *       factory: use this factory instance to build the new module.
296  *      modclass: class of module requested (filter, encoding,
297  *                demultiplexing...).
298  *       modname: name of module requested.
299  *         media: media type for new module (TC_VIDEO, TC_AUDIO, TC_EXTRA)
300  *
301  * Return value:
302  *      NULL: an error occurred, and notified via tc_log_*()
303  *      valid handle to a new module instance otherwise.
304  *
305  * Side effects:
306  *      uses tc_log*() internally.
307  *      a plugin can be loaded (except for errors!) implicitely.
308  *
309  * Preconditions:
310  *      given factory was already intialized.
311  *
312  * Postconditions:
313  *       if succeeded, module ready to use by client code.
314  *
315  * Examples:
316  *      if you want to load the "foobar" plugin, belonging to filter class,
317  *      you should use a code like this:
318  *
319  *      TCModule my_module = tc_new_module("filter", "foobar");
320  */
321 TCModule tc_new_module(TCFactory factory,
322                        const char *modclass, const char *modname, int media);
323 
324 /*
325  * tc_del_module:
326  *      destroy a module instance using given factory, unloading corrispondent
327  *      plugin from factory if needed.
328  *      This function release the maximum amount of resources possible
329  *      acquired by a given module; since some resources (originating plugin)
330  *      are shared between all instances, there is possible that some call
331  *      doesn't release all resources. Anyway, si guaranted that all resources
332  *      are released when all instances are destroyed.
333  *
334  *      PLEASE NOTE: this function automatically invokes module finalization
335  *      method on given module. You should'nt do by yourself.
336  *
337  * Parameters:
338  *      factory: a factory handle, the same one used to create the module
339  *      module: module instance to destroy.
340  *
341  * Return Value:
342  *      0  succesfull
343  *      -1 an error occurred (notified via tc_log*).
344  *
345  * Side effects:
346  *      uses tc_log*() internally.
347  *      a plugin could be unloaded implicitely.
348  *
349  * Preconditions:
350  *      factory already initialized.
351  *      ***GIVEN MODULE WAS CREATED USING GIVEN FACTORY***
352  *      to violate this condition will case an undefined behaviour.
353  *      At time of writing, factory *CANNOT* detect when this condition
354  *      is violated. So be careful.
355  *
356  *      given module instance was obtained using tc_new_module,
357  *      applying this function to a module instances obtained in a
358  *      different way causes undefined behaviour, most likely a memory
359  *      corruption.
360  *
361  * Postconditions:
362  *      resources belonging to instance are released (see above).
363  */
364 int tc_del_module(TCFactory factory, TCModule module);
365 
366 /*
367  * tc_plugin_count:
368  *      get the number of loaded plugins in a given factory.
369  *      Used mainly for debug purposes.
370  *
371  * Parameters:
372  *      factory: handle to factory to analyze.
373  *
374  * Return Value:
375  *      the number of plugins loaded at the moment.
376  *
377  * Side effects:
378  *      None
379  *
380  * Preconditions:
381  *      Given factory was already initialized.
382  *      To apply this function to an unitialized factory will cause
383  *      an undefine dbehaviour
384  *
385  * Postconditions:
386  *      None
387  */
388 int tc_plugin_count(const TCFactory factory);
389 
390 /*
391  * tc_module_count:
392  *      get the number of module created and still valid by a given
393  *      factory. Used mainly for debug purposes.
394  *
395  * Parameters:
396  *      factory: handle to factory to analyze.
397  *
398  * Return Value:
399  *      the number of module created and not yet destroyed at the moment.
400  *
401  * Side effects:
402  *      None
403  *
404  * Preconditions:
405  *      Given factory was already initialized.
406  *      To apply this function to an unitialized factory will cause
407  *      an undefine dbehaviour
408  *
409  * Postconditions:
410  *      None
411  */
412 int tc_instance_count(const TCFactory factory);
413 
414 /*
415  * tc_compare_modules:
416  *      compare two module (through it's handler) supposed to be the same
417  *      type (class + name). Used mainly for debug purposes.
418  *
419  *      This function *MUST* SCREW UP BADLY if internal checks
420  *      are absoultely clean, so assert are used at this moment.
421  *
422  * Parameters:
423  *      amod: handle to first module instance.
424  *      bmod: handle to second module instance
425  *
426  * Return value:
427  *      -1 totally different modules
428  *       0 same class (some shared data)
429  *      +1 same module instance: the two handles point to same instance
430  *
431  * Side effects:
432  *      client code can be abort()ed.
433  *
434  * Preconditions:
435  *      both module handles must refer to valid modules.
436  *
437  * Postconditions:
438  *      None
439  */
440 int tc_compare_modules(const TCModule amod, const TCModule bmod);
441 
442 #endif /* TCMODULE_CORE_H */
443