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
dcc1b323
Commit
dcc1b323
authored
Apr 08, 2013
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi/select: add support for dynamic number of outputs
parent
565c50ac
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
61 additions
and
30 deletions
+61
-30
filters.texi
doc/filters.texi
+19
-3
f_select.c
libavfilter/f_select.c
+41
-26
version.h
libavfilter/version.h
+1
-1
No files found.
doc/filters.texi
View file @
dcc1b323
...
@@ -6721,10 +6721,20 @@ This filter accepts the following options:
...
@@ -6721,10 +6721,20 @@ This filter accepts the following options:
@table @option
@table @option
@item expr, e
@item expr, e
An expression, which is evaluated for each input frame. If the expression is
Set expression, which is evaluated for each input frame.
evaluated to a non-zero value, the frame is selected and passed to the output,
otherwise it is discarded.
If the expression is evaluated to zero, the frame is discarded.
If the evaluation result is negative or NaN, the frame is sent to the
first output; otherwise it is sent to the output with index
@code{ceil(val)-1}, assuming that the input index starts from 0.
For example a value of @code{1.2} corresponds to the output with index
@code{ceil(1.2)-1 = 2-1 = 1}, that is the second output.
@item outputs, n
Set the number of outputs. The output to which to send the selected
frame is based on the result of the evaluation. Default value is 1.
@end table
@end table
The expression can contain the following constants:
The expression can contain the following constants:
...
@@ -6878,6 +6888,12 @@ ffmpeg -i video.avi -vf select='gt(scene\,0.4)',scale=160:120,tile -frames:v 1 p
...
@@ -6878,6 +6888,12 @@ ffmpeg -i video.avi -vf select='gt(scene\,0.4)',scale=160:120,tile -frames:v 1 p
Comparing @var{scene} against a value between 0.3 and 0.5 is generally a sane
Comparing @var{scene} against a value between 0.3 and 0.5 is generally a sane
choice.
choice.
@item
Send even and odd frames to separate outputs, and compose them:
@example
select=n=2:e='mod(n, 2)+1' [odd][even]; [odd] pad=h=2*ih [tmp]; [tmp][even] overlay=y=h
@end example
@end itemize
@end itemize
@section asendcmd, sendcmd
@section asendcmd, sendcmd
...
...
libavfilter/f_select.c
View file @
dcc1b323
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
* filter for selecting which frame passes in the filterchain
* filter for selecting which frame passes in the filterchain
*/
*/
#include "libavutil/avstring.h"
#include "libavutil/eval.h"
#include "libavutil/eval.h"
#include "libavutil/fifo.h"
#include "libavutil/fifo.h"
#include "libavutil/internal.h"
#include "libavutil/internal.h"
...
@@ -136,13 +137,16 @@ typedef struct {
...
@@ -136,13 +137,16 @@ typedef struct {
#endif
#endif
AVFrame
*
prev_picref
;
///< previous frame (scene detect only)
AVFrame
*
prev_picref
;
///< previous frame (scene detect only)
double
select
;
double
select
;
int
select_out
;
///< mark the selected output pad index
int
nb_outputs
;
}
SelectContext
;
}
SelectContext
;
static
int
request_frame
(
AVFilterLink
*
outlink
);
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
{
SelectContext
*
select
=
ctx
->
priv
;
SelectContext
*
select
=
ctx
->
priv
;
int
ret
;
int
i
,
ret
;
if
((
ret
=
av_expr_parse
(
&
select
->
expr
,
select
->
expr_str
,
if
((
ret
=
av_expr_parse
(
&
select
->
expr
,
select
->
expr_str
,
var_names
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
ctx
))
<
0
)
{
var_names
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
ctx
))
<
0
)
{
...
@@ -152,6 +156,17 @@ static av_cold int init(AVFilterContext *ctx)
...
@@ -152,6 +156,17 @@ static av_cold int init(AVFilterContext *ctx)
}
}
select
->
do_scene_detect
=
!!
strstr
(
select
->
expr_str
,
"scene"
);
select
->
do_scene_detect
=
!!
strstr
(
select
->
expr_str
,
"scene"
);
for
(
i
=
0
;
i
<
select
->
nb_outputs
;
i
++
)
{
AVFilterPad
pad
=
{
0
};
pad
.
name
=
av_asprintf
(
"output%d"
,
i
);
if
(
!
pad
.
name
)
return
AVERROR
(
ENOMEM
);
pad
.
type
=
ctx
->
filter
->
inputs
[
0
].
type
;
pad
.
request_frame
=
request_frame
;
ff_insert_outpad
(
ctx
,
i
,
&
pad
);
}
return
0
;
return
0
;
}
}
...
@@ -308,7 +323,15 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
...
@@ -308,7 +323,15 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
break
;
break
;
}
}
av_log
(
inlink
->
dst
,
AV_LOG_DEBUG
,
" -> select:%f
\n
"
,
res
);
if
(
res
==
0
)
{
select
->
select_out
=
-
1
;
/* drop */
}
else
if
(
isnan
(
res
)
||
res
<
0
)
{
select
->
select_out
=
0
;
/* first output */
}
else
{
select
->
select_out
=
FFMIN
(
ceilf
(
res
)
-
1
,
select
->
nb_outputs
-
1
);
/* other outputs */
}
av_log
(
inlink
->
dst
,
AV_LOG_DEBUG
,
" -> select:%f select_out:%d
\n
"
,
res
,
select
->
select_out
);
if
(
res
)
{
if
(
res
)
{
select
->
var_values
[
VAR_PREV_SELECTED_N
]
=
select
->
var_values
[
VAR_N
];
select
->
var_values
[
VAR_PREV_SELECTED_N
]
=
select
->
var_values
[
VAR_N
];
...
@@ -326,11 +349,12 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
...
@@ -326,11 +349,12 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame)
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
frame
)
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
frame
)
{
{
SelectContext
*
select
=
inlink
->
dst
->
priv
;
AVFilterContext
*
ctx
=
inlink
->
dst
;
SelectContext
*
select
=
ctx
->
priv
;
select_frame
(
inlink
->
dst
,
frame
);
select_frame
(
ctx
,
frame
);
if
(
select
->
select
)
if
(
select
->
select
)
return
ff_filter_frame
(
inlink
->
dst
->
outputs
[
0
],
frame
);
return
ff_filter_frame
(
ctx
->
outputs
[
select
->
select_out
],
frame
);
av_frame_free
(
&
frame
);
av_frame_free
(
&
frame
);
return
0
;
return
0
;
...
@@ -341,13 +365,13 @@ static int request_frame(AVFilterLink *outlink)
...
@@ -341,13 +365,13 @@ static int request_frame(AVFilterLink *outlink)
AVFilterContext
*
ctx
=
outlink
->
src
;
AVFilterContext
*
ctx
=
outlink
->
src
;
SelectContext
*
select
=
ctx
->
priv
;
SelectContext
*
select
=
ctx
->
priv
;
AVFilterLink
*
inlink
=
outlink
->
src
->
inputs
[
0
];
AVFilterLink
*
inlink
=
outlink
->
src
->
inputs
[
0
];
select
->
select
=
0
;
int
out_no
=
FF_OUTLINK_IDX
(
outlink
)
;
do
{
do
{
int
ret
=
ff_request_frame
(
inlink
);
int
ret
=
ff_request_frame
(
inlink
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
}
while
(
!
select
->
select
);
}
while
(
select
->
select_out
!=
out_no
);
return
0
;
return
0
;
}
}
...
@@ -355,10 +379,14 @@ static int request_frame(AVFilterLink *outlink)
...
@@ -355,10 +379,14 @@ static int request_frame(AVFilterLink *outlink)
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
{
SelectContext
*
select
=
ctx
->
priv
;
SelectContext
*
select
=
ctx
->
priv
;
int
i
;
av_expr_free
(
select
->
expr
);
av_expr_free
(
select
->
expr
);
select
->
expr
=
NULL
;
select
->
expr
=
NULL
;
for
(
i
=
0
;
i
<
ctx
->
nb_outputs
;
i
++
)
av_freep
(
&
ctx
->
output_pads
[
i
].
name
);
#if CONFIG_AVCODEC
#if CONFIG_AVCODEC
if
(
select
->
do_scene_detect
)
{
if
(
select
->
do_scene_detect
)
{
av_frame_free
(
&
select
->
prev_picref
);
av_frame_free
(
&
select
->
prev_picref
);
...
@@ -393,6 +421,8 @@ static int query_formats(AVFilterContext *ctx)
...
@@ -393,6 +421,8 @@ static int query_formats(AVFilterContext *ctx)
static
const
AVOption
aselect_options
[]
=
{
static
const
AVOption
aselect_options
[]
=
{
{
"expr"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
AFLAGS
},
{
"expr"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
AFLAGS
},
{
"e"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
AFLAGS
},
{
"e"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
AFLAGS
},
{
"outputs"
,
"set the number of outputs"
,
OFFSET
(
nb_outputs
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
1
,
INT_MAX
,
AFLAGS
},
{
"n"
,
"set the number of outputs"
,
OFFSET
(
nb_outputs
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
1
,
INT_MAX
,
AFLAGS
},
{
NULL
},
{
NULL
},
};
};
AVFILTER_DEFINE_CLASS
(
aselect
);
AVFILTER_DEFINE_CLASS
(
aselect
);
...
@@ -424,14 +454,6 @@ static const AVFilterPad avfilter_af_aselect_inputs[] = {
...
@@ -424,14 +454,6 @@ static const AVFilterPad avfilter_af_aselect_inputs[] = {
{
NULL
}
{
NULL
}
};
};
static
const
AVFilterPad
avfilter_af_aselect_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
},
{
NULL
}
};
AVFilter
avfilter_af_aselect
=
{
AVFilter
avfilter_af_aselect
=
{
.
name
=
"aselect"
,
.
name
=
"aselect"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Select audio frames to pass in output."
),
.
description
=
NULL_IF_CONFIG_SMALL
(
"Select audio frames to pass in output."
),
...
@@ -439,8 +461,8 @@ AVFilter avfilter_af_aselect = {
...
@@ -439,8 +461,8 @@ AVFilter avfilter_af_aselect = {
.
uninit
=
uninit
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
SelectContext
),
.
priv_size
=
sizeof
(
SelectContext
),
.
inputs
=
avfilter_af_aselect_inputs
,
.
inputs
=
avfilter_af_aselect_inputs
,
.
outputs
=
avfilter_af_aselect_outputs
,
.
priv_class
=
&
aselect_class
,
.
priv_class
=
&
aselect_class
,
.
flags
=
AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
};
};
#endif
/* CONFIG_ASELECT_FILTER */
#endif
/* CONFIG_ASELECT_FILTER */
...
@@ -451,6 +473,8 @@ AVFilter avfilter_af_aselect = {
...
@@ -451,6 +473,8 @@ AVFilter avfilter_af_aselect = {
static
const
AVOption
select_options
[]
=
{
static
const
AVOption
select_options
[]
=
{
{
"expr"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
FLAGS
},
{
"expr"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
FLAGS
},
{
"e"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
FLAGS
},
{
"e"
,
"An expression to use for selecting frames"
,
OFFSET
(
expr_str
),
AV_OPT_TYPE_STRING
,
{
.
str
=
"1"
},
.
flags
=
FLAGS
},
{
"outputs"
,
"set the number of outputs"
,
OFFSET
(
nb_outputs
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
1
,
INT_MAX
,
FLAGS
},
{
"n"
,
"set the number of outputs"
,
OFFSET
(
nb_outputs
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
1
,
INT_MAX
,
FLAGS
},
{
NULL
},
{
NULL
},
};
};
...
@@ -483,15 +507,6 @@ static const AVFilterPad avfilter_vf_select_inputs[] = {
...
@@ -483,15 +507,6 @@ static const AVFilterPad avfilter_vf_select_inputs[] = {
{
NULL
}
{
NULL
}
};
};
static
const
AVFilterPad
avfilter_vf_select_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
request_frame
=
request_frame
,
},
{
NULL
}
};
AVFilter
avfilter_vf_select
=
{
AVFilter
avfilter_vf_select
=
{
.
name
=
"select"
,
.
name
=
"select"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Select video frames to pass in output."
),
.
description
=
NULL_IF_CONFIG_SMALL
(
"Select video frames to pass in output."
),
...
@@ -503,6 +518,6 @@ AVFilter avfilter_vf_select = {
...
@@ -503,6 +518,6 @@ AVFilter avfilter_vf_select = {
.
priv_class
=
&
select_class
,
.
priv_class
=
&
select_class
,
.
inputs
=
avfilter_vf_select_inputs
,
.
inputs
=
avfilter_vf_select_inputs
,
.
outputs
=
avfilter_vf_select_outputs
,
.
flags
=
AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
};
};
#endif
/* CONFIG_SELECT_FILTER */
#endif
/* CONFIG_SELECT_FILTER */
libavfilter/version.h
View file @
dcc1b323
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 56
#define LIBAVFILTER_VERSION_MINOR 56
#define LIBAVFILTER_VERSION_MICRO 10
2
#define LIBAVFILTER_VERSION_MICRO 10
3
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment