[vlc-commits] [Git][videolan/vlc][master] 3 commits: v4l2: demux: stop when the device stops
Steve Lhomme (@robUx4)
gitlab at videolan.org
Wed Sep 2 03:18:28 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
df9d0412 by Alexandre Janniaux at 2026-09-02T03:00:48+00:00
v4l2: demux: stop when the device stops
When a device being poll()ed is unplugged, every poll() will report
POLLERR/POLLHUP and no new frames will ever be reported, leading to the
capture thread busy spinning.
Reproduced on a Logitech USB camera 046d:0825 and framework webcam with
a kill switch, capturing with
vlc -vv v4l2:///dev/video1
Note that it still doesn't trigger eof since there is no way for
asynchronous demux like v4l2 to do so currently.
- - - - -
36f6f30e by Alexandre Janniaux at 2026-09-02T03:00:48+00:00
v4l2: demux: error out when poll() fails
poll() can return EINTR, in which case we might want to retry, but when
it returns another error, we really want to exit the loop as the loop
called with the same arguments will become a busy loop.
This was introduced in 855f0b7d11bd63d929cefea112a0754fdeed3618 which
fixed the polling loop timeout and rewrote the loop as it is currently.
- - - - -
a150ca72 by Alexandre Janniaux at 2026-09-02T03:00:48+00:00
v4l2: demux: fix error reporting
If the block cannot be allocated, vlc_strerror_c will not report the
proper error since it would depend on how the block is allocated. Since
the amount allocated might also be a reason why this is reported as an
error, printing it in this case would help debugging too.
- - - - -
1 changed file:
- modules/access/v4l2/demux.c
Changes:
=====================================
modules/access/v4l2/demux.c
=====================================
@@ -85,12 +85,22 @@ static void *MmapThread(void *data)
/* Wait for data */
if (poll(ufd, numfds, -1) == -1)
{
- if (errno != EINTR)
- msg_Err(demux, "poll error: %s", vlc_strerror_c(errno));
- continue;
+ if (errno == EINTR)
+ continue;
+
+ msg_Err(demux, "poll error: %s", vlc_strerror_c(errno));
+ break;
+ }
+
+ if (ufd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ /* The device is gone, and poll will always return the same
+ * answer now . */
+ msg_Err(demux, "device unavailable");
+ break;
}
- if (ufd[0].revents)
+ if (ufd[0].revents & POLLIN)
{
int canc = vlc_savecancel();
block_t *block = GrabVideo(VLC_OBJECT(demux), sys->pool);
@@ -103,12 +113,21 @@ static void *MmapThread(void *data)
vlc_restorecancel(canc);
}
#ifdef ZVBI_COMPILED
- if (sys->vbi != NULL && ufd[1].revents)
- GrabVBI(demux, sys->vbi);
+ if (sys->vbi != NULL)
+ {
+ if (ufd[1].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ msg_Err(demux, "VBI device unavailable");
+ break;
+ }
+
+ if (ufd[1].revents & POLLIN)
+ GrabVBI(demux, sys->vbi);
+ }
#endif
}
- vlc_assert_unreachable();
+ return NULL;
}
static void *ReadThread(void *data)
@@ -138,17 +157,28 @@ static void *ReadThread(void *data)
/* Wait for data */
if (poll(ufd, numfds, -1) == -1)
{
- if (errno != EINTR)
- msg_Err(demux, "poll error: %s", vlc_strerror_c(errno));
- continue;
+ if (errno == EINTR)
+ continue;
+
+ msg_Err(demux, "poll error: %s", vlc_strerror_c(errno));
+ break;
+ }
+
+ if (ufd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ /* The device is gone, and poll will always return the same
+ * answer now . */
+ msg_Err(demux, "device unavailable");
+ break;
}
- if (ufd[0].revents)
+ if (ufd[0].revents & POLLIN)
{
block_t *block = block_Alloc(sys->blocksize);
if (unlikely(block == NULL))
{
- msg_Err(demux, "read error: %s", vlc_strerror_c(errno));
+ msg_Err(demux, "read error: cannot allocate a %"PRIu32" byte block",
+ sys->blocksize);
v4l2_read(fd, NULL, 0); /* discard frame */
continue;
}
@@ -168,11 +198,21 @@ static void *ReadThread(void *data)
vlc_restorecancel(canc);
}
#ifdef ZVBI_COMPILED
- if (sys->vbi != NULL && ufd[1].revents)
- GrabVBI(demux, sys->vbi);
+ if (sys->vbi != NULL)
+ {
+ if (ufd[1].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ msg_Err(demux, "VBI device error");
+ break;
+ }
+
+ if (ufd[1].revents & POLLIN)
+ GrabVBI(demux, sys->vbi);
+ }
#endif
}
- vlc_assert_unreachable();
+
+ return NULL;
}
static int DemuxControl( demux_t *demux, int query, va_list args )
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/298ebb401368cebddf1608aa64c7bba71cfcfc28...a150ca725406c5ffb20dc3081c8f6b10dc1ff960
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/298ebb401368cebddf1608aa64c7bba71cfcfc28...a150ca725406c5ffb20dc3081c8f6b10dc1ff960
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list