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
fe2147e9
Commit
fe2147e9
authored
Aug 02, 2012
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avconv: split configuring filter configuration to a separate file.
parent
f5e66827
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
563 additions
and
530 deletions
+563
-530
Makefile
Makefile
+1
-1
avconv.c
avconv.c
+0
-529
avconv.h
avconv.h
+2
-0
avconv_filter.c
avconv_filter.c
+560
-0
No files found.
Makefile
View file @
fe2147e9
...
...
@@ -60,7 +60,7 @@ PROGS-$(CONFIG_AVSERVER) += avserver
PROGS
:=
$
(
PROGS-yes:%
=
%
$(EXESUF)
)
OBJS
=
cmdutils.o
OBJS-avconv
=
avconv_opt.o
OBJS-avconv
=
avconv_opt.o
avconv_filter.o
TESTTOOLS
=
audiogen videogen rotozoom tiny_psnr
base64
HOSTPROGS
:=
$
(
TESTTOOLS:%
=
tests/%
)
doc/print_options
TOOLS
=
qt-faststart trasher
...
...
avconv.c
View file @
fe2147e9
...
...
@@ -111,535 +111,6 @@ int nb_output_files = 0;
FilterGraph
**
filtergraphs
;
int
nb_filtergraphs
;
/**
* Define a function for building a string containing a list of
* allowed formats,
*/
#define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator) \
static char *choose_ ## var ## s(OutputStream *ost) \
{ \
if (ost->st->codec->var != none) { \
get_name(ost->st->codec->var); \
return av_strdup(name); \
} else if (ost->enc->supported_list) { \
const type *p; \
AVIOContext *s = NULL; \
uint8_t *ret; \
int len; \
\
if (avio_open_dyn_buf(&s) < 0) \
exit_program(1); \
\
for (p = ost->enc->supported_list; *p != none; p++) { \
get_name(*p); \
avio_printf(s, "%s" separator, name); \
} \
len = avio_close_dyn_buf(s, &ret); \
ret[len - 1] = 0; \
return ret; \
} else \
return NULL; \
}
#define GET_PIX_FMT_NAME(pix_fmt)\
const char *name = av_get_pix_fmt_name(pix_fmt);
DEF_CHOOSE_FORMAT
(
enum
PixelFormat
,
pix_fmt
,
pix_fmts
,
PIX_FMT_NONE
,
GET_PIX_FMT_NAME
,
":"
)
#define GET_SAMPLE_FMT_NAME(sample_fmt)\
const char *name = av_get_sample_fmt_name(sample_fmt)
DEF_CHOOSE_FORMAT
(
enum
AVSampleFormat
,
sample_fmt
,
sample_fmts
,
AV_SAMPLE_FMT_NONE
,
GET_SAMPLE_FMT_NAME
,
","
)
#define GET_SAMPLE_RATE_NAME(rate)\
char name[16];\
snprintf(name, sizeof(name), "%d", rate);
DEF_CHOOSE_FORMAT
(
int
,
sample_rate
,
supported_samplerates
,
0
,
GET_SAMPLE_RATE_NAME
,
","
)
#define GET_CH_LAYOUT_NAME(ch_layout)\
char name[16];\
snprintf(name, sizeof(name), "0x%"PRIx64, ch_layout);
DEF_CHOOSE_FORMAT
(
uint64_t
,
channel_layout
,
channel_layouts
,
0
,
GET_CH_LAYOUT_NAME
,
","
)
static
FilterGraph
*
init_simple_filtergraph
(
InputStream
*
ist
,
OutputStream
*
ost
)
{
FilterGraph
*
fg
=
av_mallocz
(
sizeof
(
*
fg
));
if
(
!
fg
)
exit_program
(
1
);
fg
->
index
=
nb_filtergraphs
;
fg
->
outputs
=
grow_array
(
fg
->
outputs
,
sizeof
(
*
fg
->
outputs
),
&
fg
->
nb_outputs
,
fg
->
nb_outputs
+
1
);
if
(
!
(
fg
->
outputs
[
0
]
=
av_mallocz
(
sizeof
(
*
fg
->
outputs
[
0
]))))
exit_program
(
1
);
fg
->
outputs
[
0
]
->
ost
=
ost
;
fg
->
outputs
[
0
]
->
graph
=
fg
;
ost
->
filter
=
fg
->
outputs
[
0
];
fg
->
inputs
=
grow_array
(
fg
->
inputs
,
sizeof
(
*
fg
->
inputs
),
&
fg
->
nb_inputs
,
fg
->
nb_inputs
+
1
);
if
(
!
(
fg
->
inputs
[
0
]
=
av_mallocz
(
sizeof
(
*
fg
->
inputs
[
0
]))))
exit_program
(
1
);
fg
->
inputs
[
0
]
->
ist
=
ist
;
fg
->
inputs
[
0
]
->
graph
=
fg
;
ist
->
filters
=
grow_array
(
ist
->
filters
,
sizeof
(
*
ist
->
filters
),
&
ist
->
nb_filters
,
ist
->
nb_filters
+
1
);
ist
->
filters
[
ist
->
nb_filters
-
1
]
=
fg
->
inputs
[
0
];
filtergraphs
=
grow_array
(
filtergraphs
,
sizeof
(
*
filtergraphs
),
&
nb_filtergraphs
,
nb_filtergraphs
+
1
);
filtergraphs
[
nb_filtergraphs
-
1
]
=
fg
;
return
fg
;
}
static
void
init_input_filter
(
FilterGraph
*
fg
,
AVFilterInOut
*
in
)
{
InputStream
*
ist
=
NULL
;
enum
AVMediaType
type
=
avfilter_pad_get_type
(
in
->
filter_ctx
->
input_pads
,
in
->
pad_idx
);
int
i
;
// TODO: support other filter types
if
(
type
!=
AVMEDIA_TYPE_VIDEO
&&
type
!=
AVMEDIA_TYPE_AUDIO
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Only video and audio filters supported "
"currently.
\n
"
);
exit_program
(
1
);
}
if
(
in
->
name
)
{
AVFormatContext
*
s
;
AVStream
*
st
=
NULL
;
char
*
p
;
int
file_idx
=
strtol
(
in
->
name
,
&
p
,
0
);
if
(
file_idx
<
0
||
file_idx
>=
nb_input_files
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Invalid file index %d in filtegraph description %s.
\n
"
,
file_idx
,
fg
->
graph_desc
);
exit_program
(
1
);
}
s
=
input_files
[
file_idx
]
->
ctx
;
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
if
(
s
->
streams
[
i
]
->
codec
->
codec_type
!=
type
)
continue
;
if
(
check_stream_specifier
(
s
,
s
->
streams
[
i
],
*
p
==
':'
?
p
+
1
:
p
)
==
1
)
{
st
=
s
->
streams
[
i
];
break
;
}
}
if
(
!
st
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Stream specifier '%s' in filtergraph description %s "
"matches no streams.
\n
"
,
p
,
fg
->
graph_desc
);
exit_program
(
1
);
}
ist
=
input_streams
[
input_files
[
file_idx
]
->
ist_index
+
st
->
index
];
}
else
{
/* find the first unused stream of corresponding type */
for
(
i
=
0
;
i
<
nb_input_streams
;
i
++
)
{
ist
=
input_streams
[
i
];
if
(
ist
->
st
->
codec
->
codec_type
==
type
&&
ist
->
discard
)
break
;
}
if
(
i
==
nb_input_streams
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Cannot find a matching stream for "
"unlabeled input pad %d on filter %s"
,
in
->
pad_idx
,
in
->
filter_ctx
->
name
);
exit_program
(
1
);
}
}
av_assert0
(
ist
);
ist
->
discard
=
0
;
ist
->
decoding_needed
=
1
;
ist
->
st
->
discard
=
AVDISCARD_NONE
;
fg
->
inputs
=
grow_array
(
fg
->
inputs
,
sizeof
(
*
fg
->
inputs
),
&
fg
->
nb_inputs
,
fg
->
nb_inputs
+
1
);
if
(
!
(
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
=
av_mallocz
(
sizeof
(
*
fg
->
inputs
[
0
]))))
exit_program
(
1
);
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
->
ist
=
ist
;
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
->
graph
=
fg
;
ist
->
filters
=
grow_array
(
ist
->
filters
,
sizeof
(
*
ist
->
filters
),
&
ist
->
nb_filters
,
ist
->
nb_filters
+
1
);
ist
->
filters
[
ist
->
nb_filters
-
1
]
=
fg
->
inputs
[
fg
->
nb_inputs
-
1
];
}
static
int
configure_output_video_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
char
*
pix_fmts
;
OutputStream
*
ost
=
ofilter
->
ost
;
AVCodecContext
*
codec
=
ost
->
st
->
codec
;
AVFilterContext
*
last_filter
=
out
->
filter_ctx
;
int
pad_idx
=
out
->
pad_idx
;
int
ret
;
char
name
[
255
];
snprintf
(
name
,
sizeof
(
name
),
"output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
ofilter
->
filter
,
avfilter_get_by_name
(
"buffersink"
),
name
,
NULL
,
pix_fmts
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
if
(
codec
->
width
||
codec
->
height
)
{
char
args
[
255
];
AVFilterContext
*
filter
;
snprintf
(
args
,
sizeof
(
args
),
"%d:%d:flags=0x%X"
,
codec
->
width
,
codec
->
height
,
(
unsigned
)
ost
->
sws_flags
);
snprintf
(
name
,
sizeof
(
name
),
"scaler for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
filter
,
avfilter_get_by_name
(
"scale"
),
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
filter
,
0
))
<
0
)
return
ret
;
last_filter
=
filter
;
pad_idx
=
0
;
}
if
((
pix_fmts
=
choose_pix_fmts
(
ost
)))
{
AVFilterContext
*
filter
;
snprintf
(
name
,
sizeof
(
name
),
"pixel format for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
filter
,
avfilter_get_by_name
(
"format"
),
"format"
,
pix_fmts
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
filter
,
0
))
<
0
)
return
ret
;
last_filter
=
filter
;
pad_idx
=
0
;
av_freep
(
&
pix_fmts
);
}
if
(
ost
->
frame_rate
.
num
)
{
AVFilterContext
*
fps
;
char
args
[
255
];
snprintf
(
args
,
sizeof
(
args
),
"fps=%d/%d"
,
ost
->
frame_rate
.
num
,
ost
->
frame_rate
.
den
);
snprintf
(
name
,
sizeof
(
name
),
"fps for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
fps
,
avfilter_get_by_name
(
"fps"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
fps
,
0
);
if
(
ret
<
0
)
return
ret
;
last_filter
=
fps
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
ofilter
->
filter
,
0
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_output_audio_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
OutputStream
*
ost
=
ofilter
->
ost
;
AVCodecContext
*
codec
=
ost
->
st
->
codec
;
AVFilterContext
*
last_filter
=
out
->
filter_ctx
;
int
pad_idx
=
out
->
pad_idx
;
char
*
sample_fmts
,
*
sample_rates
,
*
channel_layouts
;
char
name
[
255
];
int
ret
;
snprintf
(
name
,
sizeof
(
name
),
"output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
ofilter
->
filter
,
avfilter_get_by_name
(
"abuffersink"
),
name
,
NULL
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
if
(
codec
->
channels
&&
!
codec
->
channel_layout
)
codec
->
channel_layout
=
av_get_default_channel_layout
(
codec
->
channels
);
sample_fmts
=
choose_sample_fmts
(
ost
);
sample_rates
=
choose_sample_rates
(
ost
);
channel_layouts
=
choose_channel_layouts
(
ost
);
if
(
sample_fmts
||
sample_rates
||
channel_layouts
)
{
AVFilterContext
*
format
;
char
args
[
256
];
int
len
=
0
;
if
(
sample_fmts
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"sample_fmts=%s:"
,
sample_fmts
);
if
(
sample_rates
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"sample_rates=%s:"
,
sample_rates
);
if
(
channel_layouts
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"channel_layouts=%s:"
,
channel_layouts
);
args
[
len
-
1
]
=
0
;
av_freep
(
&
sample_fmts
);
av_freep
(
&
sample_rates
);
av_freep
(
&
channel_layouts
);
snprintf
(
name
,
sizeof
(
name
),
"audio format for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
format
,
avfilter_get_by_name
(
"aformat"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
format
,
0
);
if
(
ret
<
0
)
return
ret
;
last_filter
=
format
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
ofilter
->
filter
,
0
))
<
0
)
return
ret
;
return
0
;
}
#define DESCRIBE_FILTER_LINK(f, inout, in) \
{ \
AVFilterContext *ctx = inout->filter_ctx; \
AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
int nb_pads = in ? ctx->input_count : ctx->output_count; \
AVIOContext *pb; \
\
if (avio_open_dyn_buf(&pb) < 0) \
exit_program(1); \
\
avio_printf(pb, "%s", ctx->filter->name); \
if (nb_pads > 1) \
avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
avio_w8(pb, 0); \
avio_close_dyn_buf(pb, &f->name); \
}
int
configure_output_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
av_freep
(
&
ofilter
->
name
);
DESCRIBE_FILTER_LINK
(
ofilter
,
out
,
0
);
switch
(
avfilter_pad_get_type
(
out
->
filter_ctx
->
output_pads
,
out
->
pad_idx
))
{
case
AVMEDIA_TYPE_VIDEO
:
return
configure_output_video_filter
(
fg
,
ofilter
,
out
);
case
AVMEDIA_TYPE_AUDIO
:
return
configure_output_audio_filter
(
fg
,
ofilter
,
out
);
default
:
av_assert0
(
0
);
}
}
static
int
configure_input_video_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
AVFilterContext
*
first_filter
=
in
->
filter_ctx
;
AVFilter
*
filter
=
avfilter_get_by_name
(
"buffer"
);
InputStream
*
ist
=
ifilter
->
ist
;
AVRational
tb
=
ist
->
framerate
.
num
?
av_inv_q
(
ist
->
framerate
)
:
ist
->
st
->
time_base
;
AVRational
sar
;
char
args
[
255
],
name
[
255
];
int
pad_idx
=
in
->
pad_idx
;
int
ret
;
sar
=
ist
->
st
->
sample_aspect_ratio
.
num
?
ist
->
st
->
sample_aspect_ratio
:
ist
->
st
->
codec
->
sample_aspect_ratio
;
snprintf
(
args
,
sizeof
(
args
),
"%d:%d:%d:%d:%d:%d:%d"
,
ist
->
st
->
codec
->
width
,
ist
->
st
->
codec
->
height
,
ist
->
st
->
codec
->
pix_fmt
,
tb
.
num
,
tb
.
den
,
sar
.
num
,
sar
.
den
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d input from stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
ifilter
->
filter
,
filter
,
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
(
ist
->
framerate
.
num
)
{
AVFilterContext
*
setpts
;
snprintf
(
name
,
sizeof
(
name
),
"force CFR for input from stream %d:%d"
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
setpts
,
avfilter_get_by_name
(
"setpts"
),
name
,
"N"
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
setpts
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
first_filter
=
setpts
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
ifilter
->
filter
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_input_audio_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
AVFilterContext
*
first_filter
=
in
->
filter_ctx
;
AVFilter
*
filter
=
avfilter_get_by_name
(
"abuffer"
);
InputStream
*
ist
=
ifilter
->
ist
;
int
pad_idx
=
in
->
pad_idx
;
char
args
[
255
],
name
[
255
];
int
ret
;
snprintf
(
args
,
sizeof
(
args
),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
":channel_layout=0x%"
PRIx64
,
1
,
ist
->
st
->
codec
->
sample_rate
,
ist
->
st
->
codec
->
sample_rate
,
av_get_sample_fmt_name
(
ist
->
st
->
codec
->
sample_fmt
),
ist
->
st
->
codec
->
channel_layout
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d input from stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
ifilter
->
filter
,
filter
,
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
(
audio_sync_method
>
0
)
{
AVFilterContext
*
async
;
char
args
[
256
];
int
len
=
0
;
av_log
(
NULL
,
AV_LOG_WARNING
,
"-async has been deprecated. Used the "
"asyncts audio filter instead.
\n
"
);
if
(
audio_sync_method
>
1
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"compensate=1:"
"max_comp=%d:"
,
audio_sync_method
);
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"min_delta=%f"
,
audio_drift_threshold
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d audio sync for input stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
ret
=
avfilter_graph_create_filter
(
&
async
,
avfilter_get_by_name
(
"asyncts"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
async
,
0
,
first_filter
,
pad_idx
);
if
(
ret
<
0
)
return
ret
;
first_filter
=
async
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
ifilter
->
filter
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_input_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
av_freep
(
&
ifilter
->
name
);
DESCRIBE_FILTER_LINK
(
ifilter
,
in
,
1
);
switch
(
avfilter_pad_get_type
(
in
->
filter_ctx
->
input_pads
,
in
->
pad_idx
))
{
case
AVMEDIA_TYPE_VIDEO
:
return
configure_input_video_filter
(
fg
,
ifilter
,
in
);
case
AVMEDIA_TYPE_AUDIO
:
return
configure_input_audio_filter
(
fg
,
ifilter
,
in
);
default
:
av_assert0
(
0
);
}
}
int
configure_filtergraph
(
FilterGraph
*
fg
)
{
AVFilterInOut
*
inputs
,
*
outputs
,
*
cur
;
int
ret
,
i
,
init
=
!
fg
->
graph
,
simple
=
!
fg
->
graph_desc
;
const
char
*
graph_desc
=
simple
?
fg
->
outputs
[
0
]
->
ost
->
avfilter
:
fg
->
graph_desc
;
avfilter_graph_free
(
&
fg
->
graph
);
if
(
!
(
fg
->
graph
=
avfilter_graph_alloc
()))
return
AVERROR
(
ENOMEM
);
if
(
simple
)
{
OutputStream
*
ost
=
fg
->
outputs
[
0
]
->
ost
;
char
args
[
255
];
snprintf
(
args
,
sizeof
(
args
),
"flags=0x%X"
,
(
unsigned
)
ost
->
sws_flags
);
fg
->
graph
->
scale_sws_opts
=
av_strdup
(
args
);
}
if
((
ret
=
avfilter_graph_parse2
(
fg
->
graph
,
graph_desc
,
&
inputs
,
&
outputs
))
<
0
)
return
ret
;
if
(
simple
&&
(
!
inputs
||
inputs
->
next
||
!
outputs
||
outputs
->
next
))
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Simple filtergraph '%s' does not have "
"exactly one input and output.
\n
"
,
graph_desc
);
return
AVERROR
(
EINVAL
);
}
for
(
cur
=
inputs
;
!
simple
&&
init
&&
cur
;
cur
=
cur
->
next
)
init_input_filter
(
fg
,
cur
);
for
(
cur
=
inputs
,
i
=
0
;
cur
;
cur
=
cur
->
next
,
i
++
)
if
((
ret
=
configure_input_filter
(
fg
,
fg
->
inputs
[
i
],
cur
))
<
0
)
return
ret
;
avfilter_inout_free
(
&
inputs
);
if
(
!
init
||
simple
)
{
/* we already know the mappings between lavfi outputs and output streams,
* so we can finish the setup */
for
(
cur
=
outputs
,
i
=
0
;
cur
;
cur
=
cur
->
next
,
i
++
)
configure_output_filter
(
fg
,
fg
->
outputs
[
i
],
cur
);
avfilter_inout_free
(
&
outputs
);
if
((
ret
=
avfilter_graph_config
(
fg
->
graph
,
NULL
))
<
0
)
return
ret
;
}
else
{
/* wait until output mappings are processed */
for
(
cur
=
outputs
;
cur
;)
{
fg
->
outputs
=
grow_array
(
fg
->
outputs
,
sizeof
(
*
fg
->
outputs
),
&
fg
->
nb_outputs
,
fg
->
nb_outputs
+
1
);
if
(
!
(
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
=
av_mallocz
(
sizeof
(
*
fg
->
outputs
[
0
]))))
exit_program
(
1
);
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
graph
=
fg
;
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
out_tmp
=
cur
;
cur
=
cur
->
next
;
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
out_tmp
->
next
=
NULL
;
}
}
return
0
;
}
static
int
ist_in_filtergraph
(
FilterGraph
*
fg
,
InputStream
*
ist
)
{
int
i
;
for
(
i
=
0
;
i
<
fg
->
nb_inputs
;
i
++
)
if
(
fg
->
inputs
[
i
]
->
ist
==
ist
)
return
1
;
return
0
;
}
static
void
term_exit
(
void
)
{
av_log
(
NULL
,
AV_LOG_QUIET
,
""
);
...
...
avconv.h
View file @
fe2147e9
...
...
@@ -356,5 +356,7 @@ int guess_input_channel_layout(InputStream *ist);
int
configure_filtergraph
(
FilterGraph
*
fg
);
int
configure_output_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
);
int
ist_in_filtergraph
(
FilterGraph
*
fg
,
InputStream
*
ist
);
FilterGraph
*
init_simple_filtergraph
(
InputStream
*
ist
,
OutputStream
*
ost
);
#endif
/* AVCONV_H */
avconv_filter.c
0 → 100644
View file @
fe2147e9
/*
* avconv filter configuration
*
* 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 "avconv.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/avfiltergraph.h"
#include "libavutil/audioconvert.h"
#include "libavutil/avassert.h"
#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
#include "libavutil/samplefmt.h"
/**
* Define a function for building a string containing a list of
* allowed formats,
*/
#define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
static char *choose_ ## var ## s(OutputStream *ost) \
{ \
if (ost->st->codec->var != none) { \
get_name(ost->st->codec->var); \
return av_strdup(name); \
} else if (ost->enc->supported_list) { \
const type *p; \
AVIOContext *s = NULL; \
uint8_t *ret; \
int len; \
\
if (avio_open_dyn_buf(&s) < 0) \
exit_program(1); \
\
for (p = ost->enc->supported_list; *p != none; p++) { \
get_name(*p); \
avio_printf(s, "%s" separator, name); \
} \
len = avio_close_dyn_buf(s, &ret); \
ret[len - 1] = 0; \
return ret; \
} else \
return NULL; \
}
#define GET_PIX_FMT_NAME(pix_fmt)\
const char *name = av_get_pix_fmt_name(pix_fmt);
DEF_CHOOSE_FORMAT
(
enum
PixelFormat
,
pix_fmt
,
pix_fmts
,
PIX_FMT_NONE
,
GET_PIX_FMT_NAME
,
":"
)
#define GET_SAMPLE_FMT_NAME(sample_fmt)\
const char *name = av_get_sample_fmt_name(sample_fmt)
DEF_CHOOSE_FORMAT
(
enum
AVSampleFormat
,
sample_fmt
,
sample_fmts
,
AV_SAMPLE_FMT_NONE
,
GET_SAMPLE_FMT_NAME
,
","
)
#define GET_SAMPLE_RATE_NAME(rate)\
char name[16];\
snprintf(name, sizeof(name), "%d", rate);
DEF_CHOOSE_FORMAT
(
int
,
sample_rate
,
supported_samplerates
,
0
,
GET_SAMPLE_RATE_NAME
,
","
)
#define GET_CH_LAYOUT_NAME(ch_layout)\
char name[16];\
snprintf(name, sizeof(name), "0x%"PRIx64, ch_layout);
DEF_CHOOSE_FORMAT
(
uint64_t
,
channel_layout
,
channel_layouts
,
0
,
GET_CH_LAYOUT_NAME
,
","
)
FilterGraph
*
init_simple_filtergraph
(
InputStream
*
ist
,
OutputStream
*
ost
)
{
FilterGraph
*
fg
=
av_mallocz
(
sizeof
(
*
fg
));
if
(
!
fg
)
exit_program
(
1
);
fg
->
index
=
nb_filtergraphs
;
fg
->
outputs
=
grow_array
(
fg
->
outputs
,
sizeof
(
*
fg
->
outputs
),
&
fg
->
nb_outputs
,
fg
->
nb_outputs
+
1
);
if
(
!
(
fg
->
outputs
[
0
]
=
av_mallocz
(
sizeof
(
*
fg
->
outputs
[
0
]))))
exit_program
(
1
);
fg
->
outputs
[
0
]
->
ost
=
ost
;
fg
->
outputs
[
0
]
->
graph
=
fg
;
ost
->
filter
=
fg
->
outputs
[
0
];
fg
->
inputs
=
grow_array
(
fg
->
inputs
,
sizeof
(
*
fg
->
inputs
),
&
fg
->
nb_inputs
,
fg
->
nb_inputs
+
1
);
if
(
!
(
fg
->
inputs
[
0
]
=
av_mallocz
(
sizeof
(
*
fg
->
inputs
[
0
]))))
exit_program
(
1
);
fg
->
inputs
[
0
]
->
ist
=
ist
;
fg
->
inputs
[
0
]
->
graph
=
fg
;
ist
->
filters
=
grow_array
(
ist
->
filters
,
sizeof
(
*
ist
->
filters
),
&
ist
->
nb_filters
,
ist
->
nb_filters
+
1
);
ist
->
filters
[
ist
->
nb_filters
-
1
]
=
fg
->
inputs
[
0
];
filtergraphs
=
grow_array
(
filtergraphs
,
sizeof
(
*
filtergraphs
),
&
nb_filtergraphs
,
nb_filtergraphs
+
1
);
filtergraphs
[
nb_filtergraphs
-
1
]
=
fg
;
return
fg
;
}
static
void
init_input_filter
(
FilterGraph
*
fg
,
AVFilterInOut
*
in
)
{
InputStream
*
ist
=
NULL
;
enum
AVMediaType
type
=
avfilter_pad_get_type
(
in
->
filter_ctx
->
input_pads
,
in
->
pad_idx
);
int
i
;
// TODO: support other filter types
if
(
type
!=
AVMEDIA_TYPE_VIDEO
&&
type
!=
AVMEDIA_TYPE_AUDIO
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Only video and audio filters supported "
"currently.
\n
"
);
exit_program
(
1
);
}
if
(
in
->
name
)
{
AVFormatContext
*
s
;
AVStream
*
st
=
NULL
;
char
*
p
;
int
file_idx
=
strtol
(
in
->
name
,
&
p
,
0
);
if
(
file_idx
<
0
||
file_idx
>=
nb_input_files
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Invalid file index %d in filtegraph description %s.
\n
"
,
file_idx
,
fg
->
graph_desc
);
exit_program
(
1
);
}
s
=
input_files
[
file_idx
]
->
ctx
;
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
{
if
(
s
->
streams
[
i
]
->
codec
->
codec_type
!=
type
)
continue
;
if
(
check_stream_specifier
(
s
,
s
->
streams
[
i
],
*
p
==
':'
?
p
+
1
:
p
)
==
1
)
{
st
=
s
->
streams
[
i
];
break
;
}
}
if
(
!
st
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Stream specifier '%s' in filtergraph description %s "
"matches no streams.
\n
"
,
p
,
fg
->
graph_desc
);
exit_program
(
1
);
}
ist
=
input_streams
[
input_files
[
file_idx
]
->
ist_index
+
st
->
index
];
}
else
{
/* find the first unused stream of corresponding type */
for
(
i
=
0
;
i
<
nb_input_streams
;
i
++
)
{
ist
=
input_streams
[
i
];
if
(
ist
->
st
->
codec
->
codec_type
==
type
&&
ist
->
discard
)
break
;
}
if
(
i
==
nb_input_streams
)
{
av_log
(
NULL
,
AV_LOG_FATAL
,
"Cannot find a matching stream for "
"unlabeled input pad %d on filter %s"
,
in
->
pad_idx
,
in
->
filter_ctx
->
name
);
exit_program
(
1
);
}
}
av_assert0
(
ist
);
ist
->
discard
=
0
;
ist
->
decoding_needed
=
1
;
ist
->
st
->
discard
=
AVDISCARD_NONE
;
fg
->
inputs
=
grow_array
(
fg
->
inputs
,
sizeof
(
*
fg
->
inputs
),
&
fg
->
nb_inputs
,
fg
->
nb_inputs
+
1
);
if
(
!
(
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
=
av_mallocz
(
sizeof
(
*
fg
->
inputs
[
0
]))))
exit_program
(
1
);
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
->
ist
=
ist
;
fg
->
inputs
[
fg
->
nb_inputs
-
1
]
->
graph
=
fg
;
ist
->
filters
=
grow_array
(
ist
->
filters
,
sizeof
(
*
ist
->
filters
),
&
ist
->
nb_filters
,
ist
->
nb_filters
+
1
);
ist
->
filters
[
ist
->
nb_filters
-
1
]
=
fg
->
inputs
[
fg
->
nb_inputs
-
1
];
}
static
int
configure_output_video_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
char
*
pix_fmts
;
OutputStream
*
ost
=
ofilter
->
ost
;
AVCodecContext
*
codec
=
ost
->
st
->
codec
;
AVFilterContext
*
last_filter
=
out
->
filter_ctx
;
int
pad_idx
=
out
->
pad_idx
;
int
ret
;
char
name
[
255
];
snprintf
(
name
,
sizeof
(
name
),
"output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
ofilter
->
filter
,
avfilter_get_by_name
(
"buffersink"
),
name
,
NULL
,
pix_fmts
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
if
(
codec
->
width
||
codec
->
height
)
{
char
args
[
255
];
AVFilterContext
*
filter
;
snprintf
(
args
,
sizeof
(
args
),
"%d:%d:flags=0x%X"
,
codec
->
width
,
codec
->
height
,
(
unsigned
)
ost
->
sws_flags
);
snprintf
(
name
,
sizeof
(
name
),
"scaler for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
filter
,
avfilter_get_by_name
(
"scale"
),
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
filter
,
0
))
<
0
)
return
ret
;
last_filter
=
filter
;
pad_idx
=
0
;
}
if
((
pix_fmts
=
choose_pix_fmts
(
ost
)))
{
AVFilterContext
*
filter
;
snprintf
(
name
,
sizeof
(
name
),
"pixel format for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
filter
,
avfilter_get_by_name
(
"format"
),
"format"
,
pix_fmts
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
filter
,
0
))
<
0
)
return
ret
;
last_filter
=
filter
;
pad_idx
=
0
;
av_freep
(
&
pix_fmts
);
}
if
(
ost
->
frame_rate
.
num
)
{
AVFilterContext
*
fps
;
char
args
[
255
];
snprintf
(
args
,
sizeof
(
args
),
"fps=%d/%d"
,
ost
->
frame_rate
.
num
,
ost
->
frame_rate
.
den
);
snprintf
(
name
,
sizeof
(
name
),
"fps for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
fps
,
avfilter_get_by_name
(
"fps"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
fps
,
0
);
if
(
ret
<
0
)
return
ret
;
last_filter
=
fps
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
ofilter
->
filter
,
0
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_output_audio_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
OutputStream
*
ost
=
ofilter
->
ost
;
AVCodecContext
*
codec
=
ost
->
st
->
codec
;
AVFilterContext
*
last_filter
=
out
->
filter_ctx
;
int
pad_idx
=
out
->
pad_idx
;
char
*
sample_fmts
,
*
sample_rates
,
*
channel_layouts
;
char
name
[
255
];
int
ret
;
snprintf
(
name
,
sizeof
(
name
),
"output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
ofilter
->
filter
,
avfilter_get_by_name
(
"abuffersink"
),
name
,
NULL
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
if
(
codec
->
channels
&&
!
codec
->
channel_layout
)
codec
->
channel_layout
=
av_get_default_channel_layout
(
codec
->
channels
);
sample_fmts
=
choose_sample_fmts
(
ost
);
sample_rates
=
choose_sample_rates
(
ost
);
channel_layouts
=
choose_channel_layouts
(
ost
);
if
(
sample_fmts
||
sample_rates
||
channel_layouts
)
{
AVFilterContext
*
format
;
char
args
[
256
];
int
len
=
0
;
if
(
sample_fmts
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"sample_fmts=%s:"
,
sample_fmts
);
if
(
sample_rates
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"sample_rates=%s:"
,
sample_rates
);
if
(
channel_layouts
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"channel_layouts=%s:"
,
channel_layouts
);
args
[
len
-
1
]
=
0
;
av_freep
(
&
sample_fmts
);
av_freep
(
&
sample_rates
);
av_freep
(
&
channel_layouts
);
snprintf
(
name
,
sizeof
(
name
),
"audio format for output stream %d:%d"
,
ost
->
file_index
,
ost
->
index
);
ret
=
avfilter_graph_create_filter
(
&
format
,
avfilter_get_by_name
(
"aformat"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
format
,
0
);
if
(
ret
<
0
)
return
ret
;
last_filter
=
format
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
last_filter
,
pad_idx
,
ofilter
->
filter
,
0
))
<
0
)
return
ret
;
return
0
;
}
#define DESCRIBE_FILTER_LINK(f, inout, in) \
{ \
AVFilterContext *ctx = inout->filter_ctx; \
AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
int nb_pads = in ? ctx->input_count : ctx->output_count; \
AVIOContext *pb; \
\
if (avio_open_dyn_buf(&pb) < 0) \
exit_program(1); \
\
avio_printf(pb, "%s", ctx->filter->name); \
if (nb_pads > 1) \
avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
avio_w8(pb, 0); \
avio_close_dyn_buf(pb, &f->name); \
}
int
configure_output_filter
(
FilterGraph
*
fg
,
OutputFilter
*
ofilter
,
AVFilterInOut
*
out
)
{
av_freep
(
&
ofilter
->
name
);
DESCRIBE_FILTER_LINK
(
ofilter
,
out
,
0
);
switch
(
avfilter_pad_get_type
(
out
->
filter_ctx
->
output_pads
,
out
->
pad_idx
))
{
case
AVMEDIA_TYPE_VIDEO
:
return
configure_output_video_filter
(
fg
,
ofilter
,
out
);
case
AVMEDIA_TYPE_AUDIO
:
return
configure_output_audio_filter
(
fg
,
ofilter
,
out
);
default
:
av_assert0
(
0
);
}
}
static
int
configure_input_video_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
AVFilterContext
*
first_filter
=
in
->
filter_ctx
;
AVFilter
*
filter
=
avfilter_get_by_name
(
"buffer"
);
InputStream
*
ist
=
ifilter
->
ist
;
AVRational
tb
=
ist
->
framerate
.
num
?
av_inv_q
(
ist
->
framerate
)
:
ist
->
st
->
time_base
;
AVRational
sar
;
char
args
[
255
],
name
[
255
];
int
pad_idx
=
in
->
pad_idx
;
int
ret
;
sar
=
ist
->
st
->
sample_aspect_ratio
.
num
?
ist
->
st
->
sample_aspect_ratio
:
ist
->
st
->
codec
->
sample_aspect_ratio
;
snprintf
(
args
,
sizeof
(
args
),
"%d:%d:%d:%d:%d:%d:%d"
,
ist
->
st
->
codec
->
width
,
ist
->
st
->
codec
->
height
,
ist
->
st
->
codec
->
pix_fmt
,
tb
.
num
,
tb
.
den
,
sar
.
num
,
sar
.
den
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d input from stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
ifilter
->
filter
,
filter
,
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
(
ist
->
framerate
.
num
)
{
AVFilterContext
*
setpts
;
snprintf
(
name
,
sizeof
(
name
),
"force CFR for input from stream %d:%d"
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
setpts
,
avfilter_get_by_name
(
"setpts"
),
name
,
"N"
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
((
ret
=
avfilter_link
(
setpts
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
first_filter
=
setpts
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
ifilter
->
filter
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_input_audio_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
AVFilterContext
*
first_filter
=
in
->
filter_ctx
;
AVFilter
*
filter
=
avfilter_get_by_name
(
"abuffer"
);
InputStream
*
ist
=
ifilter
->
ist
;
int
pad_idx
=
in
->
pad_idx
;
char
args
[
255
],
name
[
255
];
int
ret
;
snprintf
(
args
,
sizeof
(
args
),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
":channel_layout=0x%"
PRIx64
,
1
,
ist
->
st
->
codec
->
sample_rate
,
ist
->
st
->
codec
->
sample_rate
,
av_get_sample_fmt_name
(
ist
->
st
->
codec
->
sample_fmt
),
ist
->
st
->
codec
->
channel_layout
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d input from stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
if
((
ret
=
avfilter_graph_create_filter
(
&
ifilter
->
filter
,
filter
,
name
,
args
,
NULL
,
fg
->
graph
))
<
0
)
return
ret
;
if
(
audio_sync_method
>
0
)
{
AVFilterContext
*
async
;
char
args
[
256
];
int
len
=
0
;
av_log
(
NULL
,
AV_LOG_WARNING
,
"-async has been deprecated. Used the "
"asyncts audio filter instead.
\n
"
);
if
(
audio_sync_method
>
1
)
len
+=
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"compensate=1:"
"max_comp=%d:"
,
audio_sync_method
);
snprintf
(
args
+
len
,
sizeof
(
args
)
-
len
,
"min_delta=%f"
,
audio_drift_threshold
);
snprintf
(
name
,
sizeof
(
name
),
"graph %d audio sync for input stream %d:%d"
,
fg
->
index
,
ist
->
file_index
,
ist
->
st
->
index
);
ret
=
avfilter_graph_create_filter
(
&
async
,
avfilter_get_by_name
(
"asyncts"
),
name
,
args
,
NULL
,
fg
->
graph
);
if
(
ret
<
0
)
return
ret
;
ret
=
avfilter_link
(
async
,
0
,
first_filter
,
pad_idx
);
if
(
ret
<
0
)
return
ret
;
first_filter
=
async
;
pad_idx
=
0
;
}
if
((
ret
=
avfilter_link
(
ifilter
->
filter
,
0
,
first_filter
,
pad_idx
))
<
0
)
return
ret
;
return
0
;
}
static
int
configure_input_filter
(
FilterGraph
*
fg
,
InputFilter
*
ifilter
,
AVFilterInOut
*
in
)
{
av_freep
(
&
ifilter
->
name
);
DESCRIBE_FILTER_LINK
(
ifilter
,
in
,
1
);
switch
(
avfilter_pad_get_type
(
in
->
filter_ctx
->
input_pads
,
in
->
pad_idx
))
{
case
AVMEDIA_TYPE_VIDEO
:
return
configure_input_video_filter
(
fg
,
ifilter
,
in
);
case
AVMEDIA_TYPE_AUDIO
:
return
configure_input_audio_filter
(
fg
,
ifilter
,
in
);
default
:
av_assert0
(
0
);
}
}
int
configure_filtergraph
(
FilterGraph
*
fg
)
{
AVFilterInOut
*
inputs
,
*
outputs
,
*
cur
;
int
ret
,
i
,
init
=
!
fg
->
graph
,
simple
=
!
fg
->
graph_desc
;
const
char
*
graph_desc
=
simple
?
fg
->
outputs
[
0
]
->
ost
->
avfilter
:
fg
->
graph_desc
;
avfilter_graph_free
(
&
fg
->
graph
);
if
(
!
(
fg
->
graph
=
avfilter_graph_alloc
()))
return
AVERROR
(
ENOMEM
);
if
(
simple
)
{
OutputStream
*
ost
=
fg
->
outputs
[
0
]
->
ost
;
char
args
[
255
];
snprintf
(
args
,
sizeof
(
args
),
"flags=0x%X"
,
(
unsigned
)
ost
->
sws_flags
);
fg
->
graph
->
scale_sws_opts
=
av_strdup
(
args
);
}
if
((
ret
=
avfilter_graph_parse2
(
fg
->
graph
,
graph_desc
,
&
inputs
,
&
outputs
))
<
0
)
return
ret
;
if
(
simple
&&
(
!
inputs
||
inputs
->
next
||
!
outputs
||
outputs
->
next
))
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Simple filtergraph '%s' does not have "
"exactly one input and output.
\n
"
,
graph_desc
);
return
AVERROR
(
EINVAL
);
}
for
(
cur
=
inputs
;
!
simple
&&
init
&&
cur
;
cur
=
cur
->
next
)
init_input_filter
(
fg
,
cur
);
for
(
cur
=
inputs
,
i
=
0
;
cur
;
cur
=
cur
->
next
,
i
++
)
if
((
ret
=
configure_input_filter
(
fg
,
fg
->
inputs
[
i
],
cur
))
<
0
)
return
ret
;
avfilter_inout_free
(
&
inputs
);
if
(
!
init
||
simple
)
{
/* we already know the mappings between lavfi outputs and output streams,
* so we can finish the setup */
for
(
cur
=
outputs
,
i
=
0
;
cur
;
cur
=
cur
->
next
,
i
++
)
configure_output_filter
(
fg
,
fg
->
outputs
[
i
],
cur
);
avfilter_inout_free
(
&
outputs
);
if
((
ret
=
avfilter_graph_config
(
fg
->
graph
,
NULL
))
<
0
)
return
ret
;
}
else
{
/* wait until output mappings are processed */
for
(
cur
=
outputs
;
cur
;)
{
fg
->
outputs
=
grow_array
(
fg
->
outputs
,
sizeof
(
*
fg
->
outputs
),
&
fg
->
nb_outputs
,
fg
->
nb_outputs
+
1
);
if
(
!
(
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
=
av_mallocz
(
sizeof
(
*
fg
->
outputs
[
0
]))))
exit_program
(
1
);
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
graph
=
fg
;
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
out_tmp
=
cur
;
cur
=
cur
->
next
;
fg
->
outputs
[
fg
->
nb_outputs
-
1
]
->
out_tmp
->
next
=
NULL
;
}
}
return
0
;
}
int
ist_in_filtergraph
(
FilterGraph
*
fg
,
InputStream
*
ist
)
{
int
i
;
for
(
i
=
0
;
i
<
fg
->
nb_inputs
;
i
++
)
if
(
fg
->
inputs
[
i
]
->
ist
==
ist
)
return
1
;
return
0
;
}
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