Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
399c7ab9
Commit
399c7ab9
authored
Apr 25, 2017
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter: add video oscilloscope filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
8341d0dd
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
463 additions
and
0 deletions
+463
-0
Changelog
Changelog
+2
-0
filters.texi
doc/filters.texi
+78
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
vf_datascope.c
libavfilter/vf_datascope.c
+381
-0
No files found.
Changelog
View file @
399c7ab9
...
@@ -5,6 +5,8 @@ version <next>:
...
@@ -5,6 +5,8 @@ version <next>:
- deflicker video filter
- deflicker video filter
- doubleweave video filter
- doubleweave video filter
- lumakey video filter
- lumakey video filter
- pixscope video filter
- oscilloscope video filter
version 3.3:
version 3.3:
- CrystalHD decoder moved to new decode API
- CrystalHD decoder moved to new decode API
...
...
doc/filters.texi
View file @
399c7ab9
...
@@ -10233,6 +10233,84 @@ other parameters is 0.
...
@@ -10233,6 +10233,84 @@ other parameters is 0.
These parameters correspond to the parameters assigned to the
These parameters correspond to the parameters assigned to the
libopencv function @code{cvSmooth}.
libopencv function @code{cvSmooth}.
@section oscilloscope
2D Video Oscilloscope.
Useful to measure spatial impulse, step responses, chroma delays, etc.
It accepts the following parameters:
@table @option
@item x
Set scope center x position.
@item y
Set scope center y position.
@item s
Set scope size, relative to frame diagonal.
@item t
Set scope tilt/rotation.
@item o
Set trace opacity.
@item tx
Set trace center x position.
@item ty
Set trace center y position.
@item tw
Set trace width, relative to width of frame.
@item th
Set trace height, relative to height of frame.
@item c
Set which components to trace. By default it traces first three components.
@item g
Draw trace grid. By default is enabled.
@item st
Draw some statistics. By default is enabled.
@item sc
Draw scope. By default is enabled.
@end table
@subsection Examples
@itemize
@item
Inspect full first row of video frame.
@example
oscilloscope=x=0.5:y=0:s=1
@end example
@item
Inspect full last row of video frame.
@example
oscilloscope=x=0.5:y=1:s=1
@end example
@item
Inspect full 5th line of video frame of height 1080.
@example
oscilloscope=x=0.5:y=5/1080:s=1
@end example
@item
Inspect full last column of video frame.
@example
oscilloscope=x=1:y=0.5:s=1:t=1
@end example
@end itemize
@anchor{overlay}
@anchor{overlay}
@section overlay
@section overlay
...
...
libavfilter/Makefile
View file @
399c7ab9
...
@@ -236,6 +236,7 @@ OBJS-$(CONFIG_NULL_FILTER) += vf_null.o
...
@@ -236,6 +236,7 @@ OBJS-$(CONFIG_NULL_FILTER) += vf_null.o
OBJS-$(CONFIG_OCR_FILTER)
+=
vf_ocr.o
OBJS-$(CONFIG_OCR_FILTER)
+=
vf_ocr.o
OBJS-$(CONFIG_OCV_FILTER)
+=
vf_libopencv.o
OBJS-$(CONFIG_OCV_FILTER)
+=
vf_libopencv.o
OBJS-$(CONFIG_OPENCL)
+=
deshake_opencl.o
unsharp_opencl.o
OBJS-$(CONFIG_OPENCL)
+=
deshake_opencl.o
unsharp_opencl.o
OBJS-$(CONFIG_OSCILLOSCOPE_FILTER)
+=
vf_datascope.o
OBJS-$(CONFIG_OVERLAY_FILTER)
+=
vf_overlay.o
dualinput.o
framesync.o
OBJS-$(CONFIG_OVERLAY_FILTER)
+=
vf_overlay.o
dualinput.o
framesync.o
OBJS-$(CONFIG_OWDENOISE_FILTER)
+=
vf_owdenoise.o
OBJS-$(CONFIG_OWDENOISE_FILTER)
+=
vf_owdenoise.o
OBJS-$(CONFIG_PAD_FILTER)
+=
vf_pad.o
OBJS-$(CONFIG_PAD_FILTER)
+=
vf_pad.o
...
...
libavfilter/allfilters.c
View file @
399c7ab9
...
@@ -246,6 +246,7 @@ static void register_all(void)
...
@@ -246,6 +246,7 @@ static void register_all(void)
REGISTER_FILTER
(
NULL
,
null
,
vf
);
REGISTER_FILTER
(
NULL
,
null
,
vf
);
REGISTER_FILTER
(
OCR
,
ocr
,
vf
);
REGISTER_FILTER
(
OCR
,
ocr
,
vf
);
REGISTER_FILTER
(
OCV
,
ocv
,
vf
);
REGISTER_FILTER
(
OCV
,
ocv
,
vf
);
REGISTER_FILTER
(
OSCILLOSCOPE
,
oscilloscope
,
vf
);
REGISTER_FILTER
(
OVERLAY
,
overlay
,
vf
);
REGISTER_FILTER
(
OVERLAY
,
overlay
,
vf
);
REGISTER_FILTER
(
OWDENOISE
,
owdenoise
,
vf
);
REGISTER_FILTER
(
OWDENOISE
,
owdenoise
,
vf
);
REGISTER_FILTER
(
PAD
,
pad
,
vf
);
REGISTER_FILTER
(
PAD
,
pad
,
vf
);
...
...
libavfilter/vf_datascope.c
View file @
399c7ab9
...
@@ -641,3 +641,384 @@ AVFilter ff_vf_pixscope = {
...
@@ -641,3 +641,384 @@ AVFilter ff_vf_pixscope = {
.
inputs
=
pixscope_inputs
,
.
inputs
=
pixscope_inputs
,
.
outputs
=
pixscope_outputs
,
.
outputs
=
pixscope_outputs
,
};
};
typedef
struct
PixelValues
{
uint16_t
p
[
4
];
}
PixelValues
;
typedef
struct
OscilloscopeContext
{
const
AVClass
*
class
;
float
xpos
,
ypos
;
float
tx
,
ty
;
float
size
;
float
tilt
;
float
theight
,
twidth
;
float
o
;
int
components
;
int
grid
;
int
statistics
;
int
scope
;
int
x1
,
y1
,
x2
,
y2
;
int
ox
,
oy
;
int
height
,
width
;
int
max
;
int
nb_planes
;
int
nb_comps
;
int
is_rgb
;
uint8_t
rgba_map
[
4
];
FFDrawContext
draw
;
FFDrawColor
dark
;
FFDrawColor
black
;
FFDrawColor
white
;
FFDrawColor
green
;
FFDrawColor
blue
;
FFDrawColor
red
;
FFDrawColor
cyan
;
FFDrawColor
magenta
;
FFDrawColor
gray
;
FFDrawColor
*
colors
[
4
];
int
nb_values
;
PixelValues
*
values
;
void
(
*
pick_color
)(
FFDrawContext
*
draw
,
FFDrawColor
*
color
,
AVFrame
*
in
,
int
x
,
int
y
,
int
*
value
);
void
(
*
draw_trace
)(
struct
OscilloscopeContext
*
s
,
AVFrame
*
frame
);
}
OscilloscopeContext
;
#define OOFFSET(x) offsetof(OscilloscopeContext, x)
static
const
AVOption
oscilloscope_options
[]
=
{
{
"x"
,
"set scope x position"
,
OOFFSET
(
xpos
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
5
},
0
,
1
,
FLAGS
},
{
"y"
,
"set scope y position"
,
OOFFSET
(
ypos
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
5
},
0
,
1
,
FLAGS
},
{
"s"
,
"set scope size"
,
OOFFSET
(
size
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
8
},
0
,
1
,
FLAGS
},
{
"t"
,
"set scope tilt"
,
OOFFSET
(
tilt
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
5
},
0
,
1
,
FLAGS
},
{
"o"
,
"set trace opacity"
,
OOFFSET
(
o
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
8
},
0
,
1
,
FLAGS
},
{
"tx"
,
"set trace x position"
,
OOFFSET
(
tx
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
5
},
0
,
1
,
FLAGS
},
{
"ty"
,
"set trace y position"
,
OOFFSET
(
ty
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
9
},
0
,
1
,
FLAGS
},
{
"tw"
,
"set trace width"
,
OOFFSET
(
twidth
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
8
},.
1
,
1
,
FLAGS
},
{
"th"
,
"set trace height"
,
OOFFSET
(
theight
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
0
.
3
},.
1
,
1
,
FLAGS
},
{
"c"
,
"set components to trace"
,
OOFFSET
(
components
),
AV_OPT_TYPE_INT
,
{.
i64
=
7
},
0
,
15
,
FLAGS
},
{
"g"
,
"draw trace grid"
,
OOFFSET
(
grid
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
"st"
,
"draw statistics"
,
OOFFSET
(
statistics
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
"sc"
,
"draw scope"
,
OOFFSET
(
scope
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
oscilloscope
);
static
void
oscilloscope_uninit
(
AVFilterContext
*
ctx
)
{
OscilloscopeContext
*
s
=
ctx
->
priv
;
av_freep
(
&
s
->
values
);
}
static
void
draw_line
(
FFDrawContext
*
draw
,
int
x0
,
int
y0
,
int
x1
,
int
y1
,
AVFrame
*
out
,
FFDrawColor
*
color
)
{
int
dx
=
FFABS
(
x1
-
x0
),
sx
=
x0
<
x1
?
1
:
-
1
;
int
dy
=
FFABS
(
y1
-
y0
),
sy
=
y0
<
y1
?
1
:
-
1
;
int
err
=
(
dx
>
dy
?
dx
:
-
dy
)
/
2
,
e2
;
int
p
,
i
;
for
(;;)
{
if
(
x0
>=
0
&&
y0
>=
0
&&
x0
<
out
->
width
&&
y0
<
out
->
height
)
{
for
(
p
=
0
;
p
<
draw
->
nb_planes
;
p
++
)
{
if
(
draw
->
desc
->
comp
[
p
].
depth
==
8
)
{
if
(
draw
->
nb_planes
==
1
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
out
->
data
[
0
][
y0
*
out
->
linesize
[
0
]
+
x0
*
draw
->
pixelstep
[
0
]
+
i
]
=
color
->
comp
[
0
].
u8
[
i
];
}
}
else
{
out
->
data
[
p
][
out
->
linesize
[
p
]
*
(
y0
>>
draw
->
vsub
[
p
])
+
(
x0
>>
draw
->
hsub
[
p
])]
=
color
->
comp
[
p
].
u8
[
0
];
}
}
else
{
if
(
draw
->
nb_planes
==
1
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
AV_WN16
(
out
->
data
[
0
]
+
y0
*
out
->
linesize
[
0
]
+
2
*
(
x0
*
draw
->
pixelstep
[
0
]
+
i
),
color
->
comp
[
0
].
u16
[
i
]);
}
}
else
{
AV_WN16
(
out
->
data
[
p
]
+
out
->
linesize
[
p
]
*
(
y0
>>
draw
->
vsub
[
p
])
+
(
x0
>>
draw
->
hsub
[
p
])
*
2
,
color
->
comp
[
p
].
u16
[
0
]);
}
}
}
}
if
(
x0
==
x1
&&
y0
==
y1
)
break
;
e2
=
err
;
if
(
e2
>-
dx
)
{
err
-=
dy
;
x0
+=
sx
;
}
if
(
e2
<
dy
)
{
err
+=
dx
;
y0
+=
sy
;
}
}
}
static
void
draw_trace8
(
OscilloscopeContext
*
s
,
AVFrame
*
frame
)
{
int
i
,
c
;
for
(
i
=
1
;
i
<
s
->
nb_values
;
i
++
)
{
for
(
c
=
0
;
c
<
s
->
nb_comps
;
c
++
)
{
if
((
1
<<
c
)
&
s
->
components
)
{
int
x
=
i
*
s
->
width
/
s
->
nb_values
;
int
px
=
(
i
-
1
)
*
s
->
width
/
s
->
nb_values
;
int
py
=
s
->
height
-
s
->
values
[
i
-
1
].
p
[
c
]
*
s
->
height
/
256
;
int
y
=
s
->
height
-
s
->
values
[
i
].
p
[
c
]
*
s
->
height
/
256
;
draw_line
(
&
s
->
draw
,
s
->
ox
+
x
,
s
->
oy
+
y
,
s
->
ox
+
px
,
s
->
oy
+
py
,
frame
,
s
->
colors
[
c
]);
}
}
}
}
static
void
draw_trace16
(
OscilloscopeContext
*
s
,
AVFrame
*
frame
)
{
int
i
,
c
;
for
(
i
=
1
;
i
<
s
->
nb_values
;
i
++
)
{
for
(
c
=
0
;
c
<
s
->
nb_comps
;
c
++
)
{
if
((
1
<<
c
)
&
s
->
components
)
{
int
x
=
i
*
s
->
width
/
s
->
nb_values
;
int
px
=
(
i
-
1
)
*
s
->
width
/
s
->
nb_values
;
int
py
=
s
->
height
-
s
->
values
[
i
-
1
].
p
[
c
]
*
s
->
height
/
s
->
max
;
int
y
=
s
->
height
-
s
->
values
[
i
].
p
[
c
]
*
s
->
height
/
s
->
max
;
draw_line
(
&
s
->
draw
,
s
->
ox
+
x
,
s
->
oy
+
y
,
s
->
ox
+
px
,
s
->
oy
+
py
,
frame
,
s
->
colors
[
c
]);
}
}
}
}
static
int
oscilloscope_config_input
(
AVFilterLink
*
inlink
)
{
OscilloscopeContext
*
s
=
inlink
->
dst
->
priv
;
int
cx
,
cy
,
size
;
double
tilt
;
s
->
nb_planes
=
av_pix_fmt_count_planes
(
inlink
->
format
);
ff_draw_init
(
&
s
->
draw
,
inlink
->
format
,
0
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
dark
,
(
uint8_t
[]){
0
,
0
,
0
,
s
->
o
*
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
black
,
(
uint8_t
[]){
0
,
0
,
0
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
white
,
(
uint8_t
[]){
255
,
255
,
255
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
green
,
(
uint8_t
[]){
0
,
255
,
0
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
blue
,
(
uint8_t
[]){
0
,
0
,
255
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
red
,
(
uint8_t
[]){
255
,
0
,
0
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
cyan
,
(
uint8_t
[]){
0
,
255
,
255
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
magenta
,
(
uint8_t
[]){
255
,
0
,
255
,
255
}
);
ff_draw_color
(
&
s
->
draw
,
&
s
->
gray
,
(
uint8_t
[]){
128
,
128
,
128
,
255
}
);
s
->
nb_comps
=
s
->
draw
.
desc
->
nb_components
;
s
->
is_rgb
=
s
->
draw
.
desc
->
flags
&
AV_PIX_FMT_FLAG_RGB
;
if
(
s
->
is_rgb
)
{
s
->
colors
[
0
]
=
&
s
->
red
;
s
->
colors
[
1
]
=
&
s
->
green
;
s
->
colors
[
2
]
=
&
s
->
blue
;
s
->
colors
[
3
]
=
&
s
->
white
;
ff_fill_rgba_map
(
s
->
rgba_map
,
inlink
->
format
);
}
else
{
s
->
colors
[
0
]
=
&
s
->
white
;
s
->
colors
[
1
]
=
&
s
->
cyan
;
s
->
colors
[
2
]
=
&
s
->
magenta
;
s
->
colors
[
3
]
=
&
s
->
white
;
s
->
rgba_map
[
0
]
=
0
;
s
->
rgba_map
[
1
]
=
1
;
s
->
rgba_map
[
2
]
=
2
;
s
->
rgba_map
[
3
]
=
3
;
}
if
(
s
->
draw
.
desc
->
comp
[
0
].
depth
<=
8
)
{
s
->
pick_color
=
pick_color8
;
s
->
draw_trace
=
draw_trace8
;
}
else
{
s
->
pick_color
=
pick_color16
;
s
->
draw_trace
=
draw_trace16
;
}
s
->
max
=
(
1
<<
s
->
draw
.
desc
->
comp
[
0
].
depth
);
cx
=
s
->
xpos
*
(
inlink
->
w
-
1
);
cy
=
s
->
ypos
*
(
inlink
->
h
-
1
);
s
->
height
=
s
->
theight
*
inlink
->
h
;
s
->
width
=
s
->
twidth
*
inlink
->
w
;
size
=
hypot
(
inlink
->
w
,
inlink
->
h
);
s
->
values
=
av_calloc
(
size
,
sizeof
(
*
s
->
values
));
if
(
!
s
->
values
)
return
AVERROR
(
ENOMEM
);
size
*=
s
->
size
;
tilt
=
(
s
->
tilt
-
0
.
5
)
*
M_PI
;
s
->
x1
=
cx
-
size
/
2
.
0
*
cos
(
tilt
);
s
->
x2
=
cx
+
size
/
2
.
0
*
cos
(
tilt
);
s
->
y1
=
cy
-
size
/
2
.
0
*
sin
(
tilt
);
s
->
y2
=
cy
+
size
/
2
.
0
*
sin
(
tilt
);
s
->
ox
=
(
inlink
->
w
-
s
->
width
)
*
s
->
tx
;
s
->
oy
=
(
inlink
->
h
-
s
->
height
)
*
s
->
ty
;
return
0
;
}
static
void
draw_scope
(
OscilloscopeContext
*
s
,
int
x0
,
int
y0
,
int
x1
,
int
y1
,
AVFrame
*
out
,
PixelValues
*
p
,
int
state
)
{
int
dx
=
FFABS
(
x1
-
x0
),
sx
=
x0
<
x1
?
1
:
-
1
;
int
dy
=
FFABS
(
y1
-
y0
),
sy
=
y0
<
y1
?
1
:
-
1
;
int
err
=
(
dx
>
dy
?
dx
:
-
dy
)
/
2
,
e2
;
for
(;;)
{
if
(
x0
>=
0
&&
y0
>=
0
&&
x0
<
out
->
width
&&
y0
<
out
->
height
)
{
FFDrawColor
color
=
{
{
0
}
};
int
value
[
4
]
=
{
0
};
s
->
pick_color
(
&
s
->
draw
,
&
color
,
out
,
x0
,
y0
,
value
);
s
->
values
[
s
->
nb_values
].
p
[
0
]
=
value
[
0
];
s
->
values
[
s
->
nb_values
].
p
[
1
]
=
value
[
1
];
s
->
values
[
s
->
nb_values
].
p
[
2
]
=
value
[
2
];
s
->
values
[
s
->
nb_values
].
p
[
3
]
=
value
[
3
];
s
->
nb_values
++
;
if
(
s
->
scope
)
{
if
(
s
->
draw
.
desc
->
comp
[
0
].
depth
==
8
)
{
if
(
s
->
draw
.
nb_planes
==
1
)
{
int
i
;
for
(
i
=
0
;
i
<
s
->
draw
.
pixelstep
[
0
];
i
++
)
out
->
data
[
0
][
out
->
linesize
[
0
]
*
y0
+
x0
*
s
->
draw
.
pixelstep
[
0
]
+
i
]
=
255
*
((
s
->
nb_values
+
state
)
&
1
);
}
else
{
out
->
data
[
0
][
out
->
linesize
[
0
]
*
y0
+
x0
]
=
255
*
((
s
->
nb_values
+
state
)
&
1
);
}
}
else
{
if
(
s
->
draw
.
nb_planes
==
1
)
{
int
i
;
for
(
i
=
0
;
i
<
s
->
draw
.
pixelstep
[
0
];
i
++
)
AV_WN16
(
out
->
data
[
0
]
+
out
->
linesize
[
0
]
*
y0
+
2
*
x0
*
(
s
->
draw
.
pixelstep
[
0
]
+
i
),
(
s
->
max
-
1
)
*
((
s
->
nb_values
+
state
)
&
1
));
}
else
{
AV_WN16
(
out
->
data
[
0
]
+
out
->
linesize
[
0
]
*
y0
+
2
*
x0
,
(
s
->
max
-
1
)
*
((
s
->
nb_values
+
state
)
&
1
));
}
}
}
}
if
(
x0
==
x1
&&
y0
==
y1
)
break
;
e2
=
err
;
if
(
e2
>-
dx
)
{
err
-=
dy
;
x0
+=
sx
;
}
if
(
e2
<
dy
)
{
err
+=
dx
;
y0
+=
sy
;
}
}
}
static
int
oscilloscope_filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
frame
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
OscilloscopeContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
float
average
[
4
]
=
{
0
};
int
max
[
4
]
=
{
0
};
int
min
[
4
]
=
{
INT_MAX
,
INT_MAX
,
INT_MAX
,
INT_MAX
};
int
i
,
c
;
s
->
nb_values
=
0
;
draw_scope
(
s
,
s
->
x1
,
s
->
y1
,
s
->
x2
,
s
->
y2
,
frame
,
s
->
values
,
inlink
->
frame_count_in
&
1
);
ff_blend_rectangle
(
&
s
->
draw
,
&
s
->
dark
,
frame
->
data
,
frame
->
linesize
,
frame
->
width
,
frame
->
height
,
s
->
ox
,
s
->
oy
,
s
->
width
,
s
->
height
+
20
*
s
->
statistics
);
if
(
s
->
grid
)
{
ff_fill_rectangle
(
&
s
->
draw
,
&
s
->
gray
,
frame
->
data
,
frame
->
linesize
,
s
->
ox
,
s
->
oy
,
s
->
width
-
1
,
1
);
for
(
i
=
1
;
i
<
5
;
i
++
)
{
ff_fill_rectangle
(
&
s
->
draw
,
&
s
->
gray
,
frame
->
data
,
frame
->
linesize
,
s
->
ox
,
s
->
oy
+
i
*
(
s
->
height
-
1
)
/
4
,
s
->
width
,
1
);
}
for
(
i
=
0
;
i
<
10
;
i
++
)
{
ff_fill_rectangle
(
&
s
->
draw
,
&
s
->
gray
,
frame
->
data
,
frame
->
linesize
,
s
->
ox
+
i
*
(
s
->
width
-
1
)
/
10
,
s
->
oy
,
1
,
s
->
height
);
}
ff_fill_rectangle
(
&
s
->
draw
,
&
s
->
gray
,
frame
->
data
,
frame
->
linesize
,
s
->
ox
+
s
->
width
-
1
,
s
->
oy
,
1
,
s
->
height
);
}
s
->
draw_trace
(
s
,
frame
);
for
(
i
=
0
;
i
<
s
->
nb_values
;
i
++
)
{
for
(
c
=
0
;
c
<
s
->
nb_comps
;
c
++
)
{
if
((
1
<<
c
)
&
s
->
components
)
{
max
[
c
]
=
FFMAX
(
max
[
c
],
s
->
values
[
i
].
p
[
c
]);
min
[
c
]
=
FFMIN
(
min
[
c
],
s
->
values
[
i
].
p
[
c
]);
average
[
c
]
+=
s
->
values
[
i
].
p
[
c
];
}
}
}
for
(
c
=
0
;
c
<
s
->
nb_comps
;
c
++
)
{
average
[
c
]
/=
s
->
nb_values
;
}
if
(
s
->
statistics
&&
s
->
height
>
10
&&
s
->
width
>
280
*
av_popcount
(
s
->
components
))
{
for
(
c
=
0
,
i
=
0
;
c
<
s
->
nb_comps
;
c
++
)
{
if
((
1
<<
c
)
&
s
->
components
)
{
const
char
rgba
[
4
]
=
{
'R'
,
'G'
,
'B'
,
'A'
};
const
char
yuva
[
4
]
=
{
'Y'
,
'U'
,
'V'
,
'A'
};
char
text
[
128
];
snprintf
(
text
,
sizeof
(
text
),
"%c avg:%.1f min:%d max:%d
\n
"
,
s
->
is_rgb
?
rgba
[
c
]
:
yuva
[
c
],
average
[
s
->
rgba_map
[
c
]],
min
[
s
->
rgba_map
[
c
]],
max
[
s
->
rgba_map
[
c
]]);
draw_text
(
&
s
->
draw
,
frame
,
&
s
->
white
,
s
->
ox
+
2
+
280
*
i
++
,
s
->
oy
+
s
->
height
+
4
,
text
,
0
);
}
}
}
return
ff_filter_frame
(
outlink
,
frame
);
}
static
const
AVFilterPad
oscilloscope_inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
filter_frame
=
oscilloscope_filter_frame
,
.
config_props
=
oscilloscope_config_input
,
.
needs_writable
=
1
,
},
{
NULL
}
};
static
const
AVFilterPad
oscilloscope_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
},
{
NULL
}
};
AVFilter
ff_vf_oscilloscope
=
{
.
name
=
"oscilloscope"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"2D Video Oscilloscope."
),
.
priv_size
=
sizeof
(
OscilloscopeContext
),
.
priv_class
=
&
oscilloscope_class
,
.
query_formats
=
query_formats
,
.
uninit
=
oscilloscope_uninit
,
.
inputs
=
oscilloscope_inputs
,
.
outputs
=
oscilloscope_outputs
,
};
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