mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
v4l2: reuse fd when opening the same path
When we open the same device multiple times, reuse the file structure and dup the fd.
This commit is contained in:
parent
4cb1c790a4
commit
0f13d5a65e
1 changed files with 58 additions and 20 deletions
|
|
@ -259,6 +259,8 @@ static struct file *make_file(void)
|
|||
|
||||
static void free_file(struct file *file)
|
||||
{
|
||||
pw_log_info("fd:%d", file->fd);
|
||||
|
||||
if (file->loop)
|
||||
pw_thread_loop_stop(file->loop);
|
||||
|
||||
|
|
@ -287,6 +289,7 @@ static void free_file(struct file *file)
|
|||
|
||||
static void unref_file(struct file *file)
|
||||
{
|
||||
pw_log_debug("fd:%d ref:%d", file->fd, file->ref);
|
||||
if (ATOMIC_DEC(file->ref) <= 0)
|
||||
free_file(file);
|
||||
}
|
||||
|
|
@ -300,6 +303,7 @@ static int add_fd_map(int fd, struct file *file)
|
|||
map->fd = fd;
|
||||
map->file = file;
|
||||
ATOMIC_INC(file->ref);
|
||||
pw_log_debug("fd:%d (%d) ref:%d", fd, file->fd, file->ref);
|
||||
}
|
||||
pthread_mutex_unlock(&globals.lock);
|
||||
return 0;
|
||||
|
|
@ -331,14 +335,13 @@ static bool add_dev_for_serial(uint32_t dev, uint32_t serial)
|
|||
static struct fd_map *find_fd_map_unlocked(int fd)
|
||||
{
|
||||
struct fd_map *map;
|
||||
|
||||
pw_array_for_each(map, &globals.fd_maps) {
|
||||
if (map->fd == fd) {
|
||||
ATOMIC_INC(map->file->ref);
|
||||
pw_log_debug("fd:%d find:%d ref:%d", map->fd, fd, map->file->ref);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -357,6 +360,30 @@ static struct file *find_file(int fd)
|
|||
return file;
|
||||
}
|
||||
|
||||
static struct file *find_file_by_dev(uint32_t dev)
|
||||
{
|
||||
struct fd_map *map = NULL, *tmp;
|
||||
struct file *file = NULL;
|
||||
|
||||
pthread_mutex_lock(&globals.lock);
|
||||
pw_array_for_each(tmp, &globals.fd_maps) {
|
||||
if (tmp->file->dev_id == dev) {
|
||||
if (tmp->file->fd == -1)
|
||||
tmp->file->fd = tmp->fd;
|
||||
ATOMIC_INC(tmp->file->ref);
|
||||
map = tmp;
|
||||
pw_log_debug("dev:%d find:%d ref:%d",
|
||||
tmp->file->dev_id, dev, tmp->file->ref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (map != NULL)
|
||||
file = map->file;
|
||||
pthread_mutex_unlock(&globals.lock);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static struct file *remove_fd_map(int fd)
|
||||
{
|
||||
pthread_mutex_lock(&globals.lock);
|
||||
|
|
@ -366,6 +393,7 @@ static struct file *remove_fd_map(int fd)
|
|||
|
||||
if (map != NULL) {
|
||||
file = map->file;
|
||||
pw_log_debug("fd:%d find:%d", map->fd, fd);
|
||||
pw_array_remove(&globals.fd_maps, map);
|
||||
}
|
||||
|
||||
|
|
@ -701,6 +729,24 @@ static const struct pw_registry_events registry_events = {
|
|||
.global_remove = registry_event_global_remove,
|
||||
};
|
||||
|
||||
static int v4l2_dup(int oldfd)
|
||||
{
|
||||
int res;
|
||||
struct file *file;
|
||||
|
||||
res = globals.old_fops.dup(oldfd);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
if ((file = find_file(oldfd)) != NULL) {
|
||||
add_fd_map(res, file);
|
||||
unref_file(file);
|
||||
pw_log_info("fd:%d -> %d (%s)", oldfd,
|
||||
res, strerror(res < 0 ? errno : 0));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
||||
{
|
||||
int res;
|
||||
|
|
@ -715,6 +761,12 @@ static int v4l2_openat(int dirfd, const char *path, int oflag, mode_t mode)
|
|||
if (passthrough)
|
||||
return globals.old_fops.openat(dirfd, path, oflag, mode);
|
||||
|
||||
if ((file = find_file_by_dev(dev_id)) != NULL) {
|
||||
res = v4l2_dup(file->fd);
|
||||
unref_file(file);
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((file = make_file()) == NULL)
|
||||
goto error;
|
||||
|
||||
|
|
@ -792,24 +844,6 @@ error:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int v4l2_dup(int oldfd)
|
||||
{
|
||||
int res;
|
||||
struct file *file;
|
||||
|
||||
res = globals.old_fops.dup(oldfd);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
if ((file = find_file(oldfd)) != NULL) {
|
||||
add_fd_map(res, file);
|
||||
unref_file(file);
|
||||
pw_log_info("fd:%d -> %d (%s)", oldfd,
|
||||
res, strerror(res < 0 ? errno : 0));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int v4l2_close(int fd)
|
||||
{
|
||||
struct file *file;
|
||||
|
|
@ -817,8 +851,12 @@ static int v4l2_close(int fd)
|
|||
if ((file = remove_fd_map(fd)) == NULL)
|
||||
return globals.old_fops.close(fd);
|
||||
|
||||
pw_log_info("fd:%d (%d)", fd, file->fd);
|
||||
|
||||
if (fd != file->fd)
|
||||
spa_system_close(file->l->system, fd);
|
||||
else
|
||||
file->fd = -1;
|
||||
|
||||
unref_file(file);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue