[vlc-commits] v4l2: use thread instead of polling
Rémi Denis-Courmont
git at videolan.org
Tue Apr 10 22:15:09 CEST 2012
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Apr 10 23:10:55 2012 +0300| [855f0b7d11bd63d929cefea112a0754fdeed3618] | committer: Rémi Denis-Courmont
v4l2: use thread instead of polling
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=855f0b7d11bd63d929cefea112a0754fdeed3618
---
modules/access/v4l2/demux.c | 188 ++++++++++++++++++++++++-------------------
modules/access/v4l2/v4l2.h | 1 +
2 files changed, 105 insertions(+), 84 deletions(-)
diff --git a/modules/access/v4l2/demux.c b/modules/access/v4l2/demux.c
index 45ff4fc..8c14920 100644
--- a/modules/access/v4l2/demux.c
+++ b/modules/access/v4l2/demux.c
@@ -41,8 +41,9 @@
#include "v4l2.h"
+static void *StreamThread (void *);
+static void *ReadThread (void *);
static int DemuxControl( demux_t *, int, va_list );
-static int Demux( demux_t * );
static int InitVideo (demux_t *, int);
int DemuxOpen( vlc_object_t *obj )
@@ -86,7 +87,7 @@ int DemuxOpen( vlc_object_t *obj )
sys->i_fd = fd;
sys->controls = ControlsInit (VLC_OBJECT(demux), fd);
- demux->pf_demux = Demux;
+ demux->pf_demux = NULL;
demux->pf_control = DemuxControl;
demux->info.i_update = 0;
demux->info.i_title = 0;
@@ -256,7 +257,6 @@ static void GetAR (int fd, unsigned *restrict num, unsigned *restrict den)
static int InitVideo (demux_t *demux, int fd)
{
demux_sys_t *sys = demux->p_sys;
- enum v4l2_buf_type buf_type;
/* Get device capabilites */
struct v4l2_capability cap;
@@ -291,16 +291,6 @@ static int InitVideo (demux_t *demux, int fd)
return -1;
}
- if (caps & V4L2_CAP_STREAMING)
- sys->io = IO_METHOD_MMAP;
- else if (caps & V4L2_CAP_READWRITE)
- sys->io = IO_METHOD_READ;
- else
- {
- msg_Err (demux, "no supported I/O method");
- return -1;
- }
-
if (SetupInput (VLC_OBJECT(demux), fd))
return -1;
@@ -437,13 +427,9 @@ static int InitVideo (demux_t *demux, int fd)
sys->p_es = es_out_Add (demux->out, &es_fmt);
/* Init I/O method */
- switch (sys->io)
+ void *(*entry) (void *);
+ if (caps & V4L2_CAP_STREAMING)
{
- case IO_METHOD_READ:
- sys->blocksize = fmt.fmt.pix.sizeimage;
- break;
-
- case IO_METHOD_MMAP:
if (InitMmap (VLC_OBJECT(demux), sys, fd))
return -1;
for (unsigned int i = 0; i < sys->i_nbuffers; i++)
@@ -461,18 +447,30 @@ static int InitVideo (demux_t *demux, int fd)
}
}
- buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (v4l2_ioctl (fd, VIDIOC_STREAMON, &buf_type) < 0)
{
msg_Err (demux, "cannot start streaming: %m");
return -1;
}
- break;
- default:
- assert (0);
+ sys->io = IO_METHOD_MMAP;
+ entry = StreamThread;
+ }
+ else if (caps & V4L2_CAP_READWRITE)
+ {
+ sys->blocksize = fmt.fmt.pix.sizeimage;
+ sys->io = IO_METHOD_READ;
+ entry = ReadThread;
+ }
+ else
+ {
+ msg_Err (demux, "no supported I/O method");
+ return -1;
}
+ if (vlc_clone (&sys->thread, entry, demux, VLC_THREAD_PRIORITY_INPUT))
+ return -1;
return 0;
}
@@ -482,6 +480,9 @@ void DemuxClose( vlc_object_t *obj )
demux_sys_t *sys = demux->p_sys;
int fd = sys->i_fd;
+ vlc_cancel (sys->thread);
+ vlc_join (sys->thread, NULL);
+
/* Stop video capture */
switch( sys->io )
{
@@ -529,6 +530,86 @@ void DemuxClose( vlc_object_t *obj )
free( sys );
}
+static void *StreamThread (void *data)
+{
+ demux_t *demux = data;
+ demux_sys_t *sys = demux->p_sys;
+ int fd = sys->i_fd;
+ struct pollfd ufd[1];
+
+ ufd[0].fd = fd;
+ ufd[0].events = POLLIN | POLLPRI;
+
+ for (;;)
+ {
+ /* Wait for data */
+ if (poll (ufd, 1, -1) == -1)
+ {
+ if (errno != EINTR)
+ msg_Err (demux, "poll error: %m");
+ continue;
+ }
+
+ int canc = vlc_savecancel ();
+ block_t *block = GrabVideo (VLC_OBJECT(demux), sys);
+ if (block != NULL)
+ {
+ block->i_pts = block->i_dts = mdate ();
+ block->i_flags |= sys->i_block_flags;
+ es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
+ es_out_Send (demux->out, sys->p_es, block);
+ }
+ vlc_restorecancel (canc);
+ }
+
+ assert (0);
+}
+
+static void *ReadThread (void *data)
+{
+ demux_t *demux = data;
+ demux_sys_t *sys = demux->p_sys;
+ int fd = sys->i_fd;
+ struct pollfd ufd[1];
+
+ ufd[0].fd = fd;
+ ufd[0].events = POLLIN | POLLPRI;
+
+ for (;;)
+ {
+ /* Wait for data */
+ if (poll (ufd, 1, -1) == -1)
+ {
+ if (errno != EINTR)
+ msg_Err (demux, "poll error: %m");
+ continue;
+ }
+
+ block_t *block = block_Alloc (sys->blocksize);
+ if (unlikely(block == NULL))
+ {
+ msg_Err (demux, "read error: %m");
+ v4l2_read (fd, NULL, 0); /* discard frame */
+ continue;
+ }
+ block->i_pts = block->i_dts = mdate ();
+ block->i_flags |= sys->i_block_flags;
+
+ int canc = vlc_savecancel ();
+ ssize_t val = v4l2_read (fd, block->p_buffer, block->i_buffer);
+ if (val != -1)
+ {
+ block->i_buffer = val;
+ es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
+ es_out_Send (demux->out, sys->p_es, block);
+ }
+ else
+ block_Release (block);
+ vlc_restorecancel (canc);
+ }
+ assert (0);
+}
+
static int DemuxControl( demux_t *demux, int query, va_list args )
{
switch( query )
@@ -556,64 +637,3 @@ static int DemuxControl( demux_t *demux, int query, va_list args )
return VLC_EGENERIC;
}
-
-/** Gets a frame in read/write mode */
-static block_t *BlockRead( vlc_object_t *obj, int fd, size_t size )
-{
- block_t *block = block_Alloc( size );
- if( unlikely(block == NULL) )
- return NULL;
-
- ssize_t val = v4l2_read( fd, block->p_buffer, size );
- if( val == -1 )
- {
- block_Release( block );
- switch( errno )
- {
- case EAGAIN:
- return NULL;
- case EIO: /* could be ignored per specification */
- /* fall through */
- default:
- msg_Err( obj, "cannot read frame: %m" );
- return NULL;
- }
- }
- block->i_buffer = val;
- return block;
-}
-
-static int Demux( demux_t *demux )
-{
- demux_sys_t *sys = demux->p_sys;
- struct pollfd ufd;
-
- ufd.fd = sys->i_fd;
- ufd.events = POLLIN|POLLPRI;
- /* Wait for data */
- /* FIXME: remove timeout */
- while( poll( &ufd, 1, 500 ) == -1 )
- if( errno != EINTR )
- {
- msg_Err( demux, "poll error: %m" );
- return -1;
- }
-
- if( ufd.revents == 0 )
- return 1;
-
- block_t *block;
-
- if( sys->io == IO_METHOD_READ )
- block = BlockRead( VLC_OBJECT(demux), ufd.fd, sys->blocksize );
- else
- block = GrabVideo( VLC_OBJECT(demux), sys );
- if( block == NULL )
- return 1;
-
- block->i_pts = block->i_dts = mdate();
- block->i_flags |= sys->i_block_flags;
- es_out_Control( demux->out, ES_OUT_SET_PCR, block->i_pts );
- es_out_Send( demux->out, sys->p_es, block );
- return 1;
-}
diff --git a/modules/access/v4l2/v4l2.h b/modules/access/v4l2/v4l2.h
index 63b53e2..db9c8ae 100644
--- a/modules/access/v4l2/v4l2.h
+++ b/modules/access/v4l2/v4l2.h
@@ -81,6 +81,7 @@ typedef struct vlc_v4l2_ctrl vlc_v4l2_ctrl_t;
struct demux_sys_t
{
int i_fd;
+ vlc_thread_t thread;
/* Video */
io_method io;
More information about the vlc-commits
mailing list