Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
07586b68
F
Ffmpeg
项目概览
小白菜888
/
Ffmpeg
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Ffmpeg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
07586b68
编写于
5月 07, 2011
作者:
S
Stefano Sabatini
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
lavfi: add select filter
Address trac issue #92.
上级
3c2c52ba
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
471 addition
and
1 deletion
+471
-1
Changelog
Changelog
+1
-0
doc/filters.texi
doc/filters.texi
+116
-0
libavfilter/Makefile
libavfilter/Makefile
+1
-0
libavfilter/allfilters.c
libavfilter/allfilters.c
+1
-0
libavfilter/avfilter.h
libavfilter/avfilter.h
+1
-1
libavfilter/vf_select.c
libavfilter/vf_select.c
+351
-0
未找到文件。
Changelog
浏览文件 @
07586b68
...
...
@@ -18,6 +18,7 @@ version <next>:
- 9bit and 10bit H.264 decoding
- 9bit and 10bit FFV1 encoding / decoding
- split filter added
- select filter added
version 0.7_beta1:
...
...
doc/filters.texi
浏览文件 @
07586b68
...
...
@@ -1163,6 +1163,122 @@ scale="trunc(3/2*iw/hsub)*hsub:trunc(3/2*ih/vsub)*vsub"
scale='min(500\, iw*3/2):-1'
@end example
@section select
Select frames to pass in output.
It accepts in input an expression, which is evaluated for each input
frame. If the expression is evaluated to a non-zero value, the frame
is selected and passed to the output, otherwise it is discarded.
The expression can contain the following constants:
@table @option
@item PI
Greek PI
@item PHI
golden ratio
@item E
Euler number
@item n
the sequential number of the filtered frame, starting from 0
@item selected_n
the sequential number of the selected frame, starting from 0
@item prev_selected_n
the sequential number of the last selected frame, NAN if undefined
@item TB
timebase of the input timestamps
@item pts
the PTS (Presentation TimeStamp) of the filtered video frame,
expressed in @var{TB} units, NAN if undefined
@item t
the PTS (Presentation TimeStamp) of the filtered video frame,
expressed in seconds, NAN if undefined
@item prev_pts
the PTS of the previously filtered video frame, NAN if undefined
@item prev_selected_pts
the PTS of the last previously filtered video frame, NAN if undefined
@item prev_selected_t
the PTS of the last previously selected video frame, NAN if undefined
@item start_pts
the PTS of the first video frame in the video, NAN if undefined
@item start_t
the time of the first video frame in the video, NAN if undefined
@item pict_type
the picture type of the filtered frame, can assume one of the following
values:
@table @option
@item PICT_TYPE_I
@item PICT_TYPE_P
@item PICT_TYPE_B
@item PICT_TYPE_S
@item PICT_TYPE_SI
@item PICT_TYPE_SP
@item PICT_TYPE_BI
@end table
@item interlace_type
the frame interlace type, can assume one of the following values:
@table @option
@item INTERLACE_TYPE_P
the frame is progressive (not interlaced)
@item INTERLACE_TYPE_T
the frame is top-field-first
@item INTERLACE_TYPE_B
the frame is bottom-field-first
@end table
@item key
1 if the filtered frame is a key-frame, 0 otherwise
@item pos
the position in the file of the filtered frame, -1 if the information
is not available (e.g. for synthetic video)
@end table
The default value of the select expression is "1".
Some examples follow:
@example
# select all frames in input
select
# the above is the same as:
select=1
# skip all frames:
select=0
# select only I-frames
select='eq(pict_type\,PICT_TYPE_I)'
# select one frame every 100
select='not(mod(n\,100))'
# select only frames contained in the 10-20 time interval
select='gte(t\,10)*lte(t\,20)'
# select only I frames contained in the 10-20 time interval
select='gte(t\,10)*lte(t\,20)*eq(pict_type\,PICT_TYPE_I)'
# select frames with a minimum distance of 10 seconds
select='isnan(prev_selected_t)+gte(t-prev_selected_t\,10)'
@end example
@anchor{setdar}
@section setdar
...
...
libavfilter/Makefile
浏览文件 @
07586b68
...
...
@@ -46,6 +46,7 @@ OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o
OBJS-$(CONFIG_PAD_FILTER)
+=
vf_pad.o
OBJS-$(CONFIG_PIXDESCTEST_FILTER)
+=
vf_pixdesctest.o
OBJS-$(CONFIG_SCALE_FILTER)
+=
vf_scale.o
OBJS-$(CONFIG_SELECT_FILTER)
+=
vf_select.o
OBJS-$(CONFIG_SETDAR_FILTER)
+=
vf_aspect.o
OBJS-$(CONFIG_SETPTS_FILTER)
+=
vf_setpts.o
OBJS-$(CONFIG_SETSAR_FILTER)
+=
vf_aspect.o
...
...
libavfilter/allfilters.c
浏览文件 @
07586b68
...
...
@@ -62,6 +62,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
PAD
,
pad
,
vf
);
REGISTER_FILTER
(
PIXDESCTEST
,
pixdesctest
,
vf
);
REGISTER_FILTER
(
SCALE
,
scale
,
vf
);
REGISTER_FILTER
(
SELECT
,
select
,
vf
);
REGISTER_FILTER
(
SETDAR
,
setdar
,
vf
);
REGISTER_FILTER
(
SETPTS
,
setpts
,
vf
);
REGISTER_FILTER
(
SETSAR
,
setsar
,
vf
);
...
...
libavfilter/avfilter.h
浏览文件 @
07586b68
...
...
@@ -26,7 +26,7 @@
#include "libavutil/samplefmt.h"
#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 1
0
#define LIBAVFILTER_VERSION_MINOR 1
1
#define LIBAVFILTER_VERSION_MICRO 0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
libavfilter/vf_select.c
0 → 100644
浏览文件 @
07586b68
/*
* Copyright (c) 2011 Stefano Sabatini
*
* 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
* filter for selecting which frame passes in the filterchain
*/
#include "libavutil/eval.h"
#include "libavutil/fifo.h"
#include "avfilter.h"
static
const
char
*
var_names
[]
=
{
"E"
,
///< Euler number
"PHI"
,
///< golden ratio
"PI"
,
///< greek pi
"TB"
,
///< timebase
"pts"
,
///< original pts in the file of the frame
"start_pts"
,
///< first PTS in the stream, expressed in TB units
"prev_pts"
,
///< previous frame PTS
"prev_selected_pts"
,
///< previous selected frame PTS
"t"
,
///< first PTS in seconds
"start_t"
,
///< first PTS in the stream, expressed in seconds
"prev_t"
,
///< previous frame time
"prev_selected_t"
,
///< previously selected time
"pict_type"
,
///< the type of picture in the movie
"PICT_TYPE_I"
,
"PICT_TYPE_P"
,
"PICT_TYPE_B"
,
"PICT_TYPE_S"
,
"PICT_TYPE_SI"
,
"PICT_TYPE_SP"
,
"PICT_TYPE_BI"
,
"interlace_type"
,
///< the frame interlace type
"INTERLACE_TYPE_P"
,
"INTERLACE_TYPE_T"
,
"INTERLACE_TYPE_B"
,
"n"
,
///< frame number (starting from zero)
"selected_n"
,
///< selected frame number (starting from zero)
"prev_selected_n"
,
///< number of the last selected frame
"key"
,
///< tell if the frame is a key frame
"pos"
,
///< original position in the file of the frame
NULL
};
enum
var_name
{
VAR_E
,
VAR_PHI
,
VAR_PI
,
VAR_TB
,
VAR_PTS
,
VAR_START_PTS
,
VAR_PREV_PTS
,
VAR_PREV_SELECTED_PTS
,
VAR_T
,
VAR_START_T
,
VAR_PREV_T
,
VAR_PREV_SELECTED_T
,
VAR_PICT_TYPE
,
VAR_PICT_TYPE_I
,
VAR_PICT_TYPE_P
,
VAR_PICT_TYPE_B
,
VAR_PICT_TYPE_S
,
VAR_PICT_TYPE_SI
,
VAR_PICT_TYPE_SP
,
VAR_PICT_TYPE_BI
,
VAR_INTERLACE_TYPE
,
VAR_INTERLACE_TYPE_P
,
VAR_INTERLACE_TYPE_T
,
VAR_INTERLACE_TYPE_B
,
VAR_N
,
VAR_SELECTED_N
,
VAR_PREV_SELECTED_N
,
VAR_KEY
,
VAR_POS
,
VAR_VARS_NB
};
#define FIFO_SIZE 8
typedef
struct
{
AVExpr
*
expr
;
double
var_values
[
VAR_VARS_NB
];
double
select
;
int
cache_frames
;
AVFifoBuffer
*
pending_frames
;
///< FIFO buffer of video frames
}
SelectContext
;
static
av_cold
int
init
(
AVFilterContext
*
ctx
,
const
char
*
args
,
void
*
opaque
)
{
SelectContext
*
select
=
ctx
->
priv
;
int
ret
;
if
((
ret
=
av_expr_parse
(
&
select
->
expr
,
args
?
args
:
"1"
,
var_names
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
ctx
))
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error while parsing expression '%s'
\n
"
,
args
);
return
ret
;
}
select
->
pending_frames
=
av_fifo_alloc
(
FIFO_SIZE
*
sizeof
(
AVFilterBufferRef
*
));
if
(
!
select
->
pending_frames
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to allocate pending frames buffer.
\n
"
);
return
AVERROR
(
ENOMEM
);
}
return
0
;
}
#define INTERLACE_TYPE_P 0
#define INTERLACE_TYPE_T 1
#define INTERLACE_TYPE_B 2
static
int
config_input
(
AVFilterLink
*
inlink
)
{
SelectContext
*
select
=
inlink
->
dst
->
priv
;
select
->
var_values
[
VAR_E
]
=
M_E
;
select
->
var_values
[
VAR_PHI
]
=
M_PHI
;
select
->
var_values
[
VAR_PI
]
=
M_PI
;
select
->
var_values
[
VAR_N
]
=
0
.
0
;
select
->
var_values
[
VAR_SELECTED_N
]
=
0
.
0
;
select
->
var_values
[
VAR_TB
]
=
av_q2d
(
inlink
->
time_base
);
select
->
var_values
[
VAR_PREV_PTS
]
=
NAN
;
select
->
var_values
[
VAR_PREV_SELECTED_PTS
]
=
NAN
;
select
->
var_values
[
VAR_PREV_SELECTED_T
]
=
NAN
;
select
->
var_values
[
VAR_START_PTS
]
=
NAN
;
select
->
var_values
[
VAR_START_T
]
=
NAN
;
select
->
var_values
[
VAR_PICT_TYPE_I
]
=
AV_PICTURE_TYPE_I
;
select
->
var_values
[
VAR_PICT_TYPE_P
]
=
AV_PICTURE_TYPE_P
;
select
->
var_values
[
VAR_PICT_TYPE_B
]
=
AV_PICTURE_TYPE_B
;
select
->
var_values
[
VAR_PICT_TYPE_SI
]
=
AV_PICTURE_TYPE_SI
;
select
->
var_values
[
VAR_PICT_TYPE_SP
]
=
AV_PICTURE_TYPE_SP
;
select
->
var_values
[
VAR_INTERLACE_TYPE_P
]
=
INTERLACE_TYPE_P
;
select
->
var_values
[
VAR_INTERLACE_TYPE_T
]
=
INTERLACE_TYPE_T
;
select
->
var_values
[
VAR_INTERLACE_TYPE_B
]
=
INTERLACE_TYPE_B
;;
return
0
;
}
#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
static
int
select_frame
(
AVFilterContext
*
ctx
,
AVFilterBufferRef
*
picref
)
{
SelectContext
*
select
=
ctx
->
priv
;
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
double
res
;
if
(
isnan
(
select
->
var_values
[
VAR_START_PTS
]))
select
->
var_values
[
VAR_START_PTS
]
=
TS2D
(
picref
->
pts
);
select
->
var_values
[
VAR_PTS
]
=
TS2D
(
picref
->
pts
);
select
->
var_values
[
VAR_T
]
=
picref
->
pts
*
av_q2d
(
inlink
->
time_base
);
select
->
var_values
[
VAR_POS
]
=
picref
->
pos
==
-
1
?
NAN
:
picref
->
pos
;
select
->
var_values
[
VAR_PREV_PTS
]
=
TS2D
(
picref
->
pts
);
select
->
var_values
[
VAR_INTERLACE_TYPE
]
=
!
picref
->
video
->
interlaced
?
INTERLACE_TYPE_P
:
picref
->
video
->
top_field_first
?
INTERLACE_TYPE_T
:
INTERLACE_TYPE_B
;
select
->
var_values
[
VAR_PICT_TYPE
]
=
picref
->
video
->
pict_type
;
res
=
av_expr_eval
(
select
->
expr
,
select
->
var_values
,
NULL
);
av_log
(
inlink
->
dst
,
AV_LOG_DEBUG
,
"n:%d pts:%d t:%f pos:%d interlace_type:%c key:%d pict_type:%c "
"-> select:%f
\n
"
,
(
int
)
select
->
var_values
[
VAR_N
],
(
int
)
select
->
var_values
[
VAR_PTS
],
select
->
var_values
[
VAR_T
],
(
int
)
select
->
var_values
[
VAR_POS
],
select
->
var_values
[
VAR_INTERLACE_TYPE
]
==
INTERLACE_TYPE_P
?
'P'
:
select
->
var_values
[
VAR_INTERLACE_TYPE
]
==
INTERLACE_TYPE_T
?
'T'
:
select
->
var_values
[
VAR_INTERLACE_TYPE
]
==
INTERLACE_TYPE_B
?
'B'
:
'?'
,
(
int
)
select
->
var_values
[
VAR_KEY
],
av_get_picture_type_char
(
select
->
var_values
[
VAR_PICT_TYPE
]),
res
);
select
->
var_values
[
VAR_N
]
+=
1
.
0
;
if
(
res
)
{
select
->
var_values
[
VAR_PREV_SELECTED_N
]
=
select
->
var_values
[
VAR_N
];
select
->
var_values
[
VAR_PREV_SELECTED_PTS
]
=
select
->
var_values
[
VAR_PTS
];
select
->
var_values
[
VAR_PREV_SELECTED_T
]
=
select
->
var_values
[
VAR_T
];
select
->
var_values
[
VAR_SELECTED_N
]
+=
1
.
0
;
}
return
res
;
}
static
void
start_frame
(
AVFilterLink
*
inlink
,
AVFilterBufferRef
*
picref
)
{
SelectContext
*
select
=
inlink
->
dst
->
priv
;
select
->
select
=
select_frame
(
inlink
->
dst
,
picref
);
if
(
select
->
select
)
{
/* frame was requested through poll_frame */
if
(
select
->
cache_frames
)
{
if
(
!
av_fifo_space
(
select
->
pending_frames
))
av_log
(
inlink
->
dst
,
AV_LOG_ERROR
,
"Buffering limit reached, cannot cache more frames
\n
"
);
else
av_fifo_generic_write
(
select
->
pending_frames
,
&
picref
,
sizeof
(
picref
),
NULL
);
return
;
}
avfilter_start_frame
(
inlink
->
dst
->
outputs
[
0
],
avfilter_ref_buffer
(
picref
,
~
0
));
}
}
static
void
draw_slice
(
AVFilterLink
*
inlink
,
int
y
,
int
h
,
int
slice_dir
)
{
SelectContext
*
select
=
inlink
->
dst
->
priv
;
if
(
select
->
select
&&
!
select
->
cache_frames
)
avfilter_draw_slice
(
inlink
->
dst
->
outputs
[
0
],
y
,
h
,
slice_dir
);
}
static
void
end_frame
(
AVFilterLink
*
inlink
)
{
SelectContext
*
select
=
inlink
->
dst
->
priv
;
AVFilterBufferRef
*
picref
=
inlink
->
cur_buf
;
if
(
select
->
select
)
{
if
(
select
->
cache_frames
)
return
;
avfilter_end_frame
(
inlink
->
dst
->
outputs
[
0
]);
}
avfilter_unref_buffer
(
picref
);
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
SelectContext
*
select
=
ctx
->
priv
;
AVFilterLink
*
inlink
=
outlink
->
src
->
inputs
[
0
];
select
->
select
=
0
;
if
(
av_fifo_size
(
select
->
pending_frames
))
{
AVFilterBufferRef
*
picref
;
av_fifo_generic_read
(
select
->
pending_frames
,
&
picref
,
sizeof
(
picref
),
NULL
);
avfilter_start_frame
(
outlink
,
avfilter_ref_buffer
(
picref
,
~
0
));
avfilter_draw_slice
(
outlink
,
0
,
outlink
->
h
,
1
);
avfilter_end_frame
(
outlink
);
avfilter_unref_buffer
(
picref
);
return
0
;
}
while
(
!
select
->
select
)
{
int
ret
=
avfilter_request_frame
(
inlink
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
poll_frame
(
AVFilterLink
*
outlink
)
{
SelectContext
*
select
=
outlink
->
src
->
priv
;
AVFilterLink
*
inlink
=
outlink
->
src
->
inputs
[
0
];
int
count
,
ret
;
if
(
!
av_fifo_size
(
select
->
pending_frames
))
{
if
((
count
=
avfilter_poll_frame
(
inlink
))
<=
0
)
return
count
;
/* request frame from input, and apply select condition to it */
select
->
cache_frames
=
1
;
while
(
count
--
&&
av_fifo_space
(
select
->
pending_frames
))
{
ret
=
avfilter_request_frame
(
inlink
);
if
(
ret
<
0
)
break
;
}
select
->
cache_frames
=
0
;
}
return
av_fifo_size
(
select
->
pending_frames
)
/
sizeof
(
AVFilterBufferRef
*
);
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
SelectContext
*
select
=
ctx
->
priv
;
AVFilterBufferRef
*
picref
;
int
i
;
av_expr_free
(
select
->
expr
);
select
->
expr
=
NULL
;
for
(
i
=
0
;
i
<
av_fifo_size
(
select
->
pending_frames
)
/
sizeof
(
picref
);
i
++
)
{
av_fifo_generic_read
(
select
->
pending_frames
,
&
picref
,
sizeof
(
picref
),
NULL
);
avfilter_unref_buffer
(
picref
);
}
av_fifo_free
(
select
->
pending_frames
);
}
AVFilter
avfilter_vf_select
=
{
.
name
=
"select"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Select frames to pass in output."
),
.
init
=
init
,
.
uninit
=
uninit
,
.
priv_size
=
sizeof
(
SelectContext
),
.
inputs
=
(
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
get_video_buffer
=
avfilter_null_get_video_buffer
,
.
config_props
=
config_input
,
.
start_frame
=
start_frame
,
.
draw_slice
=
draw_slice
,
.
end_frame
=
end_frame
},
{
.
name
=
NULL
}},
.
outputs
=
(
AVFilterPad
[])
{{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
poll_frame
=
poll_frame
,
.
request_frame
=
request_frame
,
},
{
.
name
=
NULL
}},
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录