<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix"><br>
<small>Hi,<br>
<br>
</small><small>Please find below and in 2 additional patches the
modified freeze video filter<br>
Unfortunately I was not able to keep the file wrapped to 79
columns when including your comments.<br>
<br>
Of course I'll do the same for the other proposed filters.<br>
<br>
Best regards<br>
<br>
Vianney<br>
<br>
<br>
<br>
---<br>
modules/video_filter/freeze.c | 430
++++++++++++++++++++++++++++++++++++++++++<br>
1 file changed, 430 insertions(+)<br>
create mode 100644 modules/video_filter/freeze.c<br>
<br>
diff --git a/modules/video_filter/freeze.c
b/modules/video_filter/freeze.c<br>
new file mode 100644<br>
index 0000000..75c134a<br>
--- /dev/null<br>
+++ b/modules/video_filter/freeze.c<br>
@@ -0,0 +1,430 @@<br>
+/*****************************************************************************<br>
+ * freeze.c : Freezing video filter<br>
+
*****************************************************************************<br>
+ * Copyright (C) 2013 Vianney Boyer<br>
+ * $Id$<br>
+ *<br>
+ * Authors: Vianney Boyer <vlcvboyer -at- gmail -dot-
com><br>
+ *<br>
+ * This program is free software; you can redistribute it
and/or modify it<br>
+ * under the terms of the GNU Lesser General Public License as
published by<br>
+ * the Free Software Foundation; either version 2.1 of the
License, or<br>
+ * (at your option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be
useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty
of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU Lesser General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU Lesser General
Public License<br>
+ * along with this program; if not, write to the Free Software
Foundation,<br>
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301,
USA.<br>
+
*****************************************************************************/<br>
+<br>
+/*****************************************************************************<br>
+ * Preamble<br>
+
*****************************************************************************/<br>
+<br>
+#ifdef HAVE_CONFIG_H<br>
+# include "config.h"<br>
+#endif<br>
+<br>
+#include <vlc_common.h><br>
+#include <vlc_plugin.h><br>
+#include <vlc_filter.h><br>
+<br>
+#include "filter_picture.h"<br>
+<br>
+#ifndef MOD<br>
+# define MOD(a, b) ((((a)%(b)) + (b))%(b))<br>
+#endif<br>
+<br>
+struct filter_sys_t {<br>
+ bool b_init;<br>
+<br>
+ int32_t i_planes;<br>
+ int32_t *i_height;<br>
+ int32_t *i_width;<br>
+ int32_t *i_visible_pitch;<br>
+ int8_t ***pi_freezed_picture; /* records freezed pixels
*/<br>
+ int16_t **pi_freezing_countdown; /* freezed pixel delay
*/<br>
+ bool **pb_update_cache; /* update chache request
*/<br>
+ vlc_mutex_t lock;<br>
+<br>
+};<br>
+<br>
+/*****************************************************************************<br>
+ * Prototypes<br>
+
*****************************************************************************/<br>
+<br>
+picture_t *Filter( filter_t *, picture_t * );<br>
+<br>
+int freeze_mouse( filter_t *, vlc_mouse_t *,<br>
+ const vlc_mouse_t *, const vlc_mouse_t * );<br>
+int freeze_allocate_data( filter_t *, picture_t * );<br>
+void freeze_free_allocated_data( filter_t * );<br>
+<br>
+<br>
+/*****************************************************************************<br>
+ * Module descriptor<br>
+
*****************************************************************************/<br>
+<br>
+#define CFG_PREFIX "freeze-"<br>
+<br>
+int Open ( vlc_object_t * );<br>
+void Close( vlc_object_t * );<br>
+<br>
+vlc_module_begin()<br>
+ set_description( N_("Freezing interactive video filter") )<br>
+ set_shortname( N_("Freeze" ) )<br>
+ set_capability( "video filter2", 0 )<br>
+ set_category( CAT_VIDEO )<br>
+ set_subcategory( SUBCAT_VIDEO_VFILTER )<br>
+<br>
+ set_callbacks( Open, Close )<br>
+vlc_module_end()<br>
+<br>
+/*****************************************************************************<br>
+ * Local prototypes<br>
+
*****************************************************************************/<br>
+<br>
+/**<br>
+ * Open the filter<br>
+ */<br>
+int Open( vlc_object_t *p_this )<br>
+{<br>
+ filter_t *p_filter = (filter_t *)p_this;<br>
+ filter_sys_t *p_sys;<br>
+<br>
+ /* Assert video in match with video out */<br>
+ if( !es_format_IsSimilar( &p_filter->fmt_in,
&p_filter->fmt_out ) ) {<br>
+ msg_Err( p_filter, "Input and output format does not
match" );<br>
+ return VLC_EGENERIC;<br>
+ }<br>
+<br>
+ /* Reject 0 bpp and unsupported chroma */<br>
+ const vlc_fourcc_t fourcc =
p_filter->fmt_in.video.i_chroma;<br>
+ const vlc_chroma_description_t *p_chroma<br>
+ = vlc_fourcc_GetChromaDescription(
p_filter->fmt_in.video.i_chroma );<br>
+ if( !p_chroma || p_chroma->pixel_size == 0<br>
+ || p_chroma->plane_count < 3 ||
p_chroma->pixel_size > 1<br>
+ || !vlc_fourcc_IsYUV( fourcc ) )<br>
+ {<br>
+ msg_Err( p_filter, "Unsupported chroma (%4.4s)",
(char*)&fourcc );<br>
+ return VLC_EGENERIC;<br>
+ }<br>
+<br>
+ /* Allocate structure */<br>
+ p_filter->p_sys = p_sys = calloc(1, sizeof( *p_sys ) );<br>
+ if( unlikely(!p_sys) )<br>
+ return VLC_ENOMEM;<br>
+<br>
+ /* init data */<br>
+<br>
+ vlc_mutex_init( &p_sys->lock );<br>
+<br>
+ p_filter->pf_video_filter = Filter;<br>
+ p_filter->pf_video_mouse = freeze_mouse;<br>
+<br>
+ return VLC_SUCCESS;<br>
+}<br>
+<br>
+/**<br>
+ * Close the filter<br>
+ */<br>
+void Close( vlc_object_t *p_this ) {<br>
+ filter_t *p_filter = (filter_t *)p_this;<br>
+ filter_sys_t *p_sys = p_filter->p_sys;<br>
+<br>
+ vlc_mutex_destroy( &p_sys->lock );<br>
+<br>
+ /* Free allocated memory */<br>
+ freeze_free_allocated_data( p_filter );<br>
+ free( p_sys );<br>
+}<br>
+<br>
+/**<br>
+ * Filter a picture<br>
+ */<br>
+picture_t *Filter( filter_t *p_filter, picture_t *p_pic_in ) {<br>
+ if( !p_pic_in || !p_filter) return NULL;<br>
+<br>
+ filter_sys_t *p_sys = p_filter->p_sys;<br>
+<br>
+ picture_t *p_pic_out = filter_NewPicture( p_filter );<br>
+ if( unlikely(!p_pic_out) ) {<br>
+ picture_Release( p_pic_in );<br>
+ return NULL;<br>
+ }<br>
+<br>
+ /*<br>
+ * allocate data<br>
+ */<br>
+ if ( unlikely(!p_sys->b_init) )<br>
+ if (freeze_allocate_data( p_filter, p_pic_in ) !=
VLC_SUCCESS)<br>
+ {<br>
+ picture_Release( p_pic_in );<br>
+ return NULL;<br>
+ }<br>
+ p_sys->b_init = true;<br>
+<br>
+ /*<br>
+ * preset output pic: raw copy src to dst<br>
+ */<br>
+ picture_CopyPixels(p_pic_out, p_pic_in);<br>
+<br>
+ /*<br>
+ * lock shared data mutex<br>
+ */<br>
+ vlc_mutex_lock( &p_sys->lock );<br>
+<br>
+ /*<br>
+ * cache original pict pixels selected with mouse pointer<br>
+ */<br>
+ for ( int32_t i_p = 0; i_p < p_sys->i_planes; i_p++ )<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[i_p]; i_r++ )<br>
+ for ( int32_t i_c = 0; i_c <
p_sys->i_width[i_p]; i_c++ )<br>
+ {<br>
+ uint32_t i_Yr = i_r *
p_sys->i_height[Y_PLANE]<br>
+ / p_sys->i_height[i_p];<br>
+ uint32_t i_Yc = i_c *
p_sys->i_width[Y_PLANE]<br>
+ / p_sys->i_width[i_p];<br>
+<br>
+ if ( p_sys->pb_update_cache[i_Yr][i_Yc] )<br>
+ p_sys->pi_freezed_picture[i_p][i_r][i_c]<br>
+ =
p_pic_in->p[i_p].p_pixels[i_r*p_pic_out->p[i_p].i_pitch<br>
+ +
i_c*p_pic_out->p[i_p].i_pixel_pitch];<br>
+ }<br>
+<br>
+ /*<br>
+ * countdown freezed pixel delay & reset pb_update_cache
flag<br>
+ */<br>
+ for ( int32_t i_Yr = 0; i_Yr <
p_sys->i_height[Y_PLANE]; i_Yr++)<br>
+ for ( int32_t i_Yc = 0; i_Yc <
p_sys->i_width[Y_PLANE]; i_Yc++)<br>
+ {<br>
+ if ( p_sys->pi_freezing_countdown[i_Yr][i_Yc]
> 0 )<br>
+ p_sys->pi_freezing_countdown[i_Yr][i_Yc]--;<br>
+ p_sys->pb_update_cache[i_Yr][i_Yc] = false;<br>
+ }<br>
+<br>
+ /*<br>
+ * apply filter: draw freezed pixels over current picture<br>
+ */<br>
+ for ( int32_t i_p = 0; i_p < p_sys->i_planes; i_p++ )<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[i_p]; i_r++ )<br>
+ for ( int32_t i_c = 0; i_c <
p_sys->i_width[i_p]; i_c++ )<br>
+ {<br>
+ uint32_t i_Yr = i_r *
p_sys->i_height[Y_PLANE]<br>
+ / p_sys->i_height[i_p];<br>
+ uint32_t i_Yc = i_c *
p_sys->i_width[Y_PLANE]<br>
+ / p_sys->i_width[i_p];<br>
+<br>
+ if (
p_sys->pi_freezing_countdown[i_Yr][i_Yc] > 0 )<br>
+ p_pic_out->p[i_p].p_pixels[i_r *
p_pic_out->p[i_p].i_pitch<br>
+ + i_c *
p_pic_out->p[i_p].i_pixel_pitch]<br>
+ =
p_sys->pi_freezed_picture[i_p][i_r][i_c];<br>
+ }<br>
+<br>
+ /*<br>
+ * release shared data mutex<br>
+ */<br>
+ vlc_mutex_unlock( &p_sys->lock );<br>
+<br>
+ return CopyInfoAndRelease( p_pic_out, p_pic_in );<br>
+}<br>
+<br>
+/*<br>
+ * mouse callback<br>
+ **/<br>
+int freeze_mouse( filter_t *p_filter, vlc_mouse_t *p_mouse,<br>
+ const vlc_mouse_t *p_old, const vlc_mouse_t
*p_new )<br>
+{<br>
+ filter_sys_t *p_sys = p_filter->p_sys;<br>
+ const video_format_t *p_fmt_in =
&p_filter->fmt_in.video;<br>
+<br>
+ /* Only take events inside the video area */<br>
+ if( p_new->i_x < 0 || p_new->i_x >=
(int)p_fmt_in->i_width ||<br>
+ p_new->i_y < 0 || p_new->i_y >=
(int)p_fmt_in->i_height )<br>
+ return VLC_EGENERIC;<br>
+<br>
+ if ( unlikely(!p_sys->b_init) )<br>
+ {<br>
+ *p_mouse = *p_new;<br>
+ return VLC_SUCCESS;<br>
+ }<br>
+<br>
+ int32_t i_base_timeout = 0;<br>
+ if( vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT )
)<br>
+ i_base_timeout = 100;<br>
+ else if( vlc_mouse_IsLeftPressed( p_new ) )<br>
+ i_base_timeout = 50;<br>
+<br>
+ vlc_mutex_lock( &p_sys->lock );<br>
+<br>
+ if( i_base_timeout > 0 )<br>
+ {<br>
+ /*<br>
+ * find pixels selected by user to apply freezing
filter<br>
+ */<br>
+ int32_t i_min_sq_radius = (p_sys->i_width[Y_PLANE] /
15)<br>
+ * (p_sys->i_width[Y_PLANE] /
15);<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[Y_PLANE]; i_r++)<br>
+ for ( int32_t i_c = 0; i_c <
p_sys->i_width[Y_PLANE]; i_c++)<br>
+ {<br>
+ int32_t i_sq_dist = ( p_new->i_x - i_c )<br>
+ * ( p_new->i_x - i_c )<br>
+ + ( p_new->i_y - i_r )<br>
+ * ( p_new->i_y - i_r );<br>
+ i_sq_dist = __MAX(0, i_sq_dist -
i_min_sq_radius);<br>
+<br>
+ uint16_t i_timeout = __MAX(i_base_timeout -
i_sq_dist, 0);<br>
+<br>
+ /* ask to update chache for pixel to be freezed
just now */<br>
+ if ( p_sys->pi_freezing_countdown[i_r][i_c]
== 0 && i_timeout > 0)<br>
+ p_sys->pb_update_cache[i_r][i_c] =
true;<br>
+<br>
+ /* set freezing delay */<br>
+ if ( p_sys->pi_freezing_countdown[i_r][i_c]
< i_timeout )<br>
+ p_sys->pi_freezing_countdown[i_r][i_c]
= i_timeout;<br>
+ }<br>
+ }<br>
+<br>
+ vlc_mutex_unlock( &p_sys->lock );<br>
+<br>
+ return VLC_EGENERIC;<br>
+}<br>
+<br>
+<br>
+/*<br>
+ * Allocate data<br>
+ */<br>
+int freeze_allocate_data( filter_t *p_filter, picture_t
*p_pic_in )<br>
+{<br>
+ filter_sys_t *p_sys = p_filter->p_sys;<br>
+<br>
+ freeze_free_allocated_data( p_filter );<br>
+<br>
+ /*<br>
+ * take into account different characteristics for each
plane<br>
+ */<br>
+ p_sys->i_planes = p_pic_in->i_planes;<br>
+ p_sys->i_height = calloc( p_sys->i_planes,
sizeof(int32_t) );<br>
+ p_sys->i_width = calloc( p_sys->i_planes,
sizeof(int32_t) );<br>
+ p_sys->i_visible_pitch = calloc( p_sys->i_planes,
sizeof(int32_t) );<br>
+<br>
+ if ( unlikely( !p_sys->i_height || !p_sys->i_width ||
!p_sys->i_visible_pitch ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+<br>
+ /* init data */<br>
+ for ( int32_t i_p = 0; i_p < p_sys->i_planes; i_p++ )<br>
+ {<br>
+ p_sys->i_visible_pitch [i_p] = (int)
p_pic_in->p[i_p].i_visible_pitch;<br>
+ p_sys->i_height[i_p] = (int)
p_pic_in->p[i_p].i_visible_lines;<br>
+ p_sys->i_width[i_p] = (int)
p_pic_in->p[i_p].i_visible_pitch<br>
+ /
p_pic_in->p[i_p].i_pixel_pitch;<br>
+ }<br>
+<br>
+ /* buffer used to countdown freezing delay */<br>
+ p_sys->pi_freezing_countdown<br>
+ = calloc( p_sys->i_height[Y_PLANE], sizeof(int16_t*)
);<br>
+ if ( unlikely( !p_sys->pi_freezing_countdown ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[Y_PLANE]; i_r++ )<br>
+ {<br>
+ p_sys->pi_freezing_countdown[i_r]<br>
+ = calloc( p_sys->i_width[Y_PLANE],
sizeof(int16_t) );<br>
+ if ( unlikely( !p_sys->pi_freezing_countdown[i_r] )
)<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+ }<br>
+<br>
+ /* buffer used to cache freezed pixels colors */<br>
+ p_sys->pi_freezed_picture = calloc( p_sys->i_planes,
sizeof(int8_t**) );<br>
+ if( unlikely( !p_sys->pi_freezed_picture ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+<br>
+ for ( int32_t i_p = 0; i_p < p_sys->i_planes; i_p++)<br>
+ {<br>
+ p_sys->pi_freezed_picture[i_p]<br>
+ = calloc( p_sys->i_height[i_p], sizeof(int8_t*)
);<br>
+ if ( unlikely(!p_sys->pi_freezed_picture[i_p]) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[i_p]; i_r++ )<br>
+ {<br>
+ p_sys->pi_freezed_picture[i_p][i_r]<br>
+ = calloc( p_sys->i_width[i_p],
sizeof(int8_t) );<br>
+ if ( unlikely(
!p_sys->pi_freezed_picture[i_p][i_r] ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ /* flag used to manage freezed pixels cache update */<br>
+ p_sys->pb_update_cache<br>
+ = calloc( p_sys->i_height[Y_PLANE], sizeof(bool*) );<br>
+ if( unlikely( !p_sys->pb_update_cache ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[Y_PLANE]; i_r++ )<br>
+ {<br>
+ p_sys->pb_update_cache[i_r]<br>
+ = calloc( p_sys->i_width[Y_PLANE], sizeof(bool)
);<br>
+ if ( unlikely( !p_sys->pb_update_cache[i_r] ) )<br>
+ {<br>
+ freeze_free_allocated_data( p_filter );<br>
+ return VLC_ENOMEM;<br>
+ }<br>
+ }<br>
+<br>
+ return VLC_SUCCESS;<br>
+}<br>
+<br>
+/**<br>
+ * Free allocated data<br>
+ */<br>
+void freeze_free_allocated_data( filter_t *p_filter ) {<br>
+ filter_sys_t *p_sys = p_filter->p_sys;<br>
+<br>
+ if (p_sys->pi_freezing_countdown)<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[Y_PLANE]; i_r++ )<br>
+ free( p_sys->pi_freezing_countdown[i_r] );<br>
+ FREENULL( p_sys->pi_freezing_countdown );<br>
+<br>
+ if ( p_sys->pb_update_cache )<br>
+ for ( int32_t i_r = 0; i_r <
p_sys->i_height[Y_PLANE]; i_r++ )<br>
+ free( p_sys->pb_update_cache[i_r] );<br>
+ FREENULL( p_sys->pb_update_cache );<br>
+<br>
+ if ( p_sys->pi_freezed_picture )<br>
+ for ( int32_t i_p=0; i_p < p_sys->i_planes; i_p++
) {<br>
+ for ( int32_t i_r=0; i_r <
p_sys->i_height[i_p]; i_r++ )<br>
+ free( p_sys->pi_freezed_picture[i_p][i_r] );<br>
+ free( p_sys->pi_freezed_picture[i_p] );<br>
+ }<br>
+ FREENULL( p_sys->pi_freezed_picture );<br>
+<br>
+ p_sys->i_planes = 0;<br>
+ FREENULL( p_sys->i_height );<br>
+ FREENULL( p_sys->i_width );<br>
+ FREENULL( p_sys->i_visible_pitch );<br>
+}<br>
-- <br>
1.8.1.2<br>
<br>
<br>
</small><br>
Le 25/07/2013 13:37, Jean-Baptiste Kempf a écrit :<br>
</div>
<blockquote cite="mid:20130725113734.GA21257@videolan.org"
type="cite">
<pre wrap="">On 25 Jul, Vianney Boyer wrote :
</pre>
<blockquote type="cite">
<pre wrap=""> modules/video_filter/freeze.c | 402
++++++++++++++++++++++++++++++++++++++++++
modules/video_filter/freeze.h | 49 +++++
</pre>
</blockquote>
<pre wrap="">
Why do you need a .h here?
</pre>
<blockquote type="cite">
<pre wrap="">+ /* Allocate structure */
+ p_filter->p_sys = p_sys = calloc(1, sizeof( *p_sys ) );
+ if( !p_sys )
</pre>
</blockquote>
<pre wrap="">
unlikely()
</pre>
<blockquote type="cite">
<pre wrap="">+ for (int32_t i_p=0; i_p < p_sys->i_planes; i_p++)
</pre>
</blockquote>
<pre wrap="">
Please use spaces around = signs.
And the style does not match the previous one.
</pre>
<blockquote type="cite">
<pre wrap="">+ p_sys->i_height = calloc( p_sys->i_planes, sizeof(*p_sys->i_height) );
+ p_sys->i_width = calloc( p_sys->i_planes, sizeof(*p_sys->i_width) );
+ p_sys->i_visible_pitch
+ = calloc( p_sys->i_planes,
sizeof(*p_sys->i_visible_pitch) );
</pre>
</blockquote>
<pre wrap="">
Those calloc are confusing.
</pre>
<blockquote type="cite">
<pre wrap="">+ if (p_sys->i_height) FREENULL( p_sys->i_height );
+ if (p_sys->i_width) FREENULL( p_sys->i_width );
+ if (p_sys->i_visible_pitch) FREENULL( p_sys->i_visible_pitch );
</pre>
</blockquote>
<pre wrap="">
free(NULL) is OK in VLC.
Best regards,
</pre>
</blockquote>
<br>
</body>
</html>