Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
FFmpeg
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
libremedia
Tethys
FFmpeg
Commits
ee56d9bc
Commit
ee56d9bc
authored
8 years ago
by
Paul B Mahol
Browse files
Options
Downloads
Patches
Plain Diff
avfilter/vf_signalstats: add >8 bit depth support
parent
7ae52f8a
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
libavfilter/vf_signalstats.c
+420
-16
420 additions, 16 deletions
libavfilter/vf_signalstats.c
with
420 additions
and
16 deletions
libavfilter/vf_signalstats.c
+
420
−
16
View file @
ee56d9bc
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#include
"libavutil/intreadwrite.h"
#include
"libavutil/opt.h"
#include
"libavutil/opt.h"
#include
"libavutil/pixdesc.h"
#include
"libavutil/pixdesc.h"
#include
"internal.h"
#include
"internal.h"
...
@@ -38,6 +39,7 @@ typedef struct {
...
@@ -38,6 +39,7 @@ typedef struct {
int
chromaw
;
// width of chroma plane
int
chromaw
;
// width of chroma plane
int
hsub
;
// horizontal subsampling
int
hsub
;
// horizontal subsampling
int
vsub
;
// vertical subsampling
int
vsub
;
// vertical subsampling
int
depth
;
// pixel depth
int
fs
;
// pixel count per frame
int
fs
;
// pixel count per frame
int
cfs
;
// pixel count per frame of chroma planes
int
cfs
;
// pixel count per frame of chroma planes
int
outfilter
;
// FilterMode
int
outfilter
;
// FilterMode
...
@@ -48,6 +50,8 @@ typedef struct {
...
@@ -48,6 +50,8 @@ typedef struct {
int
nb_jobs
;
int
nb_jobs
;
int
*
jobs_rets
;
int
*
jobs_rets
;
int
*
histy
,
*
histu
,
*
histv
,
*
histsat
;
AVFrame
*
frame_sat
;
AVFrame
*
frame_sat
;
AVFrame
*
frame_hue
;
AVFrame
*
frame_hue
;
}
SignalstatsContext
;
}
SignalstatsContext
;
...
@@ -105,6 +109,10 @@ static av_cold void uninit(AVFilterContext *ctx)
...
@@ -105,6 +109,10 @@ static av_cold void uninit(AVFilterContext *ctx)
av_frame_free
(
&
s
->
frame_sat
);
av_frame_free
(
&
s
->
frame_sat
);
av_frame_free
(
&
s
->
frame_hue
);
av_frame_free
(
&
s
->
frame_hue
);
av_freep
(
&
s
->
jobs_rets
);
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
)
static
int
query_formats
(
AVFilterContext
*
ctx
)
...
@@ -115,6 +123,13 @@ static int query_formats(AVFilterContext *ctx)
...
@@ -115,6 +123,13 @@ static int query_formats(AVFilterContext *ctx)
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUV440P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ411P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ411P
,
AV_PIX_FMT_YUVJ440P
,
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
AV_PIX_FMT_NONE
};
};
...
@@ -150,6 +165,16 @@ static int config_props(AVFilterLink *outlink)
...
@@ -150,6 +165,16 @@ static int config_props(AVFilterLink *outlink)
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
outlink
->
format
);
const
AVPixFmtDescriptor
*
desc
=
av_pix_fmt_desc_get
(
outlink
->
format
);
s
->
hsub
=
desc
->
log2_chroma_w
;
s
->
hsub
=
desc
->
log2_chroma_w
;
s
->
vsub
=
desc
->
log2_chroma_h
;
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
->
w
=
inlink
->
w
;
outlink
->
h
=
inlink
->
h
;
outlink
->
h
=
inlink
->
h
;
...
@@ -173,7 +198,7 @@ static int config_props(AVFilterLink *outlink)
...
@@ -173,7 +198,7 @@ static int config_props(AVFilterLink *outlink)
return
0
;
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
chromax
=
x
>>
s
->
hsub
;
const
int
chromay
=
y
>>
s
->
vsub
;
const
int
chromay
=
y
>>
s
->
vsub
;
...
@@ -182,7 +207,17 @@ static void burn_frame(const SignalstatsContext *s, AVFrame *f, int x, int y)
...
@@ -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
];
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
;
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
@@ -210,7 +245,42 @@ static int filter_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
...
@@ -210,7 +245,42 @@ static int filter_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
chromav
<
16
||
chromav
>
240
;
chromav
<
16
||
chromav
>
240
;
score
+=
filt
;
score
+=
filt
;
if
(
out
&&
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
;
return
score
;
...
@@ -221,7 +291,7 @@ static int filter_tout_outlier(uint8_t x, uint8_t y, uint8_t z)
...
@@ -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?
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
;
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
@@ -255,14 +325,55 @@ static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
...
@@ -255,14 +325,55 @@ static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
filt
=
FILTER3
(
2
)
&&
FILTER3
(
1
);
filt
=
FILTER3
(
2
)
&&
FILTER3
(
1
);
score
+=
filt
;
score
+=
filt
;
if
(
filt
&&
out
)
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
{
}
else
{
for
(
x
=
1
;
x
<
w
-
1
;
x
++
)
{
for
(
x
=
1
;
x
<
w
-
1
;
x
++
)
{
filt
=
FILTER3
(
1
);
filt
=
FILTER3
(
1
);
score
+=
filt
;
score
+=
filt
;
if
(
filt
&&
out
)
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)
...
@@ -271,7 +382,7 @@ static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define VREP_START 4
#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
;
ThreadData
*
td
=
arg
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
const
SignalstatsContext
*
s
=
ctx
->
priv
;
...
@@ -300,24 +411,60 @@ static int filter_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
...
@@ -300,24 +411,60 @@ static int filter_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
score
+=
filt
;
score
+=
filt
;
if
(
filt
&&
out
)
if
(
filt
&&
out
)
for
(
x
=
0
;
x
<
w
;
x
++
)
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
;
return
score
*
w
;
}
}
static
const
struct
{
static
const
struct
{
const
char
*
name
;
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
[]
=
{
}
filters_def
[]
=
{
{
"TOUT"
,
filter_tout
},
{
"TOUT"
,
filter
8_tout
,
filter16
_tout
},
{
"VREP"
,
filter_vrep
},
{
"VREP"
,
filter
8_vrep
,
filter16
_vrep
},
{
"BRNG"
,
filter_brng
},
{
"BRNG"
,
filter
8_brng
,
filter16
_brng
},
{
NULL
}
{
NULL
}
};
};
#define DEPTH 256
#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
;
int
i
,
j
;
ThreadDataHueSatMetrics
*
td
=
arg
;
ThreadDataHueSatMetrics
*
td
=
arg
;
...
@@ -355,7 +502,46 @@ static int compute_sat_hue_metrics(AVFilterContext *ctx, void *arg, int jobnr, i
...
@@ -355,7 +502,46 @@ static int compute_sat_hue_metrics(AVFilterContext *ctx, void *arg, int jobnr, i
return
0
;
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
;
AVFilterContext
*
ctx
=
link
->
dst
;
SignalstatsContext
*
s
=
ctx
->
priv
;
SignalstatsContext
*
s
=
ctx
->
priv
;
...
@@ -409,7 +595,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
...
@@ -409,7 +595,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
av_frame_make_writable
(
out
);
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
));
NULL
,
FFMIN
(
s
->
chromah
,
ctx
->
graph
->
nb_threads
));
// Calculate luma histogram and difference with previous frame or field.
// Calculate luma histogram and difference with previous frame or field.
...
@@ -449,7 +635,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
...
@@ -449,7 +635,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
.
out
=
out
!=
in
&&
s
->
outfilter
==
fil
?
out
:
NULL
,
.
out
=
out
!=
in
&&
s
->
outfilter
==
fil
?
out
:
NULL
,
};
};
memset
(
s
->
jobs_rets
,
0
,
s
->
nb_jobs
*
sizeof
(
*
s
->
jobs_rets
));
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
);
&
td
,
s
->
jobs_rets
,
s
->
nb_jobs
);
for
(
i
=
0
;
i
<
s
->
nb_jobs
;
i
++
)
for
(
i
=
0
;
i
<
s
->
nb_jobs
;
i
++
)
filtot
[
fil
]
+=
s
->
jobs_rets
[
i
];
filtot
[
fil
]
+=
s
->
jobs_rets
[
i
];
...
@@ -563,6 +749,224 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
...
@@ -563,6 +749,224 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
return
ff_filter_frame
(
outlink
,
out
);
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
[]
=
{
static
const
AVFilterPad
signalstats_inputs
[]
=
{
{
{
.
name
=
"default"
,
.
name
=
"default"
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment