|
Roadmap |
Site sponsored by
IGEL
|
||
|
|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [directfb-dev] Re: [PATCH] v4l system-only surface support
On Thu, Jun 27, 2002 at 11:38:16PM +0200, Denis Oliver Kropp wrote: > I'm not sure if the field syncing is correct. It's confusing when to sync, > grab and copy which buffer in v4l. The grab happens asynchronously and should > be started before copying the buffer that has just been synced. New patch attached. I've separated v4l_to_surface() and v4l_surface_listener() to video and system variants and hopefully fixed the field syncing. And it uses dfb_memcpy() now so should be more efficient also. What do you think? -- Ville Syrjälä syrjala@sci.fi http://www.sci.fi/~syrjala/
Index: interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c
===================================================================
RCS file: /cvs/directfb/DirectFB/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c,v
retrieving revision 1.31
diff -u -r1.31 idirectfbvideoprovider_v4l.c
--- interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c 27 Jun 2002 19:34:38 -0000 1.31
+++ interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c 28 Jun 2002 12:30:30 -0000
@@ -64,6 +64,7 @@
#include <misc/util.h>
#include <misc/mem.h>
+#include <misc/memcpy.h>
static DFBResult
Probe( IDirectFBVideoProvider_ProbeContext *ctx );
@@ -99,9 +100,13 @@
static const unsigned int zero = 0;
static const unsigned int one = 1;
-static void* FrameThread( void *context );
-static ReactionResult v4l_surface_listener( const void *msg_data, void *ctx );
-static DFBResult v4l_to_surface( CoreSurface *surface, DFBRectangle *rect,
+static void* VideoThread( void *context );
+static void* SystemThread( void *context );
+static ReactionResult v4l_videosurface_listener( const void *msg_data, void *ctx );
+static ReactionResult v4l_systemsurface_listener( const void *msg_data, void *ctx );
+static DFBResult v4l_to_videosurface( CoreSurface *surface, DFBRectangle *rect,
+ IDirectFBVideoProvider_V4L_data *data );
+static DFBResult v4l_to_systemsurface( CoreSurface *surface, DFBRectangle *rect,
IDirectFBVideoProvider_V4L_data *data );
static DFBResult v4l_stop( IDirectFBVideoProvider_V4L_data *data );
static void v4l_deinit( IDirectFBVideoProvider_V4L_data *data );
@@ -233,7 +238,10 @@
data->callback = callback;
data->ctx = ctx;
- return v4l_to_surface( dst_data->surface, &rect, data );
+ if (dst_data->caps & DSCAPS_SYSTEMONLY)
+ return v4l_to_systemsurface( dst_data->surface, &rect, data );
+ else
+ return v4l_to_videosurface( dst_data->surface, &rect, data );
}
static DFBResult IDirectFBVideoProvider_V4L_Stop(
@@ -382,6 +390,7 @@
ioctl( fd, VIDIOCGCAP, &data->vcap );
ioctl( fd, VIDIOCCAPTURE, &zero );
+
ioctl( fd, VIDIOCGMBUF, &data->vmbuf );
data->buffer = mmap( NULL, data->vmbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
@@ -412,73 +421,81 @@
* bogus thread to generate callback,
* because video4linux does not support syncing in overlay mode
*/
-static void* FrameThread( void *ctx )
+static void* VideoThread( void *ctx )
{
IDirectFBVideoProvider_V4L_data *data =
(IDirectFBVideoProvider_V4L_data*)ctx;
- int field = 0;
+ int field = 0;
+ struct timeval tv;
- if (data->destination->caps & DSCAPS_SYSTEMONLY) {
- __u8 *src, *dst;
- int src_pitch = DFB_BYTES_PER_LINE( data->destination->format, data->destination->width );
- int dst_pitch = data->destination->back_buffer->system.pitch * (data->destination->caps & DSCAPS_INTERLACED ? 2 : 1);
- int h;
- while (1) {
- data->vmmap.frame = field;
- ioctl( data->fd, VIDIOCSYNC, &field );
- pthread_testcancel();
-
- ioctl( data->fd, VIDIOCMCAPTURE, &data->vmmap );
-
- src = (__u8 *) data->buffer + data->vmbuf.offsets[field];
- dst = (__u8 *) data->destination->back_buffer->system.addr;
- h = data->destination->height;
- if (data->destination->caps & DSCAPS_INTERLACED) {
- dst += field * data->destination->back_buffer->system.pitch;
- h += field ? 0 : 1;
- h /= 2;
- }
-
- while (h--) {
- memcpy( dst, src, src_pitch );
- src += src_pitch;
- dst += dst_pitch;
- }
- if (data->destination->caps & DSCAPS_INTERLACED) {
- dfb_surface_notify_listeners( data->destination,
- field ? CSNF_SET_ODD : CSNF_SET_EVEN );
- field = !field;
- }
- if (data->callback)
- data->callback(data->ctx);
+ while (1) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 20000;
+ select( 0, 0, 0, 0, &tv );
+
+ pthread_testcancel();
+
+ if (data->destination->caps & DSCAPS_INTERLACED) {
+ dfb_surface_notify_listeners( data->destination,
+ field ? CSNF_SET_ODD : CSNF_SET_EVEN );
+ field = !field;
}
- } else {
- struct timeval tv;
- while (1) {
- tv.tv_sec = 0;
- tv.tv_usec = 20000;
- select( 0, 0, 0, 0, &tv );
-
- pthread_testcancel();
-
- if (data->destination->caps & DSCAPS_INTERLACED) {
- dfb_surface_notify_listeners( data->destination,
- field ? CSNF_SET_ODD : CSNF_SET_EVEN );
- field = !field;
- }
+ if (data->callback)
+ data->callback( data->ctx );
+ }
+
+ return NULL;
+}
+
+/*
+ * thread to capture data from v4l buffers and generate callback
+ */
+static void* SystemThread( void *ctx )
+{
+ IDirectFBVideoProvider_V4L_data *data =
+ (IDirectFBVideoProvider_V4L_data*)ctx;
+ CoreSurface *surface = data->destination;
- if (data->callback)
- data->callback( data->ctx );
+ __u8 *src, *dst;
+ int dst_pitch, src_pitch, h;
+ int field = 0;
+
+ src_pitch = DFB_BYTES_PER_LINE( surface->format, surface->width );
+ while (1) {
+ data->vmmap.frame = field;
+ ioctl( data->fd, VIDIOCMCAPTURE, &data->vmmap );
+
+ if (data->vmbuf.frames == 2)
+ field = !field;
+
+ ioctl( data->fd, VIDIOCSYNC, &field );
+
+ pthread_testcancel();
+
+ h = surface->height;
+ src = (__u8 *) data->buffer + data->vmbuf.offsets[field];
+ dfb_surface_soft_lock( surface, DSLF_WRITE, (void**)&dst, &dst_pitch, 0 );
+ while (h--) {
+ dfb_memcpy( dst, src, src_pitch );
+ src += src_pitch;
+ dst += dst_pitch;
}
+ dfb_surface_unlock( surface, 0 );
+
+ if (data->destination->caps & DSCAPS_INTERLACED)
+ dfb_surface_notify_listeners( data->destination,
+ field ? CSNF_SET_ODD : CSNF_SET_EVEN );
+
+ if (data->callback)
+ data->callback(data->ctx);
}
return NULL;
}
-
-static ReactionResult v4l_surface_listener( const void *msg_data, void *ctx )
+static ReactionResult v4l_videosurface_listener( const void *msg_data, void *ctx )
{
CoreSurfaceNotification *notification = (CoreSurfaceNotification*) msg_data;
IDirectFBVideoProvider_V4L_data *data = (IDirectFBVideoProvider_V4L_data*) ctx;
@@ -489,28 +506,42 @@
}*/
CoreSurface *surface = data->destination;
- if (!surface)
- return RS_OK;
+ if (notification->flags & CSNF_VIDEO) {
+ if (surface && surface->back_buffer->video.health == CSH_INVALID) {
+ v4l_stop( data );
+ return RS_REMOVE;
+ }
+ }
- if (notification->flags & CSNF_SYSTEM &&
- surface->caps & DSCAPS_SYSTEMONLY &&
- surface->back_buffer->system.health == CSH_INVALID) {
- v4l_stop( data );
- return RS_REMOVE;
- } else if (notification->flags & CSNF_VIDEO &&
- !(surface->caps & DSCAPS_SYSTEMONLY) &&
- surface->back_buffer->video.health == CSH_INVALID) {
+ return RS_OK;
+}
+
+static ReactionResult v4l_systemsurface_listener( const void *msg_data, void *ctx )
+{
+ CoreSurfaceNotification *notification = (CoreSurfaceNotification*) msg_data;
+ IDirectFBVideoProvider_V4L_data *data = (IDirectFBVideoProvider_V4L_data*) ctx;
+
+/* if ((notification->flags & (CSNF_DESTROY | CSNF_SIZEFORMAT))) {
v4l_stop( data );
return RS_REMOVE;
+ }*/
+ CoreSurface *surface = data->destination;
+
+ if (notification->flags & CSNF_SYSTEM) {
+ if (surface && surface->back_buffer->system.health == CSH_INVALID) {
+ v4l_stop( data );
+ return RS_REMOVE;
+ }
}
return RS_OK;
}
+
/************/
-static DFBResult v4l_to_surface( CoreSurface *surface, DFBRectangle *rect,
- IDirectFBVideoProvider_V4L_data *data )
+static DFBResult v4l_to_videosurface( CoreSurface *surface, DFBRectangle *rect,
+ IDirectFBVideoProvider_V4L_data *data )
{
DFBResult ret;
int bpp, palette;
@@ -519,22 +550,11 @@
if (surface->caps & DSCAPS_FLIPPING)
return DFB_UNSUPPORTED;
- if (surface->caps & DSCAPS_INTERLACED &&
- surface->caps & DSCAPS_SYSTEMONLY &&
- data->vmbuf.frames < 2)
- return DFB_UNSUPPORTED;
-
dfb_surfacemanager_lock( surface->manager );
- if (surface->caps & DSCAPS_SYSTEMONLY) {
- ret = dfb_surfacemanager_assure_system( surface->manager, buffer );
- if (!ret)
- buffer->system.locked++;
- } else {
- ret = dfb_surfacemanager_assure_video( surface->manager, buffer );
- if (!ret)
- buffer->video.locked++;
- }
+ ret = dfb_surfacemanager_assure_video( surface->manager, buffer );
+ if (!ret)
+ buffer->video.locked++;
dfb_surfacemanager_unlock( surface->manager );
@@ -569,43 +589,12 @@
break;
default:
BUG( "unknown pixel format" );
- if (surface->caps & DSCAPS_SYSTEMONLY)
- buffer->system.locked--;
- else
- buffer->video.locked--;
+ buffer->video.locked--;
return DFB_BUG;
}
- if (surface->caps & DSCAPS_SYSTEMONLY) {
- data->vmmap.width = surface->width;
- data->vmmap.height = surface->height;
- data->vmmap.format = palette;
- data->vmmap.frame = 0;
- if (ioctl(data->fd, VIDIOCMCAPTURE, &data->vmmap) < 0) {
- DFBResult ret = errno2dfb(errno);
-
- PERRORMSG("DirectFB/v4l: "
- "Could not start capturing (VIDIOCMCAPTURE failed)!\n");
-
- buffer->system.locked--;
- return ret;
- }
- if (surface->caps & DSCAPS_INTERLACED) {
- data->vmmap.frame = 1;
- if (ioctl(data->fd, VIDIOCMCAPTURE, &data->vmmap) < 0) {
- DFBResult ret = errno2dfb(errno);
-
- PERRORMSG("DirectFB/v4l: "
- "Could not start capturing (VIDIOCMCAPTURE failed)!\n");
-
- buffer->system.locked--;
- return ret;
- }
- }
- } else {
+ {
struct video_buffer b;
- struct video_picture p;
- struct video_window win;
b.base = (void*)dfb_gfxcard_memory_physical( buffer->video.offset );
b.width = surface->width;
@@ -622,6 +611,9 @@
buffer->video.locked--;
return ret;
}
+ }
+ {
+ struct video_picture p;
if (ioctl( data->fd, VIDIOCGPICT, &p ) < 0) {
DFBResult ret = errno2dfb( errno );
@@ -643,6 +635,9 @@
buffer->video.locked--;
return ret;
}
+ }
+ {
+ struct video_window win;
win.width = rect->w;
win.height = rect->h;
@@ -662,28 +657,110 @@
return ret;
}
}
-
+
if (!data->cleanup)
data->cleanup = dfb_core_cleanup_add( v4l_cleanup, data, true );
- if (!(surface->caps & DSCAPS_SYSTEMONLY)) {
- if (ioctl( data->fd, VIDIOCCAPTURE, &one ) < 0) {
- DFBResult ret = errno2dfb( errno );
+ if (ioctl( data->fd, VIDIOCCAPTURE, &one ) < 0) {
+ DFBResult ret = errno2dfb( errno );
- PERRORMSG( "DirectFB/v4l: "
- "Could not start capturing (VIDIOCCAPTURE failed)!\n" );
+ PERRORMSG( "DirectFB/v4l: "
+ "Could not start capturing (VIDIOCCAPTURE failed)!\n" );
- buffer->video.locked--;
+ buffer->video.locked--;
+ return ret;
+ }
+
+ data->destination = surface;
+
+ reactor_attach( surface->reactor, v4l_videosurface_listener, data );
+
+ if (data->callback || surface->caps & DSCAPS_INTERLACED)
+ pthread_create( &data->thread, NULL, VideoThread, data );
+
+ return DFB_OK;
+}
+
+static DFBResult v4l_to_systemsurface( CoreSurface *surface, DFBRectangle *rect,
+ IDirectFBVideoProvider_V4L_data *data )
+{
+ DFBResult ret;
+ int bpp, palette, i;
+ SurfaceBuffer *buffer = surface->back_buffer;
+
+ if (surface->caps & DSCAPS_FLIPPING)
+ return DFB_UNSUPPORTED;
+
+ if (data->vmbuf.frames > 2 ||
+ (surface->caps & DSCAPS_INTERLACED && data->vmbuf.frames < 2))
+ return DFB_UNSUPPORTED;
+
+ dfb_surfacemanager_lock( surface->manager );
+
+ ret = dfb_surfacemanager_assure_system( surface->manager, buffer );
+ if (!ret)
+ buffer->system.locked++;
+
+ dfb_surfacemanager_unlock( surface->manager );
+
+ if (ret)
+ return ret;
+
+ switch (surface->format) {
+ case DSPF_YUY2:
+ bpp = 16;
+ palette = VIDEO_PALETTE_YUYV;
+ break;
+ case DSPF_UYVY:
+ bpp = 16;
+ palette = VIDEO_PALETTE_UYVY;
+ break;
+ case DSPF_RGB15:
+ bpp = 15;
+ palette = VIDEO_PALETTE_RGB555;
+ break;
+ case DSPF_RGB16:
+ bpp = 16;
+ palette = VIDEO_PALETTE_RGB565;
+ break;
+ case DSPF_RGB24:
+ bpp = 24;
+ palette = VIDEO_PALETTE_RGB24;
+ break;
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ bpp = 32;
+ palette = VIDEO_PALETTE_RGB32;
+ break;
+ default:
+ BUG( "unknown pixel format" );
+ buffer->system.locked--;
+ return DFB_BUG;
+ }
+
+ data->vmmap.width = surface->width;
+ data->vmmap.height = surface->height;
+ data->vmmap.format = palette;
+ for (i = 0; i < data->vmbuf.frames; i++) {
+ data->vmmap.frame = i;
+ if (ioctl(data->fd, VIDIOCMCAPTURE, &data->vmmap) < 0) {
+ DFBResult ret = errno2dfb(errno);
+
+ PERRORMSG("DirectFB/v4l: "
+ "Could not start capturing (VIDIOCMCAPTURE failed)!\n");
+
+ buffer->system.locked--;
return ret;
}
}
+ if (!data->cleanup)
+ data->cleanup = dfb_core_cleanup_add( v4l_cleanup, data, true );
data->destination = surface;
- reactor_attach( surface->reactor, v4l_surface_listener, data );
-
- if (data->callback || surface->caps & DSCAPS_INTERLACED || surface->caps & DSCAPS_SYSTEMONLY)
- pthread_create( &data->thread, NULL, FrameThread, data );
+ reactor_attach( surface->reactor, v4l_systemsurface_listener, data );
+
+ pthread_create( &data->thread, NULL, SystemThread, data );
return DFB_OK;
}
@@ -704,7 +781,7 @@
return ret;
}
-
+
if (!data->destination)
return DFB_OK;
|
|
| directfb.org |
|
Development |
|
Old Archives |