summaryrefslogtreecommitdiff
path: root/libavdevice
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-01-11 02:23:55 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-01-11 02:44:43 +0100
commit0e7fc3cafe838b32c3af73954acf9de2f9240ffd (patch)
treef0c534b98818c2712dbeed7f08b4ba831e0de23d /libavdevice
parenta9bd29e15e8d4ab4afaba7c31ebc0063c1df2db9 (diff)
parent9472d37d8e137df1e78e973b8b0e0d5607a799d5 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (22 commits) rv34: frame-level multi-threading mpegvideo: claim ownership of referenced pictures aacsbr: prevent out of bounds memcpy(). ipmovie: fix pts for CODEC_ID_INTERPLAY_DPCM sierravmd: fix audio pts bethsoftvideo: Use bytestream2 functions to prevent buffer overreads. bmpenc: support for PIX_FMT_RGB444 swscale: fix crash in fast_bilinear code when compiled with -mred-zone. swscale: specify register type. rv34: use get_bits_left() avconv: reinitialize the filtergraph on resolution change. vsrc_buffer: error on changing frame parameters. avconv: fix -copyinkf. fate: Update file checksums after the mov muxer change in a78dbada55d6 movenc: Don't store a nonzero creation time if nothing was set by the caller bmpdec: support for rgb444 with bitfields compression rgb2rgb: allow conversion for <15 bpp doc: fix stray reference to FFmpeg v4l2: use C99 struct initializer v4l2: poll the file descriptor ... Conflicts: avconv.c libavcodec/aacsbr.c libavcodec/bethsoftvideo.c libavcodec/kmvc.c libavdevice/v4l2.c libavfilter/vsrc_buffer.c libswscale/swscale_unscaled.c libswscale/x86/input.asm tests/ref/acodec/alac tests/ref/acodec/pcm_s16be tests/ref/acodec/pcm_s24be tests/ref/acodec/pcm_s32be tests/ref/acodec/pcm_s8 tests/ref/lavf/mov tests/ref/vsynth1/dnxhd_1080i tests/ref/vsynth1/mpeg4 tests/ref/vsynth1/qtrle tests/ref/vsynth1/svq1 tests/ref/vsynth2/dnxhd_1080i tests/ref/vsynth2/mpeg4 tests/ref/vsynth2/qtrle tests/ref/vsynth2/svq1 Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavdevice')
-rw-r--r--libavdevice/v4l2.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 0b00abbf10..29ec6afc49 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -38,6 +38,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
+#include <poll.h>
#if HAVE_SYS_VIDEOIO_H
#include <sys/videoio.h>
#else
@@ -54,6 +55,7 @@
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/avstring.h"
+#include "libavutil/mathematics.h"
#if CONFIG_LIBV4L2
#include <libv4l2.h>
@@ -79,6 +81,7 @@ struct video_data {
int frame_format; /* V4L2_PIX_FMT_* */
int width, height;
int frame_size;
+ int timeout;
int interlaced;
int top_field_first;
@@ -197,14 +200,11 @@ static int device_init(AVFormatContext *ctx, int *width, int *height,
{
struct video_data *s = ctx->priv_data;
int fd = s->fd;
- struct v4l2_format fmt;
+ struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
struct v4l2_pix_format *pix = &fmt.fmt.pix;
int res;
- memset(&fmt, 0, sizeof(struct v4l2_format));
-
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pix->width = *width;
pix->height = *height;
pix->pixelformat = pix_fmt;
@@ -362,13 +362,14 @@ static void list_formats(AVFormatContext *ctx, int fd, int type)
static int mmap_init(AVFormatContext *ctx)
{
- struct video_data *s = ctx->priv_data;
- struct v4l2_requestbuffers req = {0};
int i, res;
+ struct video_data *s = ctx->priv_data;
+ struct v4l2_requestbuffers req = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .count = desired_video_buffers,
+ .memory = V4L2_MEMORY_MMAP
+ };
- req.count = desired_video_buffers;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
res = v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req);
if (res < 0) {
if (errno == EINVAL) {
@@ -397,11 +398,11 @@ static int mmap_init(AVFormatContext *ctx)
}
for (i = 0; i < req.count; i++) {
- struct v4l2_buffer buf = {0};
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
+ struct v4l2_buffer buf = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .index = i,
+ .memory = V4L2_MEMORY_MMAP
+ };
res = v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
if (res < 0) {
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
@@ -431,7 +432,7 @@ static int mmap_init(AVFormatContext *ctx)
static void mmap_release_buffer(AVPacket *pkt)
{
- struct v4l2_buffer buf = {0};
+ struct v4l2_buffer buf = { 0 };
int res, fd;
struct buff_data *buf_descriptor = pkt->priv;
@@ -456,12 +457,20 @@ static void mmap_release_buffer(AVPacket *pkt)
static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
{
struct video_data *s = ctx->priv_data;
- struct v4l2_buffer buf = {0};
+ struct v4l2_buffer buf = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .memory = V4L2_MEMORY_MMAP
+ };
struct buff_data *buf_descriptor;
+ struct pollfd p = { .fd = s->fd, .events = POLLIN };
int res;
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
+ res = poll(&p, 1, s->timeout);
+ if (res < 0)
+ return AVERROR(errno);
+
+ if (!(p.revents & (POLLIN | POLLERR | POLLHUP)))
+ return AVERROR(EAGAIN);
/* FIXME: Some special treatment might be needed in case of loss of signal... */
while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
@@ -513,11 +522,11 @@ static int mmap_start(AVFormatContext *ctx)
int i, res;
for (i = 0; i < s->buffers; i++) {
- struct v4l2_buffer buf = {0};
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
+ struct v4l2_buffer buf = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .index = i,
+ .memory = V4L2_MEMORY_MMAP
+ };
res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
if (res < 0) {
@@ -560,12 +569,12 @@ static void mmap_close(struct video_data *s)
static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
{
struct video_data *s = s1->priv_data;
- struct v4l2_input input = {0};
- struct v4l2_standard standard = {0};
- struct v4l2_streamparm streamparm = {0};
+ struct v4l2_input input = { 0 };
+ struct v4l2_standard standard = { 0 };
+ struct v4l2_streamparm streamparm = { 0 };
struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
+ AVRational framerate_q = { 0 };
int i, ret;
- AVRational framerate_q={0};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -596,7 +605,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
s->standard);
/* set tv standard */
- for (i = 0;; i++) {
+ for(i=0;;i++) {
standard.index = i;
ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
@@ -649,6 +658,10 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
s1->streams[0]->codec->time_base.den = tpf->denominator;
s1->streams[0]->codec->time_base.num = tpf->numerator;
+ s->timeout = 100 +
+ av_rescale_q(1, s1->streams[0]->codec->time_base,
+ (AVRational){1, 1000});
+
return 0;
}
@@ -722,11 +735,15 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
}
if (s->pixel_format) {
+ AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);
+
+ if (codec)
+ s1->video_codec_id = codec->id;
pix_fmt = av_get_pix_fmt(s->pixel_format);
- if (pix_fmt == PIX_FMT_NONE) {
- av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n",
+ if (pix_fmt == PIX_FMT_NONE && !codec) {
+ av_log(s1, AV_LOG_ERROR, "No such input format: %s.\n",
s->pixel_format);
res = AVERROR(EINVAL);
@@ -832,7 +849,8 @@ static const AVOption options[] = {
{ "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC },
{ "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC },
{ "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
- { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "pixel_format", "Preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "input_format", "Preferred pixel format (for raw video) or codec name", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" },
{ "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" },