From 0c77ef2434f882d45ce03e2fd842cccbcf91f16c Mon Sep 17 00:00:00 2001 From: schodet Date: Sun, 13 Mar 2005 20:09:56 +0000 Subject: Ajout de video4linux. --- 2005/i/robert/src/video4linux/Makefile.defs | 7 + 2005/i/robert/src/video4linux/test_video4linux.cc | 84 +++++++++++ 2005/i/robert/src/video4linux/video4linux.cc | 174 ++++++++++++++++++++++ 2005/i/robert/src/video4linux/video4linux.hh | 63 ++++++++ 4 files changed, 328 insertions(+) create mode 100644 2005/i/robert/src/video4linux/Makefile.defs create mode 100644 2005/i/robert/src/video4linux/test_video4linux.cc create mode 100644 2005/i/robert/src/video4linux/video4linux.cc create mode 100644 2005/i/robert/src/video4linux/video4linux.hh (limited to '2005/i') diff --git a/2005/i/robert/src/video4linux/Makefile.defs b/2005/i/robert/src/video4linux/Makefile.defs new file mode 100644 index 0000000..b56218b --- /dev/null +++ b/2005/i/robert/src/video4linux/Makefile.defs @@ -0,0 +1,7 @@ +PROGRAMS += test_video4linux + +video4linux_OBJECTS = video4linux.o + +test_video4linux_OBJECTS = test_video4linux.o $(video4linux_OBJECTS) $(utils_OBJECTS) + +test_video4linux: $(test_video4linux_OBJECTS) diff --git a/2005/i/robert/src/video4linux/test_video4linux.cc b/2005/i/robert/src/video4linux/test_video4linux.cc new file mode 100644 index 0000000..9abdf4a --- /dev/null +++ b/2005/i/robert/src/video4linux/test_video4linux.cc @@ -0,0 +1,84 @@ +// test_video4linux.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// 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.hh" +#include "utils/errno_exception.hh" + +#include +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + try + { + if (argc != 3) + throw std::runtime_error ("Syntaxe : fichier " + "{rgb|bgr|yuv|yuv422}"); + std::string format (argv[2]); + Image::PixelFormat pf; + if (format == "rgb") + pf = Image::rgb; + else if (format == "bgr") + pf = Image::bgr; + else if (format == "yuv") + pf = Image::yuv; + else if (format == "yuv422") + pf = Image::yuv422; + else + throw std::invalid_argument ("Syntaxe : fichier {rgb|yuv422}"); + Video4Linux vid ("/dev/video", pf); + vid.calibrate (); + int w, h; + vid.getParam (w, h, pf); + std::cout << w << ' ' << h << std::endl; + int s; + s = Image::getBufSize (w, h, pf); + uint8_t *buf = new uint8_t[s]; + for (int i = 0; i < 10; ++i) + { + vid.read (buf, s); + std::ostringstream os; + os << argv[1] << std::setw (3) << std::setfill ('0') << i << '.' + << argv[2]; + int fd = open (os.str ().c_str (), O_WRONLY | O_CREAT, 0666); + if (fd == -1) + throw errno_exception (argv[1], errno); + write (fd, buf, s); + close (fd); + } + delete[] buf; + return 0; + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } +} diff --git a/2005/i/robert/src/video4linux/video4linux.cc b/2005/i/robert/src/video4linux/video4linux.cc new file mode 100644 index 0000000..406012f --- /dev/null +++ b/2005/i/robert/src/video4linux/video4linux.cc @@ -0,0 +1,174 @@ +// video4linux.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// 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.hh" +#include "utils/errno_exception.hh" +#include "utils/fd_set.hh" + +#include +#include +#include +#include +#include +#include + +/// Constructeur. +Video4Linux::Video4Linux (const char *dev, Image::PixelFormat pixelFormat, + int brightness /*58000*/) + : fd_ (-1), width_ (-1), height_ (-1), pixelFormat_ (pixelFormat), + rgb_ (pixelFormat == Image::rgb || pixelFormat == Image::bgr), + brightness_ (brightness), contrast_ (32768) +{ + if (pixelFormat == Image::hsi) + throw std::invalid_argument ("hsi not supported by Video4Linux"); + open (dev); +} + +/// Destructeur. +Video4Linux::~Video4Linux (void) +{ + close (); +} + +/// Lit une image, lance une exception en cas d'erreur. +void +Video4Linux::read (uint8_t *buf, unsigned size) +{ + if (buf && size != width_ * height_ * bpp_) + throw std::invalid_argument ("Video4Linux::read"); + // 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 (pixelFormat_) + { + case Image::rgb: + for (int i = 0; i < width_ * height_; ++i) + { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 3; + } + break; + memcpy (buf, map, size); + break; + case Image::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 Image::bgr: + case Image::yuv422: + case Image::hsi: + memcpy (buf, map, size); + break; + } + } + // Munmap. + munmap (map, bufSize_); +} + +/// Calibre la caméra. +void +Video4Linux::calibrate (void) +{ + for (int i = 0; i < 100; ++i) + read (0, 0); +} + +/// Attend qu'une image soit disponible, retourne true si oui. +bool +Video4Linux::wait (int timeout/*-1*/) +{ + FdSet fds; + fds.set (fd_); + return fds.wait (timeout); +} + +/// 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. + 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_ = Image::getBytePerPixel (pixelFormat_); + pic.brightness = brightness_; + pic.contrast = contrast_; + ioctl (fd_, VIDIOCSPICT, &pic); + // Channel. + 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_); +} + diff --git a/2005/i/robert/src/video4linux/video4linux.hh b/2005/i/robert/src/video4linux/video4linux.hh new file mode 100644 index 0000000..1a38056 --- /dev/null +++ b/2005/i/robert/src/video4linux/video4linux.hh @@ -0,0 +1,63 @@ +#ifndef video4linux_hh +#define video4linux_hh +// video4linux.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// 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 "image/image_reader.hh" + +/// Classe d'accés à Video4Linux. C'est un ImageReader. +class Video4Linux : public ImageReader +{ + private: + int fd_; + int width_, height_; + unsigned bufSize_; + Image::PixelFormat pixelFormat_; + bool rgb_; + int brightness_, contrast_; + unsigned bpp_; + public: + /// Constructeur. + Video4Linux (const char *dev, Image::PixelFormat pixelFormat, + int brightness = 58000); + /// Destructeur. + ~Video4Linux (void); + /// Récupère les paramètres de l'image. + void getParam (int &width, int &height, + Image::PixelFormat &pixelFormat) const + { width = width_; height = height_; pixelFormat = pixelFormat_; } + /// Lit une image, lance une exception en cas d'erreur. + void read (uint8_t *buf, unsigned size); + /// Calibre la caméra. + void calibrate (void); + /// Attend qu'une image soit disponible, retourne true si oui. + bool wait (int timeout = -1); + protected: + /// Ouvre le périphérique. + void open (const char *dev); + /// Ferme le périphérique. + void close (void); +}; + +#endif // video4linux_hh -- cgit v1.2.3