Panda3D

webcamVideoCursorOpenCV.cxx

00001 // Filename: webcamVideoCursorOpenCV.cxx
00002 // Created by:  drose (20Oct10)
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 "webcamVideoOpenCV.h"
00016 
00017 #ifdef HAVE_OPENCV
00018 
00019 #include "pStatTimer.h"
00020 
00021 TypeHandle WebcamVideoCursorOpenCV::_type_handle;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: WebcamVideoCursorOpenCV::Constructor
00025 //       Access: Published
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 WebcamVideoCursorOpenCV::
00029 WebcamVideoCursorOpenCV(WebcamVideoOpenCV *src) : MovieVideoCursor(src) {
00030   _size_x = src->_size_x;
00031   _size_y = src->_size_y;
00032   _num_components = 3;
00033   _length = 1.0E10;
00034   _can_seek = false;
00035   _can_seek_fast = false;
00036   _aborted = false;
00037   _last_start = -1.0;
00038   _next_start = 0.0;
00039   _streaming = true;
00040   _ready = false;
00041 
00042   _capture = cvCaptureFromCAM(src->_camera_index);
00043   if (_capture != NULL) {
00044     _size_x = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
00045     _size_y = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
00046     _ready = true;
00047   }
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: WebcamVideoCursorOpenCV::Destructor
00052 //       Access: Published, Virtual
00053 //  Description:
00054 ////////////////////////////////////////////////////////////////////
00055 WebcamVideoCursorOpenCV::
00056 ~WebcamVideoCursorOpenCV() {
00057   if (_capture != NULL) {
00058     cvReleaseCapture(&_capture);
00059     _capture = NULL;
00060   }
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: WebcamVideoCursorOpenCV::fetch_into_buffer
00065 //       Access: Published, Virtual
00066 //  Description:
00067 ////////////////////////////////////////////////////////////////////
00068 void WebcamVideoCursorOpenCV::
00069 fetch_into_buffer(double time, unsigned char *block, bool bgra) {
00070   if (!_ready) {
00071     return;
00072   }
00073 
00074   unsigned char *dest = block;
00075   int num_components = bgra ? 4 : 3;
00076   ssize_t dest_x_pitch = num_components;  // Assume component_width == 1
00077   ssize_t dest_y_pitch = _size_x * dest_x_pitch;
00078 
00079   const unsigned char *r, *g, *b;
00080   ssize_t x_pitch, y_pitch;
00081   if (get_frame_data(r, g, b, x_pitch, y_pitch)) {
00082     if (num_components == 3 && x_pitch == 3) {
00083       // The easy case--copy the whole thing in, row by row.
00084       ssize_t copy_bytes = _size_x * dest_x_pitch;
00085       nassertv(copy_bytes <= dest_y_pitch && copy_bytes <= abs(y_pitch));
00086       
00087       for (int y = 0; y < _size_y; ++y) {
00088         memcpy(dest, r, copy_bytes);
00089         dest += dest_y_pitch;
00090         r += y_pitch;
00091       }
00092 
00093     } else {
00094       // The harder case--interleave in the color channels, pixel by
00095       // pixel.
00096       
00097       for (int y = 0; y < _size_y; ++y) {
00098         ssize_t dx = 0;
00099         ssize_t sx = 0;
00100         for (int x = 0; x < _size_x; ++x) {
00101           dest[dx] = r[sx];
00102           dest[dx + 1] = g[sx];
00103           dest[dx + 2] = b[sx];
00104           dx += dest_x_pitch;
00105           sx += x_pitch;
00106         }
00107         dest += dest_y_pitch;
00108         r += y_pitch;
00109         g += y_pitch;
00110         b += y_pitch;
00111       }
00112     }
00113   }
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: WebcamVideoCursorOpenCV::get_frame_data
00118 //       Access: Private
00119 //  Description: Gets the data needed to traverse through the
00120 //               decompressed buffer.  Returns true on success, false
00121 //               on failure.
00122 //
00123 //               In the case of a success indication (true return
00124 //               value), the three pointers r, g, b are loaded with
00125 //               the addresses of the three components of the
00126 //               bottom-left pixel of the image.  (They will be
00127 //               adjacent in memory in the case of an interleaved
00128 //               image, and separated in the case of a
00129 //               separate-channel image.)  The x_pitch value is filled
00130 //               with the amount to add to each pointer to advance to
00131 //               the pixel to the right; and the y_pitch value is
00132 //               filled with the amount to add to each pointer to
00133 //               advance to the pixel above.  Note that these values
00134 //               may be negative (particularly in the case of a
00135 //               top-down image).
00136 ////////////////////////////////////////////////////////////////////
00137 bool WebcamVideoCursorOpenCV::
00138 get_frame_data(const unsigned char *&r,
00139                const unsigned char *&g,
00140                const unsigned char *&b,
00141                ssize_t &x_pitch, ssize_t &y_pitch) {
00142   nassertr(ready(), false);
00143 
00144   IplImage *image = cvQueryFrame(_capture);
00145   if (image == NULL) {
00146     return false;
00147   }
00148 
00149   r = (const unsigned char *)image->imageData;
00150   g = r + 1;
00151   b = g + 1;
00152   x_pitch = 3;
00153   y_pitch = image->widthStep;
00154 
00155   if (image->dataOrder == 1) {
00156     // Separate channel images.  That means a block of r, followed by
00157     // a block of g, followed by a block of b.
00158     x_pitch = 1;
00159     g = r + image->height * y_pitch;
00160     b = g + image->height * y_pitch;
00161   }
00162 
00163   if (image->origin == 0) {
00164     // The image data starts with the top row and ends with the bottom
00165     // row--the opposite of Texture::_ram_data's storage convention.
00166     // Therefore, we must increment the initial pointers to the last
00167     // row, and count backwards.
00168     r += (image->height - 1) * y_pitch;
00169     g += (image->height - 1) * y_pitch;
00170     b += (image->height - 1) * y_pitch;
00171     y_pitch = -y_pitch;
00172   }
00173 
00174   return true;
00175 }
00176 
00177 #endif
 All Classes Functions Variables Enumerations