// video4linux.cc // nono - programme du robot 2004. {{{ // // Copyright (C) 2004 Nicolas Schodet // // Robot APB Team/Efrei 2004. // Web: http://assos.efrei.fr/robot/ // Email: robot AT efrei DOT fr // // This program 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. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // }}} #include "video4linux.h" #include "utils/errno_exception.h" #include #include #include #include #include #include //XXX /// Constructeur. Video4Linux::Video4Linux (const char *dev, ColorSpace colorSpace, int brightness = 58000) : fd_ (-1), width_ (-1), height_ (-1), colorSpace_ (colorSpace), rgb_ (colorSpace == ImageLoader::rgb || colorSpace == ImageLoader::bgr), brightness_ (brightness), contrast_ (32768) { open (dev); } /// Destructeur. Video4Linux::~Video4Linux (void) { close (); } /// Lit une image, retourne le nombre d'octets lus. int Video4Linux::read (void *buf, int size) const { if (buf && size != getBufSize ()) return 0; // Mmap. void *map; map = mmap (0, bufsize_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0); // Capture. video_mmap mmap; mmap.format = rgb_ ? VIDEO_PALETTE_RGB24 : VIDEO_PALETTE_YUV422; mmap.frame = 0; mmap.width = width_; mmap.height = height_; ioctl (fd_, VIDIOCMCAPTURE, &mmap); // Sync. ioctl (fd_, VIDIOCSYNC, &mmap); // Copy. if (buf) { unsigned char *src = reinterpret_cast (map); unsigned char *dst = reinterpret_cast (buf); switch (colorSpace_) { case ImageLoader::rgb: for (int i = 0; i < width_ * height_; ++i) { *dst++ = src[2]; *dst++ = src[1]; *dst++ = src[0]; src += 3; } break; case ImageLoader::bgr: memcpy (buf, map, size); break; case ImageLoader::yuv: for (int i = 0; i < width_ * height_ / 2; ++i) { *dst++ = src[0]; // Y1 *dst++ = src[1]; // U *dst++ = src[3]; // V *dst++ = src[2]; // Y2 *dst++ = src[1]; // U *dst++ = src[3]; // V src += 4; } break; case ImageLoader::yuv422: memcpy (buf, map, size); break; } } // Munmap. munmap (map, bufsize_); return size; } /// Calibre la caméra. void Video4Linux::calibrate (void) { std::cout << "Calibration... " << std::flush; for (int i = 0; i < 100; ++i) read (0, 0); std::cout << "ok" << std::endl; } /// Ouvre le périphérique. void Video4Linux::open (const char *dev) { if (fd_ != -1) close (); fd_ = ::open (dev, O_RDWR); if (fd_ == -1) throw errno_exception (dev, errno); // On récupère les cap dont on se tappe ! video_capability cap; if (ioctl (fd_, VIDIOCGCAP, &cap) == -1) throw errno_exception (dev, errno); // On veut du RGB24. video_picture pic; ioctl (fd_, VIDIOCGPICT, &pic); pic.palette = rgb_ ? VIDEO_PALETTE_RGB24 : VIDEO_PALETTE_YUV422; bpp_ = colorSpace_ == ImageLoader::yuv422 ? 2 : 3; pic.brightness = brightness_; pic.contrast = contrast_; ioctl (fd_, VIDIOCSPICT, &pic); // Channel de merde. video_channel chn; ioctl (fd_, VIDIOCGCHAN, &chn); chn.channel = 0; chn.norm = VIDEO_MODE_PAL; ioctl (fd_, VIDIOCSCHAN, &chn); // Récupères les infos sur la camera. video_window win; ioctl (fd_, VIDIOCGWIN, &win); width_ = win.width; height_ = win.height; // Initialisation mmap. video_mbuf mbuf; ioctl (fd_, VIDIOCGMBUF, &mbuf); bufsize_ = mbuf.size; } /// Ferme le périphérique. void Video4Linux::close (void) { ::close (fd_); }