Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
24d7d66f
Commit
24d7d66f
authored
Aug 18, 2013
by
Vianney Boyer
Committed by
Jean-Baptiste Kempf
Aug 18, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Freeze: Freeze interactive video filter
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
ad351712
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
418 additions
and
2 deletions
+418
-2
NEWS
NEWS
+1
-0
modules/LIST
modules/LIST
+2
-1
modules/video_filter/Modules.am
modules/video_filter/Modules.am
+3
-1
modules/video_filter/freeze.c
modules/video_filter/freeze.c
+411
-0
po/POTFILES.in
po/POTFILES.in
+1
-0
No files found.
NEWS
View file @
24d7d66f
...
...
@@ -15,6 +15,7 @@ Video Output:
Video Filter:
* New Oldmovie effect filter
* New VHS effect filter
* New Freeze effect filter
libVLC:
* add equalizer API libvlc_audio_equalizer_* functions
...
...
modules/LIST
View file @
24d7d66f
List of vlc plugins (
384
)
List of vlc plugins (
413
)
$Id$
* a52: A/52 basic parser/packetizer
* a52tofloat32: A/52 audio converter & decoder plugin, using liba52
...
...
@@ -133,6 +133,7 @@ $Id$
* fluidsynth: Software MIDI synthetizer using libfluidsynth
* folder: folder meta data and art finder
* freetype: Utility to put text on video using freetype2
* freeze: picture freezing video filter
* g711: G.711 audio codec
* gain: Gain audio filter
* gaussianblur: gaussian blur video filter
...
...
modules/video_filter/Modules.am
View file @
24d7d66f
...
...
@@ -135,6 +135,7 @@ SOURCES_hqdn3d = hqdn3d.c hqdn3d.h
SOURCES_anaglyph = anaglyph.c
SOURCES_oldmovie = oldmovie.c
SOURCES_vhs = vhs.c
SOURCES_freeze = freeze.c
noinst_HEADERS = filter_picture.h
libvlc_LTLIBRARIES += \
...
...
@@ -179,5 +180,6 @@ libvlc_LTLIBRARIES += \
libhqdn3d_plugin.la \
libanaglyph_plugin.la \
liboldmovie_plugin.la \
libvhs_plugin.la
libvhs_plugin.la \
libfreeze_plugin.la
modules/video_filter/freeze.c
0 → 100644
View file @
24d7d66f
/*****************************************************************************
* freeze.c : Freezing video filter
*****************************************************************************
* Copyright (C) 2013 Vianney Boyer
* $Id$
*
* Authors: Vianney Boyer <vlcvboyer -at- gmail -dot- com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_filter.h>
#include "filter_picture.h"
#ifndef MOD
# define MOD(a, b) ((((a)%(b)) + (b))%(b))
#endif
struct
filter_sys_t
{
bool
b_init
;
int32_t
i_planes
;
int32_t
*
i_height
;
int32_t
*
i_width
;
int32_t
*
i_visible_pitch
;
int8_t
***
pi_freezed_picture
;
/* records freezed pixels */
int16_t
**
pi_freezing_countdown
;
/* freezed pixel delay */
bool
**
pb_update_cache
;
/* update chache request */
};
/*****************************************************************************
* Prototypes
*****************************************************************************/
static
picture_t
*
Filter
(
filter_t
*
,
picture_t
*
);
static
int
freeze_mouse
(
filter_t
*
,
vlc_mouse_t
*
,
const
vlc_mouse_t
*
,
const
vlc_mouse_t
*
);
static
int
freeze_allocate_data
(
filter_t
*
,
picture_t
*
);
static
void
freeze_free_allocated_data
(
filter_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define CFG_PREFIX "freeze-"
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_description
(
N_
(
"Freezing interactive video filter"
)
)
set_shortname
(
N_
(
"Freeze"
)
)
set_capability
(
"video filter2"
,
0
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VFILTER
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/**
* Open the filter
*/
static
int
Open
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
;
/* Assert video in match with video out */
if
(
!
es_format_IsSimilar
(
&
p_filter
->
fmt_in
,
&
p_filter
->
fmt_out
)
)
{
msg_Err
(
p_filter
,
"Input and output format does not match"
);
return
VLC_EGENERIC
;
}
/* Reject 0 bpp and unsupported chroma */
const
vlc_fourcc_t
fourcc
=
p_filter
->
fmt_in
.
video
.
i_chroma
;
const
vlc_chroma_description_t
*
p_chroma
=
vlc_fourcc_GetChromaDescription
(
p_filter
->
fmt_in
.
video
.
i_chroma
);
if
(
!
p_chroma
||
p_chroma
->
pixel_size
==
0
||
p_chroma
->
plane_count
<
3
||
p_chroma
->
pixel_size
>
1
||
!
vlc_fourcc_IsYUV
(
fourcc
)
)
{
msg_Err
(
p_filter
,
"Unsupported chroma (%4.4s)"
,
(
char
*
)
&
fourcc
);
return
VLC_EGENERIC
;
}
/* Allocate structure */
p_filter
->
p_sys
=
p_sys
=
calloc
(
1
,
sizeof
(
*
p_sys
)
);
if
(
unlikely
(
!
p_sys
)
)
return
VLC_ENOMEM
;
/* init data */
p_filter
->
pf_video_filter
=
Filter
;
p_filter
->
pf_video_mouse
=
freeze_mouse
;
return
VLC_SUCCESS
;
}
/**
* Close the filter
*/
static
void
Close
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
/* Free allocated memory */
freeze_free_allocated_data
(
p_filter
);
free
(
p_sys
);
}
/**
* Filter a picture
*/
static
picture_t
*
Filter
(
filter_t
*
p_filter
,
picture_t
*
p_pic_in
)
{
if
(
!
p_pic_in
||
!
p_filter
)
return
NULL
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
picture_t
*
p_pic_out
=
filter_NewPicture
(
p_filter
);
if
(
unlikely
(
!
p_pic_out
)
)
{
picture_Release
(
p_pic_in
);
return
NULL
;
}
/*
* allocate data
*/
if
(
unlikely
(
!
p_sys
->
b_init
)
)
if
(
freeze_allocate_data
(
p_filter
,
p_pic_in
)
!=
VLC_SUCCESS
)
{
picture_Release
(
p_pic_in
);
return
NULL
;
}
p_sys
->
b_init
=
true
;
/*
* preset output pic: raw copy src to dst
*/
picture_CopyPixels
(
p_pic_out
,
p_pic_in
);
/*
* cache original pict pixels selected with mouse pointer
*/
for
(
int32_t
i_p
=
0
;
i_p
<
p_sys
->
i_planes
;
i_p
++
)
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
i_p
];
i_r
++
)
for
(
int32_t
i_c
=
0
;
i_c
<
p_sys
->
i_width
[
i_p
];
i_c
++
)
{
uint32_t
i_Yr
=
i_r
*
p_sys
->
i_height
[
Y_PLANE
]
/
p_sys
->
i_height
[
i_p
];
uint32_t
i_Yc
=
i_c
*
p_sys
->
i_width
[
Y_PLANE
]
/
p_sys
->
i_width
[
i_p
];
if
(
p_sys
->
pb_update_cache
[
i_Yr
][
i_Yc
]
)
p_sys
->
pi_freezed_picture
[
i_p
][
i_r
][
i_c
]
=
p_pic_in
->
p
[
i_p
].
p_pixels
[
i_r
*
p_pic_out
->
p
[
i_p
].
i_pitch
+
i_c
*
p_pic_out
->
p
[
i_p
].
i_pixel_pitch
];
}
/*
* countdown freezed pixel delay & reset pb_update_cache flag
*/
for
(
int32_t
i_Yr
=
0
;
i_Yr
<
p_sys
->
i_height
[
Y_PLANE
];
i_Yr
++
)
for
(
int32_t
i_Yc
=
0
;
i_Yc
<
p_sys
->
i_width
[
Y_PLANE
];
i_Yc
++
)
{
if
(
p_sys
->
pi_freezing_countdown
[
i_Yr
][
i_Yc
]
>
0
)
p_sys
->
pi_freezing_countdown
[
i_Yr
][
i_Yc
]
--
;
p_sys
->
pb_update_cache
[
i_Yr
][
i_Yc
]
=
false
;
}
/*
* apply filter: draw freezed pixels over current picture
*/
for
(
int32_t
i_p
=
0
;
i_p
<
p_sys
->
i_planes
;
i_p
++
)
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
i_p
];
i_r
++
)
for
(
int32_t
i_c
=
0
;
i_c
<
p_sys
->
i_width
[
i_p
];
i_c
++
)
{
uint32_t
i_Yr
=
i_r
*
p_sys
->
i_height
[
Y_PLANE
]
/
p_sys
->
i_height
[
i_p
];
uint32_t
i_Yc
=
i_c
*
p_sys
->
i_width
[
Y_PLANE
]
/
p_sys
->
i_width
[
i_p
];
if
(
p_sys
->
pi_freezing_countdown
[
i_Yr
][
i_Yc
]
>
0
)
p_pic_out
->
p
[
i_p
].
p_pixels
[
i_r
*
p_pic_out
->
p
[
i_p
].
i_pitch
+
i_c
*
p_pic_out
->
p
[
i_p
].
i_pixel_pitch
]
=
p_sys
->
pi_freezed_picture
[
i_p
][
i_r
][
i_c
];
}
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
/*
* mouse callback
**/
static
int
freeze_mouse
(
filter_t
*
p_filter
,
vlc_mouse_t
*
p_mouse
,
const
vlc_mouse_t
*
p_old
,
const
vlc_mouse_t
*
p_new
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
const
video_format_t
*
p_fmt_in
=
&
p_filter
->
fmt_in
.
video
;
/* Only take events inside the video area */
if
(
p_new
->
i_x
<
0
||
p_new
->
i_x
>=
(
int
)
p_fmt_in
->
i_width
||
p_new
->
i_y
<
0
||
p_new
->
i_y
>=
(
int
)
p_fmt_in
->
i_height
)
return
VLC_EGENERIC
;
if
(
unlikely
(
!
p_sys
->
b_init
)
)
{
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
int32_t
i_base_timeout
=
0
;
if
(
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
)
i_base_timeout
=
100
;
else
if
(
vlc_mouse_IsLeftPressed
(
p_new
)
)
i_base_timeout
=
50
;
if
(
i_base_timeout
>
0
)
{
/*
* find pixels selected by user to apply freezing filter
*/
int32_t
i_min_sq_radius
=
(
p_sys
->
i_width
[
Y_PLANE
]
/
15
)
*
(
p_sys
->
i_width
[
Y_PLANE
]
/
15
);
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
Y_PLANE
];
i_r
++
)
for
(
int32_t
i_c
=
0
;
i_c
<
p_sys
->
i_width
[
Y_PLANE
];
i_c
++
)
{
int32_t
i_sq_dist
=
(
p_new
->
i_x
-
i_c
)
*
(
p_new
->
i_x
-
i_c
)
+
(
p_new
->
i_y
-
i_r
)
*
(
p_new
->
i_y
-
i_r
);
i_sq_dist
=
__MAX
(
0
,
i_sq_dist
-
i_min_sq_radius
);
uint16_t
i_timeout
=
__MAX
(
i_base_timeout
-
i_sq_dist
,
0
);
/* ask to update chache for pixel to be freezed just now */
if
(
p_sys
->
pi_freezing_countdown
[
i_r
][
i_c
]
==
0
&&
i_timeout
>
0
)
p_sys
->
pb_update_cache
[
i_r
][
i_c
]
=
true
;
/* set freezing delay */
if
(
p_sys
->
pi_freezing_countdown
[
i_r
][
i_c
]
<
i_timeout
)
p_sys
->
pi_freezing_countdown
[
i_r
][
i_c
]
=
i_timeout
;
}
}
return
VLC_EGENERIC
;
}
/*
* Allocate data
*/
static
int
freeze_allocate_data
(
filter_t
*
p_filter
,
picture_t
*
p_pic_in
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
freeze_free_allocated_data
(
p_filter
);
/*
* take into account different characteristics for each plane
*/
p_sys
->
i_planes
=
p_pic_in
->
i_planes
;
p_sys
->
i_height
=
calloc
(
p_sys
->
i_planes
,
sizeof
(
int32_t
)
);
p_sys
->
i_width
=
calloc
(
p_sys
->
i_planes
,
sizeof
(
int32_t
)
);
p_sys
->
i_visible_pitch
=
calloc
(
p_sys
->
i_planes
,
sizeof
(
int32_t
)
);
if
(
unlikely
(
!
p_sys
->
i_height
||
!
p_sys
->
i_width
||
!
p_sys
->
i_visible_pitch
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
/* init data */
for
(
int32_t
i_p
=
0
;
i_p
<
p_sys
->
i_planes
;
i_p
++
)
{
p_sys
->
i_visible_pitch
[
i_p
]
=
(
int
)
p_pic_in
->
p
[
i_p
].
i_visible_pitch
;
p_sys
->
i_height
[
i_p
]
=
(
int
)
p_pic_in
->
p
[
i_p
].
i_visible_lines
;
p_sys
->
i_width
[
i_p
]
=
(
int
)
p_pic_in
->
p
[
i_p
].
i_visible_pitch
/
p_pic_in
->
p
[
i_p
].
i_pixel_pitch
;
}
/* buffer used to countdown freezing delay */
p_sys
->
pi_freezing_countdown
=
calloc
(
p_sys
->
i_height
[
Y_PLANE
],
sizeof
(
int16_t
*
)
);
if
(
unlikely
(
!
p_sys
->
pi_freezing_countdown
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
Y_PLANE
];
i_r
++
)
{
p_sys
->
pi_freezing_countdown
[
i_r
]
=
calloc
(
p_sys
->
i_width
[
Y_PLANE
],
sizeof
(
int16_t
)
);
if
(
unlikely
(
!
p_sys
->
pi_freezing_countdown
[
i_r
]
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
}
/* buffer used to cache freezed pixels colors */
p_sys
->
pi_freezed_picture
=
calloc
(
p_sys
->
i_planes
,
sizeof
(
int8_t
**
)
);
if
(
unlikely
(
!
p_sys
->
pi_freezed_picture
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
for
(
int32_t
i_p
=
0
;
i_p
<
p_sys
->
i_planes
;
i_p
++
)
{
p_sys
->
pi_freezed_picture
[
i_p
]
=
calloc
(
p_sys
->
i_height
[
i_p
],
sizeof
(
int8_t
*
)
);
if
(
unlikely
(
!
p_sys
->
pi_freezed_picture
[
i_p
])
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
i_p
];
i_r
++
)
{
p_sys
->
pi_freezed_picture
[
i_p
][
i_r
]
=
calloc
(
p_sys
->
i_width
[
i_p
],
sizeof
(
int8_t
)
);
if
(
unlikely
(
!
p_sys
->
pi_freezed_picture
[
i_p
][
i_r
]
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
}
}
/* flag used to manage freezed pixels cache update */
p_sys
->
pb_update_cache
=
calloc
(
p_sys
->
i_height
[
Y_PLANE
],
sizeof
(
bool
*
)
);
if
(
unlikely
(
!
p_sys
->
pb_update_cache
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
Y_PLANE
];
i_r
++
)
{
p_sys
->
pb_update_cache
[
i_r
]
=
calloc
(
p_sys
->
i_width
[
Y_PLANE
],
sizeof
(
bool
)
);
if
(
unlikely
(
!
p_sys
->
pb_update_cache
[
i_r
]
)
)
{
freeze_free_allocated_data
(
p_filter
);
return
VLC_ENOMEM
;
}
}
return
VLC_SUCCESS
;
}
/**
* Free allocated data
*/
static
void
freeze_free_allocated_data
(
filter_t
*
p_filter
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
if
(
p_sys
->
pi_freezing_countdown
)
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
Y_PLANE
];
i_r
++
)
free
(
p_sys
->
pi_freezing_countdown
[
i_r
]
);
FREENULL
(
p_sys
->
pi_freezing_countdown
);
if
(
p_sys
->
pb_update_cache
)
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
Y_PLANE
];
i_r
++
)
free
(
p_sys
->
pb_update_cache
[
i_r
]
);
FREENULL
(
p_sys
->
pb_update_cache
);
if
(
p_sys
->
pi_freezed_picture
)
for
(
int32_t
i_p
=
0
;
i_p
<
p_sys
->
i_planes
;
i_p
++
)
{
for
(
int32_t
i_r
=
0
;
i_r
<
p_sys
->
i_height
[
i_p
];
i_r
++
)
free
(
p_sys
->
pi_freezed_picture
[
i_p
][
i_r
]
);
free
(
p_sys
->
pi_freezed_picture
[
i_p
]
);
}
FREENULL
(
p_sys
->
pi_freezed_picture
);
p_sys
->
i_planes
=
0
;
FREENULL
(
p_sys
->
i_height
);
FREENULL
(
p_sys
->
i_width
);
FREENULL
(
p_sys
->
i_visible_pitch
);
}
po/POTFILES.in
View file @
24d7d66f
...
...
@@ -1095,6 +1095,7 @@ modules/video_filter/erase.c
modules/video_filter/extract.c
modules/video_filter/filter_event_info.h
modules/video_filter/filter_picture.h
modules/video_filter/freeze.c
modules/video_filter/gaussianblur.c
modules/video_filter/gradfun.c
modules/video_filter/gradient.c
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment