[FFmpeg-devel] [PATCH] lavd/v4l2: implement consistent error handling

Stefano Sabatini stefasab at gmail.com
Sun Feb 10 12:18:03 CET 2013


In particular, avoid use of non-thread-safe strerror(), and store errno
before calling av_log().
---
 libavdevice/v4l2.c |  154 +++++++++++++++++++++++-----------------------------
 1 file changed, 68 insertions(+), 86 deletions(-)

diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 2e4b395..5b355de 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -164,7 +164,7 @@ static int device_open(AVFormatContext *ctx)
 {
     struct v4l2_capability cap;
     int fd;
-    int res, err;
+    int ret;
     int flags = O_RDWR;
 
     if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
@@ -173,20 +173,16 @@ static int device_open(AVFormatContext *ctx)
 
     fd = v4l2_open(ctx->filename, flags, 0);
     if (fd < 0) {
-        err = errno;
-
+        ret = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s: %s\n",
-               ctx->filename, strerror(err));
-
-        return AVERROR(err);
+               ctx->filename, av_err2str(ret));
+        return ret;
     }
 
-    res = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap);
-    if (res < 0) {
-        err = errno;
+    if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
+        ret = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
-               strerror(err));
-
+               av_err2str(ret));
         goto fail;
     }
 
@@ -195,16 +191,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");
-        err = ENODEV;
-
+        ret = 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");
-        err = ENOSYS;
-
+        ret = AVERROR(ENOSYS);
         goto fail;
     }
 
@@ -212,7 +206,7 @@ static int device_open(AVFormatContext *ctx)
 
 fail:
     v4l2_close(fd);
-    return AVERROR(err);
+    return ret;
 }
 
 static int device_init(AVFormatContext *ctx, int *width, int *height,
@@ -392,12 +386,12 @@ static void list_standards(AVFormatContext *ctx)
         return;
 
     for (standard.index = 0; ; standard.index++) {
-        ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
-        if (ret < 0) {
-            if (errno == EINVAL)
+        if (v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
+            ret = errno;
+            if (ret == EINVAL) {
                 break;
-            else {
-                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMSTD): %s\n", strerror(errno));
+            } else {
+                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMSTD): %s\n", av_err2str(ret));
                 return;
             }
         }
@@ -416,14 +410,10 @@ static int mmap_init(AVFormatContext *ctx)
         .memory = V4L2_MEMORY_MMAP
     };
 
-    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");
-        } else {
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
-        }
-        return AVERROR(errno);
+    if (v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req) < 0) {
+        res = AVERROR(errno);
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS): %s\n", av_err2str(res));
+        return res;
     }
 
     if (req.count < 2) {
@@ -449,27 +439,27 @@ static int mmap_init(AVFormatContext *ctx)
             .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");
-            return AVERROR(errno);
+        if (v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf) < 0) {
+            res = AVERROR(errno);
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF): %s\n", av_err2str(res));
+            return res;
         }
 
         s->buf_len[i] = buf.length;
         if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
             av_log(ctx, AV_LOG_ERROR,
-                   "Buffer len [%d] = %d != %d\n",
+                   "buf_len[%d] = %d < expected frame size %d\n",
                    i, s->buf_len[i], s->frame_size);
-
-            return -1;
+            return AVERROR(ENOMEM);
         }
         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));
-            return AVERROR(errno);
+            res = AVERROR(errno);
+            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", av_err2str(res));
+            return res;
         }
     }
 
@@ -491,10 +481,10 @@ static void mmap_release_buffer(AVPacket *pkt)
     fd = buf_descriptor->fd;
     av_free(buf_descriptor);
 
-    res = v4l2_ioctl(fd, VIDIOC_QBUF, &buf);
-    if (res < 0)
-        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
-               strerror(errno));
+    if (v4l2_ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
+        res = AVERROR(errno);
+        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
+    }
 
     pkt->data = NULL;
     pkt->size = 0;
@@ -577,10 +567,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
             pkt->size = 0;
             return AVERROR(EAGAIN);
         }
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",
-               strerror(errno));
-
-        return AVERROR(errno);
+        res = AVERROR(errno);
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res));
+        return res;
     }
 
     if (buf.index >= s->buffers) {
@@ -598,7 +587,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
         av_log(ctx, AV_LOG_ERROR,
                "The v4l2 frame is %d bytes, but %d bytes are expected\n",
                buf.bytesused, s->frame_size);
-
         return AVERROR_INVALIDDATA;
     }
 
@@ -617,7 +605,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
          */
         av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
         res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
-
         return AVERROR(ENOMEM);
     }
     buf_descriptor->fd = s->fd;
@@ -640,22 +627,18 @@ static int mmap_start(AVFormatContext *ctx)
             .memory = V4L2_MEMORY_MMAP
         };
 
-        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);
+        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));
+            return res;
         }
     }
 
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    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);
+    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));
+        return res;
     }
 
     return 0;
@@ -700,20 +683,20 @@ static int v4l2_set_parameters(AVFormatContext *s1)
             /* set tv standard */
             for (i = 0; ; i++) {
                 standard.index = i;
-                ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
+                if (v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0)
+                    ret = AVERROR(errno);
                 if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
                     break;
             }
             if (ret < 0) {
-                ret = errno;
                 av_log(s1, AV_LOG_ERROR, "Unknown or unsupported standard '%s'\n", s->standard);
-                return AVERROR(ret);
+                return ret;
             }
 
             if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
-                ret = errno;
-                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_STD): %s\n", strerror(errno));
-                return AVERROR(ret);
+                ret = AVERROR(errno);
+                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_STD): %s\n", av_err2str(ret));
+                return ret;
             }
         } else {
             av_log(s1, AV_LOG_WARNING,
@@ -726,11 +709,10 @@ static int v4l2_set_parameters(AVFormatContext *s1)
         tpf = &standard.frameperiod;
         for (i = 0; ; i++) {
             standard.index = i;
-            ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
-            if (ret < 0) {
-                ret = errno;
-                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMSTD): %s\n", strerror(errno));
-                return AVERROR(ret);
+            if (v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
+                ret = AVERROR(errno);
+                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMSTD): %s\n", av_err2str(ret));
+                return ret;
             }
             if (standard.id == s->std_id) {
                 av_log(s1, AV_LOG_DEBUG,
@@ -745,9 +727,9 @@ static int v4l2_set_parameters(AVFormatContext *s1)
 
     streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) < 0) {
-        ret = errno;
-        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno));
-        return AVERROR(ret);
+        ret = AVERROR(errno);
+        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
+        return ret;
     }
 
     if (framerate_q.num && framerate_q.den) {
@@ -760,9 +742,9 @@ static int v4l2_set_parameters(AVFormatContext *s1)
             tpf->denominator = framerate_q.num;
 
             if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) < 0) {
-                ret = errno;
-                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n", strerror(errno));
-                return AVERROR(ret);
+                ret = AVERROR(errno);
+                av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n", av_err2str(ret));
+                return ret;
             }
 
             if (framerate_q.num != tpf->denominator ||
@@ -857,16 +839,16 @@ static int v4l2_read_header(AVFormatContext *s1)
     /* set tv video input */
     av_log(s1, AV_LOG_DEBUG, "Selecting input_channel: %d\n", s->channel);
     if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &s->channel) < 0) {
-        res = errno;
-        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_INPUT): %s\n", strerror(errno));
-        return AVERROR(res);
+        res = AVERROR(errno);
+        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_INPUT): %s\n", av_err2str(res));
+        return res;
     }
 
     input.index = s->channel;
     if (v4l2_ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
-        res = errno;
-        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMINPUT): %s\n", strerror(errno));
-        return AVERROR(res);
+        res = AVERROR(errno);
+        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMINPUT): %s\n", av_err2str(res));
+        return res;
     }
     s->std_id = input.std;
     av_log(s1, AV_LOG_DEBUG, "input_channel: %d, input_name: %s\n",
@@ -907,9 +889,9 @@ static int v4l2_read_header(AVFormatContext *s1)
                "Querying the device for the current frame size\n");
         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
         if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
-            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n",
-                   strerror(errno));
-            return AVERROR(errno);
+            res = AVERROR(errno);
+            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", av_err2str(res));
+            return res;
         }
 
         s->width  = fmt.fmt.pix.width;
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list