2 * filter_obscure.c -- obscure filter
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "filter_obscure.h"
23 #include <framework/mlt_frame.h>
24 #include <framework/mlt_deque.h>
42 /** Parse a geometry property string.
45 static void geometry_parse( struct geometry_s
*geometry
, struct geometry_s
*defaults
, char *property
)
47 // Assign from defaults if available
48 if ( defaults
!= NULL
)
50 geometry
->x
= defaults
->x
;
51 geometry
->y
= defaults
->y
;
52 geometry
->w
= defaults
->w
;
53 geometry
->h
= defaults
->h
;
54 geometry
->mask_w
= defaults
->mask_w
;
55 geometry
->mask_h
= defaults
->mask_h
;
59 geometry
->mask_w
= 20;
60 geometry
->mask_h
= 20;
63 // Parse the geomtry string
64 if ( property
!= NULL
)
65 sscanf( property
, "%f,%f:%fx%f:%dx%d", &geometry
->x
, &geometry
->y
, &geometry
->w
, &geometry
->h
, &geometry
->mask_w
, &geometry
->mask_h
);
68 /** A Timism but not as clean ;-).
71 static float lerp( float value
, float lower
, float upper
)
75 else if ( value
> upper
)
80 /** Calculate real geometry.
83 static void geometry_calculate( struct geometry_s
*output
, struct geometry_s
*in
, struct geometry_s
*out
, float position
)
85 // Calculate this frames geometry
86 output
->x
= lerp( in
->x
+ ( out
->x
- in
->x
) * position
, 0, 100 );
87 output
->y
= lerp( in
->y
+ ( out
->y
- in
->y
) * position
, 0, 100 );
88 output
->w
= lerp( in
->w
+ ( out
->w
- in
->w
) * position
, 0, 100 - output
->x
);
89 output
->h
= lerp( in
->h
+ ( out
->h
- in
->h
) * position
, 0, 100 - output
->y
);
90 output
->mask_w
= in
->mask_w
+ ( out
->mask_w
- in
->mask_w
) * position
;
91 output
->mask_h
= in
->mask_h
+ ( out
->mask_h
- in
->mask_h
) * position
;
94 /** Calculate the position for this frame.
97 static float position_calculate( mlt_filter
this, mlt_frame frame
)
99 // Get the in and out position
100 mlt_position in
= mlt_filter_get_in( this );
101 mlt_position out
= mlt_filter_get_out( this );
103 // Get the position of the frame
104 mlt_position position
= mlt_frame_get_position( frame
);
107 return ( float )( position
- in
) / ( float )( out
- in
+ 1 );
110 /** The averaging function...
113 void obscure_average( uint8_t *start
, int width
, int height
, int stride
)
117 int Y
= ( *start
+ *( start
+ 2 ) ) / 2;
118 int U
= *( start
+ 1 );
119 int V
= *( start
+ 3 );
121 for ( y
= 0; y
< height
; y
++ )
123 uint8_t *p
= start
+ y
* stride
;
124 for ( x
= 0; x
< width
/ 2; x
++ )
126 Y
= ( Y
+ *p
++ ) / 2;
127 U
= ( U
+ *p
++ ) / 2;
128 Y
= ( Y
+ *p
++ ) / 2;
129 V
= ( V
+ *p
++ ) / 2;
133 for ( y
= 0; y
< height
; y
++ )
135 uint8_t *p
= start
+ y
* stride
;
136 for ( x
= 0; x
< width
/ 2; x
++ )
147 /** The obscurer rendering function...
150 static void obscure_render( uint8_t *image
, int width
, int height
, struct geometry_s result
)
152 int area_x
= ( result
.x
/ 100 ) * width
;
153 int area_y
= ( result
.y
/ 100 ) * height
;
154 int area_w
= ( result
.w
/ 100 ) * width
;
155 int area_h
= ( result
.h
/ 100 ) * height
;
157 int mw
= result
.mask_w
;
158 int mh
= result
.mask_h
;
162 uint8_t *p
= image
+ area_y
* width
* 2 + area_x
* 2;
164 for ( w
= 0; w
< area_w
; w
+= mw
)
166 for ( h
= 0; h
< area_h
; h
+= mh
)
168 int aw
= w
+ mw
> area_w ? mw
- ( w
+ mw
- area_w
) : mw
;
169 int ah
= h
+ mh
> area_h ? mh
- ( h
+ mh
- area_h
) : mh
;
170 if ( aw
> 1 && ah
> 1 );
171 obscure_average( p
+ h
* width
* 2 + w
* 2, aw
, ah
, width
* 2 );
179 static int filter_get_image( mlt_frame frame
, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
181 // Get the frame properties
182 mlt_properties frame_properties
= mlt_frame_properties( frame
);
184 // Fetch the obscure stack for this frame
185 mlt_deque deque
= mlt_properties_get_data( frame_properties
, "filter_obscure", NULL
);
187 // Pop the top of stack now
188 mlt_filter
this = mlt_deque_pop_back( deque
);
190 // Get the image from the frame
191 if ( mlt_frame_get_image( frame
, image
, format
, width
, height
, 1 ) == 0 )
195 // Get the filter properties
196 mlt_properties properties
= mlt_filter_properties( this );
198 // Structures for geometry
199 struct geometry_s result
;
200 struct geometry_s start
;
201 struct geometry_s end
;
203 // Calculate the position
204 float position
= position_calculate( this, frame
);
206 // Now parse the geometries
207 geometry_parse( &start
, NULL
, mlt_properties_get( properties
, "start" ) );
208 geometry_parse( &end
, &start
, mlt_properties_get( properties
, "end" ) );
210 // Do the calculation
211 geometry_calculate( &result
, &start
, &end
, position
);
213 // Now actually render it
214 obscure_render( *image
, *width
, *height
, result
);
221 /** Filter processing.
224 static mlt_frame
filter_process( mlt_filter
this, mlt_frame frame
)
226 // Get the frame properties
227 mlt_properties frame_properties
= mlt_frame_properties( frame
);
229 // Fetch the obscure stack for this frame
230 mlt_deque deque
= mlt_properties_get_data( frame_properties
, "filter_obscure", NULL
);
232 // Create stack if necessary
236 deque
= mlt_deque_init( );
238 // Assign to the frame
239 mlt_properties_set_data( frame_properties
, "filter_obscure", deque
, 0, ( mlt_destructor
)mlt_deque_close
, NULL
);
242 // Push this on to the obscure stack
243 mlt_deque_push_back( deque
, this );
245 // Push the get image call
246 mlt_frame_push_get_image( frame
, filter_get_image
);
251 /** Constructor for the filter.
254 mlt_filter
filter_obscure_init( void *arg
)
256 mlt_filter
this = calloc( 1, sizeof( struct mlt_filter_s
) );
257 mlt_properties properties
= mlt_filter_properties( this );
258 mlt_filter_init( this, NULL
);
259 this->process
= filter_process
;
260 mlt_properties_set( properties
, "start", "40,40:20x20" );
261 mlt_properties_set( properties
, "end", "" );