ffmpeg | branch: master | Clément Bœsch <[email protected]> | Wed Mar 22 17:55:18 2017 +0100| [b7336faa39b8ea26d01817cb6a7bf26a795d0580] | committer: Clément Bœsch
Merge commit '3a165c187da7d74f46f6c1778294e8c5a3a7151f' * commit '3a165c187da7d74f46f6c1778294e8c5a3a7151f': v4l2: convert to stdatomic Merged-by: Clément Bœsch <[email protected]> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b7336faa39b8ea26d01817cb6a7bf26a795d0580 --- libavdevice/v4l2-common.h | 1 - libavdevice/v4l2.c | 16 +++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libavdevice/v4l2-common.h b/libavdevice/v4l2-common.h index 40c7164..0cbaec8 100644 --- a/libavdevice/v4l2-common.h +++ b/libavdevice/v4l2-common.h @@ -35,7 +35,6 @@ #endif #include <linux/videodev2.h> #endif -#include "libavutil/atomic.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/log.h" diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index dada8ce..1562975 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -30,6 +30,8 @@ * V4L2_PIX_FMT_* and AV_PIX_FMT_* */ +#include <stdatomic.h> + #include "v4l2-common.h" #include <dirent.h> @@ -78,7 +80,7 @@ struct video_data { int64_t last_time_m; int buffers; - volatile int buffers_queued; + atomic_int buffers_queued; void **buf_start; unsigned int *buf_len; char *standard; @@ -402,7 +404,7 @@ static int enqueue_buffer(struct video_data *s, struct v4l2_buffer *buf) res = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res)); } else { - avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); + atomic_fetch_add(&s->buffers_queued, 1); } return res; @@ -510,9 +512,9 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) 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); #ifdef V4L2_BUF_FLAG_ERROR if (buf.flags & V4L2_BUF_FLAG_ERROR) { @@ -538,7 +540,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) } /* Image is at s->buff_start[buf.index] */ - if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) { + if (atomic_load(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) { /* when we start getting low on queued buffers, fall back on copying data */ res = av_new_packet(pkt, buf.bytesused); if (res < 0) { @@ -607,7 +609,7 @@ static int mmap_start(AVFormatContext *ctx) return res; } } - s->buffers_queued = s->buffers; + atomic_store(&s->buffers_queued, s->buffers); type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) { @@ -1000,7 +1002,7 @@ static int v4l2_read_close(AVFormatContext *ctx) { 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(ctx, AV_LOG_WARNING, "Some buffers are still owned by the caller on " "close.\n"); ====================================================================== diff --cc libavdevice/v4l2-common.h index 40c7164,0000000..0cbaec8 mode 100644,000000..100644 --- a/libavdevice/v4l2-common.h +++ b/libavdevice/v4l2-common.h @@@ -1,62 -1,0 +1,61 @@@ +/* + * 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/atomic.h" +#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 */ diff --cc libavdevice/v4l2.c index dada8ce,0479121..1562975 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@@ -19,23 -27,31 +19,25 @@@ * 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; @@@ -68,17 -62,15 +70,17 @@@ 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; } +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 { - avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1); ++ 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); _______________________________________________ ffmpeg-cvslog mailing list [email protected] http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog
