Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
1b8e061c
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,发现更多精彩内容 >>
提交
1b8e061c
编写于
8月 31, 2017
作者:
N
Nicolas George
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
lavfi: remove framesync.
上级
61b0b03f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
0 addition
and
640 deletion
+0
-640
libavfilter/framesync.c
libavfilter/framesync.c
+0
-343
libavfilter/framesync.h
libavfilter/framesync.h
+0
-297
未找到文件。
libavfilter/framesync.c
已删除
100644 → 0
浏览文件 @
61b0b03f
/*
* Copyright (c) 2013 Nicolas George
*
* 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
*/
#define FF_INTERNAL_FIELDS 1
#include "framequeue.h"
#include "libavutil/avassert.h"
#include "avfilter.h"
#include "bufferqueue.h"
#include "framesync.h"
#include "internal.h"
#define OFFSET(member) offsetof(FFFrameSync, member)
static
const
char
*
framesync_name
(
void
*
ptr
)
{
return
"framesync"
;
}
static
const
AVClass
framesync_class
=
{
.
version
=
LIBAVUTIL_VERSION_INT
,
.
class_name
=
"framesync"
,
.
item_name
=
framesync_name
,
.
category
=
AV_CLASS_CATEGORY_FILTER
,
.
option
=
NULL
,
.
parent_log_context_offset
=
OFFSET
(
parent
),
};
enum
{
STATE_BOF
,
STATE_RUN
,
STATE_EOF
,
};
int
ff_framesync_init
(
FFFrameSync
*
fs
,
void
*
parent
,
unsigned
nb_in
)
{
fs
->
class
=
&
framesync_class
;
fs
->
parent
=
parent
;
fs
->
nb_in
=
nb_in
;
fs
->
in
=
av_calloc
(
nb_in
,
sizeof
(
*
fs
->
in
));
if
(
!
fs
->
in
)
return
AVERROR
(
ENOMEM
);
return
0
;
}
static
void
framesync_sync_level_update
(
FFFrameSync
*
fs
)
{
unsigned
i
,
level
=
0
;
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
if
(
fs
->
in
[
i
].
state
!=
STATE_EOF
)
level
=
FFMAX
(
level
,
fs
->
in
[
i
].
sync
);
av_assert0
(
level
<=
fs
->
sync_level
);
if
(
level
<
fs
->
sync_level
)
av_log
(
fs
,
AV_LOG_VERBOSE
,
"Sync level %u
\n
"
,
level
);
if
(
level
)
fs
->
sync_level
=
level
;
else
fs
->
eof
=
1
;
}
int
ff_framesync_configure
(
FFFrameSync
*
fs
)
{
unsigned
i
;
int64_t
gcd
,
lcm
;
if
(
!
fs
->
time_base
.
num
)
{
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
{
if
(
fs
->
in
[
i
].
sync
)
{
if
(
fs
->
time_base
.
num
)
{
gcd
=
av_gcd
(
fs
->
time_base
.
den
,
fs
->
in
[
i
].
time_base
.
den
);
lcm
=
(
fs
->
time_base
.
den
/
gcd
)
*
fs
->
in
[
i
].
time_base
.
den
;
if
(
lcm
<
AV_TIME_BASE
/
2
)
{
fs
->
time_base
.
den
=
lcm
;
fs
->
time_base
.
num
=
av_gcd
(
fs
->
time_base
.
num
,
fs
->
in
[
i
].
time_base
.
num
);
}
else
{
fs
->
time_base
.
num
=
1
;
fs
->
time_base
.
den
=
AV_TIME_BASE
;
break
;
}
}
else
{
fs
->
time_base
=
fs
->
in
[
i
].
time_base
;
}
}
}
if
(
!
fs
->
time_base
.
num
)
{
av_log
(
fs
,
AV_LOG_ERROR
,
"Impossible to set time base
\n
"
);
return
AVERROR
(
EINVAL
);
}
av_log
(
fs
,
AV_LOG_VERBOSE
,
"Selected %d/%d time base
\n
"
,
fs
->
time_base
.
num
,
fs
->
time_base
.
den
);
}
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
fs
->
in
[
i
].
pts
=
fs
->
in
[
i
].
pts_next
=
AV_NOPTS_VALUE
;
fs
->
sync_level
=
UINT_MAX
;
framesync_sync_level_update
(
fs
);
return
0
;
}
static
void
framesync_advance
(
FFFrameSync
*
fs
)
{
int
latest
;
unsigned
i
;
int64_t
pts
;
if
(
fs
->
eof
)
return
;
while
(
!
fs
->
frame_ready
)
{
latest
=
-
1
;
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
{
if
(
!
fs
->
in
[
i
].
have_next
)
{
if
(
latest
<
0
||
fs
->
in
[
i
].
pts
<
fs
->
in
[
latest
].
pts
)
latest
=
i
;
}
}
if
(
latest
>=
0
)
{
fs
->
in_request
=
latest
;
break
;
}
pts
=
fs
->
in
[
0
].
pts_next
;
for
(
i
=
1
;
i
<
fs
->
nb_in
;
i
++
)
if
(
fs
->
in
[
i
].
pts_next
<
pts
)
pts
=
fs
->
in
[
i
].
pts_next
;
if
(
pts
==
INT64_MAX
)
{
fs
->
eof
=
1
;
break
;
}
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
{
if
(
fs
->
in
[
i
].
pts_next
==
pts
||
(
fs
->
in
[
i
].
before
==
EXT_INFINITY
&&
fs
->
in
[
i
].
state
==
STATE_BOF
))
{
av_frame_free
(
&
fs
->
in
[
i
].
frame
);
fs
->
in
[
i
].
frame
=
fs
->
in
[
i
].
frame_next
;
fs
->
in
[
i
].
pts
=
fs
->
in
[
i
].
pts_next
;
fs
->
in
[
i
].
frame_next
=
NULL
;
fs
->
in
[
i
].
pts_next
=
AV_NOPTS_VALUE
;
fs
->
in
[
i
].
have_next
=
0
;
fs
->
in
[
i
].
state
=
fs
->
in
[
i
].
frame
?
STATE_RUN
:
STATE_EOF
;
if
(
fs
->
in
[
i
].
sync
==
fs
->
sync_level
&&
fs
->
in
[
i
].
frame
)
fs
->
frame_ready
=
1
;
if
(
fs
->
in
[
i
].
state
==
STATE_EOF
&&
fs
->
in
[
i
].
after
==
EXT_STOP
)
fs
->
eof
=
1
;
}
}
if
(
fs
->
eof
)
fs
->
frame_ready
=
0
;
if
(
fs
->
frame_ready
)
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
if
((
fs
->
in
[
i
].
state
==
STATE_BOF
&&
fs
->
in
[
i
].
before
==
EXT_STOP
))
fs
->
frame_ready
=
0
;
fs
->
pts
=
pts
;
}
}
static
int64_t
framesync_pts_extrapolate
(
FFFrameSync
*
fs
,
unsigned
in
,
int64_t
pts
)
{
/* Possible enhancement: use the link's frame rate */
return
pts
+
1
;
}
static
void
framesync_inject_frame
(
FFFrameSync
*
fs
,
unsigned
in
,
AVFrame
*
frame
)
{
int64_t
pts
;
av_assert0
(
!
fs
->
in
[
in
].
have_next
);
if
(
frame
)
{
pts
=
av_rescale_q
(
frame
->
pts
,
fs
->
in
[
in
].
time_base
,
fs
->
time_base
);
frame
->
pts
=
pts
;
}
else
{
pts
=
fs
->
in
[
in
].
state
!=
STATE_RUN
||
fs
->
in
[
in
].
after
==
EXT_INFINITY
?
INT64_MAX
:
framesync_pts_extrapolate
(
fs
,
in
,
fs
->
in
[
in
].
pts
);
fs
->
in
[
in
].
sync
=
0
;
framesync_sync_level_update
(
fs
);
}
fs
->
in
[
in
].
frame_next
=
frame
;
fs
->
in
[
in
].
pts_next
=
pts
;
fs
->
in
[
in
].
have_next
=
1
;
}
int
ff_framesync_add_frame
(
FFFrameSync
*
fs
,
unsigned
in
,
AVFrame
*
frame
)
{
av_assert1
(
in
<
fs
->
nb_in
);
if
(
!
fs
->
in
[
in
].
have_next
)
framesync_inject_frame
(
fs
,
in
,
frame
);
else
ff_bufqueue_add
(
fs
,
&
fs
->
in
[
in
].
queue
,
frame
);
return
0
;
}
void
ff_framesync_next
(
FFFrameSync
*
fs
)
{
unsigned
i
;
av_assert0
(
!
fs
->
frame_ready
);
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
if
(
!
fs
->
in
[
i
].
have_next
&&
fs
->
in
[
i
].
queue
.
available
)
framesync_inject_frame
(
fs
,
i
,
ff_bufqueue_get
(
&
fs
->
in
[
i
].
queue
));
fs
->
frame_ready
=
0
;
framesync_advance
(
fs
);
}
void
ff_framesync_drop
(
FFFrameSync
*
fs
)
{
fs
->
frame_ready
=
0
;
}
int
ff_framesync_get_frame
(
FFFrameSync
*
fs
,
unsigned
in
,
AVFrame
**
rframe
,
unsigned
get
)
{
AVFrame
*
frame
;
unsigned
need_copy
=
0
,
i
;
int64_t
pts_next
;
int
ret
;
if
(
!
fs
->
in
[
in
].
frame
)
{
*
rframe
=
NULL
;
return
0
;
}
frame
=
fs
->
in
[
in
].
frame
;
if
(
get
)
{
/* Find out if we need to copy the frame: is there another sync
stream, and do we know if its current frame will outlast this one? */
pts_next
=
fs
->
in
[
in
].
have_next
?
fs
->
in
[
in
].
pts_next
:
INT64_MAX
;
for
(
i
=
0
;
i
<
fs
->
nb_in
&&
!
need_copy
;
i
++
)
if
(
i
!=
in
&&
fs
->
in
[
i
].
sync
&&
(
!
fs
->
in
[
i
].
have_next
||
fs
->
in
[
i
].
pts_next
<
pts_next
))
need_copy
=
1
;
if
(
need_copy
)
{
if
(
!
(
frame
=
av_frame_clone
(
frame
)))
return
AVERROR
(
ENOMEM
);
if
((
ret
=
av_frame_make_writable
(
frame
))
<
0
)
{
av_frame_free
(
&
frame
);
return
ret
;
}
}
else
{
fs
->
in
[
in
].
frame
=
NULL
;
}
fs
->
frame_ready
=
0
;
}
*
rframe
=
frame
;
return
0
;
}
void
ff_framesync_uninit
(
FFFrameSync
*
fs
)
{
unsigned
i
;
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
{
av_frame_free
(
&
fs
->
in
[
i
].
frame
);
av_frame_free
(
&
fs
->
in
[
i
].
frame_next
);
ff_bufqueue_discard_all
(
&
fs
->
in
[
i
].
queue
);
}
av_freep
(
&
fs
->
in
);
}
int
ff_framesync_process_frame
(
FFFrameSync
*
fs
,
unsigned
all
)
{
int
ret
,
count
=
0
;
av_assert0
(
fs
->
on_event
);
while
(
1
)
{
ff_framesync_next
(
fs
);
if
(
fs
->
eof
||
!
fs
->
frame_ready
)
break
;
if
((
ret
=
fs
->
on_event
(
fs
))
<
0
)
return
ret
;
ff_framesync_drop
(
fs
);
count
++
;
if
(
!
all
)
break
;
}
if
(
!
count
&&
fs
->
eof
)
return
AVERROR_EOF
;
return
count
;
}
int
ff_framesync_filter_frame
(
FFFrameSync
*
fs
,
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
int
ret
;
if
((
ret
=
ff_framesync_process_frame
(
fs
,
1
))
<
0
)
return
ret
;
if
((
ret
=
ff_framesync_add_frame
(
fs
,
FF_INLINK_IDX
(
inlink
),
in
))
<
0
)
return
ret
;
if
((
ret
=
ff_framesync_process_frame
(
fs
,
0
))
<
0
)
return
ret
;
return
0
;
}
int
ff_framesync_request_frame
(
FFFrameSync
*
fs
,
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
int
input
,
ret
,
i
;
if
((
ret
=
ff_framesync_process_frame
(
fs
,
0
))
<
0
)
return
ret
;
if
(
ret
>
0
)
return
0
;
if
(
fs
->
eof
)
return
AVERROR_EOF
;
input
=
fs
->
in_request
;
/* Detect status change early */
for
(
i
=
0
;
i
<
fs
->
nb_in
;
i
++
)
if
(
!
ff_framequeue_queued_frames
(
&
ctx
->
inputs
[
i
]
->
fifo
)
&&
ctx
->
inputs
[
i
]
->
status_in
&&
!
ctx
->
inputs
[
i
]
->
status_out
)
input
=
i
;
ret
=
ff_request_frame
(
ctx
->
inputs
[
input
]);
if
(
ret
==
AVERROR_EOF
)
{
if
((
ret
=
ff_framesync_add_frame
(
fs
,
input
,
NULL
))
<
0
)
return
ret
;
if
((
ret
=
ff_framesync_process_frame
(
fs
,
0
))
<
0
)
return
ret
;
ret
=
0
;
}
return
ret
;
}
libavfilter/framesync.h
已删除
100644 → 0
浏览文件 @
61b0b03f
/*
* Copyright (c) 2013 Nicolas George
*
* 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
*/
#ifndef AVFILTER_FRAMESYNC_H
#define AVFILTER_FRAMESYNC_H
#include "bufferqueue.h"
/*
* TODO
* Callback-based API similar to dualinput.
* Export convenient options.
*/
/**
* This API is intended as a helper for filters that have several video
* input and need to combine them somehow. If the inputs have different or
* variable frame rate, getting the input frames to match requires a rather
* complex logic and a few user-tunable options.
*
* In this API, when a set of synchronized input frames is ready to be
* procesed is called a frame event. Frame event can be generated in
* response to input frames on any or all inputs and the handling of
* situations where some stream extend beyond the beginning or the end of
* others can be configured.
*
* The basic working of this API is the following:
*
* - When a frame is available on any input, add it using
* ff_framesync_add_frame().
*
* - When a frame event is ready to be processed (i.e. after adding a frame
* or when requested on input):
* - call ff_framesync_next();
* - if fs->frame_ready is true, process the frames;
* - call ff_framesync_drop().
*/
/**
* Stream extrapolation mode
*
* Describe how the frames of a stream are extrapolated before the first one
* and after EOF to keep sync with possibly longer other streams.
*/
enum
FFFrameSyncExtMode
{
/**
* Completely stop all streams with this one.
*/
EXT_STOP
,
/**
* Ignore this stream and continue processing the other ones.
*/
EXT_NULL
,
/**
* Extend the frame to infinity.
*/
EXT_INFINITY
,
};
/**
* Input stream structure
*/
typedef
struct
FFFrameSyncIn
{
/**
* Queue of incoming AVFrame, and NULL to mark EOF
*/
struct
FFBufQueue
queue
;
/**
* Extrapolation mode for timestamps before the first frame
*/
enum
FFFrameSyncExtMode
before
;
/**
* Extrapolation mode for timestamps after the last frame
*/
enum
FFFrameSyncExtMode
after
;
/**
* Time base for the incoming frames
*/
AVRational
time_base
;
/**
* Current frame, may be NULL before the first one or after EOF
*/
AVFrame
*
frame
;
/**
* Next frame, for internal use
*/
AVFrame
*
frame_next
;
/**
* PTS of the current frame
*/
int64_t
pts
;
/**
* PTS of the next frame, for internal use
*/
int64_t
pts_next
;
/**
* Boolean flagging the next frame, for internal use
*/
uint8_t
have_next
;
/**
* State: before first, in stream or after EOF, for internal use
*/
uint8_t
state
;
/**
* Synchronization level: frames on input at the highest sync level will
* generate output frame events.
*
* For example, if inputs #0 and #1 have sync level 2 and input #2 has
* sync level 1, then a frame on either input #0 or #1 will generate a
* frame event, but not a frame on input #2 until both inputs #0 and #1
* have reached EOF.
*
* If sync is 0, no frame event will be generated.
*/
unsigned
sync
;
}
FFFrameSyncIn
;
/**
* Frame sync structure.
*/
typedef
struct
FFFrameSync
{
const
AVClass
*
class
;
void
*
parent
;
/**
* Number of input streams
*/
unsigned
nb_in
;
/**
* Time base for the output events
*/
AVRational
time_base
;
/**
* Timestamp of the current event
*/
int64_t
pts
;
/**
* Callback called when a frame event is ready
*/
int
(
*
on_event
)(
struct
FFFrameSync
*
fs
);
/**
* Opaque pointer, not used by the API
*/
void
*
opaque
;
/**
* Index of the input that requires a request
*/
unsigned
in_request
;
/**
* Synchronization level: only inputs with the same sync level are sync
* sources.
*/
unsigned
sync_level
;
/**
* Flag indicating that a frame event is ready
*/
uint8_t
frame_ready
;
/**
* Flag indicating that output has reached EOF.
*/
uint8_t
eof
;
/**
* Pointer to array of inputs.
*/
FFFrameSyncIn
*
in
;
}
FFFrameSync
;
/**
* Initialize a frame sync structure.
*
* The entire structure is expected to be already set to 0.
*
* @param fs frame sync structure to initialize
* @param parent parent object, used for logging
* @param nb_in number of inputs
* @return >= 0 for success or a negative error code
*/
int
ff_framesync_init
(
FFFrameSync
*
fs
,
void
*
parent
,
unsigned
nb_in
);
/**
* Configure a frame sync structure.
*
* Must be called after all options are set but before all use.
*
* @return >= 0 for success or a negative error code
*/
int
ff_framesync_configure
(
FFFrameSync
*
fs
);
/**
* Free all memory currently allocated.
*/
void
ff_framesync_uninit
(
FFFrameSync
*
fs
);
/**
* Add a frame to an input
*
* Typically called from the filter_frame() method.
*
* @param fs frame sync structure
* @param in index of the input
* @param frame input frame, or NULL for EOF
*/
int
ff_framesync_add_frame
(
FFFrameSync
*
fs
,
unsigned
in
,
AVFrame
*
frame
);
/**
* Prepare the next frame event.
*
* The status of the operation can be found in fs->frame_ready and fs->eof.
*/
void
ff_framesync_next
(
FFFrameSync
*
fs
);
/**
* Drop the current frame event.
*/
void
ff_framesync_drop
(
FFFrameSync
*
fs
);
/**
* Get the current frame in an input.
*
* @param fs frame sync structure
* @param in index of the input
* @param rframe used to return the current frame (or NULL)
* @param get if not zero, the calling code needs to get ownership of
* the returned frame; the current frame will either be
* duplicated or removed from the framesync structure
*/
int
ff_framesync_get_frame
(
FFFrameSync
*
fs
,
unsigned
in
,
AVFrame
**
rframe
,
unsigned
get
);
/**
* Process one or several frame using the on_event callback.
*
* @return number of frames processed or negative error code
*/
int
ff_framesync_process_frame
(
FFFrameSync
*
fs
,
unsigned
all
);
/**
* Accept a frame on a filter input.
*
* This function can be the complete implementation of all filter_frame
* methods of a filter using framesync.
*/
int
ff_framesync_filter_frame
(
FFFrameSync
*
fs
,
AVFilterLink
*
inlink
,
AVFrame
*
in
);
/**
* Request a frame on the filter output.
*
* This function can be the complete implementation of all filter_frame
* methods of a filter using framesync if it has only one output.
*/
int
ff_framesync_request_frame
(
FFFrameSync
*
fs
,
AVFilterLink
*
outlink
);
#endif
/* AVFILTER_FRAMESYNC_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录