2 * filter_obscure.c -- obscure filter
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
42 /** Parse a value from a geometry string.
45 static inline float parse_value( char **ptr
, int normalisation
, char delim
, float defaults
)
47 float value
= defaults
;
49 if ( *ptr
!= NULL
&& **ptr
!= '\0' )
52 value
= strtod( *ptr
, &end
);
56 value
= ( value
/ 100.0 ) * normalisation
;
57 while ( *end
== delim
|| *end
== '%' )
66 /** Parse a geometry property string.
69 static void geometry_parse( struct geometry_s
*geometry
, struct geometry_s
*defaults
, char *property
, int nw
, int nh
)
71 // Assign normalised width and height
75 // Assign from defaults if available
76 if ( defaults
!= NULL
)
78 geometry
->x
= defaults
->x
;
79 geometry
->y
= defaults
->y
;
80 geometry
->w
= defaults
->w
;
81 geometry
->h
= defaults
->h
;
82 geometry
->mask_w
= defaults
->mask_w
;
83 geometry
->mask_h
= defaults
->mask_h
;
91 geometry
->mask_w
= 20;
92 geometry
->mask_h
= 20;
95 // Parse the geomtry string
96 if ( property
!= NULL
)
99 geometry
->x
= parse_value( &ptr
, nw
, ',', geometry
->x
);
100 geometry
->y
= parse_value( &ptr
, nh
, ':', geometry
->y
);
101 geometry
->w
= parse_value( &ptr
, nw
, 'x', geometry
->w
);
102 geometry
->h
= parse_value( &ptr
, nh
, ':', geometry
->h
);
103 geometry
->mask_w
= parse_value( &ptr
, nw
, 'x', geometry
->mask_w
);
104 geometry
->mask_h
= parse_value( &ptr
, nh
, ' ', geometry
->mask_h
);
108 /** A Timism but not as clean ;-).
111 static float lerp( float value
, float lower
, float upper
)
115 else if ( value
> upper
)
120 /** Calculate real geometry.
123 static void geometry_calculate( struct geometry_s
*output
, struct geometry_s
*in
, struct geometry_s
*out
, float position
, int ow
, int oh
)
125 // Calculate this frames geometry
126 output
->x
= lerp( ( in
->x
+ ( out
->x
- in
->x
) * position
) / ( float )out
->nw
* ow
, 0, ow
);
127 output
->y
= lerp( ( in
->y
+ ( out
->y
- in
->y
) * position
) / ( float )out
->nh
* oh
, 0, oh
);
128 output
->w
= lerp( ( in
->w
+ ( out
->w
- in
->w
) * position
) / ( float )out
->nw
* ow
, 0, ow
- output
->x
);
129 output
->h
= lerp( ( in
->h
+ ( out
->h
- in
->h
) * position
) / ( float )out
->nh
* oh
, 0, oh
- output
->y
);
130 output
->mask_w
= in
->mask_w
+ ( out
->mask_w
- in
->mask_w
) * position
;
131 output
->mask_h
= in
->mask_h
+ ( out
->mask_h
- in
->mask_h
) * position
;
134 /** Calculate the position for this frame.
137 static float position_calculate( mlt_filter
this, mlt_frame frame
)
139 // Get the in and out position
140 mlt_position in
= mlt_filter_get_in( this );
141 mlt_position out
= mlt_filter_get_out( this );
143 // Get the position of the frame
144 mlt_position position
= mlt_frame_get_position( frame
);
147 return ( float )( position
- in
) / ( float )( out
- in
+ 1 );
150 /** The averaging function...
153 static inline void obscure_average( uint8_t *start
, int width
, int height
, int stride
)
157 register int Y
= ( *start
+ *( start
+ 2 ) ) / 2;
158 register int U
= *( start
+ 1 );
159 register int V
= *( start
+ 3 );
161 register int components
= width
>> 1;
170 Y
= ( Y
+ *p
++ ) >> 1;
171 U
= ( U
+ *p
++ ) >> 1;
172 Y
= ( Y
+ *p
++ ) >> 1;
173 V
= ( V
+ *p
++ ) >> 1;
178 start
-= height
* stride
;
196 /** The obscurer rendering function...
199 static void obscure_render( uint8_t *image
, int width
, int height
, struct geometry_s result
)
201 int area_x
= result
.x
;
202 int area_y
= result
.y
;
203 int area_w
= result
.w
;
204 int area_h
= result
.h
;
206 int mw
= result
.mask_w
;
207 int mh
= result
.mask_h
;
213 uint8_t *p
= image
+ area_y
* width
* 2 + area_x
* 2;
215 for ( w
= 0; w
< area_w
; w
+= mw
)
217 for ( h
= 0; h
< area_h
; h
+= mh
)
219 aw
= w
+ mw
> area_w ? mw
- ( w
+ mw
- area_w
) : mw
;
220 ah
= h
+ mh
> area_h ? mh
- ( h
+ mh
- area_h
) : mh
;
221 if ( aw
> 1 && ah
> 1 )
222 obscure_average( p
+ h
* ( width
<< 1 ) + ( w
<< 1 ), aw
, ah
, width
<< 1 );
230 static int filter_get_image( mlt_frame frame
, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
232 // Get the frame properties
233 mlt_properties frame_properties
= MLT_FRAME_PROPERTIES( frame
);
235 // Pop the top of stack now
236 mlt_filter
this = mlt_frame_pop_service( frame
);
238 // Get the image from the frame
239 int error
= mlt_frame_get_image( frame
, image
, format
, width
, height
, 1 );
241 // Get the image from the frame
242 if ( error
== 0 && *format
== mlt_image_yuv422
)
246 // Get the filter properties
247 mlt_properties properties
= MLT_FILTER_PROPERTIES( this );
249 // Obtain the normalised width and height from the frame
250 int normalised_width
= mlt_properties_get_int( frame_properties
, "normalised_width" );
251 int normalised_height
= mlt_properties_get_int( frame_properties
, "normalised_height" );
253 // Structures for geometry
254 struct geometry_s result
;
255 struct geometry_s start
;
256 struct geometry_s end
;
258 // Retrieve the position
259 float position
= mlt_properties_get_double(frame_properties
, "filter_position");
261 // Now parse the geometries
262 geometry_parse( &start
, NULL
, mlt_properties_get( properties
, "start" ), normalised_width
, normalised_height
);
263 geometry_parse( &end
, &start
, mlt_properties_get( properties
, "end" ), normalised_width
, normalised_height
);
265 // Do the calculation
266 geometry_calculate( &result
, &start
, &end
, position
, *width
, *height
);
268 // Now actually render it
269 obscure_render( *image
, *width
, *height
, result
);
276 /** Filter processing.
279 static mlt_frame
filter_process( mlt_filter
this, mlt_frame frame
)
281 // Push this on to the service stack
282 mlt_frame_push_service( frame
, this );
284 // Calculate the position for the filter effect
285 float position
= position_calculate( this, frame
);
286 mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame
), "filter_position", position
);
288 // Push the get image call
289 mlt_frame_push_get_image( frame
, filter_get_image
);
294 /** Constructor for the filter.
297 mlt_filter
filter_obscure_init( mlt_profile profile
, mlt_service_type type
, const char *id
, char *arg
)
299 mlt_filter
this = mlt_filter_new( );
302 mlt_properties properties
= MLT_FILTER_PROPERTIES( this );
303 this->process
= filter_process
;
304 mlt_properties_set( properties
, "start", arg
!= NULL ? arg
: "0%,0%:100%x100%" );
305 mlt_properties_set( properties
, "end", "" );