Panda3D

webcamVideoV4L.cxx

00001 // Filename: webcamVideoV4L.cxx
00002 // Created by: rdb (11Jun2010)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "webcamVideoV4L.h"
00016 
00017 #ifdef HAVE_VIDEO4LINUX
00018 
00019 #include "webcamVideoCursorV4L.h"
00020 #include "dcast.h"
00021 
00022 #include <fcntl.h>
00023 #include <sys/ioctl.h>
00024 #include <linux/videodev.h>
00025 #include <linux/videodev2.h>
00026 
00027 TypeHandle WebcamVideoV4L::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: find_all_webcams_v4l
00031 //       Access: Public, Static
00032 //  Description: Finds all Video4Linux webcams and adds them to
00033 //               the global list _all_webcams.
00034 ////////////////////////////////////////////////////////////////////
00035 void find_all_webcams_v4l() {
00036   struct video_capability cap;
00037   struct v4l2_capability cap2;
00038 
00039   vector_string devs;
00040   GlobPattern pattern ("/dev/video*");
00041   pattern.match_files(devs);
00042   for (vector_string::iterator it = devs.begin(); it != devs.end(); ++it) {
00043     int fd = open(it->c_str(), O_RDWR);
00044     if (fd != -1) {
00045       // Check for Video4Linux2 capabilities
00046       if (ioctl(fd, VIDIOC_QUERYCAP, &cap2) != -1) {
00047         if ((cap2.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
00048             (cap2.capabilities & V4L2_CAP_STREAMING)) {
00049           struct v4l2_fmtdesc fmt;
00050           for (int i = 0;; i++) {
00051             memset(&fmt, 0, sizeof fmt);
00052             fmt.index = i;
00053             fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00054             if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
00055               break;
00056             }
00057             struct v4l2_frmsizeenum frmsizeenum;
00058             for (int j = 0;; j++) {
00059               memset(&frmsizeenum, 0, sizeof frmsizeenum);
00060               frmsizeenum.index = j;
00061               frmsizeenum.pixel_format = fmt.pixelformat;
00062               if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == -1) {
00063                 break;
00064               }
00065               if (frmsizeenum.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
00066                 continue;
00067               }
00068               struct v4l2_frmivalenum frmivalenum;
00069               for (int k = 0;; k++) {
00070                 memset(&frmivalenum, 0, sizeof frmivalenum);
00071                 frmivalenum.index = k;
00072                 frmivalenum.pixel_format = fmt.pixelformat;
00073                 frmivalenum.width = frmsizeenum.discrete.width;
00074                 frmivalenum.height = frmsizeenum.discrete.height;
00075                 if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) == -1) {
00076                   break;
00077                 }
00078                 if (frmivalenum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
00079                   continue;
00080                 }
00081 
00082                 // Create a new webcam video object
00083                 PT(WebcamVideoV4L) wc = new WebcamVideoV4L;
00084                 wc->set_name((const char*) cap2.card);
00085                 wc->_device = *it;
00086                 wc->_size_x = frmsizeenum.discrete.width;
00087                 wc->_size_y = frmsizeenum.discrete.height;
00088                 wc->_fps = ((double) frmivalenum.discrete.denominator) / ((double) frmivalenum.discrete.numerator);
00089                 wc->_pformats.push_back(fmt.pixelformat);
00090 
00091                 // Iterate through the webcams to make sure we don't put any duplicates in there
00092                 pvector<PT(WebcamVideo)>::iterator wvi;
00093                 for (wvi = WebcamVideoV4L::_all_webcams.begin(); wvi != WebcamVideoV4L::_all_webcams.end(); ++wvi) {
00094                   if ((*wvi)->is_of_type(WebcamVideoV4L::get_class_type())) {
00095                     PT(WebcamVideoV4L) wv_v4l = DCAST(WebcamVideoV4L, *wvi);
00096                     if (wv_v4l->_device == wc->_device &&
00097                         wv_v4l->_size_x == wc->_size_x &&
00098                         wv_v4l->_size_y == wc->_size_y &&
00099                         wv_v4l->_fps == wc->_fps) {
00100                       wv_v4l->_pformats.push_back(fmt.pixelformat);
00101                       break;
00102                     }
00103                   }
00104                 }
00105                 // Did the loop finish, meaning that a webcam of these
00106                 // properties does not exist? Add it.
00107                 if (wvi == WebcamVideoV4L::_all_webcams.end()) {
00108                   WebcamVideoV4L::_all_webcams.push_back(DCAST(WebcamVideo, wc));
00109                 }
00110               }
00111             }
00112           }
00113           continue;
00114         }
00115       }
00116 
00117       // Check for Video4Linux capabilities
00118       if (ioctl(fd, VIDIOCGCAP, &cap) != -1) {
00119         if (cap.type & VID_TYPE_CAPTURE) {
00120           //TODO: Video4Linux support
00121           continue;
00122         }
00123       }
00124     }
00125     close(fd);
00126   }
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: WebcamVideoV4L::open
00131 //       Access: Published, Virtual
00132 //  Description: Open this video, returning a MovieVideoCursor.
00133 ////////////////////////////////////////////////////////////////////
00134 PT(MovieVideoCursor) WebcamVideoV4L::
00135 open() {
00136   return new WebcamVideoCursorV4L(this);
00137 }
00138 
00139 #endif
 All Classes Functions Variables Enumerations