static gboolean process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *result) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); Priv *p = (Priv*)o->chant_data; guchar *capbuf; static gboolean inited = FALSE; if (!inited && o->fps != 0) { inited= TRUE; g_timeout_add (1000/o->fps, update, operation); } if (!p->active) return FALSE; v4lgrabf (p->vd); capbuf = v4lgetaddress (p->vd); v4lsyncf (p->vd); if (!capbuf) { g_warning ("no capbuf found"); return FALSE; } if (p->decode) { guchar foobuf[o->width*o->height*3]; /* XXX: foobuf is unneeded the conversions resets for every * scanline and could thus have been done in a line by line * manner an fed into the output buffer */ gint y; for (y = 0; y < p->h; y++) { gint x; guchar *dst = &foobuf[y*p->w*3]; guchar *ysrc = (guchar *) (capbuf + (y) * (p->w) * 1); guchar *usrc = (guchar *) (capbuf + (p->w) * (p->h) + (y) / 2 * (p->w) / 2); guchar *vsrc = (guchar *) (capbuf + (p->w) * (p->h) + ((p->w) * (p->h)) / 4 + (y) / 2 * (p->w) / 2); for (x = 0; x < p->w; x++) { gint R, G, B; #ifndef byteclamp #define byteclamp(j) do{if(j<0)j=0; else if(j>255)j=255;}while(0) #endif #define YUV82RGB8(Y,U,V,R,G,B)do{\ R= ((Y<<15) + 37355*(V-128))>>15;\ G= ((Y<<15) -12911* (U-128) - 19038*(V-128))>>15;\ B= ((Y<<15) +66454* (U-128) )>>15;\ byteclamp(R);\ byteclamp(G);\ byteclamp(B);\ }while(0) /* the format support for this code is not very good, but it * works for the devices I have tested with, conversion even * for chroma subsampled images is something we should let * babl handle. */ YUV82RGB8 (*ysrc, *usrc, *vsrc, R, G, B); dst[0] = B; dst[1] = G; dst[2] = R; dst += 3; ysrc++; if (x % 2) { usrc++; vsrc++; } } } gegl_buffer_set (output, NULL, NULL, foobuf, GEGL_AUTO_ROWSTRIDE); } else { gegl_buffer_set (output, NULL, NULL, capbuf, GEGL_AUTO_ROWSTRIDE); } return TRUE; }
static int read_frame(GeglOperation *operation, GeglBuffer *output) { GeglProperties *o = GEGL_PROPERTIES (operation); Priv *p= (Priv*)o->user_data; struct v4l2_buffer buf; unsigned int i; switch (p->io) { case IO_METHOD_READ: if (-1 == read(p->fd, p->buffers[0].start, p->buffers[0].length)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: errno_exit("read"); } } //process_image(priv, p->buffers[0].start, p->buffers[0].length); gegl_buffer_set (output, NULL, 0, NULL, p->buffers[0].start, GEGL_AUTO_ROWSTRIDE); break; case IO_METHOD_MMAP: CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(p->fd, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: errno_exit("VIDIOC_DQBUF"); } } assert(buf.index < p->n_buffers); //process_image(priv, p->buffers[buf.index].start, buf.bytesused); // // { guchar *capbuf = p->buffers[buf.index].start; guchar foobuf[o->width*o->height*4]; /* XXX: foobuf is unneeded the conversions resets for every * scanline and could thus have been done in a line by line * manner an fed into the output buffer */ gint y; for (y = 0; y < p->h; y++) { gint x; guchar *dst = &foobuf[y*p->w*4]; guchar *ysrc = (guchar *) (capbuf + (y) * (p->w) * 2); guchar *usrc = ysrc + 3; guchar *vsrc = ysrc + 1; for (x = 0; x < p->w; x++) { gint R, G, B; #ifndef byteclamp #define byteclamp(j) do{if(j<0)j=0; else if(j>255)j=255;}while(0) #endif #define YUV82RGB8(Y,U,V,R,G,B)do{\ R= ((Y<<15) + 37355*(V-128))>>15;\ G= ((Y<<15) -12911* (U-128) - 19038*(V-128))>>15;\ B= ((Y<<15) +66454* (U-128) )>>15;\ byteclamp(R);\ byteclamp(G);\ byteclamp(B);\ }while(0) /* the format support for this code is not very good, but it * works for the devices I have tested with, conversion even * for chroma subsampled images is something we should let * babl handle. */ YUV82RGB8 (*ysrc, *usrc, *vsrc, R, G, B); #if 0 dst[0] = *ysrc; dst[1] = *ysrc; dst[2] = *ysrc; #else dst[0] = B; dst[1] = G; dst[2] = R; dst[3] = 255; #endif dst += 4; ysrc += 2; if (x % 2) { usrc += 4; vsrc += 4; } } } gegl_buffer_set (output, NULL, 0, NULL, foobuf, GEGL_AUTO_ROWSTRIDE); } if (-1 == xioctl(p->fd, VIDIOC_QBUF, &buf)) errno_exit("VIDIOC_QBUF"); break; case IO_METHOD_USERPTR: CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_USERPTR; if (-1 == xioctl(p->fd, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: errno_exit("VIDIOC_DQBUF"); } } for (i = 0; i < p->n_buffers; ++i) if (buf.m.userptr == (unsigned long)p->buffers[i].start && buf.length == p->buffers[i].length) break; assert(i < p->n_buffers); //process_image(priv, (void *)buf.m.userptr, buf.bytesused); gegl_buffer_set (output, NULL, 0, NULL, (void*)buf.m.userptr, GEGL_AUTO_ROWSTRIDE); if (-1 == xioctl(p->fd, VIDIOC_QBUF, &buf)) errno_exit("VIDIOC_QBUF"); break; } return 1; }