DirectFB - Home of the pragmatist Roadmap


[directfb-dev] [PATCH] v4l system-only surface support
Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[directfb-dev] [PATCH] v4l system-only surface support



This patch adds system-only surface support to the v4l videoprovider. I'm
fairly sure that the interlace vs. non-interlace stuff is broken. My first
time hacking with v4l and I've been unable to find any docs on the api.
Also I don't have a long enough antenna cable for my bttv card so I can
only see garbage on the screen. At least my computer didn't catch fire :)
Anyone care to beat it to a decent shape? It's 4:30 in the morining so I
think I'll sleep for a while...

-- 
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
--- /home/villes/cvs/directfb/DirectFB/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c	Tue Jun 25 02:01:21 2002
+++ interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_v4l.c	Thu Jun 27 03:41:41 2002
@@ -38,6 +38,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/select.h>
+#include <sys/mman.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <linux/videodev.h>
@@ -84,6 +85,9 @@
      char                    *filename;
      int                      fd;
      struct video_capability  vcap;
+     struct video_mmap        vmmap;
+     struct video_mbuf        vmbuf;
+     void                    *buffer;
      pthread_t                thread;
      CoreSurface             *destination;
      DVFrameCallback          callback;
@@ -378,6 +382,8 @@
 
      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 );
 
      data->filename = DFBSTRDUP( filename );
      data->fd = fd;
@@ -411,24 +417,61 @@
      IDirectFBVideoProvider_V4L_data *data =
           (IDirectFBVideoProvider_V4L_data*)ctx;
 
-     int            even = 0;
-     struct timeval tv;
+     int            field = 0;
 
-     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,
-                                             even ? CSNF_SET_EVEN : CSNF_SET_ODD );
-               even = !even;
+     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);
           }
+     } else {
+          struct timeval tv;
 
-          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;
+               }
+
+               if (data->callback)
+                    data->callback( data->ctx );
+          }
      }
 
      return NULL;
@@ -444,14 +487,21 @@
           v4l_stop( data );
           return RS_REMOVE;
      }*/
+     CoreSurface *surface = data->destination;
 
-     if (notification->flags & CSNF_VIDEO) {
-          CoreSurface *surface = data->destination;
+     if (!surface)
+          return RS_OK;
 
-          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) {
+          v4l_stop( data );
+          return RS_REMOVE;
      }
 
      return RS_OK;
@@ -469,11 +519,22 @@
      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 );
 
-     ret = dfb_surfacemanager_assure_video( surface->manager, buffer );
-     if (!ret)
-          buffer->video.locked++;
+     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++;
+     }
 
      dfb_surfacemanager_unlock( surface->manager );
 
@@ -508,12 +569,43 @@
                break;
           default:
                BUG( "unknown pixel format" );
-               buffer->video.locked--;
+               if (surface->caps & DSCAPS_SYSTEMONLY)
+                    buffer->system.locked--;
+               else
+                    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;
@@ -530,10 +622,6 @@
                buffer->video.locked--;
                return ret;
           }
-     }
-
-     {
-          struct video_picture p;
 
           if (ioctl( data->fd, VIDIOCGPICT, &p ) < 0) {
                DFBResult ret = errno2dfb( errno );
@@ -555,10 +643,6 @@
                buffer->video.locked--;
                return ret;
           }
-     }
-
-     {
-          struct video_window win;
 
           win.width = rect->w;
           win.height = rect->h;
@@ -582,21 +666,23 @@
      if (!data->cleanup)
           data->cleanup = dfb_core_cleanup_add( v4l_cleanup, data, true );
 
-     if (ioctl( data->fd, VIDIOCCAPTURE, &one ) < 0) {
-          DFBResult ret = errno2dfb( errno );
+     if (!(surface->caps & DSCAPS_SYSTEMONLY)) {
+          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--;
-          return ret;
+               buffer->video.locked--;
+               return ret;
+          }
      }
 
      data->destination = surface;
 
      reactor_attach( surface->reactor, v4l_surface_listener, data );
      
-     if (data->callback || surface->caps & DSCAPS_INTERLACED)
+     if (data->callback || surface->caps & DSCAPS_INTERLACED || surface->caps & DSCAPS_SYSTEMONLY)
           pthread_create( &data->thread, NULL, FrameThread, data );
 
      return DFB_OK;
@@ -618,11 +704,15 @@
 
           return ret;
      }
+     
+     if (!data->destination)
+          return DFB_OK;
 
-     if (data->destination) {
+     if (data->destination->caps & DSCAPS_SYSTEMONLY)
+          data->destination->back_buffer->system.locked--;
+     else
           data->destination->back_buffer->video.locked--;
-          data->destination = NULL;
-     }
+     data->destination = NULL;
 
      return DFB_OK;
 }
@@ -636,6 +726,7 @@
 
      v4l_stop( data );
 
+     munmap( data->buffer, data->vmbuf.size );
      close( data->fd );
      data->fd = -1;
 }

Home | Main Index | Thread Index


directfb.org / Development / Old Archives