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
ee56d9bc
Commit
ee56d9bc
authored
Jul 28, 2016
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_signalstats: add >8 bit depth support
parent
7ae52f8a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
420 additions
and
16 deletions
+420
-16
vf_signalstats.c
libavfilter/vf_signalstats.c
+420
-16
No files found.
libavfilter/vf_signalstats.c
View file @
ee56d9bc
...
...
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "internal.h"
...
...
@@ -38,6 +39,7 @@ typedef struct {
int
chromaw
;
// width of chroma plane
int
hsub
;
// horizontal subsampling
int
vsub
;
// vertical subsampling
int
depth
;
// pixel depth
int
fs
;
// pixel count per frame
int
cfs
;
// pixel count per frame of chroma planes
int
outfilter
;
// FilterMode
...
...
@@ -48,6 +50,8 @@ typedef struct {
int
nb_jobs
;
int
*
jobs_rets
;
int
*
histy
,
*
histu
,
*
histv
,
*
histsat
;
AVFrame
*
frame_sat
;
AVFrame
*
frame_hue
;
}
SignalstatsContext
;
...
...
@@ -105,6 +109,10 @@ static av_cold void uninit(AVFilterContext *ctx)
av_frame_free
(
&
s
->
frame_sat
);
av_frame_free
(
&
s
->
frame_hue
);
av_freep
(
&
s
->
jobs_rets
);
av_freep
(
&
s
->
histy
);
av_freep
(
&
s
->
histu
);
av_freep
(
&
s
->
histv
);
av_freep
(
&
s
->
histsat
);
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
...
...
@@ -115,6 +123,13 @@ static int query_formats(AVFilterContext *ctx)
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ411P
,
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_YUV444P9
,
AV_PIX_FMT_YUV422P9
,
AV_PIX_FMT_YUV420P9
,
AV_PIX_FMT_YUV444P10
,
AV_PIX_FMT_YUV422P10
,
AV_PIX_FMT_YUV420P10
,
AV_PIX_FMT_YUV440P10
,
AV_PIX_FMT_YUV444P12
,
AV_PIX_FMT_YUV422P12
,
AV_PIX_FMT_YUV420P12
,
AV_PIX_FMT_YUV440P12
,
AV_PIX_FMT_YUV444P14
,
AV_PIX_FMT_YUV422P14
,
AV_PIX_FMT_YUV420P14
,
AV_PIX_FMT_YUV444P16
,
AV_PIX_FMT_YUV422P16
,
AV_PIX_FMT_YUV420P16
,
AV_PIX_FMT_NONE
};
...
...
@@ -150,6 +165,16 @@ static int config_props(AVFilterLink *outlink)
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
outlink
->
format
);
s
->
hsub
=
desc
->
log2_chroma_w
;
s
->
vsub
=
desc
->
log2_chroma_h
;
s
->
depth
=
desc
->
comp
[
0
].
depth
;
if
(
s
->
depth
>
8
)
{
s
->
histy
=
av_malloc_array
(
1
<<
s
->
depth
,
sizeof
(
*
s
->
histy
));
s
->
histu
=
av_malloc_array
(
1
<<
s
->
depth
,
sizeof
(
*
s
->
histu
));
s
->
histv
=
av_malloc_array
(
1
<<
s
->
depth
,
sizeof
(
*
s
->
histv
));
s
->
histsat
=
av_malloc_array
(
1
<<
s
->
depth
,
sizeof
(
*
s
->
histsat
));
if
(
!
s
->
histy
||
!
s
->
histu
||
!
s
->
histv
||
!
s
->
histsat
)
return
AVERROR
(
ENOMEM
);
}
outlink
->
w
=
inlink
->
w
;
outlink
->
h
=
inlink
->
h
;
...
...
@@ -173,7 +198,7 @@ static int config_props(AVFilterLink *outlink)
return
0
;
}
static
void
burn_frame
(
const
SignalstatsContext
*
s
,
AVFrame
*
f
,
int
x
,
int
y
)
static
void
burn_frame
8
(
const
SignalstatsContext
*
s
,
AVFrame
*
f
,
int
x
,
int
y
)
{
const
int
chromax
=
x
>>
s
->
hsub
;
const
int
chromay
=
y
>>
s
->
vsub
;
...
...
@@ -182,7 +207,17 @@ static void burn_frame(const SignalstatsContext *s, AVFrame *f, int x, int y)
f
->
data
[
2
][
chromay
*
f
->
linesize
[
2
]
+
chromax
]
=
s
->
yuv_color
[
2
];
}
static
int
filter_brng
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
static
void
burn_frame16
(
const
SignalstatsContext
*
s
,
AVFrame
*
f
,
int
x
,
int
y
)
{
const
int
chromax
=
x
>>
s
->
hsub
;
const
int
chromay
=
y
>>
s
->
vsub
;
const
int
mult
=
1
<<
(
s
->
depth
-
8
);
AV_WN16
(
f
->
data
[
0
]
+
y
*
f
->
linesize
[
0
]
+
x
*
2
,
s
->
yuv_color
[
0
]
*
mult
);
AV_WN16
(
f
->
data
[
1
]
+
chromay
*
f
->
linesize
[
1
]
+
chromax
*
2
,
s
->
yuv_color
[
1
]
*
mult
);
AV_WN16
(
f
->
data
[
2
]
+
chromay
*
f
->
linesize
[
2
]
+
chromax
*
2
,
s
->
yuv_color
[
2
]
*
mult
);
}
static
int
filter8_brng
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
...
@@ -210,7 +245,42 @@ static int filter_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
chromav
<
16
||
chromav
>
240
;
score
+=
filt
;
if
(
out
&&
filt
)
burn_frame
(
s
,
out
,
x
,
y
);
burn_frame8
(
s
,
out
,
x
,
y
);
}
}
return
score
;
}
static
int
filter16_brng
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
AVFrame
*
in
=
td
->
in
;
AVFrame
*
out
=
td
->
out
;
const
int
mult
=
1
<<
(
s
->
depth
-
8
);
const
int
w
=
in
->
width
;
const
int
h
=
in
->
height
;
const
int
slice_start
=
(
h
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
h
*
(
jobnr
+
1
))
/
nb_jobs
;
int
x
,
y
,
score
=
0
;
for
(
y
=
slice_start
;
y
<
slice_end
;
y
++
)
{
const
int
yc
=
y
>>
s
->
vsub
;
const
uint16_t
*
pluma
=
(
uint16_t
*
)
&
in
->
data
[
0
][
y
*
in
->
linesize
[
0
]];
const
uint16_t
*
pchromau
=
(
uint16_t
*
)
&
in
->
data
[
1
][
yc
*
in
->
linesize
[
1
]];
const
uint16_t
*
pchromav
=
(
uint16_t
*
)
&
in
->
data
[
2
][
yc
*
in
->
linesize
[
2
]];
for
(
x
=
0
;
x
<
w
;
x
++
)
{
const
int
xc
=
x
>>
s
->
hsub
;
const
int
luma
=
pluma
[
x
];
const
int
chromau
=
pchromau
[
xc
];
const
int
chromav
=
pchromav
[
xc
];
const
int
filt
=
luma
<
16
*
mult
||
luma
>
235
*
mult
||
chromau
<
16
*
mult
||
chromau
>
240
*
mult
||
chromav
<
16
*
mult
||
chromav
>
240
*
mult
;
score
+=
filt
;
if
(
out
&&
filt
)
burn_frame16
(
s
,
out
,
x
,
y
);
}
}
return
score
;
...
...
@@ -221,7 +291,7 @@ static int filter_tout_outlier(uint8_t x, uint8_t y, uint8_t z)
return
((
abs
(
x
-
y
)
+
abs
(
z
-
y
))
/
2
)
-
abs
(
z
-
x
)
>
4
;
// make 4 configurable?
}
static
int
filter_tout
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
static
int
filter
8
_tout
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
...
@@ -255,14 +325,55 @@ static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
filt
=
FILTER3
(
2
)
&&
FILTER3
(
1
);
score
+=
filt
;
if
(
filt
&&
out
)
burn_frame
(
s
,
out
,
x
,
y
);
burn_frame8
(
s
,
out
,
x
,
y
);
}
}
else
{
for
(
x
=
1
;
x
<
w
-
1
;
x
++
)
{
filt
=
FILTER3
(
1
);
score
+=
filt
;
if
(
filt
&&
out
)
burn_frame8
(
s
,
out
,
x
,
y
);
}
}
}
return
score
;
}
static
int
filter16_tout
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
AVFrame
*
in
=
td
->
in
;
AVFrame
*
out
=
td
->
out
;
const
int
w
=
in
->
width
;
const
int
h
=
in
->
height
;
const
int
slice_start
=
(
h
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
h
*
(
jobnr
+
1
))
/
nb_jobs
;
const
uint16_t
*
p
=
(
uint16_t
*
)
in
->
data
[
0
];
int
lw
=
in
->
linesize
[
0
]
/
2
;
int
x
,
y
,
score
=
0
,
filt
;
for
(
y
=
slice_start
;
y
<
slice_end
;
y
++
)
{
if
(
y
-
1
<
0
||
y
+
1
>=
h
)
continue
;
// detect two pixels above and below (to eliminate interlace artefacts)
// should check that video format is infact interlaced.
if
(
y
-
2
>=
0
&&
y
+
2
<
h
)
{
for
(
x
=
1
;
x
<
w
-
1
;
x
++
)
{
filt
=
FILTER3
(
2
)
&&
FILTER3
(
1
);
score
+=
filt
;
if
(
filt
&&
out
)
burn_frame16
(
s
,
out
,
x
,
y
);
}
}
else
{
for
(
x
=
1
;
x
<
w
-
1
;
x
++
)
{
filt
=
FILTER3
(
1
);
score
+=
filt
;
if
(
filt
&&
out
)
burn_frame
(
s
,
out
,
x
,
y
);
burn_frame
16
(
s
,
out
,
x
,
y
);
}
}
}
...
...
@@ -271,7 +382,7 @@ static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define VREP_START 4
static
int
filter_vrep
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
static
int
filter
8
_vrep
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
...
@@ -300,24 +411,60 @@ static int filter_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
score
+=
filt
;
if
(
filt
&&
out
)
for
(
x
=
0
;
x
<
w
;
x
++
)
burn_frame
(
s
,
out
,
x
,
y
);
burn_frame8
(
s
,
out
,
x
,
y
);
}
return
score
*
w
;
}
static
int
filter16_vrep
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
AVFrame
*
in
=
td
->
in
;
AVFrame
*
out
=
td
->
out
;
const
int
w
=
in
->
width
;
const
int
h
=
in
->
height
;
const
int
slice_start
=
(
h
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
h
*
(
jobnr
+
1
))
/
nb_jobs
;
const
uint16_t
*
p
=
(
uint16_t
*
)
in
->
data
[
0
];
const
int
lw
=
in
->
linesize
[
0
]
/
2
;
int
x
,
y
,
score
=
0
;
for
(
y
=
slice_start
;
y
<
slice_end
;
y
++
)
{
const
int
y2lw
=
(
y
-
VREP_START
)
*
lw
;
const
int
ylw
=
y
*
lw
;
int64_t
totdiff
=
0
;
int
filt
;
if
(
y
<
VREP_START
)
continue
;
for
(
x
=
0
;
x
<
w
;
x
++
)
totdiff
+=
abs
(
p
[
y2lw
+
x
]
-
p
[
ylw
+
x
]);
filt
=
totdiff
<
w
;
score
+=
filt
;
if
(
filt
&&
out
)
for
(
x
=
0
;
x
<
w
;
x
++
)
burn_frame16
(
s
,
out
,
x
,
y
);
}
return
score
*
w
;
}
static
const
struct
{
const
char
*
name
;
int
(
*
process
)(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
);
int
(
*
process8
)(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
);
int
(
*
process16
)(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
);
}
filters_def
[]
=
{
{
"TOUT"
,
filter_tout
},
{
"VREP"
,
filter_vrep
},
{
"BRNG"
,
filter_brng
},
{
"TOUT"
,
filter
8_tout
,
filter16
_tout
},
{
"VREP"
,
filter
8_vrep
,
filter16
_vrep
},
{
"BRNG"
,
filter
8_brng
,
filter16
_brng
},
{
NULL
}
};
#define DEPTH 256
static
int
compute_sat_hue_metrics
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
static
int
compute_sat_hue_metrics
8
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
int
i
,
j
;
ThreadDataHueSatMetrics
*
td
=
arg
;
...
...
@@ -355,7 +502,46 @@ static int compute_sat_hue_metrics(AVFilterContext *ctx, void *arg, int jobnr, i
return
0
;
}
static
int
filter_frame
(
AVFilterLink
*
link
,
AVFrame
*
in
)
static
int
compute_sat_hue_metrics16
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
int
i
,
j
;
ThreadDataHueSatMetrics
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
AVFrame
*
src
=
td
->
src
;
AVFrame
*
dst_sat
=
td
->
dst_sat
;
AVFrame
*
dst_hue
=
td
->
dst_hue
;
const
int
mid
=
1
<<
(
s
->
depth
-
1
);
const
int
slice_start
=
(
s
->
chromah
*
jobnr
)
/
nb_jobs
;
const
int
slice_end
=
(
s
->
chromah
*
(
jobnr
+
1
))
/
nb_jobs
;
const
int
lsz_u
=
src
->
linesize
[
1
]
/
2
;
const
int
lsz_v
=
src
->
linesize
[
2
]
/
2
;
const
uint16_t
*
p_u
=
(
uint16_t
*
)
src
->
data
[
1
]
+
slice_start
*
lsz_u
;
const
uint16_t
*
p_v
=
(
uint16_t
*
)
src
->
data
[
2
]
+
slice_start
*
lsz_v
;
const
int
lsz_sat
=
dst_sat
->
linesize
[
0
]
/
2
;
const
int
lsz_hue
=
dst_hue
->
linesize
[
0
]
/
2
;
uint16_t
*
p_sat
=
(
uint16_t
*
)
dst_sat
->
data
[
0
]
+
slice_start
*
lsz_sat
;
uint16_t
*
p_hue
=
(
uint16_t
*
)
dst_hue
->
data
[
0
]
+
slice_start
*
lsz_hue
;
for
(
j
=
slice_start
;
j
<
slice_end
;
j
++
)
{
for
(
i
=
0
;
i
<
s
->
chromaw
;
i
++
)
{
const
int
yuvu
=
p_u
[
i
];
const
int
yuvv
=
p_v
[
i
];
p_sat
[
i
]
=
hypot
(
yuvu
-
mid
,
yuvv
-
mid
);
// int or round?
((
int16_t
*
)
p_hue
)[
i
]
=
floor
((
180
/
M_PI
)
*
atan2f
(
yuvu
-
mid
,
yuvv
-
mid
)
+
180
);
}
p_u
+=
lsz_u
;
p_v
+=
lsz_v
;
p_sat
+=
lsz_sat
;
p_hue
+=
lsz_hue
;
}
return
0
;
}
static
int
filter_frame8
(
AVFilterLink
*
link
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
link
->
dst
;
SignalstatsContext
*
s
=
ctx
->
priv
;
...
...
@@ -409,7 +595,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
av_frame_make_writable
(
out
);
}
ctx
->
internal
->
execute
(
ctx
,
compute_sat_hue_metrics
,
&
td_huesat
,
ctx
->
internal
->
execute
(
ctx
,
compute_sat_hue_metrics
8
,
&
td_huesat
,
NULL
,
FFMIN
(
s
->
chromah
,
ctx
->
graph
->
nb_threads
));
// Calculate luma histogram and difference with previous frame or field.
...
...
@@ -449,7 +635,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
.
out
=
out
!=
in
&&
s
->
outfilter
==
fil
?
out
:
NULL
,
};
memset
(
s
->
jobs_rets
,
0
,
s
->
nb_jobs
*
sizeof
(
*
s
->
jobs_rets
));
ctx
->
internal
->
execute
(
ctx
,
filters_def
[
fil
].
process
,
ctx
->
internal
->
execute
(
ctx
,
filters_def
[
fil
].
process
8
,
&
td
,
s
->
jobs_rets
,
s
->
nb_jobs
);
for
(
i
=
0
;
i
<
s
->
nb_jobs
;
i
++
)
filtot
[
fil
]
+=
s
->
jobs_rets
[
i
];
...
...
@@ -563,6 +749,224 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
return
ff_filter_frame
(
outlink
,
out
);
}
static
int
filter_frame16
(
AVFilterLink
*
link
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
link
->
dst
;
SignalstatsContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
AVFrame
*
out
=
in
;
int
i
,
j
;
int
w
=
0
,
cw
=
0
,
// in
pw
=
0
,
cpw
=
0
;
// prev
int
fil
;
char
metabuf
[
128
];
unsigned
int
*
histy
=
s
->
histy
,
*
histu
=
s
->
histu
,
*
histv
=
s
->
histv
,
histhue
[
360
]
=
{
0
},
*
histsat
=
s
->
histsat
;
int
miny
=
-
1
,
minu
=
-
1
,
minv
=
-
1
;
int
maxy
=
-
1
,
maxu
=
-
1
,
maxv
=
-
1
;
int
lowy
=
-
1
,
lowu
=
-
1
,
lowv
=
-
1
;
int
highy
=
-
1
,
highu
=
-
1
,
highv
=
-
1
;
int
minsat
=
-
1
,
maxsat
=
-
1
,
lowsat
=
-
1
,
highsat
=
-
1
;
int
lowp
,
highp
,
clowp
,
chighp
;
int
accy
,
accu
,
accv
;
int
accsat
,
acchue
=
0
;
int
medhue
,
maxhue
;
int64_t
toty
=
0
,
totu
=
0
,
totv
=
0
,
totsat
=
0
;
int64_t
tothue
=
0
;
int64_t
dify
=
0
,
difu
=
0
,
difv
=
0
;
int
filtot
[
FILT_NUMB
]
=
{
0
};
AVFrame
*
prev
;
AVFrame
*
sat
=
s
->
frame_sat
;
AVFrame
*
hue
=
s
->
frame_hue
;
const
uint8_t
*
p_sat
=
sat
->
data
[
0
];
const
uint8_t
*
p_hue
=
hue
->
data
[
0
];
const
int
lsz_sat
=
sat
->
linesize
[
0
];
const
int
lsz_hue
=
hue
->
linesize
[
0
];
ThreadDataHueSatMetrics
td_huesat
=
{
.
src
=
in
,
.
dst_sat
=
sat
,
.
dst_hue
=
hue
,
};
if
(
!
s
->
frame_prev
)
s
->
frame_prev
=
av_frame_clone
(
in
);
prev
=
s
->
frame_prev
;
if
(
s
->
outfilter
!=
FILTER_NONE
)
{
out
=
av_frame_clone
(
in
);
av_frame_make_writable
(
out
);
}
ctx
->
internal
->
execute
(
ctx
,
compute_sat_hue_metrics16
,
&
td_huesat
,
NULL
,
FFMIN
(
s
->
chromah
,
ctx
->
graph
->
nb_threads
));
// Calculate luma histogram and difference with previous frame or field.
memset
(
s
->
histy
,
0
,
(
1
<<
s
->
depth
)
*
sizeof
(
*
s
->
histy
));
for
(
j
=
0
;
j
<
link
->
h
;
j
++
)
{
for
(
i
=
0
;
i
<
link
->
w
;
i
++
)
{
const
int
yuv
=
AV_RN16
(
in
->
data
[
0
]
+
w
+
i
*
2
);
histy
[
yuv
]
++
;
dify
+=
abs
(
yuv
-
AV_RN16
(
prev
->
data
[
0
]
+
pw
+
i
*
2
));
}
w
+=
in
->
linesize
[
0
];
pw
+=
prev
->
linesize
[
0
];
}
// Calculate chroma histogram and difference with previous frame or field.
memset
(
s
->
histu
,
0
,
(
1
<<
s
->
depth
)
*
sizeof
(
*
s
->
histu
));
memset
(
s
->
histv
,
0
,
(
1
<<
s
->
depth
)
*
sizeof
(
*
s
->
histv
));
memset
(
s
->
histsat
,
0
,
(
1
<<
s
->
depth
)
*
sizeof
(
*
s
->
histsat
));
for
(
j
=
0
;
j
<
s
->
chromah
;
j
++
)
{
for
(
i
=
0
;
i
<
s
->
chromaw
;
i
++
)
{
const
int
yuvu
=
AV_RN16
(
in
->
data
[
1
]
+
cw
+
i
*
2
);
const
int
yuvv
=
AV_RN16
(
in
->
data
[
2
]
+
cw
+
i
*
2
);
histu
[
yuvu
]
++
;
difu
+=
abs
(
yuvu
-
AV_RN16
(
prev
->
data
[
1
]
+
cpw
+
i
*
2
));
histv
[
yuvv
]
++
;
difv
+=
abs
(
yuvv
-
AV_RN16
(
prev
->
data
[
2
]
+
cpw
+
i
*
2
));
histsat
[
p_sat
[
i
]]
++
;
histhue
[((
int16_t
*
)
p_hue
)[
i
]]
++
;
}
cw
+=
in
->
linesize
[
1
];
cpw
+=
prev
->
linesize
[
1
];
p_sat
+=
lsz_sat
;
p_hue
+=
lsz_hue
;
}
for
(
fil
=
0
;
fil
<
FILT_NUMB
;
fil
++
)
{
if
(
s
->
filters
&
1
<<
fil
)
{
ThreadData
td
=
{
.
in
=
in
,
.
out
=
out
!=
in
&&
s
->
outfilter
==
fil
?
out
:
NULL
,
};
memset
(
s
->
jobs_rets
,
0
,
s
->
nb_jobs
*
sizeof
(
*
s
->
jobs_rets
));
ctx
->
internal
->
execute
(
ctx
,
filters_def
[
fil
].
process16
,
&
td
,
s
->
jobs_rets
,
s
->
nb_jobs
);
for
(
i
=
0
;
i
<
s
->
nb_jobs
;
i
++
)
filtot
[
fil
]
+=
s
->
jobs_rets
[
i
];
}
}
// find low / high based on histogram percentile
// these only need to be calculated once.
lowp
=
lrint
(
s
->
fs
*
10
/
100
.);
highp
=
lrint
(
s
->
fs
*
90
/
100
.);
clowp
=
lrint
(
s
->
cfs
*
10
/
100
.);
chighp
=
lrint
(
s
->
cfs
*
90
/
100
.);
accy
=
accu
=
accv
=
accsat
=
0
;
for
(
fil
=
0
;
fil
<
1
<<
s
->
depth
;
fil
++
)
{
if
(
miny
<
0
&&
histy
[
fil
])
miny
=
fil
;
if
(
minu
<
0
&&
histu
[
fil
])
minu
=
fil
;
if
(
minv
<
0
&&
histv
[
fil
])
minv
=
fil
;
if
(
minsat
<
0
&&
histsat
[
fil
])
minsat
=
fil
;
if
(
histy
[
fil
])
maxy
=
fil
;
if
(
histu
[
fil
])
maxu
=
fil
;
if
(
histv
[
fil
])
maxv
=
fil
;
if
(
histsat
[
fil
])
maxsat
=
fil
;
toty
+=
histy
[
fil
]
*
fil
;
totu
+=
histu
[
fil
]
*
fil
;
totv
+=
histv
[
fil
]
*
fil
;
totsat
+=
histsat
[
fil
]
*
fil
;
accy
+=
histy
[
fil
];
accu
+=
histu
[
fil
];
accv
+=
histv
[
fil
];
accsat
+=
histsat
[
fil
];
if
(
lowy
==
-
1
&&
accy
>=
lowp
)
lowy
=
fil
;
if
(
lowu
==
-
1
&&
accu
>=
clowp
)
lowu
=
fil
;
if
(
lowv
==
-
1
&&
accv
>=
clowp
)
lowv
=
fil
;
if
(
lowsat
==
-
1
&&
accsat
>=
clowp
)
lowsat
=
fil
;
if
(
highy
==
-
1
&&
accy
>=
highp
)
highy
=
fil
;
if
(
highu
==
-
1
&&
accu
>=
chighp
)
highu
=
fil
;
if
(
highv
==
-
1
&&
accv
>=
chighp
)
highv
=
fil
;
if
(
highsat
==
-
1
&&
accsat
>=
chighp
)
highsat
=
fil
;
}
maxhue
=
histhue
[
0
];
medhue
=
-
1
;
for
(
fil
=
0
;
fil
<
360
;
fil
++
)
{
tothue
+=
histhue
[
fil
]
*
fil
;
acchue
+=
histhue
[
fil
];
if
(
medhue
==
-
1
&&
acchue
>
s
->
cfs
/
2
)
medhue
=
fil
;
if
(
histhue
[
fil
]
>
maxhue
)
{
maxhue
=
histhue
[
fil
];
}
}
av_frame_free
(
&
s
->
frame_prev
);
s
->
frame_prev
=
av_frame_clone
(
in
);
SET_META
(
"YMIN"
,
"%d"
,
miny
);
SET_META
(
"YLOW"
,
"%d"
,
lowy
);
SET_META
(
"YAVG"
,
"%g"
,
1
.
0
*
toty
/
s
->
fs
);
SET_META
(
"YHIGH"
,
"%d"
,
highy
);
SET_META
(
"YMAX"
,
"%d"
,
maxy
);
SET_META
(
"UMIN"
,
"%d"
,
minu
);
SET_META
(
"ULOW"
,
"%d"
,
lowu
);
SET_META
(
"UAVG"
,
"%g"
,
1
.
0
*
totu
/
s
->
cfs
);
SET_META
(
"UHIGH"
,
"%d"
,
highu
);
SET_META
(
"UMAX"
,
"%d"
,
maxu
);
SET_META
(
"VMIN"
,
"%d"
,
minv
);
SET_META
(
"VLOW"
,
"%d"
,
lowv
);
SET_META
(
"VAVG"
,
"%g"
,
1
.
0
*
totv
/
s
->
cfs
);
SET_META
(
"VHIGH"
,
"%d"
,
highv
);
SET_META
(
"VMAX"
,
"%d"
,
maxv
);
SET_META
(
"SATMIN"
,
"%d"
,
minsat
);
SET_META
(
"SATLOW"
,
"%d"
,
lowsat
);
SET_META
(
"SATAVG"
,
"%g"
,
1
.
0
*
totsat
/
s
->
cfs
);
SET_META
(
"SATHIGH"
,
"%d"
,
highsat
);
SET_META
(
"SATMAX"
,
"%d"
,
maxsat
);
SET_META
(
"HUEMED"
,
"%d"
,
medhue
);
SET_META
(
"HUEAVG"
,
"%g"
,
1
.
0
*
tothue
/
s
->
cfs
);
SET_META
(
"YDIF"
,
"%g"
,
1
.
0
*
dify
/
s
->
fs
);
SET_META
(
"UDIF"
,
"%g"
,
1
.
0
*
difu
/
s
->
cfs
);
SET_META
(
"VDIF"
,
"%g"
,
1
.
0
*
difv
/
s
->
cfs
);
for
(
fil
=
0
;
fil
<
FILT_NUMB
;
fil
++
)
{
if
(
s
->
filters
&
1
<<
fil
)
{
char
metaname
[
128
];
snprintf
(
metabuf
,
sizeof
(
metabuf
),
"%g"
,
1
.
0
*
filtot
[
fil
]
/
s
->
fs
);
snprintf
(
metaname
,
sizeof
(
metaname
),
"lavfi.signalstats.%s"
,
filters_def
[
fil
].
name
);
av_dict_set
(
&
out
->
metadata
,
metaname
,
metabuf
,
0
);
}
}
if
(
in
!=
out
)
av_frame_free
(
&
in
);
return
ff_filter_frame
(
outlink
,
out
);
}
static
int
filter_frame
(
AVFilterLink
*
link
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
link
->
dst
;
SignalstatsContext
*
s
=
ctx
->
priv
;
if
(
s
->
depth
>
8
)
return
filter_frame16
(
link
,
in
);
else
return
filter_frame8
(
link
,
in
);
}
static
const
AVFilterPad
signalstats_inputs
[]
=
{
{
.
name
=
"default"
,
...
...
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