mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
v4l2: pretend a dupped fd is the same as the original one
This makes it possible to reqbufs on a dupped fd with previously reqbufs.
This commit is contained in:
parent
492920ca35
commit
6bae31e519
1 changed files with 29 additions and 11 deletions
|
|
@ -65,6 +65,8 @@ struct file_map {
|
||||||
|
|
||||||
struct fd_map {
|
struct fd_map {
|
||||||
int fd;
|
int fd;
|
||||||
|
#define FD_MAP_DUP (1<<0)
|
||||||
|
uint32_t flags;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -321,13 +323,14 @@ static void unref_file(struct file *file)
|
||||||
free_file(file);
|
free_file(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_fd_map(int fd, struct file *file)
|
static int add_fd_map(int fd, struct file *file, uint32_t flags)
|
||||||
{
|
{
|
||||||
struct fd_map *map;
|
struct fd_map *map;
|
||||||
pthread_mutex_lock(&globals.lock);
|
pthread_mutex_lock(&globals.lock);
|
||||||
map = pw_array_add(&globals.fd_maps, sizeof(*map));
|
map = pw_array_add(&globals.fd_maps, sizeof(*map));
|
||||||
if (map != NULL) {
|
if (map != NULL) {
|
||||||
map->fd = fd;
|
map->fd = fd;
|
||||||
|
map->flags = flags;
|
||||||
map->file = file;
|
map->file = file;
|
||||||
ATOMIC_INC(file->ref);
|
ATOMIC_INC(file->ref);
|
||||||
pw_log_debug("fd:%d -> file:%d ref:%d", fd, file->fd, file->ref);
|
pw_log_debug("fd:%d -> file:%d ref:%d", fd, file->fd, file->ref);
|
||||||
|
|
@ -372,15 +375,17 @@ static struct fd_map *find_fd_map_unlocked(int fd)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file *find_file(int fd)
|
static struct file *find_file(int fd, uint32_t *flags)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&globals.lock);
|
pthread_mutex_lock(&globals.lock);
|
||||||
|
|
||||||
struct fd_map *map = find_fd_map_unlocked(fd);
|
struct fd_map *map = find_fd_map_unlocked(fd);
|
||||||
struct file *file = NULL;
|
struct file *file = NULL;
|
||||||
|
|
||||||
if (map != NULL)
|
if (map != NULL) {
|
||||||
file = map->file;
|
file = map->file;
|
||||||
|
*flags = map->flags;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&globals.lock);
|
pthread_mutex_unlock(&globals.lock);
|
||||||
|
|
||||||
|
|
@ -756,24 +761,30 @@ static const struct pw_registry_events registry_events = {
|
||||||
.global_remove = registry_event_global_remove,
|
.global_remove = registry_event_global_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int v4l2_dup(int oldfd)
|
static int do_dup(int oldfd, uint32_t flags)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
uint32_t fl;
|
||||||
|
|
||||||
res = globals.old_fops.dup(oldfd);
|
res = globals.old_fops.dup(oldfd);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if ((file = find_file(oldfd)) != NULL) {
|
if ((file = find_file(oldfd, &fl)) != NULL) {
|
||||||
add_fd_map(res, file);
|
add_fd_map(res, file, flags | fl);
|
||||||
unref_file(file);
|
unref_file(file);
|
||||||
pw_log_info("fd:%d -> %d (%s)", oldfd,
|
pw_log_info("fd:%d %08x -> %d (%s)", oldfd, flags,
|
||||||
res, strerror(res < 0 ? errno : 0));
|
res, strerror(res < 0 ? errno : 0));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int v4l2_dup(int oldfd)
|
||||||
|
{
|
||||||
|
return do_dup(oldfd, FD_MAP_DUP);
|
||||||
|
}
|
||||||
|
|
||||||
static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
||||||
{
|
{
|
||||||
int res, flags;
|
int res, flags;
|
||||||
|
|
@ -788,8 +799,10 @@ static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
||||||
if (passthrough)
|
if (passthrough)
|
||||||
return globals.old_fops.openat(dirfd, path, oflag, mode);
|
return globals.old_fops.openat(dirfd, path, oflag, mode);
|
||||||
|
|
||||||
|
pw_log_info("path:%s oflag:%d mode:%d", path, oflag, mode);
|
||||||
|
|
||||||
if ((file = find_file_by_dev(dev_id)) != NULL) {
|
if ((file = find_file_by_dev(dev_id)) != NULL) {
|
||||||
res = v4l2_dup(file->fd);
|
res = do_dup(file->fd, 0);
|
||||||
unref_file(file);
|
unref_file(file);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
fcntl(res, F_SETFL, oflag);
|
fcntl(res, F_SETFL, oflag);
|
||||||
|
|
@ -858,7 +871,7 @@ static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
||||||
pw_log_info("path:%s oflag:%d mode:%d -> %d (%s)", path, oflag, mode,
|
pw_log_info("path:%s oflag:%d mode:%d -> %d (%s)", path, oflag, mode,
|
||||||
res, strerror(res < 0 ? errno : 0));
|
res, strerror(res < 0 ? errno : 0));
|
||||||
|
|
||||||
add_fd_map(res, file);
|
add_fd_map(res, file, 0);
|
||||||
add_dev_for_serial(file->dev_id, file->serial);
|
add_dev_for_serial(file->dev_id, file->serial);
|
||||||
unref_file(file);
|
unref_file(file);
|
||||||
|
|
||||||
|
|
@ -1997,8 +2010,9 @@ static int v4l2_ioctl(int fd, unsigned long int request, void *arg)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
if ((file = find_file(fd)) == NULL)
|
if ((file = find_file(fd, &flags)) == NULL)
|
||||||
return globals.old_fops.ioctl(fd, request, arg);
|
return globals.old_fops.ioctl(fd, request, arg);
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
|
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
|
||||||
|
|
@ -2010,6 +2024,9 @@ static int v4l2_ioctl(int fd, unsigned long int request, void *arg)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & FD_MAP_DUP)
|
||||||
|
fd = file->fd;
|
||||||
|
|
||||||
switch (request & 0xffffffff) {
|
switch (request & 0xffffffff) {
|
||||||
case VIDIOC_QUERYCAP:
|
case VIDIOC_QUERYCAP:
|
||||||
res = vidioc_querycap(file, (struct v4l2_capability *)arg);
|
res = vidioc_querycap(file, (struct v4l2_capability *)arg);
|
||||||
|
|
@ -2089,8 +2106,9 @@ static void *v4l2_mmap(void *addr, size_t length, int prot,
|
||||||
struct pw_map_range range;
|
struct pw_map_range range;
|
||||||
struct buffer *buf;
|
struct buffer *buf;
|
||||||
struct spa_data *data;
|
struct spa_data *data;
|
||||||
|
uint32_t fl;
|
||||||
|
|
||||||
if ((file = find_file(fd)) == NULL)
|
if ((file = find_file(fd, &fl)) == NULL)
|
||||||
return globals.old_fops.mmap(addr, length, prot, flags, fd, offset);
|
return globals.old_fops.mmap(addr, length, prot, flags, fd, offset);
|
||||||
|
|
||||||
pw_thread_loop_lock(file->loop);
|
pw_thread_loop_lock(file->loop);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue