UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
v4l2_common.h
Go to the documentation of this file.
1
7 /*
8 * Copyright (c) 2012-2024 CESNET
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, is permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * 3. Neither the name of CESNET nor the names of its contributors may be
23 * used to endorse or promote products derived from this software without
24 * specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
28 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#ifndef V4L2_COMMON_4B01337E_4F0D_48EC_91A7_D220AD919D3B
41#define V4L2_COMMON_4B01337E_4F0D_48EC_91A7_D220AD919D3B
42
43#include <linux/videodev2.h>
44#include <stdint.h>
45#include <sys/ioctl.h>
46#include <sys/mman.h>
47
48#include "types.h"
49
50#define V4L2_PROBE_MAX 64
51
52static struct {
53 enum v4l2_field v4l_f;
55} v4l2_field_map [] = {
56 { V4L2_FIELD_NONE, PROGRESSIVE },
57 { V4L2_FIELD_SEQ_TB, UPPER_FIELD_FIRST },
58 { V4L2_FIELD_SEQ_BT, LOWER_FIELD_FIRST },
59 { V4L2_FIELD_INTERLACED, INTERLACED_MERGED },
60};
61
66static struct {
67 uint32_t v4l2_fcc;
69} v4l2_ug_map[] = {
70 {V4L2_PIX_FMT_YUYV, YUYV},
71 {V4L2_PIX_FMT_UYVY, UYVY},
72 {V4L2_PIX_FMT_YUV420, I420},
73#ifdef V4L2_PIX_FMT_YUVA32
74 {V4L2_PIX_FMT_YUVA32, Y416},
75#endif
76#ifdef V4L2_PIX_FMT_Y210
77 {V4L2_PIX_FMT_Y210, Y216},
78#endif
79#ifdef V4L2_PIX_FMT_Y212
80 {V4L2_PIX_FMT_Y212, Y216},
81#endif
82#ifdef V4L2_PIX_FMT_Y216
83 {V4L2_PIX_FMT_Y216, Y216},
84#endif
85 {V4L2_PIX_FMT_RGB24, RGB},
86 {V4L2_PIX_FMT_BGR24, BGR},
87 {V4L2_PIX_FMT_RGB32, RGBA},
88#ifdef V4L2_PIX_FMT_RGBA32
89 {V4L2_PIX_FMT_RGBA32, RGBA},
90#endif
91#ifdef V4L2_PIX_FMT_RGBX32
92 {V4L2_PIX_FMT_RGBX32, RGBA},
93#endif
94#ifdef V4L2_PIX_FMT_RGBX1010102
95 {V4L2_PIX_FMT_RGBX1010102, R10k},
96#endif
97#ifdef V4L2_PIX_FMT_RGBA1010102
98 {V4L2_PIX_FMT_RGBA1010102, R10k},
99#endif
100 {V4L2_PIX_FMT_MJPEG, MJPG},
101 {V4L2_PIX_FMT_JPEG, MJPG},
102 {V4L2_PIX_FMT_H264, H264},
103 //{V4L2_PIX_FMT_H264_NO_SC, H264}, ///< H.264 without tart codes, @todo implement adding start codes (capture)
104#ifdef V4L2_PIX_FMT_HEVC
105 {V4L2_PIX_FMT_HEVC, H265},
106#endif
107#ifdef V4L2_PIX_FMT_HEVC
108 {V4L2_PIX_FMT_VP9, VP9},
109#endif
111
113 void *start;
114 size_t length;
115};
116
117static _Bool set_v4l2_buffers(int fd, struct v4l2_requestbuffers *reqbuf, struct v4l2_buffer_data *buffers) {
118 if (ioctl (fd, VIDIOC_REQBUFS, reqbuf) != 0) {
119 if (errno == EINVAL)
120 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Video capturing or mmap-streaming is not supported\n");
121 else
122 log_perror(LOG_LEVEL_ERROR, MOD_NAME "VIDIOC_REQBUFS");
123 return 0;
124
125 }
126
127 if (reqbuf->count < 2) {
128 /* You may need to free the buffers here. */
129 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Not enough buffer memory\n");
130 return 0;
131 }
132
133 for (unsigned int i = 0; i < reqbuf->count; i++) {
134 struct v4l2_buffer buf;
135 memset(&buf, 0, sizeof(buf));
136 buf.type = reqbuf->type;
137 buf.memory = V4L2_MEMORY_MMAP;
138 buf.index = i;
139
140 if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)) {
141 log_perror(LOG_LEVEL_ERROR, MOD_NAME "VIDIOC_QUERYBUF");
142 return 0;
143 }
144
145 buffers[i].length = buf.length; /* remember for munmap() */
146
147 buffers[i].start = mmap(NULL, buf.length,
148 PROT_READ | PROT_WRITE, /* recommended */
149 MAP_SHARED, /* recommended */
150 fd, buf.m.offset);
151
152 if (MAP_FAILED == buffers[i].start) {
153 /* If you do not exit here you should unmap() and free()
154 the buffers mapped so far. */
156 return 0;
157 }
158
159 buf.flags = 0;
160
161 if(ioctl(fd, VIDIOC_QBUF, &buf) != 0) {
162 log_perror(LOG_LEVEL_ERROR, MOD_NAME "Unable to enqueue buffer");
163 return 0;
164 }
165 }
166 return 1;
167}
168
169static int try_open_v4l2_device(int log_level, const char *dev_name, int cap) {
170 log_msg(LOG_LEVEL_VERBOSE, "Trying device: %s\n", dev_name);
171 int fd = open(dev_name, O_RDWR);
172 if (fd == -1) {
173 char errbuf[1024];
174 log_msg(log_level, MOD_NAME "Unable to open input device %s: %s\n",
175 dev_name, strerror_r(errno, errbuf, sizeof errbuf));
176 return -1;
177 }
178
179 struct v4l2_capability capability;
180 memset(&capability, 0, sizeof(capability));
181 if (ioctl(fd, VIDIOC_QUERYCAP, &capability) != 0) {
182 log_perror(log_level, MOD_NAME "ioctl VIDIOC_QUERYCAP");
183 close(fd);
184 return -1;
185 }
186
187 if (!(capability.device_caps & cap)) {
188 const char *cap_str = cap == V4L2_CAP_VIDEO_CAPTURE ? "capture" : "playback";
189 log_msg(log_level, MOD_NAME "%s, %s can't %s\n",capability.card,capability.bus_info, cap_str);
190 close(fd);
191 return -1;
192 }
193
194 if (!(capability.device_caps & V4L2_CAP_STREAMING)) {
195 log_msg(log_level, MOD_NAME "Streaming capability not present.\n");
196 close(fd);
197 return -1;
198 }
199
200 int index = 0;
201
202 if (ioctl(fd, VIDIOC_S_INPUT, &index) != 0) {
203 log_perror(log_level, MOD_NAME "Could not enable input (VIDIOC_S_INPUT)");
204 close(fd);
205 return -1;
206 }
207
208 return fd;
209}
210
211#endif // defined V4L2_COMMON_4B01337E_4F0D_48EC_91A7_D220AD919D3B
#define MOD_NAME
Definition audio.cpp:110
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
void log_perror(int level, const char *msg)
Definition debug.cpp:165
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
std::string_view cap_str
Definition host.cpp:748
volatile int log_level
Definition debug.cpp:65
static void start()
Definition sdp.c:202
This file contains some common data types.
interlacing_t
Definition types.h:163
@ LOWER_FIELD_FIRST
First stored field is bottom, followed by top.
Definition types.h:166
@ UPPER_FIELD_FIRST
First stored field is top, followed by bottom.
Definition types.h:165
@ PROGRESSIVE
progressive frame
Definition types.h:164
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
Definition types.h:167
codec_t
Definition types.h:65
@ YUYV
YCbCr 422 8-bit - Y0 Cb Y1 Cr.
Definition types.h:72
@ R10k
RGB 10-bit packed - RGBX, big-endian (2 bit padding)
Definition types.h:73
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ BGR
8-bit BGR
Definition types.h:88
@ Y416
interleaved little-endian YCbCr 4444 16-bit - UYVA
Definition types.h:99
@ Y216
YCbCr 422 16-bit little-endian - Y0 Cb Y1 Cr.
Definition types.h:98
@ MJPG
JPEG image, without restart intervals.
Definition types.h:85
@ H264
H.264 frame.
Definition types.h:83
@ VP9
VP9 frame.
Definition types.h:87
@ H265
H.264 frame.
Definition types.h:84
@ I420
planar YCbCr 4:2:0
Definition types.h:97
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
static struct @67 v4l2_field_map[]
codec_t ug_codec
Definition v4l2_common.h:68
enum interlacing_t ug_f
Definition v4l2_common.h:54
enum v4l2_field v4l_f
Definition v4l2_common.h:53
static struct @68 v4l2_ug_map[]
uint32_t v4l2_fcc
Definition v4l2_common.h:67
static int try_open_v4l2_device(int log_level, const char *dev_name, int cap)
static _Bool set_v4l2_buffers(int fd, struct v4l2_requestbuffers *reqbuf, struct v4l2_buffer_data *buffers)