Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
1054ab35
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,发现更多精彩内容 >>
提交
1054ab35
编写于
10月 30, 2011
作者:
C
Clément Bœsch
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
v4l2: add libv4l2 support.
上级
434db571
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
61 addition
and
27 deletion
+61
-27
Changelog
Changelog
+1
-0
configure
configure
+5
-0
doc/indevs.texi
doc/indevs.texi
+3
-0
libavdevice/v4l2.c
libavdevice/v4l2.c
+52
-27
未找到文件。
Changelog
浏览文件 @
1054ab35
...
...
@@ -75,6 +75,7 @@ easier to use. The changes are:
- new ffmpeg option: -map_channel
- volume audio filter added
- earwax audio filter added
- libv4l2 support (--enable-libv4l2)
version 0.8:
...
...
configure
浏览文件 @
1054ab35
...
...
@@ -187,6 +187,7 @@ External library support:
--enable-libstagefright-h264 enable H.264 decoding via libstagefright [no]
--enable-libtheora enable Theora encoding via libtheora [no]
--enable-libutvideo enable Ut Video decoding via libutvideo [no]
--enable-libv4l2 enable libv4l2/v4l-utils [no]
--enable-libvo-aacenc enable AAC encoding via libvo-aacenc [no]
--enable-libvo-amrwbenc enable AMR-WB encoding via libvo-amrwbenc [no]
--enable-libvorbis enable Vorbis encoding via libvorbis,
...
...
@@ -1022,6 +1023,7 @@ CONFIG_LIST="
libstagefright_h264
libtheora
libutvideo
libv4l2
libvo_aacenc
libvo_amrwbenc
libvorbis
...
...
@@ -1568,6 +1570,7 @@ jack_indev_deps="jack_jack_h sem_timedwait"
lavfi_indev_deps
=
"avfilter"
libcdio_indev_deps
=
"libcdio"
libdc1394_indev_deps
=
"libdc1394"
libv4l2_indev_deps
=
"libv4l2"
openal_indev_deps
=
"openal"
oss_indev_deps_any
=
"soundcard_h sys_soundcard_h"
oss_outdev_deps_any
=
"soundcard_h sys_soundcard_h"
...
...
@@ -3055,6 +3058,7 @@ enabled libstagefright_h264 && require_cpp libstagefright_h264 "binder/ProcessS
media/stagefright/OMXClient.h media/stagefright/OMXCodec.h"
android::OMXClient
-lstagefright
-lmedia
-lutils
-lbinder
enabled libtheora
&&
require libtheora theora/theoraenc.h th_info_init
-ltheoraenc
-ltheoradec
-logg
enabled libutvideo
&&
require_cpp utvideo
"stdint.h stdlib.h utvideo/utvideo.h utvideo/Codec.h"
'CCodec*'
-lutvideo
-lstdc
++
enabled libv4l2
&&
require_pkg_config libv4l2 libv4l2.h v4l2_ioctl
enabled libvo_aacenc
&&
require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI
-lvo-aacenc
enabled libvo_amrwbenc
&&
require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init
-lvo-amrwbenc
enabled libvorbis
&&
require libvorbis vorbis/vorbisenc.h vorbis_info_init
-lvorbisenc
-lvorbis
-logg
...
...
@@ -3383,6 +3387,7 @@ echo "libspeex enabled ${libspeex-no}"
echo
"libstagefright-h264 enabled
${
libstagefright_h264
-no
}
"
echo
"libtheora enabled
${
libtheora
-no
}
"
echo
"libutvideo enabled
${
libutvideo
-no
}
"
echo
"libv4l2 enabled
${
libv4l2
-no
}
"
echo
"libvo-aacenc support
${
libvo_aacenc
-no
}
"
echo
"libvo-amrwbenc support
${
libvo_amrwbenc
-no
}
"
echo
"libvorbis enabled
${
libvorbis
-no
}
"
...
...
doc/indevs.texi
浏览文件 @
1054ab35
...
...
@@ -513,6 +513,9 @@ input device will use the frame rate value already set in the driver.
Video4Linux support is deprecated since Linux 2.6.30, and will be
dropped in later versions.
Note that if FFmpeg is build with v4l-utils support ("--enable-libv4l2"
option), it will always be used.
Follow some usage examples of the video4linux devices with the ff*
tools.
@example
...
...
libavdevice/v4l2.c
浏览文件 @
1054ab35
...
...
@@ -52,6 +52,18 @@
#include "libavutil/pixdesc.h"
#include "libavutil/avstring.h"
#if CONFIG_LIBV4L2
#include <libv4l2.h>
#else
#define v4l2_open open
#define v4l2_close close
#define v4l2_dup dup
#define v4l2_ioctl ioctl
#define v4l2_read read
#define v4l2_mmap mmap
#define v4l2_munmap munmap
#endif
static
const
int
desired_video_buffers
=
256
;
enum
io_method
{
...
...
@@ -113,36 +125,49 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
{
struct
v4l2_capability
cap
;
int
fd
;
#if CONFIG_LIBV4L2
int
fd_libv4l
;
#endif
int
res
,
err
;
int
flags
=
O_RDWR
;
if
(
ctx
->
flags
&
AVFMT_FLAG_NONBLOCK
)
{
flags
|=
O_NONBLOCK
;
}
fd
=
open
(
ctx
->
filename
,
flags
,
0
);
fd
=
v4l2_
open
(
ctx
->
filename
,
flags
,
0
);
if
(
fd
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Cannot open video device %s : %s
\n
"
,
ctx
->
filename
,
strerror
(
errno
));
return
AVERROR
(
errno
);
}
#if CONFIG_LIBV4L2
fd_libv4l
=
v4l2_fd_open
(
fd
,
0
);
if
(
fd
<
0
)
{
err
=
AVERROR
(
errno
);
av_log
(
ctx
,
AV_LOG_ERROR
,
"Cannot open video device with libv4l neither %s : %s
\n
"
,
ctx
->
filename
,
strerror
(
errno
));
return
err
;
}
fd
=
fd_libv4l
;
#endif
res
=
ioctl
(
fd
,
VIDIOC_QUERYCAP
,
&
cap
);
res
=
v4l2_
ioctl
(
fd
,
VIDIOC_QUERYCAP
,
&
cap
);
// ENOIOCTLCMD definition only availble on __KERNEL__
if
(
res
<
0
&&
((
err
=
errno
)
==
515
))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"QUERYCAP not implemented, probably V4L device but not supporting V4L2
\n
"
);
close
(
fd
);
v4l2_
close
(
fd
);
return
AVERROR
(
515
);
}
if
(
res
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_QUERYCAP): %s
\n
"
,
strerror
(
errno
));
close
(
fd
);
v4l2_
close
(
fd
);
return
AVERROR
(
err
);
}
if
((
cap
.
capabilities
&
V4L2_CAP_VIDEO_CAPTURE
)
==
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Not a video capture device
\n
"
);
close
(
fd
);
v4l2_
close
(
fd
);
return
AVERROR
(
ENODEV
);
}
*
capabilities
=
cap
.
capabilities
;
...
...
@@ -162,7 +187,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t p
fmt
.
fmt
.
pix
.
height
=
*
height
;
fmt
.
fmt
.
pix
.
pixelformat
=
pix_fmt
;
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_INTERLACED
;
res
=
ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
);
res
=
v4l2_
ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
);
if
((
*
width
!=
fmt
.
fmt
.
pix
.
width
)
||
(
*
height
!=
fmt
.
fmt
.
pix
.
height
))
{
av_log
(
ctx
,
AV_LOG_INFO
,
"The V4L2 driver changed the video from %dx%d to %dx%d
\n
"
,
*
width
,
*
height
,
fmt
.
fmt
.
pix
.
width
,
fmt
.
fmt
.
pix
.
height
);
*
width
=
fmt
.
fmt
.
pix
.
width
;
...
...
@@ -182,7 +207,7 @@ static int first_field(int fd)
int
res
;
v4l2_std_id
std
;
res
=
ioctl
(
fd
,
VIDIOC_G_STD
,
&
std
);
res
=
v4l2_
ioctl
(
fd
,
VIDIOC_G_STD
,
&
std
);
if
(
res
<
0
)
{
return
0
;
}
...
...
@@ -245,7 +270,7 @@ static int mmap_init(AVFormatContext *ctx)
req
.
count
=
desired_video_buffers
;
req
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
req
.
memory
=
V4L2_MEMORY_MMAP
;
res
=
ioctl
(
s
->
fd
,
VIDIOC_REQBUFS
,
&
req
);
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_REQBUFS
,
&
req
);
if
(
res
<
0
)
{
if
(
errno
==
EINVAL
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Device does not support mmap
\n
"
);
...
...
@@ -278,7 +303,7 @@ static int mmap_init(AVFormatContext *ctx)
buf
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
buf
.
memory
=
V4L2_MEMORY_MMAP
;
buf
.
index
=
i
;
res
=
ioctl
(
s
->
fd
,
VIDIOC_QUERYBUF
,
&
buf
);
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_QUERYBUF
,
&
buf
);
if
(
res
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_QUERYBUF)
\n
"
);
return
AVERROR
(
errno
);
...
...
@@ -290,7 +315,7 @@ static int mmap_init(AVFormatContext *ctx)
return
-
1
;
}
s
->
buf_start
[
i
]
=
mmap
(
NULL
,
buf
.
length
,
s
->
buf_start
[
i
]
=
v4l2_mmap
(
NULL
,
buf
.
length
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
s
->
fd
,
buf
.
m
.
offset
);
if
(
s
->
buf_start
[
i
]
==
MAP_FAILED
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"mmap: %s
\n
"
,
strerror
(
errno
));
...
...
@@ -322,7 +347,7 @@ static void mmap_release_buffer(AVPacket *pkt)
fd
=
buf_descriptor
->
fd
;
av_free
(
buf_descriptor
);
res
=
ioctl
(
fd
,
VIDIOC_QBUF
,
&
buf
);
res
=
v4l2_
ioctl
(
fd
,
VIDIOC_QBUF
,
&
buf
);
if
(
res
<
0
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_QBUF): %s
\n
"
,
strerror
(
errno
));
}
...
...
@@ -341,7 +366,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
buf
.
memory
=
V4L2_MEMORY_MMAP
;
/* FIXME: Some special treatment might be needed in case of loss of signal... */
while
((
res
=
ioctl
(
s
->
fd
,
VIDIOC_DQBUF
,
&
buf
))
<
0
&&
(
errno
==
EINTR
));
while
((
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_DQBUF
,
&
buf
))
<
0
&&
(
errno
==
EINTR
));
if
(
res
<
0
)
{
if
(
errno
==
EAGAIN
)
{
pkt
->
size
=
0
;
...
...
@@ -368,7 +393,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
* allocate a buffer for memcopying into it
*/
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to allocate a buffer descriptor
\n
"
);
res
=
ioctl
(
s
->
fd
,
VIDIOC_QBUF
,
&
buf
);
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_QBUF
,
&
buf
);
return
AVERROR
(
ENOMEM
);
}
...
...
@@ -397,7 +422,7 @@ static int mmap_start(AVFormatContext *ctx)
buf
.
memory
=
V4L2_MEMORY_MMAP
;
buf
.
index
=
i
;
res
=
ioctl
(
s
->
fd
,
VIDIOC_QBUF
,
&
buf
);
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_QBUF
,
&
buf
);
if
(
res
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_QBUF): %s
\n
"
,
strerror
(
errno
));
return
AVERROR
(
errno
);
...
...
@@ -405,7 +430,7 @@ static int mmap_start(AVFormatContext *ctx)
}
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
res
=
ioctl
(
s
->
fd
,
VIDIOC_STREAMON
,
&
type
);
res
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_STREAMON
,
&
type
);
if
(
res
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_STREAMON): %s
\n
"
,
strerror
(
errno
));
return
AVERROR
(
errno
);
...
...
@@ -423,9 +448,9 @@ static void mmap_close(struct video_data *s)
/* We do not check for the result, because we could
* not do anything about it anyway...
*/
ioctl
(
s
->
fd
,
VIDIOC_STREAMOFF
,
&
type
);
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_STREAMOFF
,
&
type
);
for
(
i
=
0
;
i
<
s
->
buffers
;
i
++
)
{
munmap
(
s
->
buf_start
[
i
],
s
->
buf_len
[
i
]);
v4l2_
munmap
(
s
->
buf_start
[
i
],
s
->
buf_len
[
i
]);
}
av_free
(
s
->
buf_start
);
av_free
(
s
->
buf_len
);
...
...
@@ -450,14 +475,14 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
/* set tv video input */
input
.
index
=
s
->
channel
;
if
(
ioctl
(
s
->
fd
,
VIDIOC_ENUMINPUT
,
&
input
)
<
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_ENUMINPUT
,
&
input
)
<
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"The V4L2 driver ioctl enum input failed:
\n
"
);
return
AVERROR
(
EIO
);
}
av_log
(
s1
,
AV_LOG_DEBUG
,
"The V4L2 driver set input_id: %d, input: %s
\n
"
,
s
->
channel
,
input
.
name
);
if
(
ioctl
(
s
->
fd
,
VIDIOC_S_INPUT
,
&
input
.
index
)
<
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_S_INPUT
,
&
input
.
index
)
<
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"The V4L2 driver ioctl set input(%d) failed
\n
"
,
s
->
channel
);
return
AVERROR
(
EIO
);
...
...
@@ -469,7 +494,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
/* set tv standard */
for
(
i
=
0
;;
i
++
)
{
standard
.
index
=
i
;
ret
=
ioctl
(
s
->
fd
,
VIDIOC_ENUMSTD
,
&
standard
);
ret
=
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_ENUMSTD
,
&
standard
);
if
(
ret
<
0
||
!
av_strcasecmp
(
standard
.
name
,
s
->
standard
))
break
;
}
...
...
@@ -480,7 +505,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
av_log
(
s1
,
AV_LOG_DEBUG
,
"The V4L2 driver set standard: %s, id: %"
PRIu64
"
\n
"
,
s
->
standard
,
(
uint64_t
)
standard
.
id
);
if
(
ioctl
(
s
->
fd
,
VIDIOC_S_STD
,
&
standard
.
id
)
<
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_S_STD
,
&
standard
.
id
)
<
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"The V4L2 driver ioctl set standard(%s) failed
\n
"
,
s
->
standard
);
return
AVERROR
(
EIO
);
...
...
@@ -492,7 +517,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
framerate_q
.
den
,
framerate_q
.
num
);
tpf
->
numerator
=
framerate_q
.
den
;
tpf
->
denominator
=
framerate_q
.
num
;
if
(
ioctl
(
s
->
fd
,
VIDIOC_S_PARM
,
&
streamparm
)
!=
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_S_PARM
,
&
streamparm
)
!=
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"ioctl set time per frame(%d/%d) failed
\n
"
,
framerate_q
.
den
,
framerate_q
.
num
);
...
...
@@ -508,7 +533,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
}
}
else
{
/* if timebase value is not set, read the timebase value from the driver */
if
(
ioctl
(
s
->
fd
,
VIDIOC_G_PARM
,
&
streamparm
)
!=
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_G_PARM
,
&
streamparm
)
!=
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_G_PARM): %s
\n
"
,
strerror
(
errno
));
return
AVERROR
(
errno
);
}
...
...
@@ -590,7 +615,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
av_log
(
s1
,
AV_LOG_VERBOSE
,
"Querying the device for the current frame size
\n
"
);
fmt
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
if
(
ioctl
(
s
->
fd
,
VIDIOC_G_FMT
,
&
fmt
)
<
0
)
{
if
(
v4l2_
ioctl
(
s
->
fd
,
VIDIOC_G_FMT
,
&
fmt
)
<
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"ioctl(VIDIOC_G_FMT): %s
\n
"
,
strerror
(
errno
));
res
=
AVERROR
(
errno
);
goto
out
;
...
...
@@ -604,7 +629,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
if
(
desired_format
==
0
)
{
av_log
(
s1
,
AV_LOG_ERROR
,
"Cannot find a proper format for "
"codec_id %d, pix_fmt %d.
\n
"
,
s1
->
video_codec_id
,
pix_fmt
);
close
(
s
->
fd
);
v4l2_
close
(
s
->
fd
);
res
=
AVERROR
(
EIO
);
goto
out
;
...
...
@@ -629,7 +654,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
res
=
read_init
(
s1
);
}
if
(
res
<
0
)
{
close
(
s
->
fd
);
v4l2_
close
(
s
->
fd
);
res
=
AVERROR
(
EIO
);
goto
out
;
}
...
...
@@ -681,7 +706,7 @@ static int v4l2_read_close(AVFormatContext *s1)
mmap_close
(
s
);
}
close
(
s
->
fd
);
v4l2_
close
(
s
->
fd
);
return
0
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录