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
4a2836ea
Commit
4a2836ea
authored
Jul 23, 2015
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter: add acrossfade filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
0b6f092e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
462 additions
and
57 deletions
+462
-57
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+49
-0
Makefile
libavfilter/Makefile
+1
-0
af_afade.c
libavfilter/af_afade.c
+409
-56
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+1
-1
No files found.
Changelog
View file @
4a2836ea
...
...
@@ -26,6 +26,7 @@ version <next>:
- AAC fixed-point decoding
- sidechaincompress audio filter
- bitstream filter for converting HEVC from MP4 to Annex B
- acrossfade audio filter
version 2.7:
...
...
doc/filters.texi
View file @
4a2836ea
...
...
@@ -318,6 +318,54 @@ build.
Below is a description of the currently available audio filters.
@section acrossfade
Apply cross fade from one input audio stream to another input audio stream.
The cross fade is applied for specified duration near the end of first stream.
The filter accepts the following options:
@table @option
@item nb_samples, ns
Specify the number of samples for which the cross fade effect has to last.
At the end of the cross fade effect the first input audio will be completely
silent. Default is 44100.
@item duration, d
Specify the duration of the cross fade effect. See
@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}
for the accepted syntax.
By default the duration is determined by @var{nb_samples}.
If set this option is used instead of @var{nb_samples}.
@item overlap, o
Should first stream end overlap with second stream start. Default is enabled.
@item curve1
Set curve for cross fade transition for first stream.
@item curve2
Set curve for cross fade transition for second stream.
For description of available curve types see @ref{afade} filter description.
@end table
@subsection Examples
@itemize
@item
Cross fade from one input to another:
@example
ffmpeg -i first.flac -i second.flac -filter_complex acrossfade=d=10:c1=exp:c2=exp output.flac
@end example
@item
Cross fade from one input to another but without overlapping:
@example
ffmpeg -i first.flac -i second.flac -filter_complex acrossfade=d=10:o=0:c1=exp:c2=exp output.flac
@end example
@end itemize
@section adelay
Delay one or more audio channels.
...
...
@@ -469,6 +517,7 @@ aeval=val(0)|-val(1)
@end example
@end itemize
@anchor{afade}
@section afade
Apply fade-in/out effect to input audio.
...
...
libavfilter/Makefile
View file @
4a2836ea
...
...
@@ -29,6 +29,7 @@ OBJS = allfilters.o \
OBJS-$(CONFIG_AVCODEC)
+=
avcodec.o
OBJS-$(CONFIG_ACROSSFADE_FILTER)
+=
af_afade.o
OBJS-$(CONFIG_ADELAY_FILTER)
+=
af_adelay.o
OBJS-$(CONFIG_AECHO_FILTER)
+=
af_aecho.o
OBJS-$(CONFIG_AEVAL_FILTER)
+=
aeval.o
...
...
libavfilter/af_afade.c
View file @
4a2836ea
/*
* Copyright (c) 2013 Paul B Mahol
* Copyright (c) 2013
-2015
Paul B Mahol
*
* This file is part of FFmpeg.
*
...
...
@@ -23,6 +23,7 @@
* fade audio filter
*/
#include "libavutil/audio_fifo.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
...
...
@@ -31,15 +32,24 @@
typedef
struct
{
const
AVClass
*
class
;
int
type
;
int
curve
;
int
curve
,
curve2
;
int
nb_samples
;
int64_t
start_sample
;
int64_t
duration
;
int64_t
start_time
;
int
overlap
;
int
cf0_eof
;
int
crossfade_is_over
;
AVAudioFifo
*
fifo
[
2
];
int64_t
pts
;
void
(
*
fade_samples
)(
uint8_t
**
dst
,
uint8_t
*
const
*
src
,
int
nb_samples
,
int
channels
,
int
direction
,
int64_t
start
,
int
range
,
int
curve
);
void
(
*
crossfade_samples
)(
uint8_t
**
dst
,
uint8_t
*
const
*
cf0
,
uint8_t
*
const
*
cf1
,
int
nb_samples
,
int
channels
,
int
curve0
,
int
curve1
);
}
AudioFadeContext
;
enum
CurveType
{
TRI
,
QSIN
,
ESIN
,
HSIN
,
LOG
,
IPAR
,
QUA
,
CUB
,
SQU
,
CBR
,
PAR
,
EXP
,
IQSIN
,
IHSIN
,
DESE
,
DESI
,
NB_CURVES
};
...
...
@@ -47,52 +57,6 @@ enum CurveType { TRI, QSIN, ESIN, HSIN, LOG, IPAR, QUA, CUB, SQU, CBR, PAR, EXP,
#define OFFSET(x) offsetof(AudioFadeContext, x)
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static
const
AVOption
afade_options
[]
=
{
{
"type"
,
"set the fade direction"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
1
,
FLAGS
,
"type"
},
{
"t"
,
"set the fade direction"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
1
,
FLAGS
,
"type"
},
{
"in"
,
"fade-in"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
FLAGS
,
"type"
},
{
"out"
,
"fade-out"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
FLAGS
,
"type"
},
{
"start_sample"
,
"set number of first sample to start fading"
,
OFFSET
(
start_sample
),
AV_OPT_TYPE_INT64
,
{.
i64
=
0
},
0
,
INT64_MAX
,
FLAGS
},
{
"ss"
,
"set number of first sample to start fading"
,
OFFSET
(
start_sample
),
AV_OPT_TYPE_INT64
,
{.
i64
=
0
},
0
,
INT64_MAX
,
FLAGS
},
{
"nb_samples"
,
"set number of samples for fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"ns"
,
"set number of samples for fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"start_time"
,
"set time to start fading"
,
OFFSET
(
start_time
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"st"
,
"set time to start fading"
,
OFFSET
(
start_time
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"duration"
,
"set fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"d"
,
"set fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"curve"
,
"set fade curve type"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve"
},
{
"c"
,
"set fade curve type"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve"
},
{
"tri"
,
"linear slope"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
TRI
},
0
,
0
,
FLAGS
,
"curve"
},
{
"qsin"
,
"quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"esin"
,
"exponential sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ESIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"hsin"
,
"half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
HSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"log"
,
"logarithmic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
LOG
},
0
,
0
,
FLAGS
,
"curve"
},
{
"ipar"
,
"inverted parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IPAR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"qua"
,
"quadratic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QUA
},
0
,
0
,
FLAGS
,
"curve"
},
{
"cub"
,
"cubic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CUB
},
0
,
0
,
FLAGS
,
"curve"
},
{
"squ"
,
"square root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
SQU
},
0
,
0
,
FLAGS
,
"curve"
},
{
"cbr"
,
"cubic root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CBR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"par"
,
"parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
PAR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"exp"
,
"exponential"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
EXP
},
0
,
0
,
FLAGS
,
"curve"
},
{
"iqsin"
,
"inverted quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IQSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"ihsin"
,
"inverted half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IHSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"dese"
,
"double-exponential seat"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESE
},
0
,
0
,
FLAGS
,
"curve"
},
{
"desi"
,
"double-exponential sigmoid"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESI
},
0
,
0
,
FLAGS
,
"curve"
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
afade
);
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
AudioFadeContext
*
s
=
ctx
->
priv
;
if
(
INT64_MAX
-
s
->
nb_samples
<
s
->
start_sample
)
return
AVERROR
(
EINVAL
);
return
0
;
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
AVFilterFormats
*
formats
;
...
...
@@ -227,12 +191,12 @@ FADE(flt, float)
FADE
(
s16
,
int16_t
)
FADE
(
s32
,
int32_t
)
static
int
config_
input
(
AVFilterLink
*
in
link
)
static
int
config_
output
(
AVFilterLink
*
out
link
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterContext
*
ctx
=
outlink
->
src
;
AudioFadeContext
*
s
=
ctx
->
priv
;
switch
(
in
link
->
format
)
{
switch
(
out
link
->
format
)
{
case
AV_SAMPLE_FMT_DBL
:
s
->
fade_samples
=
fade_samples_dbl
;
break
;
case
AV_SAMPLE_FMT_DBLP
:
s
->
fade_samples
=
fade_samples_dblp
;
break
;
case
AV_SAMPLE_FMT_FLT
:
s
->
fade_samples
=
fade_samples_flt
;
break
;
...
...
@@ -244,9 +208,57 @@ static int config_input(AVFilterLink *inlink)
}
if
(
s
->
duration
)
s
->
nb_samples
=
av_rescale
(
s
->
duration
,
in
link
->
sample_rate
,
AV_TIME_BASE
);
s
->
nb_samples
=
av_rescale
(
s
->
duration
,
out
link
->
sample_rate
,
AV_TIME_BASE
);
if
(
s
->
start_time
)
s
->
start_sample
=
av_rescale
(
s
->
start_time
,
inlink
->
sample_rate
,
AV_TIME_BASE
);
s
->
start_sample
=
av_rescale
(
s
->
start_time
,
outlink
->
sample_rate
,
AV_TIME_BASE
);
return
0
;
}
#if CONFIG_AFADE_FILTER
static
const
AVOption
afade_options
[]
=
{
{
"type"
,
"set the fade direction"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
1
,
FLAGS
,
"type"
},
{
"t"
,
"set the fade direction"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
1
,
FLAGS
,
"type"
},
{
"in"
,
"fade-in"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
FLAGS
,
"type"
},
{
"out"
,
"fade-out"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
FLAGS
,
"type"
},
{
"start_sample"
,
"set number of first sample to start fading"
,
OFFSET
(
start_sample
),
AV_OPT_TYPE_INT64
,
{.
i64
=
0
},
0
,
INT64_MAX
,
FLAGS
},
{
"ss"
,
"set number of first sample to start fading"
,
OFFSET
(
start_sample
),
AV_OPT_TYPE_INT64
,
{.
i64
=
0
},
0
,
INT64_MAX
,
FLAGS
},
{
"nb_samples"
,
"set number of samples for fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"ns"
,
"set number of samples for fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"start_time"
,
"set time to start fading"
,
OFFSET
(
start_time
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"st"
,
"set time to start fading"
,
OFFSET
(
start_time
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"duration"
,
"set fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"d"
,
"set fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
INT32_MAX
,
FLAGS
},
{
"curve"
,
"set fade curve type"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve"
},
{
"c"
,
"set fade curve type"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve"
},
{
"tri"
,
"linear slope"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
TRI
},
0
,
0
,
FLAGS
,
"curve"
},
{
"qsin"
,
"quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"esin"
,
"exponential sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ESIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"hsin"
,
"half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
HSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"log"
,
"logarithmic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
LOG
},
0
,
0
,
FLAGS
,
"curve"
},
{
"ipar"
,
"inverted parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IPAR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"qua"
,
"quadratic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QUA
},
0
,
0
,
FLAGS
,
"curve"
},
{
"cub"
,
"cubic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CUB
},
0
,
0
,
FLAGS
,
"curve"
},
{
"squ"
,
"square root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
SQU
},
0
,
0
,
FLAGS
,
"curve"
},
{
"cbr"
,
"cubic root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CBR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"par"
,
"parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
PAR
},
0
,
0
,
FLAGS
,
"curve"
},
{
"exp"
,
"exponential"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
EXP
},
0
,
0
,
FLAGS
,
"curve"
},
{
"iqsin"
,
"inverted quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IQSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"ihsin"
,
"inverted half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IHSIN
},
0
,
0
,
FLAGS
,
"curve"
},
{
"dese"
,
"double-exponential seat"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESE
},
0
,
0
,
FLAGS
,
"curve"
},
{
"desi"
,
"double-exponential sigmoid"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESI
},
0
,
0
,
FLAGS
,
"curve"
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
afade
);
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
AudioFadeContext
*
s
=
ctx
->
priv
;
if
(
INT64_MAX
-
s
->
nb_samples
<
s
->
start_sample
)
return
AVERROR
(
EINVAL
);
return
0
;
}
...
...
@@ -301,15 +313,15 @@ static const AVFilterPad avfilter_af_afade_inputs[] = {
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_frame
=
filter_frame
,
.
config_props
=
config_input
,
},
{
NULL
}
};
static
const
AVFilterPad
avfilter_af_afade_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
config_props
=
config_output
,
},
{
NULL
}
};
...
...
@@ -325,3 +337,344 @@ AVFilter ff_af_afade = {
.
priv_class
=
&
afade_class
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
};
#endif
/* CONFIG_AFADE_FILTER */
#if CONFIG_ACROSSFADE_FILTER
static
const
AVOption
acrossfade_options
[]
=
{
{
"nb_samples"
,
"set number of samples for cross fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
/
10
,
FLAGS
},
{
"ns"
,
"set number of samples for cross fade duration"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
/
10
,
FLAGS
},
{
"duration"
,
"set cross fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
60
,
FLAGS
},
{
"d"
,
"set cross fade duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=
0
.
},
0
,
60
,
FLAGS
},
{
"overlap"
,
"overlap 1st stream end with 2nd stream start"
,
OFFSET
(
overlap
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
"o"
,
"overlap 1st stream end with 2nd stream start"
,
OFFSET
(
overlap
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
"curve1"
,
"set fade curve type for 1st stream"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve1"
},
{
"c1"
,
"set fade curve type for 1st stream"
,
OFFSET
(
curve
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve1"
},
{
"tri"
,
"linear slope"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
TRI
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"qsin"
,
"quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QSIN
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"esin"
,
"exponential sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ESIN
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"hsin"
,
"half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
HSIN
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"log"
,
"logarithmic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
LOG
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"ipar"
,
"inverted parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IPAR
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"qua"
,
"quadratic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QUA
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"cub"
,
"cubic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CUB
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"squ"
,
"square root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
SQU
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"cbr"
,
"cubic root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CBR
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"par"
,
"parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
PAR
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"exp"
,
"exponential"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
EXP
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"iqsin"
,
"inverted quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IQSIN
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"ihsin"
,
"inverted half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IHSIN
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"dese"
,
"double-exponential seat"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESE
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"desi"
,
"double-exponential sigmoid"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESI
},
0
,
0
,
FLAGS
,
"curve1"
},
{
"curve2"
,
"set fade curve type for 2nd stream"
,
OFFSET
(
curve2
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve2"
},
{
"c2"
,
"set fade curve type for 2nd stream"
,
OFFSET
(
curve2
),
AV_OPT_TYPE_INT
,
{.
i64
=
TRI
},
0
,
NB_CURVES
-
1
,
FLAGS
,
"curve2"
},
{
"tri"
,
"linear slope"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
TRI
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"qsin"
,
"quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QSIN
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"esin"
,
"exponential sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ESIN
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"hsin"
,
"half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
HSIN
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"log"
,
"logarithmic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
LOG
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"ipar"
,
"inverted parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IPAR
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"qua"
,
"quadratic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
QUA
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"cub"
,
"cubic"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CUB
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"squ"
,
"square root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
SQU
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"cbr"
,
"cubic root"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
CBR
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"par"
,
"parabola"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
PAR
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"exp"
,
"exponential"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
EXP
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"iqsin"
,
"inverted quarter of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IQSIN
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"ihsin"
,
"inverted half of sine wave"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
IHSIN
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"dese"
,
"double-exponential seat"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESE
},
0
,
0
,
FLAGS
,
"curve2"
},
{
"desi"
,
"double-exponential sigmoid"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
DESI
},
0
,
0
,
FLAGS
,
"curve2"
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
acrossfade
);
#define CROSSFADE_PLANAR(name, type) \
static void crossfade_samples_## name ##p(uint8_t **dst, uint8_t * const *cf0, \
uint8_t * const *cf1, \
int nb_samples, int channels, \
int curve0, int curve1) \
{ \
int i, c; \
\
for (i = 0; i < nb_samples; i++) { \
double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples); \
double gain1 = fade_gain(curve1, i, nb_samples); \
for (c = 0; c < channels; c++) { \
type *d = (type *)dst[c]; \
const type *s0 = (type *)cf0[c]; \
const type *s1 = (type *)cf1[c]; \
\
d[i] = s0[i] * gain0 + s1[i] * gain1; \
} \
} \
}
#define CROSSFADE(name, type) \
static void crossfade_samples_## name (uint8_t **dst, uint8_t * const *cf0, \
uint8_t * const *cf1, \
int nb_samples, int channels, \
int curve0, int curve1) \
{ \
type *d = (type *)dst[0]; \
const type *s0 = (type *)cf0[0]; \
const type *s1 = (type *)cf1[0]; \
int i, c, k = 0; \
\
for (i = 0; i < nb_samples; i++) { \
double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples); \
double gain1 = fade_gain(curve1, i, nb_samples); \
for (c = 0; c < channels; c++, k++) \
d[k] = s0[k] * gain0 + s1[k] * gain1; \
} \
}
CROSSFADE_PLANAR
(
dbl
,
double
)
CROSSFADE_PLANAR
(
flt
,
float
)
CROSSFADE_PLANAR
(
s16
,
int16_t
)
CROSSFADE_PLANAR
(
s32
,
int32_t
)
CROSSFADE
(
dbl
,
double
)
CROSSFADE
(
flt
,
float
)
CROSSFADE
(
s16
,
int16_t
)
CROSSFADE
(
s32
,
int32_t
)
static
int
acrossfade_filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AudioFadeContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
AVFrame
*
out
,
*
cf
[
2
]
=
{
NULL
};
int
ret
=
0
,
nb_samples
;
if
(
s
->
crossfade_is_over
)
{
in
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
in
->
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
return
ff_filter_frame
(
outlink
,
in
);
}
else
if
(
inlink
==
ctx
->
inputs
[
0
])
{
av_audio_fifo_write
(
s
->
fifo
[
0
],
(
void
**
)
in
->
extended_data
,
in
->
nb_samples
);
nb_samples
=
av_audio_fifo_size
(
s
->
fifo
[
0
])
-
s
->
nb_samples
;
if
(
nb_samples
>
0
)
{
out
=
ff_get_audio_buffer
(
outlink
,
nb_samples
);
if
(
!
out
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
av_audio_fifo_read
(
s
->
fifo
[
0
],
(
void
**
)
out
->
extended_data
,
nb_samples
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
ret
=
ff_filter_frame
(
outlink
,
out
);
}
}
else
if
(
av_audio_fifo_size
(
s
->
fifo
[
1
])
<
s
->
nb_samples
)
{
if
(
!
s
->
overlap
&&
av_audio_fifo_size
(
s
->
fifo
[
0
])
>
0
)
{
nb_samples
=
av_audio_fifo_size
(
s
->
fifo
[
0
]);
cf
[
0
]
=
ff_get_audio_buffer
(
outlink
,
nb_samples
);
out
=
ff_get_audio_buffer
(
outlink
,
nb_samples
);
if
(
!
out
||
!
cf
[
0
])
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
av_audio_fifo_read
(
s
->
fifo
[
0
],
(
void
**
)
cf
[
0
]
->
extended_data
,
nb_samples
);
s
->
fade_samples
(
out
->
extended_data
,
cf
[
0
]
->
extended_data
,
nb_samples
,
outlink
->
channels
,
-
1
,
nb_samples
-
1
,
nb_samples
,
s
->
curve
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
ret
=
ff_filter_frame
(
outlink
,
out
);
if
(
ret
<
0
)
goto
fail
;
}
av_audio_fifo_write
(
s
->
fifo
[
1
],
(
void
**
)
in
->
extended_data
,
in
->
nb_samples
);
}
else
if
(
av_audio_fifo_size
(
s
->
fifo
[
1
])
>=
s
->
nb_samples
)
{
if
(
s
->
overlap
)
{
cf
[
0
]
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
cf
[
1
]
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
out
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
if
(
!
out
||
!
cf
[
0
]
||
!
cf
[
1
])
{
av_frame_free
(
&
out
);
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
av_audio_fifo_read
(
s
->
fifo
[
0
],
(
void
**
)
cf
[
0
]
->
extended_data
,
s
->
nb_samples
);
av_audio_fifo_read
(
s
->
fifo
[
1
],
(
void
**
)
cf
[
1
]
->
extended_data
,
s
->
nb_samples
);
s
->
crossfade_samples
(
out
->
extended_data
,
cf
[
0
]
->
extended_data
,
cf
[
1
]
->
extended_data
,
s
->
nb_samples
,
av_frame_get_channels
(
in
),
s
->
curve
,
s
->
curve2
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
s
->
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
ret
=
ff_filter_frame
(
outlink
,
out
);
if
(
ret
<
0
)
goto
fail
;
}
else
{
out
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
cf
[
1
]
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
if
(
!
out
||
!
cf
[
1
])
{
ret
=
AVERROR
(
ENOMEM
);
av_frame_free
(
&
out
);
goto
fail
;
}
av_audio_fifo_read
(
s
->
fifo
[
1
],
(
void
**
)
cf
[
1
]
->
extended_data
,
s
->
nb_samples
);
s
->
fade_samples
(
out
->
extended_data
,
cf
[
1
]
->
extended_data
,
s
->
nb_samples
,
outlink
->
channels
,
1
,
0
,
s
->
nb_samples
,
s
->
curve2
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
s
->
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
ret
=
ff_filter_frame
(
outlink
,
out
);
if
(
ret
<
0
)
goto
fail
;
}
nb_samples
=
av_audio_fifo_size
(
s
->
fifo
[
1
]);
if
(
nb_samples
>
0
)
{
out
=
ff_get_audio_buffer
(
outlink
,
nb_samples
);
if
(
!
out
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
av_audio_fifo_read
(
s
->
fifo
[
1
],
(
void
**
)
out
->
extended_data
,
nb_samples
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
ret
=
ff_filter_frame
(
outlink
,
out
);
}
s
->
crossfade_is_over
=
1
;
}
fail
:
av_frame_free
(
&
in
);
av_frame_free
(
&
cf
[
0
]);
av_frame_free
(
&
cf
[
1
]);
return
ret
;
}
static
int
acrossfade_request_frame
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
AudioFadeContext
*
s
=
ctx
->
priv
;
int
ret
=
0
;
if
(
!
s
->
cf0_eof
)
{
AVFilterLink
*
cf0
=
ctx
->
inputs
[
0
];
ret
=
ff_request_frame
(
cf0
);
if
(
ret
<
0
&&
ret
!=
AVERROR_EOF
)
return
ret
;
if
(
ret
==
AVERROR_EOF
)
{
s
->
cf0_eof
=
1
;
ret
=
0
;
}
}
else
{
AVFilterLink
*
cf1
=
ctx
->
inputs
[
1
];
int
nb_samples
=
av_audio_fifo_size
(
s
->
fifo
[
1
]);
ret
=
ff_request_frame
(
cf1
);
if
(
ret
==
AVERROR_EOF
&&
nb_samples
>
0
)
{
AVFrame
*
out
=
ff_get_audio_buffer
(
outlink
,
nb_samples
);
if
(
!
out
)
return
AVERROR
(
ENOMEM
);
av_audio_fifo_read
(
s
->
fifo
[
1
],
(
void
**
)
out
->
extended_data
,
nb_samples
);
ret
=
ff_filter_frame
(
outlink
,
out
);
}
}
return
ret
;
}
static
int
acrossfade_config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
AudioFadeContext
*
s
=
ctx
->
priv
;
if
(
ctx
->
inputs
[
0
]
->
sample_rate
!=
ctx
->
inputs
[
1
]
->
sample_rate
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Inputs must have the same sample rate "
"%d for in0 vs %d for in1
\n
"
,
ctx
->
inputs
[
0
]
->
sample_rate
,
ctx
->
inputs
[
1
]
->
sample_rate
);
return
AVERROR
(
EINVAL
);
}
outlink
->
sample_rate
=
ctx
->
inputs
[
0
]
->
sample_rate
;
outlink
->
time_base
=
ctx
->
inputs
[
0
]
->
time_base
;
outlink
->
channel_layout
=
ctx
->
inputs
[
0
]
->
channel_layout
;
outlink
->
channels
=
ctx
->
inputs
[
0
]
->
channels
;
outlink
->
flags
|=
FF_LINK_FLAG_REQUEST_LOOP
;
switch
(
outlink
->
format
)
{
case
AV_SAMPLE_FMT_DBL
:
s
->
crossfade_samples
=
crossfade_samples_dbl
;
break
;
case
AV_SAMPLE_FMT_DBLP
:
s
->
crossfade_samples
=
crossfade_samples_dblp
;
break
;
case
AV_SAMPLE_FMT_FLT
:
s
->
crossfade_samples
=
crossfade_samples_flt
;
break
;
case
AV_SAMPLE_FMT_FLTP
:
s
->
crossfade_samples
=
crossfade_samples_fltp
;
break
;
case
AV_SAMPLE_FMT_S16
:
s
->
crossfade_samples
=
crossfade_samples_s16
;
break
;
case
AV_SAMPLE_FMT_S16P
:
s
->
crossfade_samples
=
crossfade_samples_s16p
;
break
;
case
AV_SAMPLE_FMT_S32
:
s
->
crossfade_samples
=
crossfade_samples_s32
;
break
;
case
AV_SAMPLE_FMT_S32P
:
s
->
crossfade_samples
=
crossfade_samples_s32p
;
break
;
}
config_output
(
outlink
);
s
->
fifo
[
0
]
=
av_audio_fifo_alloc
(
outlink
->
format
,
outlink
->
channels
,
s
->
nb_samples
);
s
->
fifo
[
1
]
=
av_audio_fifo_alloc
(
outlink
->
format
,
outlink
->
channels
,
s
->
nb_samples
);
if
(
!
s
->
fifo
[
0
]
||
!
s
->
fifo
[
1
])
return
AVERROR
(
ENOMEM
);
return
0
;
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
AudioFadeContext
*
s
=
ctx
->
priv
;
av_audio_fifo_free
(
s
->
fifo
[
0
]);
av_audio_fifo_free
(
s
->
fifo
[
1
]);
}
static
const
AVFilterPad
avfilter_af_acrossfade_inputs
[]
=
{
{
.
name
=
"crossfade0"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_frame
=
acrossfade_filter_frame
,
},
{
.
name
=
"crossfade1"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_frame
=
acrossfade_filter_frame
,
},
{
NULL
}
};
static
const
AVFilterPad
avfilter_af_acrossfade_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
request_frame
=
acrossfade_request_frame
,
.
config_props
=
acrossfade_config_output
,
},
{
NULL
}
};
AVFilter
ff_af_acrossfade
=
{
.
name
=
"acrossfade"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Cross fade two input audio streams."
),
.
query_formats
=
query_formats
,
.
priv_size
=
sizeof
(
AudioFadeContext
),
.
uninit
=
uninit
,
.
priv_class
=
&
acrossfade_class
,
.
inputs
=
avfilter_af_acrossfade_inputs
,
.
outputs
=
avfilter_af_acrossfade_outputs
,
};
#endif
/* CONFIG_ACROSSFADE_FILTER */
libavfilter/allfilters.c
View file @
4a2836ea
...
...
@@ -45,6 +45,7 @@ void avfilter_register_all(void)
return
;
initialized
=
1
;
REGISTER_FILTER
(
ACROSSFADE
,
acrossfade
,
af
);
REGISTER_FILTER
(
ADELAY
,
adelay
,
af
);
REGISTER_FILTER
(
AECHO
,
aecho
,
af
);
REGISTER_FILTER
(
AEVAL
,
aeval
,
af
);
...
...
libavfilter/version.h
View file @
4a2836ea
...
...
@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 5
#define LIBAVFILTER_VERSION_MINOR
29
#define LIBAVFILTER_VERSION_MINOR
30
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
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