Skip to content

Commit b90e721

Browse files
Merge pull request #51 from OpenHD/codex/fix-v4l2-setup-issue-leading-to-segmentation-fault
Improve Allwinner V4L2 device discovery
2 parents c3ab50b + 6367973 commit b90e721

2 files changed

Lines changed: 79 additions & 1 deletion

File tree

allwinnerv4l2display.cpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
#include <drm_fourcc.h>
1414
#include <cerrno>
1515
#include <cstdio>
16+
#include <cstdlib>
1617
#include <cstring>
1718
#include <iostream>
19+
#include <set>
20+
#include <string>
1821
#include <vector>
1922

2023
namespace {
@@ -158,13 +161,83 @@ bool AllwinnerV4L2Display::setup_drm() {
158161
return true;
159162
}
160163

164+
int AllwinnerV4L2Display::open_candidate_v4l2_device(const char* path) {
165+
if (!path)
166+
return -1;
167+
168+
int fd = open(path, O_RDWR | O_NONBLOCK);
169+
if (fd < 0)
170+
return -1;
171+
172+
struct v4l2_capability caps;
173+
memset(&caps, 0, sizeof(caps));
174+
if (ioctl(fd, VIDIOC_QUERYCAP, &caps) < 0) {
175+
close(fd);
176+
return -1;
177+
}
178+
179+
uint32_t capability_mask = caps.capabilities;
180+
if (capability_mask & V4L2_CAP_DEVICE_CAPS)
181+
capability_mask = caps.device_caps;
182+
183+
bool streaming = capability_mask & V4L2_CAP_STREAMING;
184+
bool output = capability_mask & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_OUTPUT);
185+
bool capture = capability_mask & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_CAPTURE);
186+
bool mem2mem = capability_mask & (V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M);
187+
188+
if (!streaming || !(mem2mem || (output && capture))) {
189+
close(fd);
190+
return -1;
191+
}
192+
193+
m_v4l2_driver_name = reinterpret_cast<const char*>(caps.driver);
194+
return fd;
195+
}
196+
161197
bool AllwinnerV4L2Display::setup_v4l2() {
162-
m_v4l2_fd = open("/dev/video0", O_RDWR | O_NONBLOCK);
198+
std::vector<std::string> candidates;
199+
std::set<std::string> seen;
200+
201+
m_v4l2_driver_name.clear();
202+
203+
const char* override_device = getenv("FPVUE_V4L2_DEVICE");
204+
if (override_device && override_device[0] != '\0') {
205+
candidates.emplace_back(override_device);
206+
seen.insert(candidates.back());
207+
}
208+
209+
for (int index = 0; index < 32; ++index) {
210+
char path[32];
211+
snprintf(path, sizeof(path), "/dev/video%d", index);
212+
if (seen.insert(path).second) {
213+
candidates.emplace_back(path);
214+
}
215+
}
216+
217+
for (const auto& device_path : candidates) {
218+
int fd = open_candidate_v4l2_device(device_path.c_str());
219+
if (fd >= 0) {
220+
m_v4l2_fd = fd;
221+
m_v4l2_device_path = device_path;
222+
break;
223+
}
224+
}
225+
163226
if (m_v4l2_fd < 0) {
227+
if (override_device && override_device[0] != '\0') {
228+
std::cerr << "Failed to open V4L2 device override '" << override_device
229+
<< "'." << std::endl;
230+
}
164231
perror("open v4l2");
165232
return false;
166233
}
167234

235+
std::cout << "Using Cedar V4L2 decoder " << m_v4l2_device_path;
236+
if (!m_v4l2_driver_name.empty()) {
237+
std::cout << " (driver '" << m_v4l2_driver_name << "')";
238+
}
239+
std::cout << "." << std::endl;
240+
168241
struct v4l2_format fmt;
169242
memset(&fmt, 0, sizeof(fmt));
170243
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;

allwinnerv4l2display.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define FPVUE_ALLWINNERV4L2DISPLAY_H
33

44
#include <atomic>
5+
#include <string>
56
#include <thread>
67
#include <vector>
78

@@ -41,6 +42,7 @@ class AllwinnerV4L2Display {
4142
bool setup_drm();
4243
bool setup_v4l2();
4344
void decode_loop();
45+
int open_candidate_v4l2_device(const char* path);
4446

4547
int m_port;
4648
bool m_h265;
@@ -66,6 +68,9 @@ class AllwinnerV4L2Display {
6668

6769
struct modeset_output m_output{};
6870

71+
std::string m_v4l2_device_path;
72+
std::string m_v4l2_driver_name;
73+
6974
std::vector<void*> m_output_buffers;
7075
std::vector<void*> m_capture_buffers;
7176
std::vector<int> m_capture_fbs;

0 commit comments

Comments
 (0)