/*  
    Linux Dynamic Objects header
    
    This header should be included by filters and by host applications
    using them, in order to be able to use and implement video filters.
 */

/**
   @file livido.h

   @brief Linux Video Dynamic Objects header file
*/

/**
   @mainpage LiViDO :: Linux Video Dynamic Objects


   @section intro Introduction

During the last couple of years we have been observing a blooming
development in the field of realtime video software for the Linux/GNU
platform. An increasing number of artists and other users are
exploring the possibilities of several unique software packages for
video editing, mixing and effect processing.  The question arises here
how we (the developers) balance the growing number of features against
complexity, (re)usability and manageability of larger scale software
design.

As users, we choose our applications because their features fit our
purposes , as developers we serve the needs of the users who want an
increasing number of features added to our applications while we
should focus on flexible core engines and program frameworks.

An elegant solution to this problem is to provide the Free Software
community with  a flexible architecture that allows a shared pool of video
plugins. This brings a number of benefits:

- we can give designers of plugins the opportunity to develop their
(video) processing algorithms without the distraction of resolving
interface problems;
- we can share a set of unique plugins among a great number of programs;
- we can give the user the opportunity to control at least some aspects of
the features they want.

LiViDO design is based upon extensive research that has already gone
into applications such as PD/PDP , FreeJ, EffecTV , Veejay and other video
software applications.

The LiViDO architects will provide a lightweight, flexible API based
upon these established technologies. Currently, they are in the
process of creating a plug-in architecture useful for video editing
-mixing, and modular effect processing.

The API will deliberately be kept short and simple; to achieve
compatibility with a wide range of promising Linux video software
packages it is required to find the greatest common divisor in their logical
behaviour.

The API attempts to give programmers the ability to write simple plugin
video processors in C/C++ and link them dynamically with a range of
software packages (called hosts). It should be possible for any host and
any plugin to communicate through this interface.

Plugins will reside in shared object files (*.so in Linux), suitable
for dynamic linking by dlopen() and family. The file will provide a
number of plugin types that can be used to instantiate actual plugins
so they can be connected to perform these tasks.

Some interesting links:
- http://www.piksel.no
- http://cvs.dyne.org/viewcvs.cgi/livido/?root=piksel
- http://freej.dyne.org
- http://zwizwa.fartit.com/pd/pdp/overview.html
- http://effectv.sourceforge.net
- http://veejay.sourceforge.net

   
   @section howto-make How to make a filter
   
   Instructions on how to make a video filter
   
   Somebody still needs to write them.
   Please refer to the file plugin_example.c itself.

   @section howto-use How to use filters
   
   Instructions on how to use video filters

   Somebody still needs to write them.
   Please refer to the file host_example.c itself.



   @section License
   
   LiViDO source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   LiViDO source code 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.
   Please refer to the GNU Public License for more details.
   
   You should have received a copy of the GNU Public License along
   with this source code; if not, write to: Free Software Foundation,
   Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   LiViDO is developed by:

   Denis "jaromil" Rojo - http://rastasoft.org

   Niels Elburg - http://veejay.sf.net

   Tom Schouten

   Simon de Baekker

   Kentaro Fukuchi

*/

#ifndef __LIVIDO_H__
#define __LIVIDO_H__

/** inttypes.h gives bit precision on integer types used
    (u)int(8,16,32,64)_t = (un)signed integer of a certain bit depth 
#include <inttypes.h> */

/** dynamic object loadingi, this is dlopen in GNU libc */
#include <dlfcn.h>

/** buffer allocation routines from libc */
#include <stdlib.h>

/////////////////////////////////////////////////////////////////
/// LIVIDO API VERSION 1
/////////////////////////////////////////////////////////////////

/*

  $Log: livido.h,v $
  Revision 1.5  2004/04/06 08:39:41  jaromil


  removed alloca() function,
  define to create instances from class,
  public parameters allocation and set.
  this update discards compatibility with previous revision.

  Revision 1.4  2004/03/30 18:57:20  jaromil


  now API includes class / instance mechanism
  see documentation in doxygen format inside livido.h

  also new working examples: plugin and host
  only libc needed: simple but works.

  comments welcome!


  Process me with doxygen to generate html documentation,
  or read thru this file, to explore the LiViDO API.

*/

#define LIVIDO_ID "$Id: livido.h,v 1.5 2004/04/06 08:39:41 jaromil Exp $"
///< last modification
#define LIVIDO_REVISION "$Revision: 1.5 $" ///< cvs revision number









/** 
    @defgroup palette Video palettes
    
    Livido Video Palettes
    
    a filter can specify more than one supported palette
    
    @{ */
typedef int livido_palette_t;
#define LVD_PALETTE_RGB24	(1<<0x0) ///< please comment me
#define LVD_PALETTE_RGB32	(1<<0x1) ///< please comment me
#define LVD_PALETTE_RGBP	(1<<0x2) ///< please comment me
#define LVD_PALETTE_RAW		(1<<0x3) ///< please comment me
#define	LVD_PALETTE_YUV422P	(1<<0x4) ///< please comment me
#define LVD_PALETTE_YUV420P	(1<<0x5) ///< please comment me
#define LVD_PALETTE_YUV444P	(1<<0x6) ///< please comment me
#define LVD_PALETTE_YUY2	(1<<0x7) ///< YUV422
#define	LVD_PALETTE_YUYV	(1<<0x8) ///< please comment me
#define	LVD_PALETTE_YV12	(1<<0x9) ///< YUV420
#define	LVD_PALETTE_I420	(1<<0xa) ///< YUV420

/**
   a define to know how many bytes per pixel is each palette 
   @todo please correct any errors as i'm not 100% about bpp in palettes
*/
#define LIVIDO_PALETTE_BYTES(p) \
	(p&LVD_PALETTE_RGB32)?4: \
	(p& (LVD_PALETTE_YUV422P \
	    |LVD_PALETTE_420P \
	    |LVD_PALETTE_RGB24 \
	    |LVD_PALETTE_YUV444P \
	    |LVD_PALETTE_YUY \
	    |LVD_PALETTE_YUYV \
	    |LVD_PALETTE_YV12 \
	    |LVD_PALETTE_I420)?3: \
	(p& (LVD_PALETTE_RGBP \
	     LVD_PALETTE_RAW)?1:0))
///< check how many bytes is a palette

#define LIVIDO_PALETTE_BITS(p) \
	(p&LVD_PALETTE_RGB32)?32: \
	(p& (LVD_PALETTE_YUV422P \
	    |LVD_PALETTE_420P \
	    |LVD_PALETTE_RGB24 \
	    |LVD_PALETTE_YUV444P \
	    |LVD_PALETTE_YUY \
	    |LVD_PALETTE_YUYV \
	    |LVD_PALETTE_YV12 \
	    |LVD_PALETTE_I420)?24: \
	(p& (LVD_PALETTE_RGBP \
	     LVD_PALETTE_RAW)?8:0))
///<check how many bits is a palette

///@}





/////////////////////////////////////////////////////////////////
/**
   @defgroup instance Filter instance
   
    
   An instance is the buffer created by the filter at initialization
   
   @todo write something more here about the instance mechanism, that
   is what basically lets us use the same plugin multiple times...
   
   @{ */
/////////////////////////////////////////////////////////////////

/**
   This struct is allocated by the plugin init()
   
   it should be stored by the host and free'd at the end using
   the plugin function deinit()
   
   All variables inside the livido_instance are read and write, so they
   should be set by the host application before calling the alloca()
   function.

   The parameters array holds the real values for the parameters exposed
   by the filter, some of them require a new call to init() in case
   the livido_parameter_t::need_init flag is positive.  */
typedef struct {
  /** this is where the actual parameter values are stored, it must be
      allocated by the filter when the instance is created
      (should we make a macro for that?) */
  void **parameter; ///< filter parameter values

  int input_frames;
  ///< how many input frames are being processed
  int output_frames;
  ///< how many output frames are resulting from processing
    
  int width;
  ///< width of the video frames in pixels

  int height;
  ///< height of the video frames in pixels

  livido_palette_t	palette;
  ///< palette of the video frames (see LVD_PALETTE_* defines)
	   
  void *internal; ///< filter's private buffers

} livido_instance_t;


///@}








///////////////////////////////////////////////////////////////////
/** 
    @defgroup filter_public Filter class public functions
    
    The following public functions are found in the filter class,
    they are called by the host application to operate the filter.

    First the livido_setup symbol is called, which returns a
    structure which is the filter's class. The class will hold
    function pointers for the init() deinit() alloca() and process()
    functions.

    An host application should first setup the width, height and
    palette of the class, then it can proceed to create a new instance.
    
    The init() must be called in order to create an instance of
    the filter, which will be in turn passed to process() every
    time video input are processed into output.

    @{ */
///////////////////////////////////////////////////////////////////

/**
    Initialize the internal buffers and variables for a 
    instance of the filter, according to the parameters set.

    This function should be used on a freshly created filter instance,
    as well every time a parameter which needs init
    (see livido_parameter_t::need_init) is changed.

    @brief initialize filter instance according to its parameters
    @param livido_instance_t filter instance to (re)initialize
    @return initialized filter instance
    */
typedef livido_instance_t *(livido_init_f) (livido_instance_t*);

/**
   Free memory and cleanup internal variables.
   
   It must be called by host for de-initialization of instances when they
   are no more needed.
   
   @param filter instance
   @return error code
*/
typedef int (livido_deinit_f) (livido_instance_t*); 

/**
   Process instance->input frames to instance->output frames
   
   if LVD_PROPERTY_INPLACE is set , livido_data **out may be NULL
   
   @param env filter instance
   @param in input frame(s) to be processed
   @param out output frame(s) processed,
          this is NULL if LIVIDO_PROPERTY_IS_INPLACE
   @return error code */
typedef int (livido_process_f) (livido_instance_t* env, void **in, void **out);

///@}
















/** 
    @defgroup property Filter properties
    
    Properties of a filter define aspects of its functioning,
    they are flags set on the filter class, you can check them
    from the varialbe 'property' contained in it, i.e:
    if(property&LIVIDO_PROPERTY_*)

    Filters can have the following properties:

    @{ */


/**
   If this property is set, means that the filter can run in a (soft)
   realtime environment. The plugin must not do:
					 
   -# use malloc() free() or other memory managment functions that
   allocate/free data during processing.
   -# the plugin does not access (special) files in blocking
   operations
   -# the plugin does not do any colour space conversions but has
   internal routines for processing various colour spaces
   -# host is responsible for timing operations
*/
#define LIVIDO_PROPERTY_REALTIME (1<<0x0) 
///< realtime filter property

/**
   If this property is set, the filter can do inplace operations then
   the plugin process() function will return NULL in *output and all
   the result will be in input (saves a memcpy on certain filters)
*/
#define LIVIDO_PROPERTY_INPLACE (1<<0x1)
///< inplace filter property

/**
   If this property is set, the filter is a transition between two
   video sources, like wipes that are applied for a certain lapse
   of time usually taking 2 input and producing 1 output
*/
#define LIVIDO_PROPERTY_TRANSITION (1<<0x2)
///< transition filter property

///@}







/////////////////////////////////////////////////////////////////
/**
   @defgroup parameter Filter parameters
   
   Livido Parameters are used by the plugin to describe the the
   controls of its filter, they should be parsed by the host loading
   the plugin to understand which values should be changed by the
   (user) interface.
    
   *PLEASE NOTE* That the real values are not stored here, but in the
   filter instance.
   
   @{ */
/////////////////////////////////////////////////////////////////


enum livido_param_type_enum {
  LVD_PARAM_BOOL, ///< on/off switch
  LVD_PARAM_INT, ///< integer discrete value
  LVD_PARAM_FLOAT, ///< float dense value
  LVD_PARAM_COLOR, ///< color code
  LVD_PARAM_COORD, ///< coordinate
  LVD_PARAM_STRING, ///< text string
  LVD_PARAM_DATA, ///< pointer to custom data buffer
  LVD_PARAM_END ///< end of parameter declaration
};



/**
   It holds some variables that are interesting for the
   user interface, to render triggable realtime by users.

   @brief Struct to describe the public parameters of the plugin
*/
typedef struct {
  const	char 	*name;	///< name
  const	char	*hint;	///< description
  const	int	type;	///< the parameter type (see livido_param_type_enum)
  const	void 	*min;	///< minimum value
  const	void	*max;	///< maximum value
  const void	*def;   ///< default value
  /**
     Some parameters require internal buffers to be recalculated when their
     value changes, this flag specifies that: when need_init is holding a
     positive value, the host application should call the
     livido_class_t::init function after setting a new value on this parameter. */
  const int	need_init; ///< requires the host to call the init function 
} livido_parameter_t;


#define LIVIDO_PARAM_END \
{ NULL, NULL, LVD_PARAM_END, NULL, NULL, NULL }
///< small define to mark the end of parameters when declared

///@}


/**
   @defgroup class Filter class

   The class is the filter abstraction returned by the livido_setup()
   function, which is a symbol always found in every livido plugin.

   The setup function must be called only once, the first time the
   filter is loaded, and returns a structure holding pointers to
   all functions needed to operate a filter.

   Most notably the class will contain the name of the filter,
   its property flags, palettes supported and preferred and the
   init() deinit() and process() functions, while it will also
   hold the width and height geometry for the instance when is
   created by init().

   After calling the livido_setup(), an host application must call
   init() to obtain an instance of the class.
    
   @{ */

typedef struct {

 char *name; ///< name of filter
 char *author; ///< author of filter
 char *desc; ///< long text description
 int version; ///< filter version

 int livido_api_version; ///< version of the livido api used

 livido_palette_t		preferred_palette;
 ///< filter preferred palette 
 livido_palette_t		supported_palettes;
 ///< filter supported palettes
 
 int				property;
 ///< filter properties

 int input_frames_min;
 ///< minimum input frames the filter can process
  
 int input_frames_max;
 ///< maximum input frames the filter can process
  
 int output_frames_min;
 ///< minimum output frames the filter will process

 int output_frames_max;
 ///< maximum output frames the filter will process
	
 livido_parameter_t		*parameters;
 ///< array of parameter descriptions
 
 /* function pointers follow */
 livido_init_f 			*init;
 ///< init function creates a filter instance
 livido_deinit_f		*deinit; 
 ///< deinit function destroys a filter instance
 livido_process_f 		*process;
 ///< process function munches input videos in output

} livido_class_t;
#define LIVIDO_CLASS_END \
{ NULL,NULL,NULL, \
 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, \
   NULL,NULL,NULL,NULL }

/**
   the Setup is called by the host only the first time a plugin file is loaded,
   it doesn't needs to be called at every filter instance being created
   (that is the livido_init)

   It returns a null terminated array of filter classes made available
   by the plugin.

   @brief Setup the global environment of the plugin.
   @return NULL terminated array of filter classes available */
typedef livido_class_t *(livido_setup_f) (void);



/// @}


/**
   This define is a handy way to create new filter instances from a
   filter class, it might be used by the host application once a 
   plugin class is created.
   
   It executes the following operations:

   - allocate the instance buffer
   - allocate the buffers needed for the filter parameters
   - set the filter parameters to the default values
   - set the input and output frames to minimum values
   - set width and height to 0
   - set the palette to the preferred one
   - set the internal filter instance buffer to NULL

   the above operations are necessary to create a breand new filter
   instance before setting it up and passing it to the init()

   @brief create a new clean filter instance from a filter class
   @param filter class
   @param inst pointer where to store the new filter instance */
#define LIVIDO_CREATE_INSTANCE(cl,inst) \
{ int c; size_t b; \
inst = malloc(sizeof(livido_instance_t)); \
for(c=0;cl->parameters[c].type!=LVD_PARAM_END;c++); \
inst->parameter = malloc(sizeof(void*) *c); c--; \
for(; c>0; c--) { switch(cl->parameters[c].type) { \
	case LVD_PARAM_BOOL: b=sizeof(int); break; \
	case LVD_PARAM_INT: b=sizeof(int); break; \
	case LVD_PARAM_FLOAT: b=sizeof(float); break; \
	case LVD_PARAM_COLOR: b=sizeof(unsigned int)*3; break; \
	case LVD_PARAM_COORD: b=sizeof(int)*2; break; \
	case LVD_PARAM_STRING: b=sizeof(char)*256; break; \
	case LVD_PARAM_DATA: b=sizeof(void*); break; \
	} \
  inst->parameter[c] = malloc(b); \
  memcpy(inst->parameter[c] , cl->parameters[c].def , b); } \
inst->input_frames = cl->input_frames_min; \
inst->output_frames = cl->output_frames_min; \
inst->width = inst->height = 0; \
inst->palette = cl->preferred_palette; \
inst->internal = NULL; }

#define LIVIDO_FREE_INSTANCE(cl,inst) \
{ int c; \
for(c=0;cl->parameters[c].type!=LVD_PARAM_END;c++) \
	free( inst->parameter[c] ); }

#endif
