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
ddda29b4
Commit
ddda29b4
authored
Dec 29, 2011
by
Clément Bœsch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add showspectrum filter.
parent
786f06e1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
334 additions
and
3 deletions
+334
-3
Changelog
Changelog
+1
-1
configure
configure
+1
-0
filters.texi
doc/filters.texi
+14
-0
Makefile
libavfilter/Makefile
+1
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
avf_showspectrum.c
libavfilter/avf_showspectrum.c
+314
-0
version.h
libavfilter/version.h
+2
-2
No files found.
Changelog
View file @
ddda29b4
...
@@ -23,7 +23,7 @@ version next:
...
@@ -23,7 +23,7 @@ version next:
- RTMPTS protocol support
- RTMPTS protocol support
- RTMPE protocol support
- RTMPE protocol support
- RTMPTE protocol support
- RTMPTE protocol support
- showwaves filter
- showwaves
and showspectrum
filter
- LucasArts SMUSH playback support
- LucasArts SMUSH playback support
- SAMI, RealText and SubViewer demuxers and decoders
- SAMI, RealText and SubViewer demuxers and decoders
- Heart Of Darkness PAF playback support
- Heart Of Darkness PAF playback support
...
...
configure
View file @
ddda29b4
...
@@ -1849,6 +1849,7 @@ pan_filter_deps="swresample"
...
@@ -1849,6 +1849,7 @@ pan_filter_deps="swresample"
removelogo_filter_deps
=
"avcodec avformat swscale"
removelogo_filter_deps
=
"avcodec avformat swscale"
scale_filter_deps
=
"swscale"
scale_filter_deps
=
"swscale"
select_filter_deps
=
"avcodec"
select_filter_deps
=
"avcodec"
showspectrum_filter_deps
=
"avcodec"
super2xsai_filter_deps
=
"gpl"
super2xsai_filter_deps
=
"gpl"
tinterlace_filter_deps
=
"gpl"
tinterlace_filter_deps
=
"gpl"
yadif_filter_deps
=
"gpl"
yadif_filter_deps
=
"gpl"
...
...
doc/filters.texi
View file @
ddda29b4
...
@@ -4252,6 +4252,20 @@ do not have exactly the same duration in the first file.
...
@@ -4252,6 +4252,20 @@ do not have exactly the same duration in the first file.
@end itemize
@end itemize
@section showspectrum
Convert input audio to a video output, representing the audio frequency
spectrum.
The filter accepts the following named parameters:
@table @option
@item size, s
Specify the video size for the output. Default value is @code{640x480}.
@end table
The usage is very similar to the showwaves filter; see the examples in that
section.
@section showwaves
@section showwaves
Convert input audio to a video output, representing the samples waves.
Convert input audio to a video output, representing the samples waves.
...
...
libavfilter/Makefile
View file @
ddda29b4
...
@@ -202,6 +202,7 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o
...
@@ -202,6 +202,7 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o
# multimedia filters
# multimedia filters
OBJS-$(CONFIG_CONCAT_FILTER)
+=
avf_concat.o
OBJS-$(CONFIG_CONCAT_FILTER)
+=
avf_concat.o
OBJS-$(CONFIG_SHOWSPECTRUM_FILTER)
+=
avf_showspectrum.o
OBJS-$(CONFIG_SHOWWAVES_FILTER)
+=
avf_showwaves.o
OBJS-$(CONFIG_SHOWWAVES_FILTER)
+=
avf_showwaves.o
# multimedia sources
# multimedia sources
...
...
libavfilter/allfilters.c
View file @
ddda29b4
...
@@ -143,6 +143,7 @@ void avfilter_register_all(void)
...
@@ -143,6 +143,7 @@ void avfilter_register_all(void)
/* multimedia filters */
/* multimedia filters */
REGISTER_FILTER
(
CONCAT
,
concat
,
avf
);
REGISTER_FILTER
(
CONCAT
,
concat
,
avf
);
REGISTER_FILTER
(
SHOWSPECTRUM
,
showspectrum
,
avf
);
REGISTER_FILTER
(
SHOWWAVES
,
showwaves
,
avf
);
REGISTER_FILTER
(
SHOWWAVES
,
showwaves
,
avf
);
/* multimedia sources */
/* multimedia sources */
...
...
libavfilter/avf_showspectrum.c
0 → 100644
View file @
ddda29b4
/*
* Copyright (c) 2012 Clément Bœsch
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* audio to spectrum (video) transmedia filter, based on ffplay rdft showmode
* (by Michael Niedermayer) and lavfi/avf_showwaves (by Stefano Sabatini).
*/
#include <math.h>
#include "libavcodec/avfft.h"
#include "libavutil/audioconvert.h"
#include "libavutil/opt.h"
#include "avfilter.h"
#include "internal.h"
typedef
struct
{
const
AVClass
*
class
;
int
w
,
h
;
AVFilterBufferRef
*
outpicref
;
int
req_fullfilled
;
int
xpos
;
///< x position (current column)
RDFTContext
*
rdft
;
///< Real Discrete Fourier Transform context
int
rdft_bits
;
///< number of bits (RDFT window size = 1<<rdft_bits)
FFTSample
*
rdft_data
;
///< bins holder for each (displayed) channels
int
filled
;
///< number of samples (per channel) filled in current rdft_buffer
int
consumed
;
///< number of samples (per channel) consumed from the input frame
float
*
window_func_lut
;
///< Window function LUT
}
ShowSpectrumContext
;
#define OFFSET(x) offsetof(ShowSpectrumContext, x)
static
const
AVOption
showspectrum_options
[]
=
{
{
"size"
,
"set video size"
,
OFFSET
(
w
),
AV_OPT_TYPE_IMAGE_SIZE
,
{.
str
=
"640x480"
},
0
,
0
},
{
"s"
,
"set video size"
,
OFFSET
(
w
),
AV_OPT_TYPE_IMAGE_SIZE
,
{.
str
=
"640x480"
},
0
,
0
},
{
NULL
},
};
AVFILTER_DEFINE_CLASS
(
showspectrum
);
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
)
{
ShowSpectrumContext
*
showspectrum
=
ctx
->
priv
;
int
err
;
showspectrum
->
class
=
&
showspectrum_class
;
av_opt_set_defaults
(
showspectrum
);
if
((
err
=
av_set_options_string
(
showspectrum
,
args
,
"="
,
":"
))
<
0
)
return
err
;
return
0
;
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
ShowSpectrumContext
*
showspectrum
=
ctx
->
priv
;
av_rdft_end
(
showspectrum
->
rdft
);
av_freep
(
&
showspectrum
->
rdft_data
);
av_freep
(
&
showspectrum
->
window_func_lut
);
avfilter_unref_bufferp
(
&
showspectrum
->
outpicref
);
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
AVFilterFormats
*
formats
=
NULL
;
AVFilterChannelLayouts
*
layouts
=
NULL
;
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
static
const
enum
AVSampleFormat
sample_fmts
[]
=
{
AV_SAMPLE_FMT_S16P
,
-
1
};
static
const
enum
PixelFormat
pix_fmts
[]
=
{
PIX_FMT_RGB24
,
-
1
};
/* set input audio formats */
formats
=
ff_make_format_list
(
sample_fmts
);
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ff_formats_ref
(
formats
,
&
inlink
->
out_formats
);
layouts
=
ff_all_channel_layouts
();
if
(
!
layouts
)
return
AVERROR
(
ENOMEM
);
ff_channel_layouts_ref
(
layouts
,
&
inlink
->
out_channel_layouts
);
formats
=
ff_all_samplerates
();
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ff_formats_ref
(
formats
,
&
inlink
->
out_samplerates
);
/* set output video format */
formats
=
ff_make_format_list
(
pix_fmts
);
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ff_formats_ref
(
formats
,
&
outlink
->
in_formats
);
return
0
;
}
static
int
config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
ShowSpectrumContext
*
showspectrum
=
ctx
->
priv
;
int
i
,
rdft_bits
,
win_size
;
outlink
->
w
=
showspectrum
->
w
;
outlink
->
h
=
showspectrum
->
h
;
/* RDFT window size (precision) according to the requested output frame height */
for
(
rdft_bits
=
1
;
1
<<
rdft_bits
<
2
*
outlink
->
h
;
rdft_bits
++
);
win_size
=
1
<<
rdft_bits
;
/* (re-)configuration if the video output changed (or first init) */
if
(
rdft_bits
!=
showspectrum
->
rdft_bits
)
{
AVFilterBufferRef
*
outpicref
;
av_rdft_end
(
showspectrum
->
rdft
);
showspectrum
->
rdft
=
av_rdft_init
(
rdft_bits
,
DFT_R2C
);
showspectrum
->
rdft_bits
=
rdft_bits
;
/* RDFT buffers: x2 for each (display) channel buffer */
showspectrum
->
rdft_data
=
av_realloc_f
(
showspectrum
->
rdft_data
,
2
*
win_size
,
sizeof
(
*
showspectrum
->
rdft_data
));
if
(
!
showspectrum
->
rdft_data
)
return
AVERROR
(
ENOMEM
);
showspectrum
->
filled
=
0
;
/* pre-calc windowing function (hann here) */
showspectrum
->
window_func_lut
=
av_realloc_f
(
showspectrum
->
window_func_lut
,
win_size
,
sizeof
(
*
showspectrum
->
window_func_lut
));
if
(
!
showspectrum
->
window_func_lut
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
win_size
;
i
++
)
showspectrum
->
window_func_lut
[
i
]
=
.
5
f
*
(
1
-
cos
(
2
*
M_PI
*
i
/
(
win_size
-
1
)));
/* prepare the initial picref buffer (black frame) */
avfilter_unref_bufferp
(
&
showspectrum
->
outpicref
);
showspectrum
->
outpicref
=
outpicref
=
ff_get_video_buffer
(
outlink
,
AV_PERM_WRITE
|
AV_PERM_PRESERVE
|
AV_PERM_REUSE2
,
outlink
->
w
,
outlink
->
h
);
if
(
!
outpicref
)
return
AVERROR
(
ENOMEM
);
outlink
->
sample_aspect_ratio
=
(
AVRational
){
1
,
1
};
memset
(
outpicref
->
data
[
0
],
0
,
outlink
->
h
*
outpicref
->
linesize
[
0
]);
}
if
(
showspectrum
->
xpos
>=
outlink
->
w
)
showspectrum
->
xpos
=
0
;
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"s:%dx%d RDFT window size:%d
\n
"
,
showspectrum
->
w
,
showspectrum
->
h
,
win_size
);
return
0
;
}
inline
static
void
push_frame
(
AVFilterLink
*
outlink
)
{
ShowSpectrumContext
*
showspectrum
=
outlink
->
src
->
priv
;
showspectrum
->
xpos
++
;
if
(
showspectrum
->
xpos
>=
outlink
->
w
)
showspectrum
->
xpos
=
0
;
showspectrum
->
filled
=
0
;
showspectrum
->
req_fullfilled
=
1
;
ff_start_frame
(
outlink
,
avfilter_ref_buffer
(
showspectrum
->
outpicref
,
~
AV_PERM_WRITE
));
ff_draw_slice
(
outlink
,
0
,
outlink
->
h
,
1
);
ff_end_frame
(
outlink
);
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
ShowSpectrumContext
*
showspectrum
=
outlink
->
src
->
priv
;
AVFilterLink
*
inlink
=
outlink
->
src
->
inputs
[
0
];
int
ret
;
showspectrum
->
req_fullfilled
=
0
;
do
{
ret
=
ff_request_frame
(
inlink
);
}
while
(
!
showspectrum
->
req_fullfilled
&&
ret
>=
0
);
if
(
ret
==
AVERROR_EOF
&&
showspectrum
->
outpicref
)
push_frame
(
outlink
);
return
ret
;
}
static
int
plot_spectrum_column
(
AVFilterLink
*
inlink
,
AVFilterBufferRef
*
insamples
,
int
nb_samples
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
ShowSpectrumContext
*
showspectrum
=
ctx
->
priv
;
AVFilterBufferRef
*
outpicref
=
showspectrum
->
outpicref
;
const
int
nb_channels
=
av_get_channel_layout_nb_channels
(
insamples
->
audio
->
channel_layout
);
/* nb_freq contains the power of two superior or equal to the output image
* height (or half the RDFT window size) */
const
int
nb_freq
=
1
<<
(
showspectrum
->
rdft_bits
-
1
);
const
int
win_size
=
nb_freq
<<
1
;
int
ch
,
n
,
y
;
FFTSample
*
data
[
2
];
const
int
nb_display_channels
=
FFMIN
(
nb_channels
,
2
);
const
int
start
=
showspectrum
->
filled
;
const
int
add_samples
=
FFMIN
(
win_size
-
start
,
nb_samples
);
/* fill RDFT input with the number of samples available */
for
(
ch
=
0
;
ch
<
nb_display_channels
;
ch
++
)
{
const
int16_t
*
p
=
(
int16_t
*
)
insamples
->
extended_data
[
ch
];
p
+=
showspectrum
->
consumed
;
data
[
ch
]
=
showspectrum
->
rdft_data
+
win_size
*
ch
;
// select channel buffer
for
(
n
=
0
;
n
<
add_samples
;
n
++
)
data
[
ch
][
start
+
n
]
=
p
[
n
]
*
showspectrum
->
window_func_lut
[
start
+
n
];
}
showspectrum
->
filled
+=
add_samples
;
/* complete RDFT window size? */
if
(
showspectrum
->
filled
==
win_size
)
{
/* run RDFT on each samples set */
for
(
ch
=
0
;
ch
<
nb_display_channels
;
ch
++
)
av_rdft_calc
(
showspectrum
->
rdft
,
data
[
ch
]);
/* fill a new spectrum column */
#define RE(ch) data[ch][2*y + 0]
#define IM(ch) data[ch][2*y + 1]
#define MAGNITUDE(re, im) sqrt((re)*(re) + (im)*(im))
for
(
y
=
0
;
y
<
outlink
->
h
;
y
++
)
{
// FIXME: bin[0] contains first and last bins
const
int
pos
=
showspectrum
->
xpos
*
3
+
(
outlink
->
h
-
y
-
1
)
*
outpicref
->
linesize
[
0
];
const
double
w
=
1
.
/
sqrt
(
nb_freq
);
int
a
=
sqrt
(
w
*
MAGNITUDE
(
RE
(
0
),
IM
(
0
)));
int
b
=
nb_display_channels
>
1
?
sqrt
(
w
*
MAGNITUDE
(
RE
(
1
),
IM
(
1
)))
:
a
;
a
=
FFMIN
(
a
,
255
);
b
=
FFMIN
(
b
,
255
);
outpicref
->
data
[
0
][
pos
]
=
a
;
outpicref
->
data
[
0
][
pos
+
1
]
=
b
;
outpicref
->
data
[
0
][
pos
+
2
]
=
(
a
+
b
)
/
2
;
}
outpicref
->
pts
=
insamples
->
pts
+
av_rescale_q
(
showspectrum
->
consumed
,
(
AVRational
){
1
,
inlink
->
sample_rate
},
outlink
->
time_base
);
push_frame
(
outlink
);
}
return
add_samples
;
}
static
int
filter_samples
(
AVFilterLink
*
inlink
,
AVFilterBufferRef
*
insamples
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ShowSpectrumContext
*
showspectrum
=
ctx
->
priv
;
int
left_samples
=
insamples
->
audio
->
nb_samples
;
showspectrum
->
consumed
=
0
;
while
(
left_samples
)
{
const
int
added_samples
=
plot_spectrum_column
(
inlink
,
insamples
,
left_samples
);
showspectrum
->
consumed
+=
added_samples
;
left_samples
-=
added_samples
;
}
avfilter_unref_buffer
(
insamples
);
return
0
;
}
AVFilter
avfilter_avf_showspectrum
=
{
.
name
=
"showspectrum"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Convert input audio to a spectrum video output."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
query_formats
=
query_formats
,
.
priv_size
=
sizeof
(
ShowSpectrumContext
),
.
inputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_samples
=
filter_samples
,
.
min_perms
=
AV_PERM_READ
,
},
{
.
name
=
NULL
}
},
.
outputs
=
(
const
AVFilterPad
[])
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_output
,
.
request_frame
=
request_frame
,
},
{
.
name
=
NULL
}
},
};
libavfilter/version.h
View file @
ddda29b4
...
@@ -29,8 +29,8 @@
...
@@ -29,8 +29,8 @@
#include "libavutil/avutil.h"
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 1
1
#define LIBAVFILTER_VERSION_MINOR 1
2
#define LIBAVFILTER_VERSION_MICRO 10
1
#define LIBAVFILTER_VERSION_MICRO 10
0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
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