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
9f26421b
Commit
9f26421b
authored
May 08, 2012
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: add asyncts filter.
parent
fb604ae8
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
259 additions
and
0 deletions
+259
-0
filters.texi
doc/filters.texi
+19
-0
Makefile
libavfilter/Makefile
+2
-0
af_asyncts.c
libavfilter/af_asyncts.c
+237
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
No files found.
doc/filters.texi
View file @
9f26421b
...
@@ -137,6 +137,25 @@ aformat=sample_fmts\=u8\,s16:channel_layouts\=stereo
...
@@ -137,6 +137,25 @@ aformat=sample_fmts\=u8\,s16:channel_layouts\=stereo
Pass the audio source unchanged to the output.
Pass the audio source unchanged to the output.
@section asyncts
Synchronize audio data with timestamps by squeezing/stretching it and/or
dropping samples/adding silence when needed.
The filter accepts the following named parameters:
@table @option
@item compensate
Enable stretching/squeezing the data to make it match the timestamps.
@item min_delta
Minimum difference between timestamps and audio data (in seconds) to trigger
adding/dropping samples.
@item max_comp
Maximum compensation in samples per second.
@end table
@section resample
@section resample
Convert the audio sample format, sample rate and channel layout. This filter is
Convert the audio sample format, sample rate and channel layout. This filter is
not meant to be used directly, it is inserted automatically by libavfilter
not meant to be used directly, it is inserted automatically by libavfilter
...
...
libavfilter/Makefile
View file @
9f26421b
NAME
=
avfilter
NAME
=
avfilter
FFLIBS
=
avutil swscale
FFLIBS
=
avutil swscale
FFLIBS-$(CONFIG_ASYNCTS_FILTER)
+=
avresample
FFLIBS-$(CONFIG_MOVIE_FILTER)
+=
avformat
avcodec
FFLIBS-$(CONFIG_MOVIE_FILTER)
+=
avformat
avcodec
FFLIBS-$(CONFIG_RESAMPLE_FILTER)
+=
avresample
FFLIBS-$(CONFIG_RESAMPLE_FILTER)
+=
avresample
...
@@ -24,6 +25,7 @@ OBJS = allfilters.o \
...
@@ -24,6 +25,7 @@ OBJS = allfilters.o \
OBJS-$(CONFIG_AFORMAT_FILTER)
+=
af_aformat.o
OBJS-$(CONFIG_AFORMAT_FILTER)
+=
af_aformat.o
OBJS-$(CONFIG_ANULL_FILTER)
+=
af_anull.o
OBJS-$(CONFIG_ANULL_FILTER)
+=
af_anull.o
OBJS-$(CONFIG_ASYNCTS_FILTER)
+=
af_asyncts.o
OBJS-$(CONFIG_RESAMPLE_FILTER)
+=
af_resample.o
OBJS-$(CONFIG_RESAMPLE_FILTER)
+=
af_resample.o
OBJS-$(CONFIG_ANULLSRC_FILTER)
+=
asrc_anullsrc.o
OBJS-$(CONFIG_ANULLSRC_FILTER)
+=
asrc_anullsrc.o
...
...
libavfilter/af_asyncts.c
0 → 100644
View file @
9f26421b
/*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavresample/avresample.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
#include "audio.h"
#include "avfilter.h"
typedef
struct
ASyncContext
{
const
AVClass
*
class
;
AVAudioResampleContext
*
avr
;
int64_t
pts
;
///< timestamp in samples of the first sample in fifo
int
min_delta
;
///< pad/trim min threshold in samples
/* options */
int
resample
;
float
min_delta_sec
;
int
max_comp
;
}
ASyncContext
;
#define OFFSET(x) offsetof(ASyncContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
static
const
AVOption
options
[]
=
{
{
"compensate"
,
"Stretch/squeeze the data to make it match the timestamps"
,
OFFSET
(
resample
),
AV_OPT_TYPE_INT
,
{
0
},
0
,
1
,
A
},
{
"min_delta"
,
"Minimum difference between timestamps and audio data "
"(in seconds) to trigger padding/trimmin the data."
,
OFFSET
(
min_delta_sec
),
AV_OPT_TYPE_FLOAT
,
{
0
.
1
},
0
,
INT_MAX
,
A
},
{
"max_comp"
,
"Maximum compensation in samples per second."
,
OFFSET
(
max_comp
),
AV_OPT_TYPE_INT
,
{
500
},
0
,
INT_MAX
,
A
},
{
NULL
},
};
static
const
AVClass
async_class
=
{
.
class_name
=
"asyncts filter"
,
.
item_name
=
av_default_item_name
,
.
option
=
options
,
.
version
=
LIBAVUTIL_VERSION_INT
,
};
static
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
ASyncContext
*
s
=
ctx
->
priv
;
int
ret
;
s
->
class
=
&
async_class
;
av_opt_set_defaults
(
s
);
if
((
ret
=
av_set_options_string
(
s
,
args
,
"="
,
":"
))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing options string '%s'.
\n
"
,
args
);
return
ret
;
}
av_opt_free
(
s
);
s
->
pts
=
AV_NOPTS_VALUE
;
return
0
;
}
static
void
uninit
(
AVFilterContext
*
ctx
)
{
ASyncContext
*
s
=
ctx
->
priv
;
if
(
s
->
avr
)
{
avresample_close
(
s
->
avr
);
avresample_free
(
&
s
->
avr
);
}
}
static
int
config_props
(
AVFilterLink
*
link
)
{
ASyncContext
*
s
=
link
->
src
->
priv
;
int
ret
;
s
->
min_delta
=
s
->
min_delta_sec
*
link
->
sample_rate
;
link
->
time_base
=
(
AVRational
){
1
,
link
->
sample_rate
};
s
->
avr
=
avresample_alloc_context
();
if
(
!
s
->
avr
)
return
AVERROR
(
ENOMEM
);
av_opt_set_int
(
s
->
avr
,
"in_channel_layout"
,
link
->
channel_layout
,
0
);
av_opt_set_int
(
s
->
avr
,
"out_channel_layout"
,
link
->
channel_layout
,
0
);
av_opt_set_int
(
s
->
avr
,
"in_sample_fmt"
,
link
->
format
,
0
);
av_opt_set_int
(
s
->
avr
,
"out_sample_fmt"
,
link
->
format
,
0
);
av_opt_set_int
(
s
->
avr
,
"in_sample_rate"
,
link
->
sample_rate
,
0
);
av_opt_set_int
(
s
->
avr
,
"out_sample_rate"
,
link
->
sample_rate
,
0
);
if
(
s
->
resample
)
av_opt_set_int
(
s
->
avr
,
"force_resampling"
,
1
,
0
);
if
((
ret
=
avresample_open
(
s
->
avr
))
<
0
)
return
ret
;
return
0
;
}
static
int
request_frame
(
AVFilterLink
*
link
)
{
AVFilterContext
*
ctx
=
link
->
src
;
ASyncContext
*
s
=
ctx
->
priv
;
int
ret
=
avfilter_request_frame
(
ctx
->
inputs
[
0
]);
int
nb_samples
;
/* flush the fifo */
if
(
ret
==
AVERROR_EOF
&&
(
nb_samples
=
avresample_get_delay
(
s
->
avr
)))
{
AVFilterBufferRef
*
buf
=
ff_get_audio_buffer
(
link
,
AV_PERM_WRITE
,
nb_samples
);
if
(
!
buf
)
return
AVERROR
(
ENOMEM
);
avresample_convert
(
s
->
avr
,
(
void
**
)
buf
->
extended_data
,
buf
->
linesize
[
0
],
nb_samples
,
NULL
,
0
,
0
);
buf
->
pts
=
s
->
pts
;
ff_filter_samples
(
link
,
buf
);
return
0
;
}
return
ret
;
}
static
void
write_to_fifo
(
ASyncContext
*
s
,
AVFilterBufferRef
*
buf
)
{
avresample_convert
(
s
->
avr
,
NULL
,
0
,
0
,
(
void
**
)
buf
->
extended_data
,
buf
->
linesize
[
0
],
buf
->
audio
->
nb_samples
);
avfilter_unref_buffer
(
buf
);
}
/* get amount of data currently buffered, in samples */
static
int64_t
get_delay
(
ASyncContext
*
s
)
{
return
avresample_available
(
s
->
avr
)
+
avresample_get_delay
(
s
->
avr
);
}
static
void
filter_samples
(
AVFilterLink
*
inlink
,
AVFilterBufferRef
*
buf
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ASyncContext
*
s
=
ctx
->
priv
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
int
nb_channels
=
av_get_channel_layout_nb_channels
(
buf
->
audio
->
channel_layout
);
int64_t
pts
=
(
buf
->
pts
==
AV_NOPTS_VALUE
)
?
buf
->
pts
:
av_rescale_q
(
buf
->
pts
,
inlink
->
time_base
,
outlink
->
time_base
);
int
out_size
;
int64_t
delta
;
/* buffer data until we get the first timestamp */
if
(
s
->
pts
==
AV_NOPTS_VALUE
)
{
if
(
pts
!=
AV_NOPTS_VALUE
)
{
s
->
pts
=
pts
-
get_delay
(
s
);
}
write_to_fifo
(
s
,
buf
);
return
;
}
/* now wait for the next timestamp */
if
(
pts
==
AV_NOPTS_VALUE
)
{
write_to_fifo
(
s
,
buf
);
return
;
}
/* when we have two timestamps, compute how many samples would we have
* to add/remove to get proper sync between data and timestamps */
delta
=
pts
-
s
->
pts
-
get_delay
(
s
);
out_size
=
avresample_available
(
s
->
avr
);
if
(
labs
(
delta
)
>
s
->
min_delta
)
{
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Discontinuity - %"
PRId64
" samples.
\n
"
,
delta
);
out_size
+=
delta
;
}
else
if
(
s
->
resample
)
{
int
comp
=
av_clip
(
delta
,
-
s
->
max_comp
,
s
->
max_comp
);
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Compensating %d samples per second.
\n
"
,
comp
);
avresample_set_compensation
(
s
->
avr
,
delta
,
inlink
->
sample_rate
);
}
if
(
out_size
>
0
)
{
AVFilterBufferRef
*
buf_out
=
ff_get_audio_buffer
(
outlink
,
AV_PERM_WRITE
,
out_size
);
if
(
!
buf_out
)
return
;
avresample_read
(
s
->
avr
,
(
void
**
)
buf_out
->
extended_data
,
out_size
);
buf_out
->
pts
=
s
->
pts
;
if
(
delta
>
0
)
{
av_samples_set_silence
(
buf_out
->
extended_data
,
out_size
-
delta
,
delta
,
nb_channels
,
buf
->
format
);
}
ff_filter_samples
(
outlink
,
buf_out
);
}
else
{
av_log
(
ctx
,
AV_LOG_WARNING
,
"Non-monotonous timestamps, dropping "
"whole buffer.
\n
"
);
}
/* drain any remaining buffered data */
avresample_read
(
s
->
avr
,
NULL
,
avresample_available
(
s
->
avr
));
s
->
pts
=
pts
-
avresample_get_delay
(
s
->
avr
);
avresample_convert
(
s
->
avr
,
NULL
,
0
,
0
,
(
void
**
)
buf
->
extended_data
,
buf
->
linesize
[
0
],
buf
->
audio
->
nb_samples
);
avfilter_unref_buffer
(
buf
);
}
AVFilter
avfilter_af_asyncts
=
{
.
name
=
"asyncts"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Sync audio data to timestamps"
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
ASyncContext
),
.
inputs
=
(
const
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_samples
=
filter_samples
},
{
NULL
}},
.
outputs
=
(
const
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
config_props
=
config_props
,
.
request_frame
=
request_frame
},
{
NULL
}},
};
libavfilter/allfilters.c
View file @
9f26421b
...
@@ -36,6 +36,7 @@ void avfilter_register_all(void)
...
@@ -36,6 +36,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
AFORMAT
,
aformat
,
af
);
REGISTER_FILTER
(
AFORMAT
,
aformat
,
af
);
REGISTER_FILTER
(
ANULL
,
anull
,
af
);
REGISTER_FILTER
(
ANULL
,
anull
,
af
);
REGISTER_FILTER
(
ASYNCTS
,
asyncts
,
af
);
REGISTER_FILTER
(
RESAMPLE
,
resample
,
af
);
REGISTER_FILTER
(
RESAMPLE
,
resample
,
af
);
REGISTER_FILTER
(
ANULLSRC
,
anullsrc
,
asrc
);
REGISTER_FILTER
(
ANULLSRC
,
anullsrc
,
asrc
);
...
...
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