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
7ad0d986
Commit
7ad0d986
authored
Apr 27, 2012
by
Nicolas George
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: merge asrc_abuffer into vsrc_buffer.
parent
28c57751
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
338 additions
and
381 deletions
+338
-381
Makefile
libavfilter/Makefile
+0
-1
asrc_abuffer.c
libavfilter/asrc_abuffer.c
+0
-369
vsrc_buffer.c
libavfilter/vsrc_buffer.c
+338
-11
No files found.
libavfilter/Makefile
View file @
7ad0d986
...
...
@@ -42,7 +42,6 @@ OBJS-$(CONFIG_PAN_FILTER) += af_pan.o
OBJS-$(CONFIG_SILENCEDETECT_FILTER)
+=
af_silencedetect.o
OBJS-$(CONFIG_VOLUME_FILTER)
+=
af_volume.o
OBJS-$(CONFIG_ABUFFER_FILTER)
+=
asrc_abuffer.o
OBJS-$(CONFIG_AEVALSRC_FILTER)
+=
asrc_aevalsrc.o
OBJS-$(CONFIG_AMOVIE_FILTER)
+=
src_movie.o
OBJS-$(CONFIG_ANULLSRC_FILTER)
+=
asrc_anullsrc.o
...
...
libavfilter/asrc_abuffer.c
deleted
100644 → 0
View file @
28c57751
/*
* Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
* Copyright (c) 2011 Mina Nagy Zaki
*
* 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
* memory buffer source for audio
*/
#include "libavutil/audioconvert.h"
#include "libavutil/avstring.h"
#include "libavutil/fifo.h"
#include "asrc_abuffer.h"
#include "internal.h"
typedef
struct
{
// Audio format of incoming buffers
int
sample_rate
;
unsigned
int
sample_format
;
int64_t
channel_layout
;
int
packing_format
;
// FIFO buffer of audio buffer ref pointers
AVFifoBuffer
*
fifo
;
// Normalization filters
AVFilterContext
*
aconvert
;
AVFilterContext
*
aresample
;
}
ABufferSourceContext
;
#define FIFO_SIZE 8
static
void
buf_free
(
AVFilterBuffer
*
ptr
)
{
av_free
(
ptr
);
return
;
}
static
void
set_link_source
(
AVFilterContext
*
src
,
AVFilterLink
*
link
)
{
link
->
src
=
src
;
link
->
srcpad
=
&
(
src
->
output_pads
[
0
]);
src
->
outputs
[
0
]
=
link
;
}
static
int
reconfigure_filter
(
ABufferSourceContext
*
abuffer
,
AVFilterContext
*
filt_ctx
)
{
int
ret
;
AVFilterLink
*
const
inlink
=
filt_ctx
->
inputs
[
0
];
AVFilterLink
*
const
outlink
=
filt_ctx
->
outputs
[
0
];
inlink
->
format
=
abuffer
->
sample_format
;
inlink
->
channel_layout
=
abuffer
->
channel_layout
;
inlink
->
planar
=
abuffer
->
packing_format
;
inlink
->
sample_rate
=
abuffer
->
sample_rate
;
filt_ctx
->
filter
->
uninit
(
filt_ctx
);
memset
(
filt_ctx
->
priv
,
0
,
filt_ctx
->
filter
->
priv_size
);
if
((
ret
=
filt_ctx
->
filter
->
init
(
filt_ctx
,
NULL
,
NULL
))
<
0
)
return
ret
;
if
((
ret
=
inlink
->
srcpad
->
config_props
(
inlink
))
<
0
)
return
ret
;
return
outlink
->
srcpad
->
config_props
(
outlink
);
}
static
int
insert_filter
(
ABufferSourceContext
*
abuffer
,
AVFilterLink
*
link
,
AVFilterContext
**
filt_ctx
,
const
char
*
filt_name
)
{
int
ret
;
if
((
ret
=
avfilter_open
(
filt_ctx
,
avfilter_get_by_name
(
filt_name
),
NULL
))
<
0
)
return
ret
;
link
->
src
->
outputs
[
0
]
=
NULL
;
if
((
ret
=
avfilter_link
(
link
->
src
,
0
,
*
filt_ctx
,
0
))
<
0
)
{
link
->
src
->
outputs
[
0
]
=
link
;
return
ret
;
}
set_link_source
(
*
filt_ctx
,
link
);
if
((
ret
=
reconfigure_filter
(
abuffer
,
*
filt_ctx
))
<
0
)
{
avfilter_free
(
*
filt_ctx
);
return
ret
;
}
return
0
;
}
static
void
remove_filter
(
AVFilterContext
**
filt_ctx
)
{
AVFilterLink
*
outlink
=
(
*
filt_ctx
)
->
outputs
[
0
];
AVFilterContext
*
src
=
(
*
filt_ctx
)
->
inputs
[
0
]
->
src
;
(
*
filt_ctx
)
->
outputs
[
0
]
=
NULL
;
avfilter_free
(
*
filt_ctx
);
*
filt_ctx
=
NULL
;
set_link_source
(
src
,
outlink
);
}
static
inline
void
log_input_change
(
void
*
ctx
,
AVFilterLink
*
link
,
AVFilterBufferRef
*
ref
)
{
char
old_layout_str
[
16
],
new_layout_str
[
16
];
av_get_channel_layout_string
(
old_layout_str
,
sizeof
(
old_layout_str
),
-
1
,
link
->
channel_layout
);
av_get_channel_layout_string
(
new_layout_str
,
sizeof
(
new_layout_str
),
-
1
,
ref
->
audio
->
channel_layout
);
av_log
(
ctx
,
AV_LOG_INFO
,
"Audio input format changed: "
"%s:%s:%d -> %s:%s:%d, normalizing
\n
"
,
av_get_sample_fmt_name
(
link
->
format
),
old_layout_str
,
(
int
)
link
->
sample_rate
,
av_get_sample_fmt_name
(
ref
->
format
),
new_layout_str
,
ref
->
audio
->
sample_rate
);
}
int
av_asrc_buffer_add_audio_buffer_ref
(
AVFilterContext
*
ctx
,
AVFilterBufferRef
*
samplesref
,
int
av_unused
flags
)
{
ABufferSourceContext
*
abuffer
=
ctx
->
priv
;
AVFilterLink
*
link
;
int
ret
,
logged
=
0
;
if
(
av_fifo_space
(
abuffer
->
fifo
)
<
sizeof
(
samplesref
))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Buffering limit reached. Please consume some available frames "
"before adding new ones.
\n
"
);
return
AVERROR
(
EINVAL
);
}
// Normalize input
link
=
ctx
->
outputs
[
0
];
if
(
samplesref
->
audio
->
sample_rate
!=
link
->
sample_rate
)
{
log_input_change
(
ctx
,
link
,
samplesref
);
logged
=
1
;
abuffer
->
sample_rate
=
samplesref
->
audio
->
sample_rate
;
if
(
!
abuffer
->
aresample
)
{
ret
=
insert_filter
(
abuffer
,
link
,
&
abuffer
->
aresample
,
"aresample"
);
if
(
ret
<
0
)
return
ret
;
}
else
{
link
=
abuffer
->
aresample
->
outputs
[
0
];
if
(
samplesref
->
audio
->
sample_rate
==
link
->
sample_rate
)
remove_filter
(
&
abuffer
->
aresample
);
else
if
((
ret
=
reconfigure_filter
(
abuffer
,
abuffer
->
aresample
))
<
0
)
return
ret
;
}
}
link
=
ctx
->
outputs
[
0
];
if
(
samplesref
->
format
!=
link
->
format
||
samplesref
->
audio
->
channel_layout
!=
link
->
channel_layout
||
samplesref
->
audio
->
planar
!=
link
->
planar
)
{
if
(
!
logged
)
log_input_change
(
ctx
,
link
,
samplesref
);
abuffer
->
sample_format
=
samplesref
->
format
;
abuffer
->
channel_layout
=
samplesref
->
audio
->
channel_layout
;
abuffer
->
packing_format
=
samplesref
->
audio
->
planar
;
if
(
!
abuffer
->
aconvert
)
{
ret
=
insert_filter
(
abuffer
,
link
,
&
abuffer
->
aconvert
,
"aconvert"
);
if
(
ret
<
0
)
return
ret
;
}
else
{
link
=
abuffer
->
aconvert
->
outputs
[
0
];
if
(
samplesref
->
format
==
link
->
format
&&
samplesref
->
audio
->
channel_layout
==
link
->
channel_layout
&&
samplesref
->
audio
->
planar
==
link
->
planar
)
remove_filter
(
&
abuffer
->
aconvert
);
else
if
((
ret
=
reconfigure_filter
(
abuffer
,
abuffer
->
aconvert
))
<
0
)
return
ret
;
}
}
if
(
sizeof
(
samplesref
)
!=
av_fifo_generic_write
(
abuffer
->
fifo
,
&
samplesref
,
sizeof
(
samplesref
),
NULL
))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error while writing to FIFO
\n
"
);
return
AVERROR
(
EINVAL
);
}
return
0
;
}
int
av_asrc_buffer_add_samples
(
AVFilterContext
*
ctx
,
uint8_t
*
data
[
8
],
int
linesize
[
8
],
int
nb_samples
,
int
sample_rate
,
int
sample_fmt
,
int64_t
channel_layout
,
int
planar
,
int64_t
pts
,
int
av_unused
flags
)
{
AVFilterBufferRef
*
samplesref
;
samplesref
=
avfilter_get_audio_buffer_ref_from_arrays
(
data
,
linesize
,
AV_PERM_WRITE
,
nb_samples
,
sample_fmt
,
channel_layout
,
planar
);
if
(
!
samplesref
)
return
AVERROR
(
ENOMEM
);
samplesref
->
buf
->
free
=
buf_free
;
samplesref
->
pts
=
pts
;
samplesref
->
audio
->
sample_rate
=
sample_rate
;
return
av_asrc_buffer_add_audio_buffer_ref
(
ctx
,
samplesref
,
0
);
}
int
av_asrc_buffer_add_buffer
(
AVFilterContext
*
ctx
,
uint8_t
*
buf
,
int
buf_size
,
int
sample_rate
,
int
sample_fmt
,
int64_t
channel_layout
,
int
planar
,
int64_t
pts
,
int
av_unused
flags
)
{
uint8_t
*
data
[
8
]
=
{
0
};
int
linesize
[
8
];
int
nb_channels
=
av_get_channel_layout_nb_channels
(
channel_layout
),
nb_samples
=
buf_size
/
nb_channels
/
av_get_bytes_per_sample
(
sample_fmt
);
av_samples_fill_arrays
(
data
,
linesize
,
buf
,
nb_channels
,
nb_samples
,
sample_fmt
,
16
);
return
av_asrc_buffer_add_samples
(
ctx
,
data
,
linesize
,
nb_samples
,
sample_rate
,
sample_fmt
,
channel_layout
,
planar
,
pts
,
flags
);
}
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args0
,
void
*
opaque
)
{
ABufferSourceContext
*
abuffer
=
ctx
->
priv
;
char
*
arg
=
NULL
,
*
ptr
,
chlayout_str
[
16
];
char
*
args
=
av_strdup
(
args0
);
int
ret
;
arg
=
av_strtok
(
args
,
":"
,
&
ptr
);
#define ADD_FORMAT(fmt_name) \
if (!arg) \
goto arg_fail; \
if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \
av_freep(&args); \
return ret; \
} \
if (*args) \
arg = av_strtok(NULL, ":", &ptr)
ADD_FORMAT
(
sample_rate
);
ADD_FORMAT
(
sample_format
);
ADD_FORMAT
(
channel_layout
);
ADD_FORMAT
(
packing_format
);
abuffer
->
fifo
=
av_fifo_alloc
(
FIFO_SIZE
*
sizeof
(
AVFilterBufferRef
*
));
if
(
!
abuffer
->
fifo
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to allocate fifo, filter init failed.
\n
"
);
return
AVERROR
(
ENOMEM
);
}
av_get_channel_layout_string
(
chlayout_str
,
sizeof
(
chlayout_str
),
-
1
,
abuffer
->
channel_layout
);
av_log
(
ctx
,
AV_LOG_INFO
,
"format:%s layout:%s rate:%d
\n
"
,
av_get_sample_fmt_name
(
abuffer
->
sample_format
),
chlayout_str
,
abuffer
->
sample_rate
);
av_freep
(
&
args
);
return
0
;
arg_fail:
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid arguments, must be of the form "
"sample_rate:sample_fmt:channel_layout:packing
\n
"
);
av_freep
(
&
args
);
return
AVERROR
(
EINVAL
);
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
ABufferSourceContext
*
abuffer
=
ctx
->
priv
;
av_fifo_free
(
abuffer
->
fifo
);
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
ABufferSourceContext
*
abuffer
=
ctx
->
priv
;
AVFilterFormats
*
formats
;
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
sample_format
);
avfilter_set_common_sample_formats
(
ctx
,
formats
);
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
channel_layout
);
avfilter_set_common_channel_layouts
(
ctx
,
formats
);
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
packing_format
);
avfilter_set_common_packing_formats
(
ctx
,
formats
);
return
0
;
}
static
int
config_output
(
AVFilterLink
*
outlink
)
{
ABufferSourceContext
*
abuffer
=
outlink
->
src
->
priv
;
outlink
->
sample_rate
=
abuffer
->
sample_rate
;
return
0
;
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
ABufferSourceContext
*
abuffer
=
outlink
->
src
->
priv
;
AVFilterBufferRef
*
samplesref
;
if
(
!
av_fifo_size
(
abuffer
->
fifo
))
return
AVERROR
(
EAGAIN
);
av_fifo_generic_read
(
abuffer
->
fifo
,
&
samplesref
,
sizeof
(
samplesref
),
NULL
);
avfilter_filter_samples
(
outlink
,
avfilter_ref_buffer
(
samplesref
,
~
0
));
avfilter_unref_buffer
(
samplesref
);
return
0
;
}
static
int
poll_frame
(
AVFilterLink
*
outlink
)
{
ABufferSourceContext
*
abuffer
=
outlink
->
src
->
priv
;
return
av_fifo_size
(
abuffer
->
fifo
)
/
sizeof
(
AVFilterBufferRef
*
);
}
AVFilter
avfilter_asrc_abuffer
=
{
.
name
=
"abuffer"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Buffer audio frames, and make them accessible to the filterchain."
),
.
priv_size
=
sizeof
(
ABufferSourceContext
),
.
query_formats
=
query_formats
,
.
init
=
init
,
.
uninit
=
uninit
,
.
inputs
=
(
const
AVFilterPad
[])
{{
.
name
=
NULL
}},
.
outputs
=
(
const
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
request_frame
=
request_frame
,
.
poll_frame
=
poll_frame
,
.
config_props
=
config_output
,
},
{
.
name
=
NULL
}},
};
libavfilter/vsrc_buffer.c
View file @
7ad0d986
/*
* Copyright (c) 2008 Vitor Sessak
* Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
* Copyright (c) 2011 Mina Nagy Zaki
*
* This file is part of FFmpeg.
*
...
...
@@ -28,21 +30,39 @@
#include "avcodec.h"
#include "buffersrc.h"
#include "vsrc_buffer.h"
#include "asrc_abuffer.h"
#include "libavutil/audioconvert.h"
#include "libavutil/avstring.h"
#include "libavutil/fifo.h"
#include "libavutil/imgutils.h"
typedef
struct
{
AVFilterContext
*
scale
;
AVFifoBuffer
*
fifo
;
AVRational
time_base
;
///< time_base to set in the output link
int
eof
;
unsigned
nb_failed_requests
;
/* Video only */
AVFilterContext
*
scale
;
int
h
,
w
;
enum
PixelFormat
pix_fmt
;
AVRational
time_base
;
///< time_base to set in the output link
AVRational
sample_aspect_ratio
;
char
sws_param
[
256
];
int
eof
;
unsigned
nb_failed_requests
;
/* Audio only */
// Audio format of incoming buffers
int
sample_rate
;
unsigned
int
sample_format
;
int64_t
channel_layout
;
int
packing_format
;
// Normalization filters
AVFilterContext
*
aconvert
;
AVFilterContext
*
aresample
;
}
BufferSourceContext
;
#define FIFO_SIZE 8
#define CHECK_PARAM_CHANGE(s, c, width, height, format)\
if (c->w != width || c->h != height || c->pix_fmt != format) {\
av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
...
...
@@ -186,7 +206,7 @@ unsigned av_vsrc_buffer_get_nb_failed_requests(AVFilterContext *buffer_src)
return
((
BufferSourceContext
*
)
buffer_src
->
priv
)
->
nb_failed_requests
;
}
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
static
av_cold
int
init
_video
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
BufferSourceContext
*
c
=
ctx
->
priv
;
char
pix_fmt_str
[
128
];
...
...
@@ -214,6 +234,52 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return
0
;
}
static
av_cold
int
init_audio
(
AVFilterContext
*
ctx
,
const
char
*
args0
,
void
*
opaque
)
{
BufferSourceContext
*
abuffer
=
ctx
->
priv
;
char
*
arg
=
NULL
,
*
ptr
,
chlayout_str
[
16
];
char
*
args
=
av_strdup
(
args0
);
int
ret
;
arg
=
av_strtok
(
args
,
":"
,
&
ptr
);
#define ADD_FORMAT(fmt_name) \
if (!arg) \
goto arg_fail; \
if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \
av_freep(&args); \
return ret; \
} \
if (*args) \
arg = av_strtok(NULL, ":", &ptr)
ADD_FORMAT
(
sample_rate
);
ADD_FORMAT
(
sample_format
);
ADD_FORMAT
(
channel_layout
);
ADD_FORMAT
(
packing_format
);
abuffer
->
fifo
=
av_fifo_alloc
(
FIFO_SIZE
*
sizeof
(
AVFilterBufferRef
*
));
if
(
!
abuffer
->
fifo
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to allocate fifo, filter init failed.
\n
"
);
return
AVERROR
(
ENOMEM
);
}
av_get_channel_layout_string
(
chlayout_str
,
sizeof
(
chlayout_str
),
-
1
,
abuffer
->
channel_layout
);
av_log
(
ctx
,
AV_LOG_INFO
,
"format:%s layout:%s rate:%d
\n
"
,
av_get_sample_fmt_name
(
abuffer
->
sample_format
),
chlayout_str
,
abuffer
->
sample_rate
);
av_freep
(
&
args
);
return
0
;
arg_fail:
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid arguments, must be of the form "
"sample_rate:sample_fmt:channel_layout:packing
\n
"
);
av_freep
(
&
args
);
return
AVERROR
(
EINVAL
);
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
BufferSourceContext
*
s
=
ctx
->
priv
;
...
...
@@ -228,7 +294,7 @@ static av_cold void uninit(AVFilterContext *ctx)
s
->
scale
=
NULL
;
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
static
int
query_formats
_video
(
AVFilterContext
*
ctx
)
{
BufferSourceContext
*
c
=
ctx
->
priv
;
enum
PixelFormat
pix_fmts
[]
=
{
c
->
pix_fmt
,
PIX_FMT_NONE
};
...
...
@@ -237,7 +303,27 @@ static int query_formats(AVFilterContext *ctx)
return
0
;
}
static
int
config_props
(
AVFilterLink
*
link
)
static
int
query_formats_audio
(
AVFilterContext
*
ctx
)
{
BufferSourceContext
*
abuffer
=
ctx
->
priv
;
AVFilterFormats
*
formats
;
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
sample_format
);
avfilter_set_common_sample_formats
(
ctx
,
formats
);
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
channel_layout
);
avfilter_set_common_channel_layouts
(
ctx
,
formats
);
formats
=
NULL
;
avfilter_add_format
(
&
formats
,
abuffer
->
packing_format
);
avfilter_set_common_packing_formats
(
ctx
,
formats
);
return
0
;
}
static
int
config_output_video
(
AVFilterLink
*
link
)
{
BufferSourceContext
*
c
=
link
->
src
->
priv
;
...
...
@@ -249,6 +335,13 @@ static int config_props(AVFilterLink *link)
return
0
;
}
static
int
config_output_audio
(
AVFilterLink
*
outlink
)
{
BufferSourceContext
*
abuffer
=
outlink
->
src
->
priv
;
outlink
->
sample_rate
=
abuffer
->
sample_rate
;
return
0
;
}
static
int
request_frame
(
AVFilterLink
*
link
)
{
BufferSourceContext
*
c
=
link
->
src
->
priv
;
...
...
@@ -262,11 +355,20 @@ static int request_frame(AVFilterLink *link)
}
av_fifo_generic_read
(
c
->
fifo
,
&
buf
,
sizeof
(
buf
),
NULL
);
switch
(
link
->
type
)
{
case
AVMEDIA_TYPE_VIDEO
:
/* TODO reindent */
avfilter_start_frame
(
link
,
avfilter_ref_buffer
(
buf
,
~
0
));
avfilter_draw_slice
(
link
,
0
,
link
->
h
,
1
);
avfilter_end_frame
(
link
);
avfilter_unref_buffer
(
buf
);
break
;
case
AVMEDIA_TYPE_AUDIO
:
avfilter_filter_samples
(
link
,
avfilter_ref_buffer
(
buf
,
~
0
));
break
;
default:
return
AVERROR
(
ENOSYS
);
}
return
0
;
}
...
...
@@ -279,13 +381,216 @@ static int poll_frame(AVFilterLink *link)
return
size
/
sizeof
(
AVFilterBufferRef
*
);
}
static
void
buf_free
(
AVFilterBuffer
*
ptr
)
{
av_free
(
ptr
);
return
;
}
static
void
set_link_source
(
AVFilterContext
*
src
,
AVFilterLink
*
link
)
{
link
->
src
=
src
;
link
->
srcpad
=
&
(
src
->
output_pads
[
0
]);
src
->
outputs
[
0
]
=
link
;
}
static
int
reconfigure_filter
(
BufferSourceContext
*
abuffer
,
AVFilterContext
*
filt_ctx
)
{
int
ret
;
AVFilterLink
*
const
inlink
=
filt_ctx
->
inputs
[
0
];
AVFilterLink
*
const
outlink
=
filt_ctx
->
outputs
[
0
];
inlink
->
format
=
abuffer
->
sample_format
;
inlink
->
channel_layout
=
abuffer
->
channel_layout
;
inlink
->
planar
=
abuffer
->
packing_format
;
inlink
->
sample_rate
=
abuffer
->
sample_rate
;
filt_ctx
->
filter
->
uninit
(
filt_ctx
);
memset
(
filt_ctx
->
priv
,
0
,
filt_ctx
->
filter
->
priv_size
);
if
((
ret
=
filt_ctx
->
filter
->
init
(
filt_ctx
,
NULL
,
NULL
))
<
0
)
return
ret
;
if
((
ret
=
inlink
->
srcpad
->
config_props
(
inlink
))
<
0
)
return
ret
;
return
outlink
->
srcpad
->
config_props
(
outlink
);
}
static
int
insert_filter
(
BufferSourceContext
*
abuffer
,
AVFilterLink
*
link
,
AVFilterContext
**
filt_ctx
,
const
char
*
filt_name
)
{
int
ret
;
if
((
ret
=
avfilter_open
(
filt_ctx
,
avfilter_get_by_name
(
filt_name
),
NULL
))
<
0
)
return
ret
;
link
->
src
->
outputs
[
0
]
=
NULL
;
if
((
ret
=
avfilter_link
(
link
->
src
,
0
,
*
filt_ctx
,
0
))
<
0
)
{
link
->
src
->
outputs
[
0
]
=
link
;
return
ret
;
}
set_link_source
(
*
filt_ctx
,
link
);
if
((
ret
=
reconfigure_filter
(
abuffer
,
*
filt_ctx
))
<
0
)
{
avfilter_free
(
*
filt_ctx
);
return
ret
;
}
return
0
;
}
static
void
remove_filter
(
AVFilterContext
**
filt_ctx
)
{
AVFilterLink
*
outlink
=
(
*
filt_ctx
)
->
outputs
[
0
];
AVFilterContext
*
src
=
(
*
filt_ctx
)
->
inputs
[
0
]
->
src
;
(
*
filt_ctx
)
->
outputs
[
0
]
=
NULL
;
avfilter_free
(
*
filt_ctx
);
*
filt_ctx
=
NULL
;
set_link_source
(
src
,
outlink
);
}
static
inline
void
log_input_change
(
void
*
ctx
,
AVFilterLink
*
link
,
AVFilterBufferRef
*
ref
)
{
char
old_layout_str
[
16
],
new_layout_str
[
16
];
av_get_channel_layout_string
(
old_layout_str
,
sizeof
(
old_layout_str
),
-
1
,
link
->
channel_layout
);
av_get_channel_layout_string
(
new_layout_str
,
sizeof
(
new_layout_str
),
-
1
,
ref
->
audio
->
channel_layout
);
av_log
(
ctx
,
AV_LOG_INFO
,
"Audio input format changed: "
"%s:%s:%d -> %s:%s:%d, normalizing
\n
"
,
av_get_sample_fmt_name
(
link
->
format
),
old_layout_str
,
(
int
)
link
->
sample_rate
,
av_get_sample_fmt_name
(
ref
->
format
),
new_layout_str
,
ref
->
audio
->
sample_rate
);
}
int
av_asrc_buffer_add_audio_buffer_ref
(
AVFilterContext
*
ctx
,
AVFilterBufferRef
*
samplesref
,
int
av_unused
flags
)
{
BufferSourceContext
*
abuffer
=
ctx
->
priv
;
AVFilterLink
*
link
;
int
ret
,
logged
=
0
;
if
(
av_fifo_space
(
abuffer
->
fifo
)
<
sizeof
(
samplesref
))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Buffering limit reached. Please consume some available frames "
"before adding new ones.
\n
"
);
return
AVERROR
(
EINVAL
);
}
// Normalize input
link
=
ctx
->
outputs
[
0
];
if
(
samplesref
->
audio
->
sample_rate
!=
link
->
sample_rate
)
{
log_input_change
(
ctx
,
link
,
samplesref
);
logged
=
1
;
abuffer
->
sample_rate
=
samplesref
->
audio
->
sample_rate
;
if
(
!
abuffer
->
aresample
)
{
ret
=
insert_filter
(
abuffer
,
link
,
&
abuffer
->
aresample
,
"aresample"
);
if
(
ret
<
0
)
return
ret
;
}
else
{
link
=
abuffer
->
aresample
->
outputs
[
0
];
if
(
samplesref
->
audio
->
sample_rate
==
link
->
sample_rate
)
remove_filter
(
&
abuffer
->
aresample
);
else
if
((
ret
=
reconfigure_filter
(
abuffer
,
abuffer
->
aresample
))
<
0
)
return
ret
;
}
}
link
=
ctx
->
outputs
[
0
];
if
(
samplesref
->
format
!=
link
->
format
||
samplesref
->
audio
->
channel_layout
!=
link
->
channel_layout
||
samplesref
->
audio
->
planar
!=
link
->
planar
)
{
if
(
!
logged
)
log_input_change
(
ctx
,
link
,
samplesref
);
abuffer
->
sample_format
=
samplesref
->
format
;
abuffer
->
channel_layout
=
samplesref
->
audio
->
channel_layout
;
abuffer
->
packing_format
=
samplesref
->
audio
->
planar
;
if
(
!
abuffer
->
aconvert
)
{
ret
=
insert_filter
(
abuffer
,
link
,
&
abuffer
->
aconvert
,
"aconvert"
);
if
(
ret
<
0
)
return
ret
;
}
else
{
link
=
abuffer
->
aconvert
->
outputs
[
0
];
if
(
samplesref
->
format
==
link
->
format
&&
samplesref
->
audio
->
channel_layout
==
link
->
channel_layout
&&
samplesref
->
audio
->
planar
==
link
->
planar
)
remove_filter
(
&
abuffer
->
aconvert
);
else
if
((
ret
=
reconfigure_filter
(
abuffer
,
abuffer
->
aconvert
))
<
0
)
return
ret
;
}
}
if
(
sizeof
(
samplesref
)
!=
av_fifo_generic_write
(
abuffer
->
fifo
,
&
samplesref
,
sizeof
(
samplesref
),
NULL
))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error while writing to FIFO
\n
"
);
return
AVERROR
(
EINVAL
);
}
return
0
;
}
int
av_asrc_buffer_add_samples
(
AVFilterContext
*
ctx
,
uint8_t
*
data
[
8
],
int
linesize
[
8
],
int
nb_samples
,
int
sample_rate
,
int
sample_fmt
,
int64_t
channel_layout
,
int
planar
,
int64_t
pts
,
int
av_unused
flags
)
{
AVFilterBufferRef
*
samplesref
;
samplesref
=
avfilter_get_audio_buffer_ref_from_arrays
(
data
,
linesize
,
AV_PERM_WRITE
,
nb_samples
,
sample_fmt
,
channel_layout
,
planar
);
if
(
!
samplesref
)
return
AVERROR
(
ENOMEM
);
samplesref
->
buf
->
free
=
buf_free
;
samplesref
->
pts
=
pts
;
samplesref
->
audio
->
sample_rate
=
sample_rate
;
return
av_asrc_buffer_add_audio_buffer_ref
(
ctx
,
samplesref
,
0
);
}
int
av_asrc_buffer_add_buffer
(
AVFilterContext
*
ctx
,
uint8_t
*
buf
,
int
buf_size
,
int
sample_rate
,
int
sample_fmt
,
int64_t
channel_layout
,
int
planar
,
int64_t
pts
,
int
av_unused
flags
)
{
uint8_t
*
data
[
8
]
=
{
0
};
int
linesize
[
8
];
int
nb_channels
=
av_get_channel_layout_nb_channels
(
channel_layout
),
nb_samples
=
buf_size
/
nb_channels
/
av_get_bytes_per_sample
(
sample_fmt
);
av_samples_fill_arrays
(
data
,
linesize
,
buf
,
nb_channels
,
nb_samples
,
sample_fmt
,
16
);
return
av_asrc_buffer_add_samples
(
ctx
,
data
,
linesize
,
nb_samples
,
sample_rate
,
sample_fmt
,
channel_layout
,
planar
,
pts
,
flags
);
}
AVFilter
avfilter_vsrc_buffer
=
{
.
name
=
"buffer"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Buffer video frames, and make them accessible to the filterchain."
),
.
priv_size
=
sizeof
(
BufferSourceContext
),
.
query_formats
=
query_formats
,
.
query_formats
=
query_formats
_video
,
.
init
=
init
,
.
init
=
init
_video
,
.
uninit
=
uninit
,
.
inputs
=
(
const
AVFilterPad
[])
{{
.
name
=
NULL
}},
...
...
@@ -293,6 +598,28 @@ AVFilter avfilter_vsrc_buffer = {
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
request_frame
=
request_frame
,
.
poll_frame
=
poll_frame
,
.
config_props
=
config_
props
,
},
.
config_props
=
config_
output_video
,
},
{
.
name
=
NULL
}},
};
#ifdef CONFIG_ABUFFER_FILTER
AVFilter
avfilter_asrc_abuffer
=
{
.
name
=
"abuffer"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Buffer audio frames, and make them accessible to the filterchain."
),
.
priv_size
=
sizeof
(
BufferSourceContext
),
.
query_formats
=
query_formats_audio
,
.
init
=
init_audio
,
.
uninit
=
uninit
,
.
inputs
=
(
const
AVFilterPad
[])
{{
.
name
=
NULL
}},
.
outputs
=
(
const
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
request_frame
=
request_frame
,
.
poll_frame
=
poll_frame
,
.
config_props
=
config_output_audio
,
},
{
.
name
=
NULL
}},
};
#endif
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