This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/v4l-utils.git tree:
Subject: v4l2-compliance: add helper headers Author: Hans Verkuil <[email protected]> Date: Mon Mar 31 10:22:01 2014 +0200 In order to simplify working with single and multiple planar formats these two helper headers were created: v4l-helpers.h is the C version and cv4l-helpers.h is a C++ version on top of v4l-helpers.h. For now this will only be used in v4l2-compliance, but the intention is to use it elsewhere as well eventually. Signed-off-by: Hans Verkuil <[email protected]> utils/v4l2-compliance/cv4l-helpers.h | 241 ++++++++ utils/v4l2-compliance/v4l-helpers.h | 1033 ++++++++++++++++++++++++++++++++++ 2 files changed, 1274 insertions(+), 0 deletions(-) --- http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=149be10861ebcdcee6250c5df8f5cc1c27687b32 diff --git a/utils/v4l2-compliance/cv4l-helpers.h b/utils/v4l2-compliance/cv4l-helpers.h new file mode 100644 index 0000000..2423ef9 --- /dev/null +++ b/utils/v4l2-compliance/cv4l-helpers.h @@ -0,0 +1,241 @@ +#ifndef _CV4L_HELPERS_H_ +#define _CV4L_HELPERS_H_ + +#include <v4l-helpers.h> + +class cv4l_buffer; + +class cv4l_queue : v4l_queue { + friend cv4l_buffer; +public: + cv4l_queue(v4l_fd *_fd, unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + unsigned memory = V4L2_MEMORY_MMAP) + { + fd = _fd; + v4l_queue_init(this, type, memory); + } + virtual ~cv4l_queue() + { + if (fd->fd != -1) + v4l_queue_free(fd, this); + } + + void init(unsigned type, unsigned memory) + { + if (fd->fd != -1) + v4l_queue_free(fd, this); + v4l_queue_init(this, type, memory); + } + unsigned g_type() const { return v4l_queue_g_type(this); } + unsigned g_memory() const { return v4l_queue_g_memory(this); } + bool is_planar() const { return v4l_queue_is_planar(this); } + bool is_output() const { return v4l_queue_is_output(this); } + bool is_capture() const { return v4l_queue_is_capture(this); } + bool is_video() const { return v4l_queue_is_video(this); } + bool is_vbi() const { return v4l_queue_is_vbi(this); } + bool is_sliced_vbi() const { return v4l_queue_is_sliced_vbi(this); } + bool is_sdr() const { return v4l_queue_is_sdr(this); } + unsigned g_buffers() const { return v4l_queue_g_buffers(this); } + unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); } + unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); } + unsigned g_mem_offset(unsigned index, unsigned plane) const { return v4l_queue_g_mem_offset(this, index, plane); } + void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); } + void *g_mmapping(unsigned index, unsigned plane) const { return v4l_queue_g_mmapping(this, index, plane); } + void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); } + void *g_userptr(unsigned index, unsigned plane) const { return v4l_queue_g_userptr(this, index, plane); } + void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); } + int g_fd(unsigned index, unsigned plane) const { return v4l_queue_g_fd(this, index, plane); } + + int reqbufs(unsigned count = 0) + { + return v4l_queue_reqbufs(fd, this, count); + } + bool has_create_bufs() const + { + return v4l_queue_has_create_bufs(fd, this); + } + int create_bufs(unsigned count, const v4l2_format *fmt = NULL) + { + return v4l_queue_create_bufs(fd, this, count, fmt); + } + int streamon() + { + return v4l_queue_streamon(fd, this); + } + int streamoff() + { + return v4l_queue_streamoff(fd, this); + } + int mmap_bufs(unsigned from = 0) + { + return v4l_queue_mmap_bufs(fd, this, from); + } + int munmap_bufs() + { + return v4l_queue_munmap_bufs(fd, this); + } + int alloc_bufs(unsigned from = 0) + { + return v4l_queue_alloc_bufs(fd, this, from); + } + int free_bufs() + { + return v4l_queue_free_bufs(this); + } + bool has_expbuf() + { + return v4l_queue_has_expbuf(fd); + } + int export_bufs() + { + return v4l_queue_export_bufs(fd, this); + } + void close_exported_fds() + { + v4l_queue_close_exported_fds(this); + } + void buffer_init(struct v4l_buffer *buf, unsigned index) const + { + v4l_queue_buffer_init(this, buf, index); + } + +protected: + v4l_fd *fd; +}; + +class cv4l_buffer : public v4l_buffer { +public: + cv4l_buffer(unsigned type = 0, unsigned memory = 0, unsigned index = 0) + { + init(type, memory, index); + } + cv4l_buffer(const cv4l_queue &q, unsigned index = 0) + { + init(q, index); + } + cv4l_buffer(const cv4l_buffer &b) + { + init(b); + } + virtual ~cv4l_buffer() {} + void init(unsigned type = 0, unsigned memory = 0, unsigned index = 0) + { + v4l_buffer_init(this, type, memory, index); + } + void init(const cv4l_queue &q, unsigned index = 0) + { + q.buffer_init(this, index); + } + void init(const cv4l_buffer &b) + { + *this = b; + if (is_planar()) + buf.m.planes = planes; + } + __u32 g_index() const { return v4l_buffer_g_index(this); } + void s_index(unsigned index) { v4l_buffer_s_index(this, index); } + unsigned g_type() const { return v4l_buffer_g_type(this); } + unsigned g_memory() const { return v4l_buffer_g_memory(this); } + __u32 g_flags() const { return v4l_buffer_g_flags(this); } + void s_flags(__u32 flags) { v4l_buffer_s_flags(this, flags); } + void or_flags(__u32 flags) { v4l_buffer_or_flags(this, flags); } + unsigned g_field() const { return v4l_buffer_g_field(this); } + void s_field(unsigned field) { v4l_buffer_s_field(this, field); } + __u32 g_sequence() const { return v4l_buffer_g_sequence(this); } + __u32 g_timestamp_type() const { return v4l_buffer_g_timestamp_type(this); } + __u32 g_timestamp_src() const { return v4l_buffer_g_timestamp_src(this); } + void s_timestamp_src(__u32 src) { v4l_buffer_s_timestamp_src(this, src); } + bool ts_is_copy() const { return v4l_buffer_is_copy(this); } + const timeval &g_timestamp() const { return *v4l_buffer_g_timestamp(this); } + void s_timestamp(const timeval &tv) { v4l_buffer_s_timestamp(this, &tv); } + void s_timestamp_ts(const timespec &ts) { v4l_buffer_s_timestamp_ts(this, &ts); } + void s_timestamp_clock() { v4l_buffer_s_timestamp_clock(this); } + const v4l2_timecode &g_timecode() const { return *v4l_buffer_g_timecode(this); } + void s_timecode(const v4l2_timecode &tc) { v4l_buffer_s_timecode(this, &tc); } + __u32 g_mem_offset(unsigned plane = 0) const + { + return v4l_buffer_g_mem_offset(this, plane); + } + void *g_userptr(unsigned plane = 0) const + { + return v4l_buffer_g_userptr(this, plane); + } + int g_fd(unsigned plane = 0) const + { + return v4l_buffer_g_fd(this, plane); + } + __u32 g_bytesused(unsigned plane = 0) const + { + return v4l_buffer_g_bytesused(this, plane); + } + __u32 g_length(unsigned plane = 0) const + { + return v4l_buffer_g_length(this, plane); + } + __u32 g_data_offset(unsigned plane = 0) const + { + return v4l_buffer_g_data_offset(this, plane); + } + void s_userptr(void *userptr, unsigned plane = 0) + { + v4l_buffer_s_userptr(this, plane, userptr); + } + void s_fd(int fd, unsigned plane = 0) + { + v4l_buffer_s_fd(this, plane, fd); + } + void s_bytesused(__u32 bytesused, unsigned plane = 0) + { + v4l_buffer_s_bytesused(this, plane, bytesused); + } + void s_data_offset(__u32 data_offset, unsigned plane = 0) + { + v4l_buffer_s_data_offset(this, plane, data_offset); + } + bool is_planar() const { return v4l_buffer_is_planar(this); } + bool is_output() const { return v4l_buffer_is_output(this); } + bool is_capture() const { return v4l_buffer_is_capture(this); } + bool is_video() const { return v4l_buffer_is_video(this); } + bool is_vbi() const { return v4l_buffer_is_vbi(this); } + bool is_sliced_vbi() const { return v4l_buffer_is_sliced_vbi(this); } + bool is_sdr() const { return v4l_buffer_is_sdr(this); } + unsigned g_num_planes() const + { + return v4l_buffer_g_num_planes(this); + } + + int querybuf(v4l_fd *fd, unsigned index) + { + return v4l_buffer_querybuf(fd, this, index); + } + int querybuf(const cv4l_queue &q, unsigned index) + { + return querybuf(q.fd, index); + } + int dqbuf(v4l_fd *fd) + { + return v4l_buffer_dqbuf(fd, this); + } + int dqbuf(const cv4l_queue &q) + { + return dqbuf(q.fd); + } + int qbuf(v4l_fd *fd) + { + return v4l_buffer_qbuf(fd, this); + } + int qbuf(const cv4l_queue &q) + { + return qbuf(q.fd); + } + int prepare_buf(v4l_fd *fd) + { + return v4l_buffer_prepare_buf(fd, this); + } + int prepare_buf(const cv4l_queue &q) + { + return prepare_buf(q.fd); + } +}; + +#endif diff --git a/utils/v4l2-compliance/v4l-helpers.h b/utils/v4l2-compliance/v4l-helpers.h new file mode 100644 index 0000000..b2ce6c0 --- /dev/null +++ b/utils/v4l2-compliance/v4l-helpers.h @@ -0,0 +1,1033 @@ +#ifndef _V4L_HELPERS_H_ +#define _V4L_HELPERS_H_ + +#include <linux/videodev2.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <errno.h> + +struct v4l_fd { + int fd; + int (*ioctl)(int fd, unsigned long cmd, ...); + void *(*mmap)(void *addr, size_t length, int prot, int flags, + int fd, off_t offset); + int (*munmap)(void *addr, size_t length); +}; + +static inline void v4l_fd_init(struct v4l_fd *f, int fd) +{ + f->fd = fd; + f->ioctl = ioctl; + f->mmap = mmap; + f->munmap = munmap; +} + +#define v4l_fd_libv4l2_init(f, fd) \ + do { \ + (f)->fd = fd; \ + (f)->ioctl = v4l2_ioctl; \ + (f)->mmap = v4l2_mmap; \ + (f)->munmap = v4l2_munmap; \ + } while (0) + +static inline int v4l_ioctl(struct v4l_fd *f, unsigned long cmd, void *arg) +{ + return f->ioctl(f->fd, cmd, arg) ? errno : 0; +} + +static inline void *v4l_mmap(struct v4l_fd *f, size_t length, off_t offset) +{ + return f->mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, f->fd, offset); +} + +static inline int v4l_munmap(struct v4l_fd *f, void *start, size_t length) +{ + return f->munmap(start, length) ? errno : 0; +} + +static inline bool v4l_buf_type_is_planar(unsigned type) +{ + return V4L2_TYPE_IS_MULTIPLANAR(type); +} + +static inline bool v4l_buf_type_is_output(unsigned type) +{ + return V4L2_TYPE_IS_OUTPUT(type); +} + +static inline bool v4l_buf_type_is_capture(unsigned type) +{ + return !v4l_buf_type_is_output(type); +} + +static inline bool v4l_buf_type_is_video(unsigned type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return true; + default: + return false; + } +} + +static inline bool v4l_buf_type_is_vbi(unsigned type) +{ + return type == V4L2_BUF_TYPE_VBI_CAPTURE || + type == V4L2_BUF_TYPE_VBI_OUTPUT; +} + +static inline bool v4l_buf_type_is_sliced_vbi(unsigned type) +{ + return type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE || + type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; +} + +static inline bool v4l_buf_type_is_overlay(unsigned type) +{ + return type == V4L2_BUF_TYPE_VIDEO_OVERLAY || + type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; +} + +static inline bool v4l_buf_type_is_sdr(unsigned type) +{ + return type == V4L2_BUF_TYPE_SDR_CAPTURE; +} + +static inline int v4l_querycap(struct v4l_fd *f, struct v4l2_capability *cap) +{ + return v4l_ioctl(f, VIDIOC_QUERYCAP, cap); +} + +static inline __u32 v4l_capability_g_caps(const struct v4l2_capability *cap) +{ + return (cap->capabilities & V4L2_CAP_DEVICE_CAPS) ? + cap->device_caps : cap->capabilities; +} + +static inline __u32 v4l_querycap_g_caps(struct v4l_fd *f) +{ + struct v4l2_capability cap; + + return v4l_querycap(f, &cap) ? 0 : v4l_capability_g_caps(&cap); +} + +static inline int v4l_g_fmt(struct v4l_fd *f, struct v4l2_format *fmt, unsigned type) +{ + fmt->type = type; + return v4l_ioctl(f, VIDIOC_G_FMT, fmt); +} + +static inline int v4l_try_fmt(struct v4l_fd *f, struct v4l2_format *fmt) +{ + return v4l_ioctl(f, VIDIOC_TRY_FMT, fmt); +} + +static inline int v4l_s_fmt(struct v4l_fd *f, struct v4l2_format *fmt) +{ + return v4l_ioctl(f, VIDIOC_S_FMT, fmt); +} + +static inline void v4l_format_init(struct v4l2_format *fmt, unsigned type) +{ + memset(fmt, 0, sizeof(*fmt)); + fmt->type = type; +} + +static inline void v4l_format_s_width(struct v4l2_format *fmt, __u32 width) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.width = width; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.width = width; + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + fmt->fmt.win.w.width = width; + break; + } +} + +static inline __u32 v4l_format_g_width(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.width; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.width; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + return fmt->fmt.win.w.width; + default: + return 0; + } +} + +static inline void v4l_format_s_height(struct v4l2_format *fmt, __u32 height) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.height = height; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.height = height; + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + fmt->fmt.win.w.height = height; + break; + } +} + +static inline __u32 v4l_format_g_height(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.height; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.height; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + return fmt->fmt.win.w.height; + default: + return 0; + } +} + +static inline void v4l_format_s_pixelformat(struct v4l2_format *fmt, __u32 pixelformat) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.pixelformat = pixelformat; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.pixelformat = pixelformat; + break; + case V4L2_BUF_TYPE_SDR_CAPTURE: + fmt->fmt.sdr.pixelformat = pixelformat; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + fmt->fmt.vbi.sample_format = pixelformat; + break; + } +} + +static inline __u32 v4l_format_g_pixelformat(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.pixelformat; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.pixelformat; + case V4L2_BUF_TYPE_SDR_CAPTURE: + return fmt->fmt.sdr.pixelformat; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + return fmt->fmt.vbi.sample_format; + default: + return 0; + } +} + +static inline void v4l_format_s_field(struct v4l2_format *fmt, unsigned field) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.field = field; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.field = field; + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + fmt->fmt.win.field = field; + break; + } +} + +static inline unsigned v4l_format_g_field(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.field; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.field; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + return fmt->fmt.win.field; + default: + return V4L2_FIELD_NONE; + } +} + +static inline void v4l_format_s_pix_colorspace(struct v4l2_format *fmt, + unsigned colorspace) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.colorspace = colorspace; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.colorspace = colorspace; + break; + } +} + +static inline unsigned +v4l_format_g_pix_colorspace(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.colorspace; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.colorspace; + default: + return 0; + } +} + +static inline void v4l_format_s_num_planes(struct v4l2_format *fmt, __u8 num_planes) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.num_planes = num_planes; + break; + } +} + +static inline __u8 +v4l_format_g_num_planes(const struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.num_planes; + default: + return 1; + } +} + +static inline void v4l_format_s_bytesperline(struct v4l2_format *fmt, + unsigned plane, __u32 bytesperline) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.bytesperline = bytesperline; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.plane_fmt[plane].bytesperline = bytesperline; + break; + } +} + +static inline __u32 +v4l_format_g_bytesperline(const struct v4l2_format *fmt, unsigned plane) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.bytesperline; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.plane_fmt[plane].bytesperline; + default: + return 0; + } +} + +static inline void v4l_format_s_sizeimage(struct v4l2_format *fmt, + unsigned plane, __u32 sizeimage) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + fmt->fmt.pix.sizeimage = sizeimage; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + fmt->fmt.pix_mp.plane_fmt[plane].sizeimage = sizeimage; + break; + } +} + +static inline __u32 +v4l_format_g_sizeimage(const struct v4l2_format *fmt, unsigned plane) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return fmt->fmt.pix.sizeimage; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return fmt->fmt.pix_mp.plane_fmt[plane].sizeimage; + default: + return 0; + } +} + +struct v4l_buffer { + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + struct v4l2_buffer buf; +}; + +static inline void v4l_buffer_init(struct v4l_buffer *buf, + unsigned type, unsigned memory, unsigned index) +{ + memset(buf, 0, sizeof(*buf)); + buf->buf.type = type; + buf->buf.memory = memory; + buf->buf.index = index; + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + buf->buf.m.planes = buf->planes; + buf->buf.length = VIDEO_MAX_PLANES; + } +} + +static inline bool v4l_buffer_is_planar(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_planar(buf->buf.type); +} + +static inline bool v4l_buffer_is_output(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_output(buf->buf.type); +} + +static inline bool v4l_buffer_is_capture(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_capture(buf->buf.type); +} + +static inline bool v4l_buffer_is_video(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_video(buf->buf.type); +} + +static inline bool v4l_buffer_is_vbi(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_vbi(buf->buf.type); +} + +static inline bool v4l_buffer_is_sliced_vbi(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_sliced_vbi(buf->buf.type); +} + +static inline bool v4l_buffer_is_sdr(const struct v4l_buffer *buf) +{ + return v4l_buf_type_is_sdr(buf->buf.type); +} + +static inline unsigned v4l_buffer_g_num_planes(const struct v4l_buffer *buf) +{ + if (v4l_buffer_is_planar(buf)) + return buf->buf.length; + return 1; +} + +static inline __u32 v4l_buffer_g_index(const struct v4l_buffer *buf) +{ + return buf->buf.index; +} + +static inline void v4l_buffer_s_index(struct v4l_buffer *buf, __u32 index) +{ + buf->buf.index = index; +} + +static inline unsigned v4l_buffer_g_type(const struct v4l_buffer *buf) +{ + return buf->buf.type; +} + +static inline unsigned v4l_buffer_g_memory(const struct v4l_buffer *buf) +{ + return buf->buf.memory; +} + +static inline __u32 v4l_buffer_g_flags(const struct v4l_buffer *buf) +{ + return buf->buf.flags; +} + +static inline void v4l_buffer_s_flags(struct v4l_buffer *buf, __u32 flags) +{ + buf->buf.flags = flags; +} + +static inline void v4l_buffer_or_flags(struct v4l_buffer *buf, __u32 flags) +{ + buf->buf.flags |= flags; +} + +static inline unsigned v4l_buffer_g_field(const struct v4l_buffer *buf) +{ + return buf->buf.field; +} + +static inline void v4l_buffer_s_field(struct v4l_buffer *buf, unsigned field) +{ + buf->buf.field = field; +} + +static inline __u32 v4l_buffer_g_sequence(const struct v4l_buffer *buf) +{ + return buf->buf.sequence; +} + +static inline const struct timeval *v4l_buffer_g_timestamp(const struct v4l_buffer *buf) +{ + return &buf->buf.timestamp; +} + +static inline void v4l_buffer_s_timestamp(struct v4l_buffer *buf, const struct timeval *tv) +{ + buf->buf.timestamp = *tv; +} + +static inline void v4l_buffer_s_timestamp_ts(struct v4l_buffer *buf, const struct timespec *ts) +{ + buf->buf.timestamp.tv_sec = ts->tv_sec; + buf->buf.timestamp.tv_usec = ts->tv_nsec / 1000; +} + +static inline void v4l_buffer_s_timestamp_clock(struct v4l_buffer *buf) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + v4l_buffer_s_timestamp_ts(buf, &ts); +} + +static inline const struct v4l2_timecode *v4l_buffer_g_timecode(const struct v4l_buffer *buf) +{ + return &buf->buf.timecode; +} + +static inline void v4l_buffer_s_timecode(struct v4l_buffer *buf, const struct v4l2_timecode *tc) +{ + buf->buf.timecode = *tc; +} + +static inline __u32 v4l_buffer_g_timestamp_type(const struct v4l_buffer *buf) +{ + return buf->buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MASK; +} + +static inline bool v4l_buffer_is_copy(const struct v4l_buffer *buf) +{ + return v4l_buffer_g_timestamp_type(buf) == V4L2_BUF_FLAG_TIMESTAMP_COPY; +} + +static inline __u32 v4l_buffer_g_timestamp_src(const struct v4l_buffer *buf) +{ + return buf->buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; +} + +static inline void v4l_buffer_s_timestamp_src(struct v4l_buffer *buf, __u32 src) +{ + buf->buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + buf->buf.flags |= src & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; +} + +static inline unsigned v4l_buffer_g_length(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return buf->planes[plane].length; + return buf->buf.length; +} + +static inline unsigned v4l_buffer_g_bytesused(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return buf->planes[plane].bytesused; + return buf->buf.bytesused; +} + +static inline void v4l_buffer_s_bytesused(struct v4l_buffer *buf, unsigned plane, __u32 bytesused) +{ + if (v4l_buffer_is_planar(buf)) + buf->planes[plane].bytesused = bytesused; + else + buf->buf.bytesused = bytesused; +} + +static inline unsigned v4l_buffer_g_data_offset(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return buf->planes[plane].data_offset; + return 0; +} + +static inline void v4l_buffer_s_data_offset(struct v4l_buffer *buf, unsigned plane, __u32 data_offset) +{ + if (v4l_buffer_is_planar(buf)) + buf->planes[plane].data_offset = data_offset; +} + +static inline __u32 v4l_buffer_g_mem_offset(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return buf->planes[plane].m.mem_offset; + return buf->buf.m.offset; +} + +static inline void v4l_buffer_s_userptr(struct v4l_buffer *buf, unsigned plane, void *userptr) +{ + if (v4l_buffer_is_planar(buf)) + buf->planes[plane].m.userptr = (unsigned long)userptr; + else + buf->buf.m.userptr = (unsigned long)userptr; +} + +static inline void *v4l_buffer_g_userptr(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return (void *)buf->planes[plane].m.userptr; + return (void *)buf->buf.m.userptr; +} + +static inline void v4l_buffer_s_fd(struct v4l_buffer *buf, unsigned plane, int fd) +{ + if (v4l_buffer_is_planar(buf)) + buf->planes[plane].m.fd = fd; + else + buf->buf.m.fd = fd; +} + +static inline int v4l_buffer_g_fd(const struct v4l_buffer *buf, unsigned plane) +{ + if (v4l_buffer_is_planar(buf)) + return buf->planes[plane].m.fd; + return buf->buf.m.fd; +} + +static inline int v4l_buffer_prepare_buf(struct v4l_fd *f, struct v4l_buffer *buf) +{ + return v4l_ioctl(f, VIDIOC_PREPARE_BUF, &buf->buf); +} + +static inline int v4l_buffer_qbuf(struct v4l_fd *f, struct v4l_buffer *buf) +{ + return v4l_ioctl(f, VIDIOC_QBUF, &buf->buf); +} + +static inline int v4l_buffer_dqbuf(struct v4l_fd *f, struct v4l_buffer *buf) +{ + return v4l_ioctl(f, VIDIOC_DQBUF, &buf->buf); +} + +static inline int v4l_buffer_querybuf(struct v4l_fd *f, struct v4l_buffer *buf, unsigned index) +{ + v4l_buffer_s_index(buf, index); + return v4l_ioctl(f, VIDIOC_QUERYBUF, &buf->buf); +} + +struct v4l_queue { + unsigned type; + unsigned memory; + unsigned buffers; + unsigned num_planes; + + __u32 lengths[VIDEO_MAX_PLANES]; + __u32 mem_offsets[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES]; + void *mmappings[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES]; + unsigned long userptrs[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES]; + int fds[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES]; +}; + +static inline void v4l_queue_init(struct v4l_queue *q, + unsigned type, unsigned memory) +{ + unsigned i, p; + + memset(q, 0, sizeof(*q)); + q->type = type; + q->memory = memory; + for (i = 0; i < VIDEO_MAX_FRAME; i++) + for (p = 0; p < VIDEO_MAX_PLANES; p++) + q->fds[i][p] = -1; +} + +static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) +{ + return q->type; +} + +static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) +{ + return q->memory; +} + +static inline bool v4l_queue_is_planar(const struct v4l_queue *q) +{ + return v4l_buf_type_is_planar(q->type); +} + +static inline bool v4l_queue_is_output(const struct v4l_queue *q) +{ + return v4l_buf_type_is_output(q->type); +} + +static inline bool v4l_queue_is_capture(const struct v4l_queue *q) +{ + return v4l_buf_type_is_capture(q->type); +} + +static inline bool v4l_queue_is_video(const struct v4l_queue *q) +{ + return v4l_buf_type_is_video(q->type); +} + +static inline bool v4l_queue_is_vbi(const struct v4l_queue *q) +{ + return v4l_buf_type_is_vbi(q->type); +} + +static inline bool v4l_queue_is_sliced_vbi(const struct v4l_queue *q) +{ + return v4l_buf_type_is_sliced_vbi(q->type); +} + +static inline bool v4l_queue_is_sdr(const struct v4l_queue *q) +{ + return v4l_buf_type_is_sdr(q->type); +} + +static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) +{ + return q->buffers; +} + +static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) +{ + return q->num_planes; +} + +static inline __u32 v4l_queue_g_length(const struct v4l_queue *q, unsigned plane) +{ + return q->lengths[plane]; +} + +static inline __u32 v4l_queue_g_mem_offset(const struct v4l_queue *q, unsigned index, unsigned plane) +{ + return q->mem_offsets[index][plane]; +} + +static inline void v4l_queue_s_mmapping(struct v4l_queue *q, unsigned index, unsigned plane, void *m) +{ + q->mmappings[index][plane] = m; +} + +static inline void *v4l_queue_g_mmapping(const struct v4l_queue *q, unsigned index, unsigned plane) +{ + return q->mmappings[index][plane]; +} + +static inline void v4l_queue_s_userptr(struct v4l_queue *q, unsigned index, unsigned plane, void *m) +{ + q->userptrs[index][plane] = (unsigned long)m; +} + +static inline void *v4l_queue_g_userptr(const struct v4l_queue *q, unsigned index, unsigned plane) +{ + return (void *)q->userptrs[index][plane]; +} + +static inline void v4l_queue_s_fd(struct v4l_queue *q, unsigned index, unsigned plane, int fd) +{ + q->fds[index][plane] = fd; +} + +static inline int v4l_queue_g_fd(const struct v4l_queue *q, unsigned index, unsigned plane) +{ + return q->fds[index][plane]; +} + +static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from) +{ + unsigned b, p; + int ret; + + for (b = from; b < v4l_queue_g_buffers(q); b++) { + struct v4l_buffer buf; + + v4l_buffer_init(&buf, v4l_queue_g_type(q), v4l_queue_g_memory(q), b); + ret = v4l_ioctl(f, VIDIOC_QUERYBUF, &buf.buf); + if (ret) + return ret; + if (b == 0) { + q->num_planes = v4l_buffer_g_num_planes(&buf); + for (p = 0; p < v4l_queue_g_num_planes(q); p++) + q->lengths[p] = v4l_buffer_g_length(&buf, p); + } + if (q->memory == V4L2_MEMORY_MMAP) + for (p = 0; p < q->num_planes; p++) + q->mem_offsets[b][p] = v4l_buffer_g_mem_offset(&buf, p); + } + return 0; +} + +static inline int v4l_queue_reqbufs(struct v4l_fd *f, + struct v4l_queue *q, unsigned count) +{ + struct v4l2_requestbuffers reqbufs; + int ret; + + reqbufs.type = q->type; + reqbufs.memory = q->memory; + reqbufs.count = count; + memset(reqbufs.reserved, 0, sizeof(reqbufs.reserved)); + /* + * Problem: if REQBUFS returns an error, did it free any old + * buffers or not? + */ + ret = v4l_ioctl(f, VIDIOC_REQBUFS, &reqbufs); + if (ret) + return ret; + q->buffers = reqbufs.count; + return v4l_queue_querybufs(f, q, 0); +} + +static inline bool v4l_queue_has_create_bufs(struct v4l_fd *f, const struct v4l_queue *q) +{ + struct v4l2_create_buffers createbufs; + + memset(&createbufs, 0, sizeof(createbufs)); + createbufs.format.type = q->type; + createbufs.memory = q->memory; + return v4l_ioctl(f, VIDIOC_CREATE_BUFS, &createbufs) == 0; +} + +static inline int v4l_queue_create_bufs(struct v4l_fd *f, + struct v4l_queue *q, unsigned count, const struct v4l2_format *fmt) +{ + struct v4l2_create_buffers createbufs; + int ret; + + createbufs.format.type = q->type; + createbufs.memory = q->memory; + createbufs.count = count; + if (fmt) { + createbufs.format = *fmt; + } else { + ret = v4l_ioctl(f, VIDIOC_G_FMT, &createbufs.format); + if (ret) + return ret; + } + memset(createbufs.reserved, 0, sizeof(createbufs.reserved)); + ret = v4l_ioctl(f, VIDIOC_CREATE_BUFS, &createbufs); + if (ret) + return ret; + q->buffers += createbufs.count; + return v4l_queue_querybufs(f, q, q->buffers - createbufs.count); +} + +static inline int v4l_queue_streamon(struct v4l_fd *f, struct v4l_queue *q) +{ + return v4l_ioctl(f, VIDIOC_STREAMON, &q->type); +} + +static inline int v4l_queue_streamoff(struct v4l_fd *f, struct v4l_queue *q) +{ + return v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type); +} + +static inline int v4l_queue_mmap_bufs(struct v4l_fd *f, + struct v4l_queue *q, unsigned from) +{ + unsigned b, p; + + if (q->memory != V4L2_MEMORY_MMAP && q->memory != V4L2_MEMORY_DMABUF) + return 0; + + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + void *m = MAP_FAILED; + + if (q->memory == V4L2_MEMORY_MMAP) + m = v4l_mmap(f, v4l_queue_g_length(q, p), v4l_queue_g_mem_offset(q, b, p)); + else if (q->memory == V4L2_MEMORY_DMABUF) + m = mmap(NULL, v4l_queue_g_length(q, p), + PROT_READ | PROT_WRITE, MAP_SHARED, + v4l_queue_g_fd(q, b, p), 0); + + if (m == MAP_FAILED) + return errno; + v4l_queue_s_mmapping(q, b, p, m); + } + } + return 0; +} +static inline int v4l_queue_munmap_bufs(struct v4l_fd *f, struct v4l_queue *q) +{ + unsigned b, p; + int ret = 0; + + if (q->memory != V4L2_MEMORY_MMAP && q->memory != V4L2_MEMORY_DMABUF) + return 0; + + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + void *m = v4l_queue_g_mmapping(q, b, p); + + if (m == NULL) + continue; + + if (q->memory == V4L2_MEMORY_MMAP) + ret = v4l_munmap(f, m, v4l_queue_g_length(q, p)); + else if (q->memory == V4L2_MEMORY_DMABUF) + ret = munmap(m, v4l_queue_g_length(q, p)) ? errno : 0; + if (ret) + return ret; + v4l_queue_s_mmapping(q, b, p, NULL); + } + } + return 0; +} + +static inline int v4l_queue_alloc_bufs(struct v4l_fd *f, + struct v4l_queue *q, unsigned from) +{ + unsigned b, p; + + if (q->memory != V4L2_MEMORY_USERPTR) + return 0; + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + void *m = malloc(v4l_queue_g_length(q, p)); + + if (m == NULL) + return errno; + v4l_queue_s_userptr(q, b, p, m); + } + } + return 0; +} + +static inline int v4l_queue_free_bufs(struct v4l_queue *q) +{ + unsigned b, p; + + if (q->memory != V4L2_MEMORY_USERPTR) + return 0; + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + free(v4l_queue_g_mmapping(q, b, p)); + v4l_queue_s_mmapping(q, b, p, NULL); + } + } + return 0; +} + + +static inline bool v4l_queue_has_expbuf(struct v4l_fd *f) +{ + struct v4l2_exportbuffer expbuf; + + memset(&expbuf, 0, sizeof(expbuf)); + return v4l_ioctl(f, VIDIOC_EXPBUF, &expbuf) != ENOTTY; +} + +static inline int v4l_queue_export_bufs(struct v4l_fd *f, struct v4l_queue *q) +{ + struct v4l2_exportbuffer expbuf; + unsigned b, p; + int ret = 0; + + expbuf.type = q->type; + expbuf.flags = O_RDWR; + memset(expbuf.reserved, 0, sizeof(expbuf.reserved)); + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + expbuf.index = b; + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + expbuf.plane = p; + ret = v4l_ioctl(f, VIDIOC_EXPBUF, &expbuf); + if (ret) + return ret; + v4l_queue_s_fd(q, b, p, expbuf.fd); + } + } + return 0; +} + +static inline void v4l_queue_close_exported_fds(struct v4l_queue *q) +{ + unsigned b, p; + + if (q->memory != V4L2_MEMORY_MMAP) + return; + + for (b = 0; b < v4l_queue_g_buffers(q); b++) { + for (p = 0; p < v4l_queue_g_num_planes(q); p++) { + int fd = v4l_queue_g_fd(q, b, p); + + if (fd != -1) { + close(fd); + v4l_queue_s_fd(q, b, p, -1); + } + } + } +} + +static inline void v4l_queue_free(struct v4l_fd *f, struct v4l_queue *q) +{ + v4l_queue_streamoff(f, q); + v4l_queue_free_bufs(q); + v4l_queue_munmap_bufs(f, q); + v4l_queue_close_exported_fds(q); + v4l_queue_reqbufs(f, q, 0); +} + +static inline void v4l_queue_buffer_init(const struct v4l_queue *q, struct v4l_buffer *buf, unsigned index) +{ + unsigned p; + + v4l_buffer_init(buf, v4l_queue_g_type(q), v4l_queue_g_memory(q), index); + if (v4l_queue_is_planar(q)) { + buf->buf.length = v4l_queue_g_num_planes(q); + buf->buf.m.planes = buf->planes; + } + switch (q->memory) { + case V4L2_MEMORY_USERPTR: + for (p = 0; p < v4l_queue_g_num_planes(q); p++) + v4l_buffer_s_userptr(buf, p, v4l_queue_g_userptr(q, index, p)); + break; + case V4L2_MEMORY_DMABUF: + for (p = 0; p < v4l_queue_g_num_planes(q); p++) + v4l_buffer_s_fd(buf, p, v4l_queue_g_fd(q, index, p)); + break; + default: + break; + } +} + +#endif _______________________________________________ linuxtv-commits mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits
