Imported Debian version 2.5.0~trusty1.1
[deb_ffmpeg.git] / ffmpeg / libavdevice / v4l2.c
index cf7a92cdd43a943d789ddd8d6cad84d3c59c4bd9..869564545287693cad3fc22313c31c923cdbbc87 100644 (file)
@@ -67,7 +67,7 @@ static const int desired_video_buffers = 256;
 struct video_data {
     AVClass *class;
     int fd;
-    int frame_format; /* V4L2_PIX_FMT_* */
+    int pixelformat; /* V4L2_PIX_FMT_* */
     int width, height;
     int frame_size;
     int interlaced;
@@ -108,7 +108,7 @@ static int device_open(AVFormatContext *ctx)
     struct video_data *s = ctx->priv_data;
     struct v4l2_capability cap;
     int fd;
-    int ret;
+    int err;
     int flags = O_RDWR;
 
 #define SET_WRAPPERS(prefix) do {       \
@@ -146,16 +146,16 @@ static int device_open(AVFormatContext *ctx)
 
     fd = v4l2_open(ctx->filename, flags, 0);
     if (fd < 0) {
-        ret = AVERROR(errno);
+        err = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s: %s\n",
-               ctx->filename, av_err2str(ret));
-        return ret;
+               ctx->filename, av_err2str(err));
+        return err;
     }
 
     if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
-        ret = AVERROR(errno);
+        err = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
-               av_err2str(ret));
+               av_err2str(err));
         goto fail;
     }
 
@@ -164,14 +164,14 @@ static int device_open(AVFormatContext *ctx)
 
     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
         av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n");
-        ret = AVERROR(ENODEV);
+        err = AVERROR(ENODEV);
         goto fail;
     }
 
     if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
         av_log(ctx, AV_LOG_ERROR,
                "The device does not support the streaming I/O method.\n");
-        ret = AVERROR(ENOSYS);
+        err = AVERROR(ENOSYS);
         goto fail;
     }
 
@@ -179,22 +179,23 @@ static int device_open(AVFormatContext *ctx)
 
 fail:
     v4l2_close(fd);
-    return ret;
+    return err;
 }
 
 static int device_init(AVFormatContext *ctx, int *width, int *height,
-                       uint32_t pix_fmt)
+                       uint32_t pixelformat)
 {
     struct video_data *s = ctx->priv_data;
     struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
-    struct v4l2_pix_format *pix = &fmt.fmt.pix;
     int res = 0;
 
-    pix->width = *width;
-    pix->height = *height;
-    pix->pixelformat = pix_fmt;
-    pix->field = V4L2_FIELD_ANY;
+    fmt.fmt.pix.width = *width;
+    fmt.fmt.pix.height = *height;
+    fmt.fmt.pix.pixelformat = pixelformat;
+    fmt.fmt.pix.field = V4L2_FIELD_ANY;
 
+    /* Some drivers will fail and return EINVAL when the pixelformat
+       is not supported (even if type field is valid and supported) */
     if (v4l2_ioctl(s->fd, VIDIOC_S_FMT, &fmt) < 0)
         res = AVERROR(errno);
 
@@ -206,11 +207,11 @@ static int device_init(AVFormatContext *ctx, int *width, int *height,
         *height = fmt.fmt.pix.height;
     }
 
-    if (pix_fmt != fmt.fmt.pix.pixelformat) {
+    if (pixelformat != fmt.fmt.pix.pixelformat) {
         av_log(ctx, AV_LOG_DEBUG,
                "The V4L2 driver changed the pixel format "
                "from 0x%08X to 0x%08X\n",
-               pix_fmt, fmt.fmt.pix.pixelformat);
+               pixelformat, fmt.fmt.pix.pixelformat);
         res = AVERROR(EINVAL);
     }
 
@@ -270,8 +271,8 @@ static void list_formats(AVFormatContext *ctx, int type)
     struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
 
     while(!v4l2_ioctl(s->fd, VIDIOC_ENUM_FMT, &vfd)) {
-        enum AVCodecID codec_id = avpriv_fmt_v4l2codec(vfd.pixelformat);
-        enum AVPixelFormat pix_fmt = avpriv_fmt_v4l2ff(vfd.pixelformat, codec_id);
+        enum AVCodecID codec_id = ff_fmt_v4l2codec(vfd.pixelformat);
+        enum AVPixelFormat pix_fmt = ff_fmt_v4l2ff(vfd.pixelformat, codec_id);
 
         vfd.index++;
 
@@ -505,7 +506,8 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
             return AVERROR(EAGAIN);
         }
         res = AVERROR(errno);
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res));
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",
+               av_err2str(res));
         return res;
     }
 
@@ -601,7 +603,8 @@ static int mmap_start(AVFormatContext *ctx)
 
         if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
             res = AVERROR(errno);
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
+                   av_err2str(res));
             return res;
         }
     }
@@ -610,7 +613,8 @@ static int mmap_start(AVFormatContext *ctx)
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) {
         res = AVERROR(errno);
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", av_err2str(res));
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
+               av_err2str(res));
         return res;
     }
 
@@ -727,7 +731,8 @@ static int v4l2_set_parameters(AVFormatContext *ctx)
 
             if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) < 0) {
                 ret = AVERROR(errno);
-                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n", av_err2str(ret));
+                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n",
+                       av_err2str(ret));
                 return ret;
             }
 
@@ -763,7 +768,7 @@ static int device_try_init(AVFormatContext *ctx,
 {
     int ret, i;
 
-    *desired_format = avpriv_fmt_ff2v4l(pix_fmt, ctx->video_codec_id);
+    *desired_format = ff_fmt_ff2v4l(pix_fmt, ctx->video_codec_id);
 
     if (*desired_format) {
         ret = device_init(ctx, width, height, *desired_format);
@@ -775,14 +780,14 @@ static int device_try_init(AVFormatContext *ctx,
     }
 
     if (!*desired_format) {
-        for (i = 0; avpriv_fmt_conversion_table[i].codec_id != AV_CODEC_ID_NONE; i++) {
+        for (i = 0; ff_fmt_conversion_table[i].codec_id != AV_CODEC_ID_NONE; i++) {
             if (ctx->video_codec_id == AV_CODEC_ID_NONE ||
-                avpriv_fmt_conversion_table[i].codec_id == ctx->video_codec_id) {
+                ff_fmt_conversion_table[i].codec_id == ctx->video_codec_id) {
                 av_log(ctx, AV_LOG_DEBUG, "Trying to set codec:%s pix_fmt:%s\n",
-                       avcodec_get_name(avpriv_fmt_conversion_table[i].codec_id),
-                       (char *)av_x_if_null(av_get_pix_fmt_name(avpriv_fmt_conversion_table[i].ff_fmt), "none"));
+                       avcodec_get_name(ff_fmt_conversion_table[i].codec_id),
+                       (char *)av_x_if_null(av_get_pix_fmt_name(ff_fmt_conversion_table[i].ff_fmt), "none"));
 
-                *desired_format = avpriv_fmt_conversion_table[i].v4l2_fmt;
+                *desired_format = ff_fmt_conversion_table[i].v4l2_fmt;
                 ret = device_init(ctx, width, height, *desired_format);
                 if (ret >= 0)
                     break;
@@ -801,11 +806,18 @@ static int device_try_init(AVFormatContext *ctx,
         }
     }
 
-    *codec_id = avpriv_fmt_v4l2codec(*desired_format);
+    *codec_id = ff_fmt_v4l2codec(*desired_format);
     av_assert0(*codec_id != AV_CODEC_ID_NONE);
     return ret;
 }
 
+static int v4l2_read_probe(AVProbeData *p)
+{
+    if (av_strstart(p->filename, "/dev/video", NULL))
+        return AVPROBE_SCORE_MAX - 1;
+    return 0;
+}
+
 static int v4l2_read_header(AVFormatContext *ctx)
 {
     struct video_data *s = ctx->priv_data;
@@ -873,9 +885,6 @@ static int v4l2_read_header(AVFormatContext *ctx)
 
     avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
 
-    if ((res = v4l2_set_parameters(ctx)) < 0)
-        goto fail;
-
     if (s->pixel_format) {
         AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);
 
@@ -900,7 +909,8 @@ static int v4l2_read_header(AVFormatContext *ctx)
                "Querying the device for the current frame size\n");
         if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
             res = AVERROR(errno);
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", av_err2str(res));
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n",
+                   av_err2str(res));
             goto fail;
         }
 
@@ -924,9 +934,12 @@ static int v4l2_read_header(AVFormatContext *ctx)
     if ((res = av_image_check_size(s->width, s->height, 0, ctx)) < 0)
         goto fail;
 
-    s->frame_format = desired_format;
+    s->pixelformat = desired_format;
+
+    if ((res = v4l2_set_parameters(ctx)) < 0)
+        goto fail;
 
-    st->codec->pix_fmt = avpriv_fmt_v4l2ff(desired_format, codec_id);
+    st->codec->pix_fmt = ff_fmt_v4l2ff(desired_format, codec_id);
     s->frame_size =
         avpicture_get_size(st->codec->pix_fmt, s->width, s->height);
 
@@ -1033,6 +1046,7 @@ AVInputFormat ff_v4l2_demuxer = {
     .name           = "video4linux2,v4l2",
     .long_name      = NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
     .priv_data_size = sizeof(struct video_data),
+    .read_probe     = v4l2_read_probe,
     .read_header    = v4l2_read_header,
     .read_packet    = v4l2_read_packet,
     .read_close     = v4l2_read_close,