Skip to content

Commit

Permalink
added search video capture device if configured incorrectly.
Browse files Browse the repository at this point in the history
  • Loading branch information
yjdwbj committed May 12, 2024
1 parent 1bf8d41 commit 735f584
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ You'll need `meson`, the `gstreamer-plugins-bad,gstreamer-plugins-good` library,
```sh
~$ sudo apt-get install -y gstreamer1.0-x gstreamer1.0-opencv gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-good gstreamer1.0-plugins-base gstreamer1.0-plugins-ugly \
libgstreamer-plugins-bad1.0-0 libgstreamer-plugins-base1.0-0 libgstreamer-plugins-opencv1.0-0 \
libgstreamer-plugins-bad1.0-0 libgstreamer-plugins-base1.0-0 libgstreamer-opencv1.0-0 \
libgstreamer1.0-0 libsoup-3.0-0 libjson-glib-1.0-0 sqlite3
```

Expand Down
6 changes: 3 additions & 3 deletions debian/gwc/etc/gwc/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"password": "testsoup"
},
"v4l2src": {
"width": 800,
"height": 600,
"width": 1280,
"height": 720,
"framerate": 30,
"io_mode": 2,
"device": "/dev/video1",
"device": "/dev/video2",
"type": "image/jpeg",
"format": "NV12"
},
Expand Down
5 changes: 3 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,9 @@ int main(int argc, char *argv[]) {
exit(1);
}

if (!find_video_device_fmt(&config_data.v4l2src_data)) {
g_error("Set video pixformat failed !!!\n");
if (!find_video_device_fmt(&config_data.v4l2src_data,TRUE) &&
!get_capture_device(&config_data.v4l2src_data)) {
g_error("No video capture device found!!!\n");
exit(1);
}

Expand Down
139 changes: 137 additions & 2 deletions v4l2ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
#include "v4l2ctl.h"
#include <json-glib/json-glib.h>
#include <linux/media.h>
#include <dirent.h>

static int ctrl_list[] = {V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_SHARPNESS, V4L2_CID_WHITENESS};

Expand Down Expand Up @@ -382,12 +384,122 @@ int dump_video_device_fmt(const gchar *device) {
return 0;
}

gboolean find_video_device_fmt(_v4l2src_data *data) {
static gboolean get_default_capture_device(_v4l2src_data *data) {
// This is used if the wrong video configuration is set but a valid device is found on the system.
gboolean match = FALSE;
int fd = -1;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_frmsizeenum frmsize;
struct v4l2_frmivalenum frmval;
struct v4l2_capability capability;

memset(&fmtdesc, 0, sizeof(fmtdesc));
memset(&frmsize, 0, sizeof(frmsize));
memset(&frmval, 0, sizeof(frmval));
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmtdesc.index = 0;
fmtdesc.mbus_code = 0;

fd = open(data->device, O_RDWR);
if (fd < 0) {
return match;
}

if (0 > ioctl(fd, VIDIOC_QUERYCAP, &capability)) {
goto invalid_dev;
}

if (g_str_has_prefix((const gchar *)&capability.bus_info, "platform:")) {
goto invalid_dev;
}

for (; 0 == ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) && !match ; fmtdesc.index++) {
frmsize.pixel_format = fmtdesc.pixelformat;
frmsize.index = 0;
for (; 0 == ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) && !match; frmsize.index++) {
if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE)
continue;
data->width = frmsize.discrete.width;
data->height = frmsize.discrete.height;
frmval.pixel_format = fmtdesc.pixelformat;
frmval.index = 0;
frmval.width = frmsize.discrete.width;
frmval.height = frmsize.discrete.height;
for (; 0 == ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmval); frmval.index++) {
gfloat fps = ((1.0 * frmval.discrete.denominator) / frmval.discrete.numerator);
data->framerate = (int)fps;
match = TRUE;
g_warning("!!!found an valid device: %dx%d/%d at %s\n", data->width, data->height, data->framerate, data->device);
break;
}
}
}

invalid_dev:
close(fd);
return match;
}

gboolean get_capture_device(_v4l2src_data *data) {
GList *videolist = NULL;
gboolean found = FALSE;
DIR *devdir;
struct dirent *dir;
devdir = opendir("/dev/");
if(devdir) {
while((dir = readdir(devdir)) != NULL) {
if (strlen(dir->d_name) > 5 && g_str_has_prefix(dir->d_name, "video")) {
videolist = g_list_append(videolist, g_strdup_printf("/dev/%s", dir->d_name));
}
}
closedir(devdir);
}

// find an video capture device.
for (GList *iter = videolist; iter != NULL; iter = iter->next ){
_v4l2src_data item;
item.device = iter->data;
item.width = data->width;
item.height = data->height;
item.format = data->format;
item.framerate = data->framerate;
if (find_video_device_fmt(&item,FALSE)) {
g_warning("found video capture : %s, but not match you video capture configuration!!!\n", (const gchar *)(iter->data));
g_free(data->device);
data->device = g_strdup(iter->data);
found = TRUE;
goto found_dev;
}
}

// find an default video capture settings.

for (GList *iter = videolist; iter != NULL; iter = iter->next) {
_v4l2src_data item;
item.device = iter->data;
if (get_default_capture_device(&item)) {
g_free(data->device);
data->device = g_strdup(iter->data);
data->width = item.width;
data->height = item.height;
data->framerate = item.framerate;
found = TRUE;
break;
}
}

found_dev:
g_list_free_full(videolist, g_free);
return found;
}

gboolean find_video_device_fmt(_v4l2src_data *data, const gboolean showdump) {
gboolean match = FALSE;
int fd = -1;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_frmsizeenum frmsize;
struct v4l2_frmivalenum frmval;
struct v4l2_capability capability;

memset(&fmtdesc, 0, sizeof(fmtdesc));
memset(&frmsize, 0, sizeof(frmsize));
Expand All @@ -401,6 +513,27 @@ gboolean find_video_device_fmt(_v4l2src_data *data) {
return match;
}

if( 0 > ioctl(fd, VIDIOC_QUERYCAP, &capability))
{
goto no_match;
}

if (g_str_has_prefix((const gchar *)&capability.bus_info,"platform:")) {
goto no_match;
}

#if 0
struct media_device_info mdi;
if (0 == ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi)) {
if (mdi.bus_info[0])
g_print("ioctl: has bus_info[0]: %s\n",(const gchar *)(mdi.bus_info));
else
g_print("ioctl: driver info: %s\n", (const gchar *)(mdi.driver));
} else {
g_print("ioctl: cap info: %s\n", (const gchar *)(capability.bus_info));
}
#endif

for (; 0 == ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc); fmtdesc.index++) {
frmsize.pixel_format = fmtdesc.pixelformat;
frmsize.index = 0;
Expand All @@ -426,8 +559,10 @@ gboolean find_video_device_fmt(_v4l2src_data *data) {
}
}
}

no_match:
close(fd);
if (!match)
if (!match && showdump)
dump_video_device_fmt(data->device);
return match;
}
3 changes: 2 additions & 1 deletion v4l2ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ gchar *get_device_json(const gchar* device);
int set_ctrl_value(const gchar *device,int ctrl_id, int ctrl_val);
int reset_user_ctrls(const gchar *device);
int dump_video_device_fmt(const gchar *device);
gboolean find_video_device_fmt(_v4l2src_data *data);
gboolean find_video_device_fmt(_v4l2src_data *data, const gboolean showdump);
gboolean get_capture_device(_v4l2src_data *data);

#endif // _V4L2CTL_H

0 comments on commit 735f584

Please sign in to comment.