Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

loop.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "webcam.h"


static void
process_image(void *p, Context_t *ctx)
{
  int i, j;
  unsigned char *q = p;
  Buffer8_t *dst = passive_buffer(ctx);
  Pixel_t *d = dst->buffer;

  /* XXX lame YUYV -> Y conversion */
  for (j = 0; j < CAP_HEIGHT; j++)
    for (i = 0; i < CAP_WIDTH; i++) {
      *d++ = *q;
      q += 2;
    }

  if (hflip)
    Buffer8_flip_x(dst);
}


static int
read_frame(Context_t *ctx)
{
  struct v4l2_buffer buf;
  unsigned int i;

  switch (io) {
  case IO_METHOD_READ:
    if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
      switch (errno) {
      case EAGAIN:
      return 0;

      case EIO:
      /* Could ignore EIO, see spec. */

      /* fall through */

      default:
      xperror("read");
      }
    }

    process_image(buffers[0].start, ctx);

    break;

  case IO_METHOD_MMAP:
    CLEAR(buf);

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
      switch (errno) {
      case EAGAIN:
      return 0;

      case EIO:
      /* Could ignore EIO, see spec. */

      /* fall through */

      default:
      xperror("VIDIOC_DQBUF");
      }
    }

    assert(buf.index < n_buffers);

    process_image(buffers[buf.index].start, ctx);

    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
      xperror("VIDIOC_QBUF");

    break;

  case IO_METHOD_USERPTR:
    CLEAR(buf);

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_USERPTR;

    if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
      switch (errno) {
      case EAGAIN:
      return 0;

      case EIO:
      /* Could ignore EIO, see spec. */

      /* fall through */

      default:
      xperror("BBB VIDIOC_DQBUF");
      }
    }

    for (i = 0; i < n_buffers; ++i)
      if (buf.m.userptr == (unsigned long)buffers[i].start
        && buf.length == buffers[i].length)
      break;

    assert(i < n_buffers);

    process_image((void *) buf.m.userptr, ctx);

    if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
      xperror("CCC VIDIOC_QBUF");

    break;
  }

  return 1;
}


void
loop(Context_t *ctx)
{
  for ( ; ; ) {
    fd_set fds;
    struct timeval tv;
    int r;

    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    /* Timeout. */
    tv.tv_sec = 10;
    tv.tv_usec = 0;

    r = select(fd + 1, &fds, NULL, NULL, &tv);

    if (-1 == r) {
      if (EINTR == errno)
      continue;

      xperror("select");
    }

    if (0 == r)
      xerror("select timeout\n");

    if (read_frame(ctx))
      break;

    /* EAGAIN - continue select loop. */
  }
}

Generated by  Doxygen 1.6.0   Back to index