Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
ee605aa7
Commit
ee605aa7
authored
Aug 31, 2016
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter: add gblur filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
817846d0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
373 additions
and
1 deletion
+373
-1
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+17
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+1
-1
vf_gblur.c
libavfilter/vf_gblur.c
+352
-0
No files found.
Changelog
View file @
ee605aa7
...
@@ -25,6 +25,7 @@ version <next>:
...
@@ -25,6 +25,7 @@ version <next>:
- vaguedenoiser filter
- vaguedenoiser filter
- added threads option per filter instance
- added threads option per filter instance
- weave filter
- weave filter
- gblur filter
version 3.1:
version 3.1:
...
...
doc/filters.texi
View file @
ee605aa7
...
@@ -8251,6 +8251,23 @@ option may cause flicker since the B-Frames have often larger QP. Default is
...
@@ -8251,6 +8251,23 @@ option may cause flicker since the B-Frames have often larger QP. Default is
@end table
@end table
@section gblur
Apply Gaussian blur filter.
The filter accepts the following options:
@table @option
@item sigma
Set sigma, standard deviation of Gaussian blur. Default is @code{0.5}.
@item steps
Set number of steps for Gaussian approximation. Defauls is @code{1}.
@item planes
Set which planes to filter. By default all planes are filtered.
@end table
@section geq
@section geq
The filter accepts the following options:
The filter accepts the following options:
...
...
libavfilter/Makefile
View file @
ee605aa7
...
@@ -182,6 +182,7 @@ OBJS-$(CONFIG_FRAMERATE_FILTER) += vf_framerate.o
...
@@ -182,6 +182,7 @@ OBJS-$(CONFIG_FRAMERATE_FILTER) += vf_framerate.o
OBJS-$(CONFIG_FRAMESTEP_FILTER)
+=
vf_framestep.o
OBJS-$(CONFIG_FRAMESTEP_FILTER)
+=
vf_framestep.o
OBJS-$(CONFIG_FREI0R_FILTER)
+=
vf_frei0r.o
OBJS-$(CONFIG_FREI0R_FILTER)
+=
vf_frei0r.o
OBJS-$(CONFIG_FSPP_FILTER)
+=
vf_fspp.o
OBJS-$(CONFIG_FSPP_FILTER)
+=
vf_fspp.o
OBJS-$(CONFIG_GBLUR_FILTER)
+=
vf_gblur.o
OBJS-$(CONFIG_GEQ_FILTER)
+=
vf_geq.o
OBJS-$(CONFIG_GEQ_FILTER)
+=
vf_geq.o
OBJS-$(CONFIG_GRADFUN_FILTER)
+=
vf_gradfun.o
OBJS-$(CONFIG_GRADFUN_FILTER)
+=
vf_gradfun.o
OBJS-$(CONFIG_HALDCLUT_FILTER)
+=
vf_lut3d.o
dualinput.o
framesync.o
OBJS-$(CONFIG_HALDCLUT_FILTER)
+=
vf_lut3d.o
dualinput.o
framesync.o
...
...
libavfilter/allfilters.c
View file @
ee605aa7
...
@@ -199,6 +199,7 @@ void avfilter_register_all(void)
...
@@ -199,6 +199,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
FRAMESTEP
,
framestep
,
vf
);
REGISTER_FILTER
(
FRAMESTEP
,
framestep
,
vf
);
REGISTER_FILTER
(
FREI0R
,
frei0r
,
vf
);
REGISTER_FILTER
(
FREI0R
,
frei0r
,
vf
);
REGISTER_FILTER
(
FSPP
,
fspp
,
vf
);
REGISTER_FILTER
(
FSPP
,
fspp
,
vf
);
REGISTER_FILTER
(
GBLUR
,
gblur
,
vf
);
REGISTER_FILTER
(
GEQ
,
geq
,
vf
);
REGISTER_FILTER
(
GEQ
,
geq
,
vf
);
REGISTER_FILTER
(
GRADFUN
,
gradfun
,
vf
);
REGISTER_FILTER
(
GRADFUN
,
gradfun
,
vf
);
REGISTER_FILTER
(
HALDCLUT
,
haldclut
,
vf
);
REGISTER_FILTER
(
HALDCLUT
,
haldclut
,
vf
);
...
...
libavfilter/version.h
View file @
ee605aa7
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 6
#define LIBAVFILTER_VERSION_MAJOR 6
#define LIBAVFILTER_VERSION_MINOR
59
#define LIBAVFILTER_VERSION_MINOR
60
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
libavfilter/vf_gblur.c
0 → 100644
View file @
ee605aa7
/*
* Copyright (c) 2011 Pascal Getreuer
* Copyright (c) 2016 Paul B Mahol
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
typedef
struct
GBlurContext
{
const
AVClass
*
class
;
float
sigma
;
int
steps
;
int
planes
;
int
depth
;
int
planewidth
[
4
];
int
planeheight
[
4
];
float
*
buffer
;
float
boundaryscale
;
float
postscale
;
float
nu
;
int
nb_planes
;
}
GBlurContext
;
#define OFFSET(x) offsetof(GBlurContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static
const
AVOption
gblur_options
[]
=
{
{
"sigma"
,
"set sigma"
,
OFFSET
(
sigma
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
5
},
0
.
0
,
1024
,
FLAGS
},
{
"steps"
,
"set number of steps"
,
OFFSET
(
steps
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
1
,
6
,
FLAGS
},
{
"planes"
,
"set planes to filter"
,
OFFSET
(
planes
),
AV_OPT_TYPE_INT
,
{.
i64
=
0xF
},
0
,
0xF
,
FLAGS
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
gblur
);
typedef
struct
ThreadData
{
int
height
;
int
width
;
}
ThreadData
;
static
int
filter_horizontally
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
GBlurContext
*
s
=
ctx
->
priv
;
ThreadData
*
td
=
arg
;
const
int
height
=
td
->
height
;
const
int
width
=
td
->
width
;
const
int
slice_start
=
(
height
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
height
*
(
jobnr
+
1
))
/
nb_jobs
;
const
float
boundaryscale
=
s
->
boundaryscale
;
const
int
steps
=
s
->
steps
;
const
float
nu
=
s
->
nu
;
float
*
buffer
=
s
->
buffer
;
int
y
,
x
,
step
;
float
*
ptr
;
/* Filter horizontally along each row */
for
(
y
=
slice_start
;
y
<
slice_end
;
y
++
)
{
for
(
step
=
0
;
step
<
steps
;
step
++
)
{
ptr
=
buffer
+
width
*
y
;
ptr
[
0
]
*=
boundaryscale
;
/* Filter rightwards */
for
(
x
=
1
;
x
<
width
;
x
++
)
ptr
[
x
]
+=
nu
*
ptr
[
x
-
1
];
ptr
[
x
=
width
-
1
]
*=
boundaryscale
;
/* Filter leftwards */
for
(;
x
>
0
;
x
--
)
ptr
[
x
-
1
]
+=
nu
*
ptr
[
x
];
}
}
return
0
;
}
static
int
filter_vertically
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
GBlurContext
*
s
=
ctx
->
priv
;
ThreadData
*
td
=
arg
;
const
int
height
=
td
->
height
;
const
int
width
=
td
->
width
;
const
int
slice_start
=
(
width
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
width
*
(
jobnr
+
1
))
/
nb_jobs
;
const
float
boundaryscale
=
s
->
boundaryscale
;
const
int
numpixels
=
width
*
height
;
const
int
steps
=
s
->
steps
;
const
float
nu
=
s
->
nu
;
float
*
buffer
=
s
->
buffer
;
int
i
,
x
,
step
;
float
*
ptr
;
/* Filter vertically along each column */
for
(
x
=
slice_start
;
x
<
slice_end
;
x
++
)
{
for
(
step
=
0
;
step
<
steps
;
step
++
)
{
ptr
=
buffer
+
x
;
ptr
[
0
]
*=
boundaryscale
;
/* Filter downwards */
for
(
i
=
width
;
i
<
numpixels
;
i
+=
width
)
ptr
[
i
]
+=
nu
*
ptr
[
i
-
width
];
ptr
[
i
=
numpixels
-
width
]
*=
boundaryscale
;
/* Filter upwards */
for
(;
i
>
0
;
i
-=
width
)
ptr
[
i
-
width
]
+=
nu
*
ptr
[
i
];
}
}
return
0
;
}
static
int
filter_postscale
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
GBlurContext
*
s
=
ctx
->
priv
;
ThreadData
*
td
=
arg
;
const
int
height
=
td
->
height
;
const
int
width
=
td
->
width
;
const
int64_t
numpixels
=
width
*
height
;
const
int
slice_start
=
(
numpixels
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
numpixels
*
(
jobnr
+
1
))
/
nb_jobs
;
const
float
postscale
=
s
->
postscale
;
float
*
buffer
=
s
->
buffer
;
int
i
;
for
(
i
=
slice_start
;
i
<
slice_end
;
i
++
)
buffer
[
i
]
*=
postscale
;
return
0
;
}
static
void
gaussianiir2d
(
AVFilterContext
*
ctx
,
int
plane
)
{
GBlurContext
*
s
=
ctx
->
priv
;
const
int
width
=
s
->
planewidth
[
plane
];
const
int
height
=
s
->
planeheight
[
plane
];
const
int
nb_threads
=
ff_filter_get_nb_threads
(
ctx
);
ThreadData
td
;
if
(
s
->
sigma
<=
0
||
s
->
steps
<
0
)
return
;
td
.
width
=
width
;
td
.
height
=
height
;
ctx
->
internal
->
execute
(
ctx
,
filter_horizontally
,
&
td
,
NULL
,
FFMIN
(
height
,
nb_threads
));
ctx
->
internal
->
execute
(
ctx
,
filter_vertically
,
&
td
,
NULL
,
FFMIN
(
width
,
nb_threads
));
ctx
->
internal
->
execute
(
ctx
,
filter_postscale
,
&
td
,
NULL
,
FFMIN
(
width
*
height
,
nb_threads
));
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
static
const
enum
AVPixelFormat
pix_fmts
[]
=
{
AV_PIX_FMT_YUVA444P
,
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_YUVA422P
,
AV_PIX_FMT_YUV422P
,
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ411P
,
AV_PIX_FMT_YUV411P
,
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_YUV420P9
,
AV_PIX_FMT_YUV422P9
,
AV_PIX_FMT_YUV444P9
,
AV_PIX_FMT_YUV420P10
,
AV_PIX_FMT_YUV422P10
,
AV_PIX_FMT_YUV444P10
,
AV_PIX_FMT_YUV420P12
,
AV_PIX_FMT_YUV422P12
,
AV_PIX_FMT_YUV444P12
,
AV_PIX_FMT_YUV440P12
,
AV_PIX_FMT_YUV420P14
,
AV_PIX_FMT_YUV422P14
,
AV_PIX_FMT_YUV444P14
,
AV_PIX_FMT_YUV420P16
,
AV_PIX_FMT_YUV422P16
,
AV_PIX_FMT_YUV444P16
,
AV_PIX_FMT_YUVA420P9
,
AV_PIX_FMT_YUVA422P9
,
AV_PIX_FMT_YUVA444P9
,
AV_PIX_FMT_YUVA420P10
,
AV_PIX_FMT_YUVA422P10
,
AV_PIX_FMT_YUVA444P10
,
AV_PIX_FMT_YUVA420P16
,
AV_PIX_FMT_YUVA422P16
,
AV_PIX_FMT_YUVA444P16
,
AV_PIX_FMT_GBRP
,
AV_PIX_FMT_GBRP9
,
AV_PIX_FMT_GBRP10
,
AV_PIX_FMT_GBRP12
,
AV_PIX_FMT_GBRP14
,
AV_PIX_FMT_GBRP16
,
AV_PIX_FMT_GBRAP
,
AV_PIX_FMT_GBRAP12
,
AV_PIX_FMT_GBRAP16
,
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_GRAY16
,
AV_PIX_FMT_NONE
};
return
ff_set_common_formats
(
ctx
,
ff_make_format_list
(
pix_fmts
));
}
static
int
config_input
(
AVFilterLink
*
inlink
)
{
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
inlink
->
format
);
GBlurContext
*
s
=
inlink
->
dst
->
priv
;
s
->
depth
=
desc
->
comp
[
0
].
depth
;
s
->
planewidth
[
1
]
=
s
->
planewidth
[
2
]
=
AV_CEIL_RSHIFT
(
inlink
->
w
,
desc
->
log2_chroma_w
);
s
->
planewidth
[
0
]
=
s
->
planewidth
[
3
]
=
inlink
->
w
;
s
->
planeheight
[
1
]
=
s
->
planeheight
[
2
]
=
AV_CEIL_RSHIFT
(
inlink
->
h
,
desc
->
log2_chroma_h
);
s
->
planeheight
[
0
]
=
s
->
planeheight
[
3
]
=
inlink
->
h
;
s
->
nb_planes
=
av_pix_fmt_count_planes
(
inlink
->
format
);
s
->
buffer
=
av_malloc_array
(
inlink
->
w
,
inlink
->
h
*
sizeof
(
*
s
->
buffer
));
if
(
!
s
->
buffer
)
return
AVERROR
(
ENOMEM
);
return
0
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
GBlurContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
double
dnu
,
lambda
;
float
sigma
=
s
->
sigma
;
int
steps
=
s
->
steps
;
AVFrame
*
out
;
int
plane
;
lambda
=
(
sigma
*
sigma
)
/
(
2
.
0
*
steps
);
dnu
=
(
1
.
0
+
2
.
0
*
lambda
-
sqrt
(
1
.
0
+
4
.
0
*
lambda
))
/
(
2
.
0
*
lambda
);
s
->
postscale
=
pow
(
dnu
/
lambda
,
2
*
steps
);
s
->
boundaryscale
=
1
.
0
/
(
1
.
0
-
dnu
);
s
->
nu
=
(
float
)
dnu
;
if
(
av_frame_is_writable
(
in
))
{
out
=
in
;
}
else
{
out
=
ff_get_video_buffer
(
outlink
,
outlink
->
w
,
outlink
->
h
);
if
(
!
out
)
{
av_frame_free
(
&
in
);
return
AVERROR
(
ENOMEM
);
}
av_frame_copy_props
(
out
,
in
);
}
for
(
plane
=
0
;
plane
<
s
->
nb_planes
;
plane
++
)
{
const
int
height
=
s
->
planeheight
[
plane
];
const
int
width
=
s
->
planewidth
[
plane
];
float
*
bptr
=
s
->
buffer
;
const
uint8_t
*
src
=
in
->
data
[
plane
];
const
uint16_t
*
src16
=
(
const
uint16_t
*
)
in
->
data
[
plane
];
uint8_t
*
dst
=
out
->
data
[
plane
];
uint16_t
*
dst16
=
(
uint16_t
*
)
out
->
data
[
plane
];
int
y
,
x
;
if
(
!
s
->
sigma
||
!
(
s
->
planes
&
(
1
<<
plane
)))
{
if
(
out
!=
in
)
av_image_copy_plane
(
out
->
data
[
plane
],
out
->
linesize
[
plane
],
in
->
data
[
plane
],
in
->
linesize
[
plane
],
width
*
((
s
->
depth
+
7
)
/
8
),
height
);
continue
;
}
if
(
s
->
depth
==
8
)
{
for
(
y
=
0
;
y
<
height
;
y
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
bptr
[
x
]
=
src
[
x
];
}
bptr
+=
width
;
src
+=
in
->
linesize
[
plane
];
}
}
else
{
for
(
y
=
0
;
y
<
height
;
y
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
bptr
[
x
]
=
src16
[
x
];
}
bptr
+=
width
;
src16
+=
in
->
linesize
[
plane
]
/
2
;
}
}
gaussianiir2d
(
ctx
,
plane
);
bptr
=
s
->
buffer
;
if
(
s
->
depth
==
8
)
{
for
(
y
=
0
;
y
<
height
;
y
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
dst
[
x
]
=
bptr
[
x
];
}
bptr
+=
width
;
dst
+=
out
->
linesize
[
plane
];
}
}
else
{
for
(
y
=
0
;
y
<
height
;
y
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
dst16
[
x
]
=
bptr
[
x
];
}
bptr
+=
width
;
dst16
+=
out
->
linesize
[
plane
]
/
2
;
}
}
}
if
(
out
!=
in
)
av_frame_free
(
&
in
);
return
ff_filter_frame
(
outlink
,
out
);
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
GBlurContext
*
s
=
ctx
->
priv
;
av_freep
(
&
s
->
buffer
);
}
static
const
AVFilterPad
gblur_inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_input
,
.
filter_frame
=
filter_frame
,
},
{
NULL
}
};
static
const
AVFilterPad
gblur_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
},
{
NULL
}
};
AVFilter
ff_vf_gblur
=
{
.
name
=
"gblur"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Apply Gaussian Blur filter."
),
.
priv_size
=
sizeof
(
GBlurContext
),
.
priv_class
=
&
gblur_class
,
.
uninit
=
uninit
,
.
query_formats
=
query_formats
,
.
inputs
=
gblur_inputs
,
.
outputs
=
gblur_outputs
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
|
AVFILTER_FLAG_SLICE_THREADS
,
};
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