mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-24 03:58:28 +00:00
camera: Made a pass over all the sources, cleaning up for SDL3 style, etc.
This commit is contained in:
@@ -28,27 +28,25 @@
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
#include "../../core/linux/SDL_evdev_capabilities.h"
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
#include <limits.h> /* INT_MAX */
|
||||
#include <limits.h> // INT_MAX
|
||||
|
||||
#define DEBUG_CAMERA 1
|
||||
|
||||
#define MAX_CAMERA_DEVICES 128 /* It's doubtful someone has more than that */
|
||||
#define MAX_CAMERA_DEVICES 128 // It's doubtful someone has more than that
|
||||
|
||||
static int MaybeAddDevice(const char *path);
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
static int MaybeRemoveDevice(const char *path);
|
||||
static void camera_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
static void CameraUdevCallback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
|
||||
#endif // SDL_USE_LIBUDEV
|
||||
|
||||
/*
|
||||
* List of available camera devices.
|
||||
*/
|
||||
// List of available camera devices.
|
||||
typedef struct SDL_cameralist_item
|
||||
{
|
||||
char *fname; /* Dev path name (like /dev/video0) */
|
||||
char *bus_info; /* don't add two paths with same bus_info (eg /dev/video0 and /dev/video1 */
|
||||
char *fname; // Dev path name (like /dev/video0)
|
||||
char *bus_info; // don't add two paths with same bus_info (eg /dev/video0 and /dev/video1
|
||||
SDL_CameraDeviceID instance_id;
|
||||
SDL_CameraDevice *device; /* Associated device */
|
||||
SDL_CameraDevice *device; // Associated device
|
||||
struct SDL_cameralist_item *next;
|
||||
} SDL_cameralist_item;
|
||||
|
||||
@@ -67,7 +65,7 @@ enum io_method {
|
||||
struct buffer {
|
||||
void *start;
|
||||
size_t length;
|
||||
int available; /* Is available in userspace */
|
||||
int available; // Is available in userspace
|
||||
};
|
||||
|
||||
struct SDL_PrivateCameraData
|
||||
@@ -82,34 +80,30 @@ struct SDL_PrivateCameraData
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h> /* low-level i/o */
|
||||
#include <fcntl.h> // low-level i/o
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
static int
|
||||
xioctl(int fh, int request, void *arg)
|
||||
static int xioctl(int fh, int request, void *arg)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
r = ioctl(fh, request, arg);
|
||||
} while (r == -1 && errno == EINTR);
|
||||
} while ((r == -1) && (errno == EINTR));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* -1:error 1:frame 0:no frame*/
|
||||
static int
|
||||
acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
// -1:error 1:frame 0:no frame
|
||||
static int acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
int i;
|
||||
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
size_t size = _this->hidden->buffers[0].length;
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
switch (io) {
|
||||
case IO_METHOD_READ:
|
||||
@@ -119,9 +113,8 @@ acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
// Could ignore EIO, see spec.
|
||||
// fall through
|
||||
|
||||
default:
|
||||
return SDL_SetError("read");
|
||||
@@ -145,9 +138,8 @@ acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
// Could ignore EIO, see spec.
|
||||
// fall through
|
||||
|
||||
default:
|
||||
return SDL_SetError("VIDIOC_DQBUF: %d", errno);
|
||||
@@ -180,15 +172,16 @@ acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
// Could ignore EIO, see spec.
|
||||
|
||||
/* fall through */
|
||||
// fall through
|
||||
|
||||
default:
|
||||
return SDL_SetError("VIDIOC_DQBUF");
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
if (buf.m.userptr == (unsigned long)_this->hidden->buffers[i].start && buf.length == size) {
|
||||
break;
|
||||
@@ -213,13 +206,12 @@ acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
int i;
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
if (frame->num_planes && frame->data[0] == _this->hidden->buffers[i].start) {
|
||||
@@ -268,25 +260,23 @@ ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
|
||||
/* Timeout. */
|
||||
// Timeout.
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 300 * 1000;
|
||||
|
||||
ret = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
int retval = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (ret == -1) {
|
||||
if (retval == -1) {
|
||||
if (errno == EINTR) {
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("continue ..");
|
||||
@@ -296,35 +286,34 @@ AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame)
|
||||
return SDL_SetError("select");
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Timeout. Not an error */
|
||||
if (retval == 0) {
|
||||
// Timeout. Not an error
|
||||
SDL_SetError("timeout select");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = acquire_frame(_this, frame);
|
||||
if (ret < 0) {
|
||||
retval = acquire_frame(_this, frame);
|
||||
if (retval < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 1){
|
||||
if (retval == 1){
|
||||
frame->timestampNS = SDL_GetTicksNS();
|
||||
} else if (ret == 0) {
|
||||
} else if (retval == 0) {
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("No frame continue: %s", SDL_GetError());
|
||||
#endif
|
||||
}
|
||||
|
||||
/* EAGAIN - continue select loop. */
|
||||
// EAGAIN - continue select loop.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
StopCamera(SDL_CameraDevice *_this)
|
||||
int StopCamera(SDL_CameraDevice *_this)
|
||||
{
|
||||
enum v4l2_buf_type type;
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
|
||||
switch (io) {
|
||||
@@ -343,18 +332,16 @@ StopCamera(SDL_CameraDevice *_this)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
enqueue_buffers(SDL_CameraDevice *_this)
|
||||
static int EnqueueBuffers(SDL_CameraDevice *_this)
|
||||
{
|
||||
int i;
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
switch (io) {
|
||||
case IO_METHOD_READ:
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
for (int i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
if (_this->hidden->buffers[i].available == 0) {
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
@@ -371,7 +358,7 @@ enqueue_buffers(SDL_CameraDevice *_this)
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
for (int i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
if (_this->hidden->buffers[i].available == 0) {
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
@@ -392,11 +379,10 @@ enqueue_buffers(SDL_CameraDevice *_this)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_enqueue_buffers(SDL_CameraDevice *_this)
|
||||
static int PreEnqueueBuffers(SDL_CameraDevice *_this)
|
||||
{
|
||||
struct v4l2_requestbuffers req;
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
|
||||
switch (io) {
|
||||
@@ -404,41 +390,37 @@ pre_enqueue_buffers(SDL_CameraDevice *_this)
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
{
|
||||
SDL_zero(req);
|
||||
req.count = _this->hidden->nb_buffers;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
SDL_zero(req);
|
||||
req.count = _this->hidden->nb_buffers;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
|
||||
if (errno == EINVAL) {
|
||||
return SDL_SetError("Does not support memory mapping");
|
||||
} else {
|
||||
return SDL_SetError("VIDIOC_REQBUFS");
|
||||
}
|
||||
if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
|
||||
if (errno == EINVAL) {
|
||||
return SDL_SetError("Does not support memory mapping");
|
||||
} else {
|
||||
return SDL_SetError("VIDIOC_REQBUFS");
|
||||
}
|
||||
|
||||
if (req.count < 2) {
|
||||
return SDL_SetError("Insufficient buffer memory");
|
||||
}
|
||||
|
||||
_this->hidden->nb_buffers = req.count;
|
||||
}
|
||||
|
||||
if (req.count < 2) {
|
||||
return SDL_SetError("Insufficient buffer memory");
|
||||
}
|
||||
|
||||
_this->hidden->nb_buffers = req.count;
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
{
|
||||
SDL_zero(req);
|
||||
req.count = _this->hidden->nb_buffers;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
SDL_zero(req);
|
||||
req.count = _this->hidden->nb_buffers;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
|
||||
if (errno == EINVAL) {
|
||||
return SDL_SetError("Does not support user pointer i/o");
|
||||
} else {
|
||||
return SDL_SetError("VIDIOC_REQBUFS");
|
||||
}
|
||||
if (xioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
|
||||
if (errno == EINVAL) {
|
||||
return SDL_SetError("Does not support user pointer i/o");
|
||||
} else {
|
||||
return SDL_SetError("VIDIOC_REQBUFS");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -446,34 +428,31 @@ pre_enqueue_buffers(SDL_CameraDevice *_this)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
StartCamera(SDL_CameraDevice *_this)
|
||||
int StartCamera(SDL_CameraDevice *_this)
|
||||
{
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
int fd = _this->hidden->fd;
|
||||
const int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
|
||||
|
||||
if (_this->hidden->first_start == 0) {
|
||||
_this->hidden->first_start = 1;
|
||||
} else {
|
||||
int old = _this->hidden->nb_buffers;
|
||||
const int old = _this->hidden->nb_buffers;
|
||||
// TODO mmap; doesn't work with stop->start
|
||||
#if 1
|
||||
/* Can change nb_buffers for mmap */
|
||||
if (pre_enqueue_buffers(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (old != _this->hidden->nb_buffers) {
|
||||
SDL_SetError("different nb of buffers requested");
|
||||
// Can change nb_buffers for mmap
|
||||
if (PreEnqueueBuffers(_this) < 0) {
|
||||
return -1;
|
||||
} else if (old != _this->hidden->nb_buffers) {
|
||||
return SDL_SetError("different nb of buffers requested");
|
||||
}
|
||||
#endif
|
||||
_this->hidden->first_start = 1;
|
||||
}
|
||||
|
||||
if (enqueue_buffers(_this) < 0) {
|
||||
if (EnqueueBuffers(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -493,7 +472,7 @@ StartCamera(SDL_CameraDevice *_this)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alloc_buffer_read(SDL_CameraDevice *_this, size_t buffer_size)
|
||||
static int AllocBufferRead(SDL_CameraDevice *_this, size_t buffer_size)
|
||||
{
|
||||
_this->hidden->buffers[0].length = buffer_size;
|
||||
_this->hidden->buffers[0].start = SDL_calloc(1, buffer_size);
|
||||
@@ -505,7 +484,7 @@ static int alloc_buffer_read(SDL_CameraDevice *_this, size_t buffer_size)
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_buffer_mmap(SDL_CameraDevice *_this)
|
||||
AllocBufferMmap(SDL_CameraDevice *_this)
|
||||
{
|
||||
int fd = _this->hidden->fd;
|
||||
int i;
|
||||
@@ -538,7 +517,7 @@ alloc_buffer_mmap(SDL_CameraDevice *_this)
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_buffer_userp(SDL_CameraDevice *_this, size_t buffer_size)
|
||||
AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
@@ -708,12 +687,12 @@ GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec)
|
||||
SDL_zero(fmt);
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
/* Preserve original settings as set by v4l2-ctl for example */
|
||||
// Preserve original settings as set by v4l2-ctl for example
|
||||
if (xioctl(fd, VIDIOC_G_FMT, &fmt) == -1) {
|
||||
return SDL_SetError("Error VIDIOC_G_FMT");
|
||||
}
|
||||
|
||||
/* Buggy driver paranoia. */
|
||||
// Buggy driver paranoia.
|
||||
min = fmt.fmt.pix.width * 2;
|
||||
if (fmt.fmt.pix.bytesperline < min) {
|
||||
fmt.fmt.pix.bytesperline = min;
|
||||
@@ -739,29 +718,29 @@ InitDevice(SDL_CameraDevice *_this)
|
||||
|
||||
int fd = _this->hidden->fd;
|
||||
enum io_method io = _this->hidden->io;
|
||||
int ret = -1;
|
||||
int retval = -1;
|
||||
|
||||
/* Select video input, video standard and tune here. */
|
||||
// Select video input, video standard and tune here.
|
||||
SDL_zero(cropcap);
|
||||
|
||||
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if (xioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0) {
|
||||
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
crop.c = cropcap.defrect; /* reset to default */
|
||||
crop.c = cropcap.defrect; // reset to default
|
||||
|
||||
if (xioctl(fd, VIDIOC_S_CROP, &crop) == -1) {
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
/* Cropping not supported. */
|
||||
// Cropping not supported.
|
||||
break;
|
||||
default:
|
||||
/* Errors ignored. */
|
||||
// Errors ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Errors ignored. */
|
||||
// Errors ignored.
|
||||
}
|
||||
|
||||
|
||||
@@ -790,7 +769,7 @@ InitDevice(SDL_CameraDevice *_this)
|
||||
|
||||
GetDeviceSpec(_this, &_this->spec);
|
||||
|
||||
if (pre_enqueue_buffers(_this) < 0) {
|
||||
if (PreEnqueueBuffers(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -807,28 +786,23 @@ InitDevice(SDL_CameraDevice *_this)
|
||||
|
||||
switch (io) {
|
||||
case IO_METHOD_READ:
|
||||
ret = alloc_buffer_read(_this, size);
|
||||
retval = AllocBufferRead(_this, size);
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
ret = alloc_buffer_mmap(_this);
|
||||
retval = AllocBufferMmap(_this);
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
ret = alloc_buffer_userp(_this, size);
|
||||
retval = AllocBufferUserPtr(_this, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (retval < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
CloseDevice(SDL_CameraDevice *_this)
|
||||
void CloseDevice(SDL_CameraDevice *_this)
|
||||
{
|
||||
if (!_this) {
|
||||
return;
|
||||
@@ -836,7 +810,6 @@ CloseDevice(SDL_CameraDevice *_this)
|
||||
|
||||
if (_this->hidden) {
|
||||
if (_this->hidden->buffers) {
|
||||
int i;
|
||||
enum io_method io = _this->hidden->io;
|
||||
|
||||
switch (io) {
|
||||
@@ -845,7 +818,7 @@ CloseDevice(SDL_CameraDevice *_this)
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
for (int i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
if (munmap(_this->hidden->buffers[i].start, _this->hidden->buffers[i].length) == -1) {
|
||||
SDL_SetError("munmap");
|
||||
}
|
||||
@@ -853,7 +826,7 @@ CloseDevice(SDL_CameraDevice *_this)
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
for (i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
for (int i = 0; i < _this->hidden->nb_buffers; ++i) {
|
||||
SDL_free(_this->hidden->buffers[i].start);
|
||||
}
|
||||
break;
|
||||
@@ -864,7 +837,7 @@ CloseDevice(SDL_CameraDevice *_this)
|
||||
|
||||
if (_this->hidden->fd != -1) {
|
||||
if (close(_this->hidden->fd)) {
|
||||
SDL_SetError("close camera device");
|
||||
SDL_SetError("close camera device"); // !!! FIXME: we probably won't ever see this error
|
||||
}
|
||||
}
|
||||
SDL_free(_this->hidden);
|
||||
@@ -874,13 +847,12 @@ CloseDevice(SDL_CameraDevice *_this)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
OpenDevice(SDL_CameraDevice *_this)
|
||||
int OpenDevice(SDL_CameraDevice *_this)
|
||||
{
|
||||
struct stat st;
|
||||
struct v4l2_capability cap;
|
||||
int fd;
|
||||
enum io_method io;
|
||||
int fd;
|
||||
|
||||
_this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData));
|
||||
if (_this->hidden == NULL) {
|
||||
@@ -891,19 +863,11 @@ OpenDevice(SDL_CameraDevice *_this)
|
||||
_this->hidden->fd = -1;
|
||||
|
||||
if (stat(_this->dev_name, &st) == -1) {
|
||||
SDL_SetError("Cannot identify '%s': %d, %s", _this->dev_name, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
SDL_SetError("%s is no device", _this->dev_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(_this->dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
|
||||
if (fd == -1) {
|
||||
SDL_SetError("Cannot open '%s': %d, %s", _this->dev_name, errno, strerror(errno));
|
||||
return -1;
|
||||
return SDL_SetError("Cannot identify '%s': %d, %s", _this->dev_name, errno, strerror(errno));
|
||||
} else if (!S_ISCHR(st.st_mode)) {
|
||||
return SDL_SetError("%s is no device", _this->dev_name);
|
||||
} else if ((fd = open(_this->dev_name, O_RDWR /* required */ | O_NONBLOCK, 0)) == -1) {
|
||||
return SDL_SetError("Cannot open '%s': %d, %s", _this->dev_name, errno, strerror(errno));
|
||||
}
|
||||
|
||||
_this->hidden->fd = fd;
|
||||
@@ -914,7 +878,7 @@ OpenDevice(SDL_CameraDevice *_this)
|
||||
if (_this->hidden->io == IO_METHOD_READ) {
|
||||
_this->hidden->nb_buffers = 1;
|
||||
} else {
|
||||
_this->hidden->nb_buffers = 8; /* Number of image as internal buffer, */
|
||||
_this->hidden->nb_buffers = 8; // Number of image as internal buffer,
|
||||
}
|
||||
io = _this->hidden->io;
|
||||
|
||||
@@ -954,14 +918,10 @@ OpenDevice(SDL_CameraDevice *_this)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size)
|
||||
int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size)
|
||||
{
|
||||
SDL_cameralist_item *item;
|
||||
for (item = SDL_cameralist; item; item = item->next) {
|
||||
@@ -971,54 +931,46 @@ GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size)
|
||||
}
|
||||
}
|
||||
|
||||
/* unknown instance_id */
|
||||
// unknown instance_id
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SDL_CameraDeviceID *GetCameraDevices(int *count)
|
||||
{
|
||||
/* real list of ID */
|
||||
int i = 0;
|
||||
int num = num_cameras;
|
||||
SDL_CameraDeviceID *ret;
|
||||
SDL_cameralist_item *item;
|
||||
// real list of ID
|
||||
const int num = num_cameras;
|
||||
SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*retval));
|
||||
|
||||
ret = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (item = SDL_cameralist; item; item = item->next) {
|
||||
ret[i] = item->instance_id;
|
||||
i++;
|
||||
int i = 0;
|
||||
for (SDL_cameralist_item *item = SDL_cameralist; item; item = item->next) {
|
||||
retval[i++] = item->instance_id;
|
||||
}
|
||||
|
||||
ret[num] = 0;
|
||||
retval[num] = 0;
|
||||
*count = num;
|
||||
return ret;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the subsystem by finding available devices.
|
||||
*/
|
||||
// Initializes the subsystem by finding available devices.
|
||||
int SDL_SYS_CameraInit(void)
|
||||
{
|
||||
const char pattern[] = "/dev/video%d";
|
||||
char path[PATH_MAX];
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* Limit amount of checks to MAX_CAMERA_DEVICES since we may or may not have
|
||||
* permission to some or all devices.
|
||||
*/
|
||||
i = 0;
|
||||
for (j = 0; j < MAX_CAMERA_DEVICES; ++j) {
|
||||
(void)SDL_snprintf(path, PATH_MAX, pattern, i++);
|
||||
for (int i = 0; i < MAX_CAMERA_DEVICES; i++) {
|
||||
(void)SDL_snprintf(path, PATH_MAX, pattern, i);
|
||||
if (MaybeAddDevice(path) == -2) {
|
||||
break;
|
||||
}
|
||||
@@ -1027,27 +979,22 @@ int SDL_SYS_CameraInit(void)
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
return SDL_SetError("Could not initialize UDEV");
|
||||
}
|
||||
|
||||
if (SDL_UDEV_AddCallback(camera_udev_callback) < 0) {
|
||||
} else if (SDL_UDEV_AddCallback(CameraUdevCallback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("Could not setup Video Capture <-> udev callback");
|
||||
}
|
||||
|
||||
/* Force a scan to build the initial device list */
|
||||
// Force a scan to build the initial device list
|
||||
SDL_UDEV_Scan();
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
#endif // SDL_USE_LIBUDEV
|
||||
|
||||
return num_cameras;
|
||||
}
|
||||
|
||||
|
||||
int SDL_SYS_CameraQuit(void)
|
||||
{
|
||||
SDL_cameralist_item *item;
|
||||
for (item = SDL_cameralist; item; ) {
|
||||
for (SDL_cameralist_item *item = SDL_cameralist; item; ) {
|
||||
SDL_cameralist_item *tmp = item->next;
|
||||
|
||||
SDL_free(item->fname);
|
||||
SDL_free(item->bus_info);
|
||||
SDL_free(item);
|
||||
@@ -1062,7 +1009,7 @@ int SDL_SYS_CameraQuit(void)
|
||||
}
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
static void camera_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
|
||||
static void CameraUdevCallback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
|
||||
{
|
||||
if (!devpath || !(udev_class & SDL_UDEV_DEVICE_VIDEO_CAPTURE)) {
|
||||
return;
|
||||
@@ -1081,17 +1028,15 @@ static void camera_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
#endif // SDL_USE_LIBUDEV
|
||||
|
||||
static SDL_bool DeviceExists(const char *path, const char *bus_info) {
|
||||
SDL_cameralist_item *item;
|
||||
|
||||
for (item = SDL_cameralist; item; item = item->next) {
|
||||
/* found same dev name */
|
||||
for (SDL_cameralist_item *item = SDL_cameralist; item; item = item->next) {
|
||||
// found same dev name
|
||||
if (SDL_strcmp(path, item->fname) == 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
/* found same bus_info */
|
||||
// found same bus_info
|
||||
if (SDL_strcmp(bus_info, item->bus_info) == 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
@@ -1113,7 +1058,7 @@ static int MaybeAddDevice(const char *path)
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
return -2; /* stop iterating /dev/video%d */
|
||||
return -2; // stop iterating /dev/video%d
|
||||
}
|
||||
err = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
|
||||
close(fd);
|
||||
@@ -1129,7 +1074,7 @@ static int MaybeAddDevice(const char *path)
|
||||
}
|
||||
|
||||
|
||||
/* Add new item */
|
||||
// Add new item
|
||||
item = (SDL_cameralist_item *)SDL_calloc(1, sizeof(SDL_cameralist_item));
|
||||
if (!item) {
|
||||
SDL_free(bus_info);
|
||||
@@ -1157,7 +1102,7 @@ static int MaybeAddDevice(const char *path)
|
||||
|
||||
++num_cameras;
|
||||
|
||||
/* !!! TODO: Send a add event? */
|
||||
// !!! TODO: Send a add event?
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("Added video camera ID: %d %s (%s) (total: %d)", item->instance_id, path, bus_info, num_cameras);
|
||||
#endif
|
||||
@@ -1178,7 +1123,7 @@ static int MaybeRemoveDevice(const char *path)
|
||||
}
|
||||
|
||||
for (item = SDL_cameralist; item; item = item->next) {
|
||||
/* found it, remove it. */
|
||||
// found it, remove it.
|
||||
if (SDL_strcmp(path, item->fname) == 0) {
|
||||
if (prev) {
|
||||
prev->next = item->next;
|
||||
@@ -1190,9 +1135,9 @@ static int MaybeRemoveDevice(const char *path)
|
||||
SDL_cameralist_tail = prev;
|
||||
}
|
||||
|
||||
/* Need to decrement the count */
|
||||
// Need to decrement the count
|
||||
--num_cameras;
|
||||
/* !!! TODO: Send a remove event? */
|
||||
// !!! TODO: Send a remove event?
|
||||
|
||||
SDL_free(item->fname);
|
||||
SDL_free(item->bus_info);
|
||||
@@ -1203,6 +1148,7 @@ static int MaybeRemoveDevice(const char *path)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
#endif // SDL_USE_LIBUDEV
|
||||
|
||||
#endif // SDL_CAMERA_V4L2
|
||||
|
||||
#endif /* SDL_CAMERA_V4L2 */
|
||||
|
Reference in New Issue
Block a user