Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
a7d0e7ea
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,发现更多精彩内容 >>
提交
a7d0e7ea
编写于
1月 09, 2014
作者:
V
Vittorio Giovara
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
lavfi: add framepack filter
上级
aa69cbc9
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
412 addition
and
1 deletion
+412
-1
Changelog
Changelog
+1
-0
doc/filters.texi
doc/filters.texi
+45
-0
libavfilter/Makefile
libavfilter/Makefile
+1
-0
libavfilter/allfilters.c
libavfilter/allfilters.c
+1
-0
libavfilter/version.h
libavfilter/version.h
+1
-1
libavfilter/vf_framepack.c
libavfilter/vf_framepack.c
+363
-0
未找到文件。
Changelog
浏览文件 @
a7d0e7ea
...
...
@@ -54,6 +54,7 @@ version 10:
- png standalone parser
- WebP encoding via libwebp
- ATRAC3+ decoder
- framepack filter
version 9:
...
...
doc/filters.texi
浏览文件 @
a7d0e7ea
...
...
@@ -1252,6 +1252,51 @@ frames with a negative PTS.
@end table
@section framepack
Pack two different video streams into a stereoscopic video, setting proper
metadata on supported codecs. The two views should have the same size and
framerate and processing will stop when the shorter video ends. Please note
that you may conveniently adjust view properties with the @ref{scale} and
@ref{fps} filters.
This filter accepts the following named parameters:
@table @option
@item format
Desired packing format. Supported values are:
@table @option
@item sbs
Views are next to each other (default).
@item tab
Views are on top of each other.
@item lines
Views are packed by line.
@item columns
Views are eacked by column.
@item frameseq
Views are temporally interleaved.
@end table
@end table
Some examples follow:
@example
# Convert left and right views into a frame sequential video.
avconv -i LEFT -i RIGHT -filter_complex framepack=frameseq OUTPUT
# Convert views into a side-by-side video with the same output resolution as the input.
avconv -i LEFT -i RIGHT -filter_complex [0:v]scale=w=iw/2[left],[1:v]scale=w=iw/2[right],[left][right]framepack=sbs OUTPUT
@end example
@anchor{frei0r}
@section frei0r
...
...
libavfilter/Makefile
浏览文件 @
a7d0e7ea
...
...
@@ -54,6 +54,7 @@ OBJS-$(CONFIG_FADE_FILTER) += vf_fade.o
OBJS-$(CONFIG_FIELDORDER_FILTER)
+=
vf_fieldorder.o
OBJS-$(CONFIG_FORMAT_FILTER)
+=
vf_format.o
OBJS-$(CONFIG_FPS_FILTER)
+=
vf_fps.o
OBJS-$(CONFIG_FRAMEPACK_FILTER)
+=
vf_framepack.o
OBJS-$(CONFIG_FREI0R_FILTER)
+=
vf_frei0r.o
OBJS-$(CONFIG_GRADFUN_FILTER)
+=
vf_gradfun.o
OBJS-$(CONFIG_HFLIP_FILTER)
+=
vf_hflip.o
...
...
libavfilter/allfilters.c
浏览文件 @
a7d0e7ea
...
...
@@ -74,6 +74,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
FIELDORDER
,
fieldorder
,
vf
);
REGISTER_FILTER
(
FORMAT
,
format
,
vf
);
REGISTER_FILTER
(
FPS
,
fps
,
vf
);
REGISTER_FILTER
(
FRAMEPACK
,
framepack
,
vf
);
REGISTER_FILTER
(
FREI0R
,
frei0r
,
vf
);
REGISTER_FILTER
(
GRADFUN
,
gradfun
,
vf
);
REGISTER_FILTER
(
HFLIP
,
hflip
,
vf
);
...
...
libavfilter/version.h
浏览文件 @
a7d0e7ea
...
...
@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 4
#define LIBAVFILTER_VERSION_MINOR
0
#define LIBAVFILTER_VERSION_MINOR
1
#define LIBAVFILTER_VERSION_MICRO 0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
libavfilter/vf_framepack.c
0 → 100644
浏览文件 @
a7d0e7ea
/*
* Copyright (c) 2013 Vittorio Giovara
*
* 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
*/
/**
* @file
* Generate a frame packed video, by combining two views in a single surface.
*/
#include <string.h>
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/rational.h"
#include "libavutil/stereo3d.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
#define LEFT 0
#define RIGHT 1
typedef
struct
FramepackContext
{
const
AVClass
*
class
;
const
AVPixFmtDescriptor
*
pix_desc
;
///< agreed pixel format
enum
AVStereo3DType
format
;
///< frame pack type output
AVFrame
*
input_views
[
2
];
///< input frames
int64_t
double_pts
;
///< new pts for frameseq mode
}
FramepackContext
;
static
const
enum
AVPixelFormat
formats_supported
[]
=
{
AV_PIX_FMT_YUV420P
,
AV_PIX_FMT_YUV422P
,
AV_PIX_FMT_YUV444P
,
AV_PIX_FMT_YUV410P
,
AV_PIX_FMT_YUVA420P
,
AV_PIX_FMT_YUVJ420P
,
AV_PIX_FMT_YUVJ422P
,
AV_PIX_FMT_YUVJ444P
,
AV_PIX_FMT_YUVJ440P
,
AV_PIX_FMT_NONE
};
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
// this will ensure that formats are the same on all pads
ff_set_common_formats
(
ctx
,
ff_make_format_list
(
formats_supported
));
return
0
;
}
static
av_cold
void
framepack_uninit
(
AVFilterContext
*
ctx
)
{
FramepackContext
*
s
=
ctx
->
priv
;
// clean any leftover frame
av_frame_free
(
&
s
->
input_views
[
LEFT
]);
av_frame_free
(
&
s
->
input_views
[
RIGHT
]);
}
static
int
config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
FramepackContext
*
s
=
outlink
->
src
->
priv
;
int
width
=
ctx
->
inputs
[
LEFT
]
->
w
;
int
height
=
ctx
->
inputs
[
LEFT
]
->
h
;
AVRational
time_base
=
ctx
->
inputs
[
LEFT
]
->
time_base
;
// check size and fps match on the other input
if
(
width
!=
ctx
->
inputs
[
RIGHT
]
->
w
||
height
!=
ctx
->
inputs
[
RIGHT
]
->
h
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Left and right sizes differ (%dx%d vs %dx%d).
\n
"
,
width
,
height
,
ctx
->
inputs
[
RIGHT
]
->
w
,
ctx
->
inputs
[
RIGHT
]
->
h
);
return
AVERROR_INVALIDDATA
;
}
else
if
(
av_cmp_q
(
time_base
,
ctx
->
inputs
[
RIGHT
]
->
time_base
)
!=
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Left and right framerates differ (%d/%d vs %d/%d).
\n
"
,
time_base
.
num
,
time_base
.
den
,
ctx
->
inputs
[
RIGHT
]
->
time_base
.
num
,
ctx
->
inputs
[
RIGHT
]
->
time_base
.
den
);
return
AVERROR_INVALIDDATA
;
}
s
->
pix_desc
=
av_pix_fmt_desc_get
(
outlink
->
format
);
if
(
!
s
->
pix_desc
)
return
AVERROR_BUG
;
// modify output properties as needed
switch
(
s
->
format
)
{
case
AV_STEREO3D_FRAMESEQUENCE
:
time_base
.
den
*=
2
;
s
->
double_pts
=
AV_NOPTS_VALUE
;
break
;
case
AV_STEREO3D_COLUMNS
:
case
AV_STEREO3D_SIDEBYSIDE
:
width
*=
2
;
break
;
case
AV_STEREO3D_LINES
:
case
AV_STEREO3D_TOPBOTTOM
:
height
*=
2
;
break
;
default:
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unknown packing mode."
);
return
AVERROR_INVALIDDATA
;
}
outlink
->
w
=
width
;
outlink
->
h
=
height
;
outlink
->
time_base
=
time_base
;
return
0
;
}
static
void
horizontal_frame_pack
(
FramepackContext
*
s
,
AVFrame
*
dst
,
int
interleaved
)
{
int
plane
,
i
;
int
length
=
dst
->
width
/
2
;
int
lines
=
dst
->
height
;
for
(
plane
=
0
;
plane
<
s
->
pix_desc
->
nb_components
;
plane
++
)
{
const
uint8_t
*
leftp
=
s
->
input_views
[
LEFT
]
->
data
[
plane
];
const
uint8_t
*
rightp
=
s
->
input_views
[
RIGHT
]
->
data
[
plane
];
uint8_t
*
dstp
=
dst
->
data
[
plane
];
if
(
plane
==
1
||
plane
==
2
)
{
length
=
-
(
-
(
dst
->
width
/
2
)
>>
s
->
pix_desc
->
log2_chroma_w
);
lines
=
-
(
-
(
dst
->
height
)
>>
s
->
pix_desc
->
log2_chroma_h
);
}
if
(
interleaved
)
{
for
(
i
=
0
;
i
<
lines
;
i
++
)
{
int
j
;
int
k
=
0
;
for
(
j
=
0
;
j
<
length
;
j
++
)
{
dstp
[
k
++
]
=
leftp
[
j
];
dstp
[
k
++
]
=
rightp
[
j
];
}
dstp
+=
dst
->
linesize
[
plane
];
leftp
+=
s
->
input_views
[
LEFT
]
->
linesize
[
plane
];
rightp
+=
s
->
input_views
[
RIGHT
]
->
linesize
[
plane
];
}
}
else
{
av_image_copy_plane
(
dst
->
data
[
plane
],
dst
->
linesize
[
plane
],
leftp
,
s
->
input_views
[
LEFT
]
->
linesize
[
plane
],
length
,
lines
);
av_image_copy_plane
(
dst
->
data
[
plane
]
+
length
,
dst
->
linesize
[
plane
],
rightp
,
s
->
input_views
[
RIGHT
]
->
linesize
[
plane
],
length
,
lines
);
}
}
}
static
void
vertical_frame_pack
(
FramepackContext
*
s
,
AVFrame
*
dst
,
int
interleaved
)
{
int
plane
,
offset
;
int
length
=
dst
->
width
;
int
lines
=
dst
->
height
/
2
;
for
(
plane
=
0
;
plane
<
s
->
pix_desc
->
nb_components
;
plane
++
)
{
if
(
plane
==
1
||
plane
==
2
)
{
length
=
-
(
-
(
dst
->
width
)
>>
s
->
pix_desc
->
log2_chroma_w
);
lines
=
-
(
-
(
dst
->
height
/
2
)
>>
s
->
pix_desc
->
log2_chroma_h
);
}
offset
=
interleaved
?
dst
->
linesize
[
plane
]
:
dst
->
linesize
[
plane
]
*
lines
;
av_image_copy_plane
(
dst
->
data
[
plane
],
dst
->
linesize
[
plane
]
<<
interleaved
,
s
->
input_views
[
LEFT
]
->
data
[
plane
],
s
->
input_views
[
LEFT
]
->
linesize
[
plane
],
length
,
lines
);
av_image_copy_plane
(
dst
->
data
[
plane
]
+
offset
,
dst
->
linesize
[
plane
]
<<
interleaved
,
s
->
input_views
[
RIGHT
]
->
data
[
plane
],
s
->
input_views
[
RIGHT
]
->
linesize
[
plane
],
length
,
lines
);
}
}
static
av_always_inline
void
spatial_frame_pack
(
FramepackContext
*
s
,
AVFrame
*
dst
)
{
switch
(
s
->
format
)
{
case
AV_STEREO3D_SIDEBYSIDE
:
horizontal_frame_pack
(
s
,
dst
,
0
);
break
;
case
AV_STEREO3D_COLUMNS
:
horizontal_frame_pack
(
s
,
dst
,
1
);
break
;
case
AV_STEREO3D_TOPBOTTOM
:
vertical_frame_pack
(
s
,
dst
,
0
);
break
;
case
AV_STEREO3D_LINES
:
vertical_frame_pack
(
s
,
dst
,
1
);
break
;
}
}
static
int
filter_frame_left
(
AVFilterLink
*
inlink
,
AVFrame
*
frame
)
{
FramepackContext
*
s
=
inlink
->
dst
->
priv
;
s
->
input_views
[
LEFT
]
=
frame
;
return
0
;
}
static
int
filter_frame_right
(
AVFilterLink
*
inlink
,
AVFrame
*
frame
)
{
FramepackContext
*
s
=
inlink
->
dst
->
priv
;
s
->
input_views
[
RIGHT
]
=
frame
;
return
0
;
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
FramepackContext
*
s
=
ctx
->
priv
;
AVStereo3D
*
stereo
;
int
ret
,
i
;
/* get a frame on the either input, stop as soon as a video ends */
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
!
s
->
input_views
[
i
])
{
ret
=
ff_request_frame
(
ctx
->
inputs
[
i
]);
if
(
ret
<
0
)
return
ret
;
}
}
if
(
s
->
format
==
AV_STEREO3D_FRAMESEQUENCE
)
{
if
(
s
->
double_pts
==
AV_NOPTS_VALUE
)
s
->
double_pts
=
s
->
input_views
[
LEFT
]
->
pts
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
// set correct timestamps
s
->
input_views
[
i
]
->
pts
=
s
->
double_pts
++
;
// set stereo3d side data
stereo
=
av_stereo3d_create_side_data
(
s
->
input_views
[
i
]);
if
(
!
stereo
)
return
AVERROR
(
ENOMEM
);
stereo
->
type
=
s
->
format
;
// filter the frame and immediately relinquish its pointer
ret
=
ff_filter_frame
(
outlink
,
s
->
input_views
[
i
]);
s
->
input_views
[
i
]
=
NULL
;
if
(
ret
<
0
)
return
ret
;
}
return
ret
;
}
else
{
AVFrame
*
dst
=
ff_get_video_buffer
(
outlink
,
outlink
->
w
,
outlink
->
h
);
if
(
!
dst
)
return
AVERROR
(
ENOMEM
);
spatial_frame_pack
(
s
,
dst
);
// get any property from the original frame
ret
=
av_frame_copy_props
(
dst
,
s
->
input_views
[
LEFT
]);
if
(
ret
<
0
)
{
av_frame_free
(
&
dst
);
return
ret
;
}
for
(
i
=
0
;
i
<
2
;
i
++
)
av_frame_free
(
&
s
->
input_views
[
i
]);
// set stereo3d side data
stereo
=
av_stereo3d_create_side_data
(
dst
);
if
(
!
stereo
)
{
av_frame_free
(
&
dst
);
return
AVERROR
(
ENOMEM
);
}
stereo
->
type
=
s
->
format
;
return
ff_filter_frame
(
outlink
,
dst
);
}
}
#define OFFSET(x) offsetof(FramepackContext, x)
#define V AV_OPT_FLAG_VIDEO_PARAM
static
const
AVOption
options
[]
=
{
{
"format"
,
"Frame pack output format"
,
OFFSET
(
format
),
AV_OPT_TYPE_INT
,
{
.
i64
=
AV_STEREO3D_SIDEBYSIDE
},
0
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
"sbs"
,
"Views are packed next to each other"
,
0
,
AV_OPT_TYPE_CONST
,
{
.
i64
=
AV_STEREO3D_SIDEBYSIDE
},
INT_MIN
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
"tab"
,
"Views are packed on top of each other"
,
0
,
AV_OPT_TYPE_CONST
,
{
.
i64
=
AV_STEREO3D_TOPBOTTOM
},
INT_MIN
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
"frameseq"
,
"Views are one after the other"
,
0
,
AV_OPT_TYPE_CONST
,
{
.
i64
=
AV_STEREO3D_FRAMESEQUENCE
},
INT_MIN
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
"lines"
,
"Views are interleaved by lines"
,
0
,
AV_OPT_TYPE_CONST
,
{
.
i64
=
AV_STEREO3D_LINES
},
INT_MIN
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
"columns"
,
"Views are interleaved by columns"
,
0
,
AV_OPT_TYPE_CONST
,
{
.
i64
=
AV_STEREO3D_COLUMNS
},
INT_MIN
,
INT_MAX
,
.
flags
=
V
,
.
unit
=
"format"
},
{
NULL
},
};
static
const
AVClass
framepack_class
=
{
.
class_name
=
"framepack"
,
.
item_name
=
av_default_item_name
,
.
option
=
options
,
.
version
=
LIBAVUTIL_VERSION_INT
,
};
static
const
AVFilterPad
framepack_inputs
[]
=
{
{
.
name
=
"left"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
filter_frame
=
filter_frame_left
,
.
needs_fifo
=
1
,
},
{
.
name
=
"right"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
filter_frame
=
filter_frame_right
,
.
needs_fifo
=
1
,
},
{
NULL
}
};
static
const
AVFilterPad
framepack_outputs
[]
=
{
{
.
name
=
"packed"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
config_props
=
config_output
,
.
request_frame
=
request_frame
,
},
{
NULL
}
};
AVFilter
ff_vf_framepack
=
{
.
name
=
"framepack"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Generate a frame packed stereoscopic video."
),
.
priv_size
=
sizeof
(
FramepackContext
),
.
priv_class
=
&
framepack_class
,
.
query_formats
=
query_formats
,
.
inputs
=
framepack_inputs
,
.
outputs
=
framepack_outputs
,
.
uninit
=
framepack_uninit
,
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录