User Tools

Site Tools


tutorial:writing_your_own_filter

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

tutorial:writing_your_own_filter [2010/04/14 00:29]
j.m Period.
tutorial:writing_your_own_filter [2012/11/11 08:51]
Line 1: Line 1:
-====== Writing your own filter ====== 
  
-This page tries to explain how to write your own filter. 
- 
-===== Setup & tools ===== 
- 
-First of all you need Avidemux sources (if you do plugins you don't even have to compile Avidemux itself but you still need the sources). 
- 
-For windows, you need MinGW GCC/g++ (v4.x) or cygwin GCC/g++ (v4.x). 
-MSVC will not work as there will be some C++ links and MSVC C++ is incompatible with g++. 
- 
- 
-===== Everything is a class ===== 
- 
-All filters inside Avidemux are derivative of AVDMGenericVideoStream class. 
-Only a few methods need to be defined: 
- 
-===== The constructor ===== 
- 
-It takes 2 arguments: 
-  - The previous filter in the chain, it will be copied into _in 
-  - CONFcouple * couples which contains the configuration. It it is null it means you have to use your default value. 
- 
-The constructor has to update its _info field which contains a description of the output format. 
-If you dont change fps nor width/​height you can just copy the one from the previous filter using _in<​nowiki>​-></​nowiki>​getInfo(). 
- 
-You should have a field of your class named _param which is a structure describing your parameters. 
-For example: 
- 
-<code cpp> 
-typedef struct rotateParam 
- { 
-   ​uint32_t angle; 
- ​}rotateParam;​ 
-</​code>​ 
- 
-In the constructor you can use the handy *GET* macro to retrive the parameter from CONFcouple 
-e.g. GET(angle); 
- 
-===== printConf ===== 
- 
-The next method is printConf. It is used to print the configuration in the filter dialog box. 
- 
-<code cpp> 
-char *yourClassName::​printConf (void) 
-{ 
-  static char buf[[50]]; 
-  sprintf ((char *) buf, " My rotate filter, angle :​%d",​_param->​angle);​ 
-  return buf; 
-} 
-</​code>​ 
- 
-Note that the buffer is static to avoid allocating/​freeing it as it can be complicated. 
- 
-===== GetCouple ===== 
- 
-This method is used to retrieve the current configuration. The simplest way is to use the CSET macro like this: 
- 
-<code cpp> 
-uint8_t yourClassName::​getCoupledConf (CONFcouple ** couples) 
-{ 
-  ADM_assert (_param); 
-  *couples = new CONFcouple (1); // Number of param in your structure 
-  #undef CSET 
-  #define CSET(x) ​ (*couples)->​setCouple(#​x,​(_param->​x)) 
-  CSET (angle); 
-  return 1; 
-} 
-</​code>​ 
- 
-getCoupledConf and the constructor are a pair. It is vital they use the same number of parameters and the same parameter names. Else you will have asserts popping. 
- 
-===== Configure ===== 
- 
-<code cpp>​uint8_t yourClassName::​configure (AVDMGenericVideoStream * in)</​code>​ 
- 
-This method is used to configure the filter. The parameter is the same as for the constructor. It is safer to update _in with it though. 
-It is recommended (strongly) to use dialogFactory as it will work on both GTK+ and Windows (Qt) and is quite simple to use. 
- 
-Some info: 
-  * Returning 0 means nothing has changed. 
-  * Returning 1 means you have changes something and that the filter chain might have to be rebuild. 
- 
-**Important**:​ The change must be done immediately in configure! 
- 
-===== getFrameNoAlloc ===== 
- 
-This is the central method as the work will be done here. 
- 
-<code cpp> 
-uint8_t yourClassName::​getFrameNumberNoAlloc (uint32_t inframe, 
-                              uint32_t * len, 
-                              ADMImage * data, uint32_t * flags) 
-</​code>​ 
- 
-**len** is the size in bytes of the output image. 
-**flags** can be ignored. 
-**inframe** is the frame you have to render. 
-**data** is the place when you have to render the frame. 
- 
-Remember that the filters are a chain, so each filter may ask for (any) frame to its predecessor. In most cases you will want to allocate a temporary buffer in the constructor (which is often called _uncompressed) and ask the previous filter to fill it for you. For example, the verticalFlip can be simplified like that: 
- 
-<code cpp> 
-uint8_t yourClassName::​getFrameNumberNoAlloc (uint32_t inframe, 
-                              uint32_t * len, 
-                              ADMImage * data, uint32_t * flags) 
-{ 
-  ADM_assert(inframe<​_info.nb_frames);​ // Make sure we don't go out of bounds 
-  // Read frames for the previous 
-  ADM_assert(_in->​getFrameNumberNoAlloc(inframe,​len,​_uncompressed,​flags));​ // Now _uncompressed contains the frame 
-  // Flip from _uncompressed to data, which holds the final image 
-  Return 1; // ok 
-} 
-</​code>​ 
- 
-Some notes: 
-  * All images are in YV12 format. 
-  * If you need several images to render one image out (3:2 pulldown, noise removal,​...),​ you should instantiate a VideoCache object. 
- 
-===== Declaring your filter ===== 
- 
-There are 2 ways of declaring your filter: bundled or plugin. You can do both at the same time, in the same file. 
- 
-==== Bundled filter ==== 
- 
-Is is a bit more complicated. You have to: 
-  * Declare a tag for your filter in ADM_filter/​video_filters.h 
-  * Register your filter in ADM_filter/​filter_declaration.cpp using  
- 
-<code cpp> 
-REGISTERX("​rotate","​Rotate","​Rotate the picture by 90, 180 or 270 degrees.",​VF_ROTATE,​1,​rotate_create,​rotate_script);​ 
-</​code>​ 
- 
-The first parameter is the internal name (must be unique). 
-The second and 3rd parameters are the one used for display a,d brief. 
-The fourth one is the tag you declared above. **DON'​T REUSE AN EXISTING TAG**. You would have big problems, believe me. 
-The 2 last ones must be the same as the function described below 
- 
-Let's go back to our filter C++ file. 
-First you need to declare a const which looks like 
- 
-<code cpp>​static FILTER_PARAM yourfilter_param =  { 1,"​angle"​};</​code>​ 
- 
-The first parameter is the number of parameters in your param structure followed by the parameters name, EXACTLY like in your structure. Then use these two macros: 
- 
-<code cpp> 
-BUILD_CREATE (rotate_create,​ yourClassName);​ 
-SCRIPT_CREATE (rotate_script,​ yourClassName,​ yourfilter_param);​ 
-</​code>​ 
- 
-Make sure the first parameter of these two macros match the one you used in REGISTERX. 
- 
-That's all :-). 
- 
-==== Plugin ==== 
- 
-It is simpler. 
-You still have to declare the const which looks like 
- 
-<code cpp>​static FILTER_PARAM yourfilter_param =  { 1,"​angle"​};</​code>​ 
- 
-Then 
- 
-<code cpp> 
-extern "​C"​ 
-{ 
-  SCRIPT_CREATE(FILTER_create_fromscript,​yourClassName,​yourfilter_param);​ 
-  BUILD_CREATE(FILTER_create,​yourClassName);​ 
-  char *FILTER_getName(void) 
-  { 
-    return "​DynRotate"; ​ // Name of your filter. must be unique! 
-  } 
-  char *FILTER_getDesc(void) 
-  { 
-    return "Blah blah"; // Short description of your filter 
-  } 
-  uint32_t FILTER_getVersion(void) 
-  { 
-    return 1;  // Version of your filter 
-  } 
-  uint32_t FILTER_getAPIVersion(void) 
-  { 
-    return ADM_FILTER_API_VERSION; ​ 
-  } 
-} 
-</​code>​ 
- 
-It is self contained, you don't have to change any file in ADM_filter/​xxx if it just a plugin. 
-You can do both declaration in the same file, so that it can be bundled inside Avidemux or compiled as a plugin filter. 
- 
-===== Final words ===== 
- 
-The simplest it to start from the ADM_filter/​ADM_vidDummyFilter.cpp which is a very simple filter you can build using 
- 
-//​sh(nbsp)builddummy.sh//​ on Unix 
- 
-or  
- 
-//​sh(nbsp)builddummy_win32.sh//​ on Windows (you may have to change the path/names for your gcc). 
- 
-The main differences with Avisynth are: 
-  * Image format is always YV12. 
-  * stride=width 
-  * You don't return the frame, it is given to you by the caller as argument. 
tutorial/writing_your_own_filter.txt ยท Last modified: 2012/11/11 08:51 (external edit)