Merge commit '3a165c187da7d74f46f6c1778294e8c5a3a7151f'
authorClément Bœsch <u@pkh.me>
Wed, 22 Mar 2017 16:55:18 +0000 (17:55 +0100)
committerClément Bœsch <u@pkh.me>
Wed, 22 Mar 2017 16:55:18 +0000 (17:55 +0100)
* commit '3a165c187da7d74f46f6c1778294e8c5a3a7151f':
  v4l2: convert to stdatomic

Merged-by: Clément Bœsch <u@pkh.me>
1  2 
libavdevice/v4l2-common.h
libavdevice/v4l2.c

index 40c7164,0000000..0cbaec8
mode 100644,000000..100644
--- /dev/null
@@@ -1,62 -1,0 +1,61 @@@
- #include "libavutil/atomic.h"
 +/*
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg 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.
 + *
 + * FFmpeg 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#ifndef AVDEVICE_V4L2_COMMON_H
 +#define AVDEVICE_V4L2_COMMON_H
 +
 +#undef __STRICT_ANSI__ //workaround due to broken kernel headers
 +#include "config.h"
 +#include "libavformat/internal.h"
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/mman.h>
 +#include <sys/time.h>
 +#if HAVE_SYS_VIDEOIO_H
 +#include <sys/videoio.h>
 +#else
 +#if HAVE_ASM_TYPES_H
 +#include <asm/types.h>
 +#endif
 +#include <linux/videodev2.h>
 +#endif
 +#include "libavutil/avassert.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avdevice.h"
 +#include "timefilter.h"
 +#include "libavutil/parseutils.h"
 +#include "libavutil/pixdesc.h"
 +#include "libavutil/time.h"
 +#include "libavutil/avstring.h"
 +
 +struct fmt_map {
 +    enum AVPixelFormat ff_fmt;
 +    enum AVCodecID codec_id;
 +    uint32_t v4l2_fmt;
 +};
 +
 +extern const struct fmt_map ff_fmt_conversion_table[];
 +
 +uint32_t ff_fmt_ff2v4l(enum AVPixelFormat pix_fmt, enum AVCodecID codec_id);
 +enum AVPixelFormat ff_fmt_v4l2ff(uint32_t v4l2_fmt, enum AVCodecID codec_id);
 +enum AVCodecID ff_fmt_v4l2codec(uint32_t v4l2_fmt);
 +
 +#endif /* AVDEVICE_V4L2_COMMON_H */
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 -#undef __STRICT_ANSI__ //workaround due to broken kernel headers
 -#include "config.h"
 -#include "libavformat/avformat.h"
 -#include "libavformat/internal.h"
 -#include <unistd.h>
 -#include <fcntl.h>
 +/**
 + * @file
 + * Video4Linux2 grab interface
 + *
 + * Part of this file is based on the V4L2 video capture example
 + * (http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html)
 + *
 + * Thanks to Michael Niedermayer for providing the mapping between
 + * V4L2_PIX_FMT_* and AV_PIX_FMT_*
 + */
 +
+ #include <stdatomic.h>
 -#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
 -#include <linux/videodev2.h>
++
 +#include "v4l2-common.h"
 +#include <dirent.h>
 +
 +#if CONFIG_LIBV4L2
 +#include <libv4l2.h>
  #endif
 -#include "libavutil/avassert.h"
 -#include "libavutil/imgutils.h"
 -#include "libavutil/internal.h"
 -#include "libavutil/log.h"
 -#include "libavutil/opt.h"
 -#include "libavutil/parseutils.h"
 -#include "libavutil/pixdesc.h"
 -#include "libavutil/avstring.h"
 -#include "libavutil/mathematics.h"
  
  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 timeout;
      int interlaced;
      int top_field_first;
 +    int ts_mode;
 +    TimeFilter *timefilter;
 +    int64_t last_time_m;
  
      int buffers;
-     volatile int buffers_queued;
+     atomic_int buffers_queued;
      void **buf_start;
      unsigned int *buf_len;
      char *standard;
@@@ -394,20 -421,6 +396,20 @@@ static int mmap_init(AVFormatContext *c
      return 0;
  }
  
-         avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
 +static int enqueue_buffer(struct video_data *s, struct v4l2_buffer *buf)
 +{
 +    int res = 0;
 +
 +    if (v4l2_ioctl(s->fd, VIDIOC_QBUF, buf) < 0) {
 +        res = AVERROR(errno);
 +        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
 +    } else {
++        atomic_fetch_add(&s->buffers_queued, 1);
 +    }
 +
 +    return res;
 +}
 +
  static void mmap_release_buffer(void *opaque, uint8_t *data)
  {
      struct v4l2_buffer buf = { 0 };
@@@ -510,31 -482,16 +512,31 @@@ static int mmap_read_frame(AVFormatCont
          av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n");
          return AVERROR(EINVAL);
      }
-     avpriv_atomic_int_add_and_fetch(&s->buffers_queued, -1);
+     atomic_fetch_add(&s->buffers_queued, -1);
      // always keep at least one buffer queued
-     av_assert0(avpriv_atomic_int_get(&s->buffers_queued) >= 1);
+     av_assert0(atomic_load(&s->buffers_queued) >= 1);
  
 -    if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
 -        av_log(ctx, AV_LOG_ERROR,
 -               "The v4l2 frame is %d bytes, but %d bytes are expected\n",
 -               buf.bytesused, s->frame_size);
 +#ifdef V4L2_BUF_FLAG_ERROR
 +    if (buf.flags & V4L2_BUF_FLAG_ERROR) {
 +        av_log(ctx, AV_LOG_WARNING,
 +               "Dequeued v4l2 buffer contains corrupted data (%d bytes).\n",
 +               buf.bytesused);
 +        buf.bytesused = 0;
 +    } else
 +#endif
 +    {
 +        /* CPIA is a compressed format and we don't know the exact number of bytes
 +         * used by a frame, so set it here as the driver announces it. */
 +        if (ctx->video_codec_id == AV_CODEC_ID_CPIA)
 +            s->frame_size = buf.bytesused;
  
 -        return AVERROR_INVALIDDATA;
 +        if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Dequeued v4l2 buffer contains %d bytes, but %d were expected. Flags: 0x%08X.\n",
 +                   buf.bytesused, s->frame_size, buf.flags);
 +            enqueue_buffer(s, &buf);
 +            return AVERROR_INVALIDDATA;
 +        }
      }
  
      /* Image is at s->buff_start[buf.index] */
@@@ -600,21 -558,27 +602,21 @@@ static int mmap_start(AVFormatContext *
              .memory = V4L2_MEMORY_MMAP
          };
  
 -        res = ioctl(s->fd, VIDIOC_QBUF, &buf);
 -        if (res < 0) {
 -            err = AVERROR(errno);
 -            av_strerror(err, errbuf, sizeof(errbuf));
 +        if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
 +            res = AVERROR(errno);
              av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
 -                   errbuf);
 -
 -            return err;
 +                   av_err2str(res));
 +            return res;
          }
      }
-     s->buffers_queued = s->buffers;
+     atomic_store(&s->buffers_queued, s->buffers);
  
      type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 -    res = ioctl(s->fd, VIDIOC_STREAMON, &type);
 -    if (res < 0) {
 -        err = AVERROR(errno);
 -        av_strerror(err, errbuf, sizeof(errbuf));
 +    if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) {
 +        res = AVERROR(errno);
          av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
 -               errbuf);
 -
 -        return err;
 +               av_err2str(res));
 +        return res;
      }
  
      return 0;
@@@ -996,12 -877,12 +998,12 @@@ FF_ENABLE_DEPRECATION_WARNING
      return pkt->size;
  }
  
 -static int v4l2_read_close(AVFormatContext *s1)
 +static int v4l2_read_close(AVFormatContext *ctx)
  {
 -    struct video_data *s = s1->priv_data;
 +    struct video_data *s = ctx->priv_data;
  
-     if (avpriv_atomic_int_get(&s->buffers_queued) != s->buffers)
+     if (atomic_load(&s->buffers_queued) != s->buffers)
 -        av_log(s1, AV_LOG_WARNING, "Some buffers are still owned by the caller on "
 +        av_log(ctx, AV_LOG_WARNING, "Some buffers are still owned by the caller on "
                 "close.\n");
  
      mmap_close(s);