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
c85e0ca6
Commit
c85e0ca6
authored
Aug 10, 2014
by
Clément Bœsch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/dctdnoiz: add slice threading
parent
cf24e10a
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
84 additions
and
30 deletions
+84
-30
vf_dctdnoiz.c
libavfilter/vf_dctdnoiz.c
+84
-30
No files found.
libavfilter/vf_dctdnoiz.c
View file @
c85e0ca6
...
@@ -36,18 +36,22 @@
...
@@ -36,18 +36,22 @@
static
const
char
*
const
var_names
[]
=
{
"c"
,
NULL
};
static
const
char
*
const
var_names
[]
=
{
"c"
,
NULL
};
enum
{
VAR_C
,
VAR_VARS_NB
};
enum
{
VAR_C
,
VAR_VARS_NB
};
#define MAX_THREADS 8
typedef
struct
DCTdnoizContext
{
typedef
struct
DCTdnoizContext
{
const
AVClass
*
class
;
const
AVClass
*
class
;
/* coefficient factor expression */
/* coefficient factor expression */
char
*
expr_str
;
char
*
expr_str
;
AVExpr
*
expr
;
AVExpr
*
expr
[
MAX_THREADS
]
;
double
var_values
[
VAR_VARS_NB
];
double
var_values
[
MAX_THREADS
][
VAR_VARS_NB
];
int
nb_threads
;
int
pr_width
,
pr_height
;
// width and height to process
int
pr_width
,
pr_height
;
// width and height to process
float
sigma
;
// used when no expression are st
float
sigma
;
// used when no expression are st
float
th
;
// threshold (3*sigma)
float
th
;
// threshold (3*sigma)
float
*
cbuf
[
2
][
3
];
// two planar rgb color buffers
float
*
cbuf
[
2
][
3
];
// two planar rgb color buffers
float
*
slices
[
MAX_THREADS
];
// slices buffers (1 slice buffer per thread)
float
*
weights
;
// dct coeff are cumulated with overlapping; these values are used for averaging
float
*
weights
;
// dct coeff are cumulated with overlapping; these values are used for averaging
int
p_linesize
;
// line sizes for color and weights
int
p_linesize
;
// line sizes for color and weights
int
overlap
;
// number of block overlapping pixels
int
overlap
;
// number of block overlapping pixels
...
@@ -56,7 +60,8 @@ typedef struct DCTdnoizContext {
...
@@ -56,7 +60,8 @@ typedef struct DCTdnoizContext {
int
bsize
;
// block size, 1<<n
int
bsize
;
// block size, 1<<n
void
(
*
filter_freq_func
)(
struct
DCTdnoizContext
*
s
,
void
(
*
filter_freq_func
)(
struct
DCTdnoizContext
*
s
,
const
float
*
src
,
int
src_linesize
,
const
float
*
src
,
int
src_linesize
,
float
*
dst
,
int
dst_linesize
);
float
*
dst
,
int
dst_linesize
,
int
thread_id
);
void
(
*
color_decorrelation
)(
float
**
dst
,
int
dst_linesize
,
void
(
*
color_decorrelation
)(
float
**
dst
,
int
dst_linesize
,
const
uint8_t
*
src
,
int
src_linesize
,
const
uint8_t
*
src
,
int
src_linesize
,
int
w
,
int
h
);
int
w
,
int
h
);
...
@@ -377,16 +382,17 @@ static av_always_inline void filter_freq_##bsize(const float *src, int src_lines
...
@@ -377,16 +382,17 @@ static av_always_inline void filter_freq_##bsize(const float *src, int src_lines
\
\
static void filter_freq_sigma_##bsize(DCTdnoizContext *s, \
static void filter_freq_sigma_##bsize(DCTdnoizContext *s, \
const float *src, int src_linesize, \
const float *src, int src_linesize, \
float *dst, int dst_linesize
)
\
float *dst, int dst_linesize
, int thread_id)
\
{ \
{ \
filter_freq_##bsize(src, src_linesize, dst, dst_linesize, NULL, NULL, s->th); \
filter_freq_##bsize(src, src_linesize, dst, dst_linesize, NULL, NULL, s->th); \
} \
} \
\
\
static void filter_freq_expr_##bsize(DCTdnoizContext *s, \
static void filter_freq_expr_##bsize(DCTdnoizContext *s, \
const float *src, int src_linesize, \
const float *src, int src_linesize, \
float *dst, int dst_linesize
)
\
float *dst, int dst_linesize
, int thread_id)
\
{ \
{ \
filter_freq_##bsize(src, src_linesize, dst, dst_linesize, s->expr, s->var_values, 0); \
filter_freq_##bsize(src, src_linesize, dst, dst_linesize, \
s->expr[thread_id], s->var_values[thread_id], 0); \
}
}
DEF_FILTER_FREQ_FUNCS
(
8
)
DEF_FILTER_FREQ_FUNCS
(
8
)
...
@@ -475,7 +481,7 @@ static int config_input(AVFilterLink *inlink)
...
@@ -475,7 +481,7 @@ static int config_input(AVFilterLink *inlink)
{
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterContext
*
ctx
=
inlink
->
dst
;
DCTdnoizContext
*
s
=
ctx
->
priv
;
DCTdnoizContext
*
s
=
ctx
->
priv
;
int
i
,
x
,
y
,
bx
,
by
,
linesize
,
*
iweights
;
int
i
,
x
,
y
,
bx
,
by
,
linesize
,
*
iweights
,
max_slice_h
,
slice_h
;
const
int
bsize
=
1
<<
s
->
n
;
const
int
bsize
=
1
<<
s
->
n
;
switch
(
inlink
->
format
)
{
switch
(
inlink
->
format
)
{
...
@@ -500,6 +506,11 @@ static int config_input(AVFilterLink *inlink)
...
@@ -500,6 +506,11 @@ static int config_input(AVFilterLink *inlink)
av_log
(
ctx
,
AV_LOG_WARNING
,
"The last %d vertical pixels won't be denoised
\n
"
,
av_log
(
ctx
,
AV_LOG_WARNING
,
"The last %d vertical pixels won't be denoised
\n
"
,
inlink
->
h
-
s
->
pr_height
);
inlink
->
h
-
s
->
pr_height
);
max_slice_h
=
s
->
pr_height
/
((
s
->
bsize
-
1
)
*
2
);
s
->
nb_threads
=
FFMIN3
(
MAX_THREADS
,
ctx
->
graph
->
nb_threads
,
max_slice_h
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
"threads: [max=%d hmax=%d user=%d] => %d
\n
"
,
MAX_THREADS
,
max_slice_h
,
ctx
->
graph
->
nb_threads
,
s
->
nb_threads
);
s
->
p_linesize
=
linesize
=
FFALIGN
(
s
->
pr_width
,
32
);
s
->
p_linesize
=
linesize
=
FFALIGN
(
s
->
pr_width
,
32
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
s
->
cbuf
[
i
][
0
]
=
av_malloc
(
linesize
*
s
->
pr_height
*
sizeof
(
*
s
->
cbuf
[
i
][
0
]));
s
->
cbuf
[
i
][
0
]
=
av_malloc
(
linesize
*
s
->
pr_height
*
sizeof
(
*
s
->
cbuf
[
i
][
0
]));
...
@@ -509,6 +520,27 @@ static int config_input(AVFilterLink *inlink)
...
@@ -509,6 +520,27 @@ static int config_input(AVFilterLink *inlink)
return
AVERROR
(
ENOMEM
);
return
AVERROR
(
ENOMEM
);
}
}
/* eval expressions are probably not thread safe when the eval internal
* state can be changed (typically through load & store operations) */
if
(
s
->
expr_str
)
{
for
(
i
=
0
;
i
<
s
->
nb_threads
;
i
++
)
{
int
ret
=
av_expr_parse
(
&
s
->
expr
[
i
],
s
->
expr_str
,
var_names
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
ctx
);
if
(
ret
<
0
)
return
ret
;
}
}
/* each slice will need to (pre & re)process the top and bottom block of
* the previous one in in addition to its processing area. This is because
* each pixel is averaged by all the surrounding blocks */
slice_h
=
(
int
)
ceilf
(
s
->
pr_height
/
s
->
nb_threads
)
+
(
s
->
bsize
-
1
)
*
2
;
for
(
i
=
0
;
i
<
s
->
nb_threads
;
i
++
)
{
s
->
slices
[
i
]
=
av_malloc_array
(
linesize
,
slice_h
*
sizeof
(
*
s
->
slices
[
i
]));
if
(
!
s
->
slices
[
i
])
return
AVERROR
(
ENOMEM
);
}
s
->
weights
=
av_malloc
(
s
->
pr_height
*
linesize
*
sizeof
(
*
s
->
weights
));
s
->
weights
=
av_malloc
(
s
->
pr_height
*
linesize
*
sizeof
(
*
s
->
weights
));
if
(
!
s
->
weights
)
if
(
!
s
->
weights
)
return
AVERROR
(
ENOMEM
);
return
AVERROR
(
ENOMEM
);
...
@@ -544,10 +576,6 @@ static av_cold int init(AVFilterContext *ctx)
...
@@ -544,10 +576,6 @@ static av_cold int init(AVFilterContext *ctx)
}
}
if
(
s
->
expr_str
)
{
if
(
s
->
expr_str
)
{
int
ret
=
av_expr_parse
(
&
s
->
expr
,
s
->
expr_str
,
var_names
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
ctx
);
if
(
ret
<
0
)
return
ret
;
switch
(
s
->
n
)
{
switch
(
s
->
n
)
{
case
3
:
s
->
filter_freq_func
=
filter_freq_expr_8
;
break
;
case
3
:
s
->
filter_freq_func
=
filter_freq_expr_8
;
break
;
case
4
:
s
->
filter_freq_func
=
filter_freq_expr_16
;
break
;
case
4
:
s
->
filter_freq_func
=
filter_freq_expr_16
;
break
;
...
@@ -576,36 +604,56 @@ static int query_formats(AVFilterContext *ctx)
...
@@ -576,36 +604,56 @@ static int query_formats(AVFilterContext *ctx)
return
0
;
return
0
;
}
}
static
void
filter_plane
(
AVFilterContext
*
ctx
,
typedef
struct
ThreadData
{
float
*
dst
,
int
dst_linesize
,
float
*
src
,
*
dst
;
const
float
*
src
,
int
src_linesize
,
}
ThreadData
;
int
w
,
int
h
)
static
int
filter_slice
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
{
int
x
,
y
;
int
x
,
y
;
DCTdnoizContext
*
s
=
ctx
->
priv
;
DCTdnoizContext
*
s
=
ctx
->
priv
;
float
*
dst0
=
dst
;
const
ThreadData
*
td
=
arg
;
const
float
*
weights
=
s
->
weights
;
const
int
w
=
s
->
pr_width
;
const
int
h
=
s
->
pr_height
;
const
int
slice_start
=
(
h
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
h
*
(
jobnr
+
1
))
/
nb_jobs
;
const
int
slice_start_ctx
=
FFMAX
(
slice_start
-
s
->
bsize
+
1
,
0
);
const
int
slice_end_ctx
=
FFMIN
(
slice_end
,
h
-
s
->
bsize
+
1
);
const
int
slice_h
=
slice_end_ctx
-
slice_start_ctx
;
const
int
src_linesize
=
s
->
p_linesize
;
const
int
dst_linesize
=
s
->
p_linesize
;
const
int
slice_linesize
=
s
->
p_linesize
;
float
*
dst
;
const
float
*
src
=
td
->
src
+
slice_start_ctx
*
src_linesize
;
const
float
*
weights
=
s
->
weights
+
slice_start
*
dst_linesize
;
float
*
slice
=
s
->
slices
[
jobnr
];
// reset block sums
// reset block sums
memset
(
dst
,
0
,
h
*
dst_linesize
*
sizeof
(
*
dst
));
memset
(
slice
,
0
,
(
slice_h
+
s
->
bsize
-
1
)
*
dst_linesize
*
sizeof
(
*
slice
));
// block dct sums
// block dct sums
for
(
y
=
0
;
y
<
h
-
s
->
bsize
+
1
;
y
+=
s
->
step
)
{
for
(
y
=
0
;
y
<
slice_h
;
y
+=
s
->
step
)
{
for
(
x
=
0
;
x
<
w
-
s
->
bsize
+
1
;
x
+=
s
->
step
)
for
(
x
=
0
;
x
<
w
-
s
->
bsize
+
1
;
x
+=
s
->
step
)
s
->
filter_freq_func
(
s
,
src
+
x
,
src_linesize
,
s
->
filter_freq_func
(
s
,
src
+
x
,
src_linesize
,
dst
+
x
,
dst_linesize
);
slice
+
x
,
slice_linesize
,
jobnr
);
src
+=
s
->
step
*
src_linesize
;
src
+=
s
->
step
*
src_linesize
;
dst
+=
s
->
step
*
dst
_linesize
;
slice
+=
s
->
step
*
slice
_linesize
;
}
}
// average blocks
// average blocks
dst
=
dst0
;
slice
=
s
->
slices
[
jobnr
]
+
(
slice_start
-
slice_start_ctx
)
*
slice_linesize
;
for
(
y
=
0
;
y
<
h
;
y
++
)
{
dst
=
td
->
dst
+
slice_start
*
dst_linesize
;
for
(
y
=
slice_start
;
y
<
slice_end
;
y
++
)
{
for
(
x
=
0
;
x
<
w
;
x
++
)
for
(
x
=
0
;
x
<
w
;
x
++
)
dst
[
x
]
*=
weights
[
x
];
dst
[
x
]
=
slice
[
x
]
*
weights
[
x
];
slice
+=
slice_linesize
;
dst
+=
dst_linesize
;
dst
+=
dst_linesize
;
weights
+=
dst_linesize
;
weights
+=
dst_linesize
;
}
}
return
0
;
}
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
...
@@ -632,10 +680,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
...
@@ -632,10 +680,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
s
->
color_decorrelation
(
s
->
cbuf
[
0
],
s
->
p_linesize
,
s
->
color_decorrelation
(
s
->
cbuf
[
0
],
s
->
p_linesize
,
in
->
data
[
0
],
in
->
linesize
[
0
],
in
->
data
[
0
],
in
->
linesize
[
0
],
s
->
pr_width
,
s
->
pr_height
);
s
->
pr_width
,
s
->
pr_height
);
for
(
plane
=
0
;
plane
<
3
;
plane
++
)
for
(
plane
=
0
;
plane
<
3
;
plane
++
)
{
filter_plane
(
ctx
,
s
->
cbuf
[
1
][
plane
],
s
->
p_linesize
,
ThreadData
td
=
{
s
->
cbuf
[
0
][
plane
],
s
->
p_linesize
,
.
src
=
s
->
cbuf
[
0
][
plane
],
s
->
pr_width
,
s
->
pr_height
);
.
dst
=
s
->
cbuf
[
1
][
plane
],
};
ctx
->
internal
->
execute
(
ctx
,
filter_slice
,
&
td
,
NULL
,
s
->
nb_threads
);
}
s
->
color_correlation
(
out
->
data
[
0
],
out
->
linesize
[
0
],
s
->
color_correlation
(
out
->
data
[
0
],
out
->
linesize
[
0
],
s
->
cbuf
[
1
],
s
->
p_linesize
,
s
->
cbuf
[
1
],
s
->
p_linesize
,
s
->
pr_width
,
s
->
pr_height
);
s
->
pr_width
,
s
->
pr_height
);
...
@@ -687,7 +738,10 @@ static av_cold void uninit(AVFilterContext *ctx)
...
@@ -687,7 +738,10 @@ static av_cold void uninit(AVFilterContext *ctx)
av_free
(
s
->
cbuf
[
i
][
1
]);
av_free
(
s
->
cbuf
[
i
][
1
]);
av_free
(
s
->
cbuf
[
i
][
2
]);
av_free
(
s
->
cbuf
[
i
][
2
]);
}
}
av_expr_free
(
s
->
expr
);
for
(
i
=
0
;
i
<
s
->
nb_threads
;
i
++
)
{
av_free
(
s
->
slices
[
i
]);
av_expr_free
(
s
->
expr
[
i
]);
}
}
}
static
const
AVFilterPad
dctdnoiz_inputs
[]
=
{
static
const
AVFilterPad
dctdnoiz_inputs
[]
=
{
...
@@ -718,5 +772,5 @@ AVFilter ff_vf_dctdnoiz = {
...
@@ -718,5 +772,5 @@ AVFilter ff_vf_dctdnoiz = {
.
inputs
=
dctdnoiz_inputs
,
.
inputs
=
dctdnoiz_inputs
,
.
outputs
=
dctdnoiz_outputs
,
.
outputs
=
dctdnoiz_outputs
,
.
priv_class
=
&
dctdnoiz_class
,
.
priv_class
=
&
dctdnoiz_class
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
.
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