Panda3D
|
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 _streaming = true; 00038 _ready = false; 00039 00040 _capture = cvCaptureFromCAM(src->_camera_index); 00041 if (_capture != NULL) { 00042 _size_x = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH); 00043 _size_y = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT); 00044 _ready = true; 00045 } 00046 } 00047 00048 //////////////////////////////////////////////////////////////////// 00049 // Function: WebcamVideoCursorOpenCV::Destructor 00050 // Access: Published, Virtual 00051 // Description: 00052 //////////////////////////////////////////////////////////////////// 00053 WebcamVideoCursorOpenCV:: 00054 ~WebcamVideoCursorOpenCV() { 00055 if (_capture != NULL) { 00056 cvReleaseCapture(&_capture); 00057 _capture = NULL; 00058 } 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: WebcamVideoCursorOpenCV::fetch_buffer 00063 // Access: Published, Virtual 00064 // Description: 00065 //////////////////////////////////////////////////////////////////// 00066 PT(MovieVideoCursor::Buffer) WebcamVideoCursorOpenCV:: 00067 fetch_buffer() { 00068 if (!_ready) { 00069 return NULL; 00070 } 00071 00072 PT(Buffer) buffer = get_standard_buffer(); 00073 unsigned char *dest = buffer->_block; 00074 int num_components = get_num_components(); 00075 nassertr(num_components == 3, NULL); 00076 int dest_x_pitch = num_components; // Assume component_width == 1 00077 int dest_y_pitch = _size_x * dest_x_pitch; 00078 00079 const unsigned char *r, *g, *b; 00080 int 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 int copy_bytes = _size_x * dest_x_pitch; 00085 nassertr(copy_bytes <= dest_y_pitch && copy_bytes <= abs(y_pitch), NULL); 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 int dx = 0; 00099 int 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 return buffer; 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: WebcamVideoCursorOpenCV::get_frame_data 00120 // Access: Private 00121 // Description: Gets the data needed to traverse through the 00122 // decompressed buffer. Returns true on success, false 00123 // on failure. 00124 // 00125 // In the case of a success indication (true return 00126 // value), the three pointers r, g, b are loaded with 00127 // the addresses of the three components of the 00128 // bottom-left pixel of the image. (They will be 00129 // adjacent in memory in the case of an interleaved 00130 // image, and separated in the case of a 00131 // separate-channel image.) The x_pitch value is filled 00132 // with the amount to add to each pointer to advance to 00133 // the pixel to the right; and the y_pitch value is 00134 // filled with the amount to add to each pointer to 00135 // advance to the pixel above. Note that these values 00136 // may be negative (particularly in the case of a 00137 // top-down image). 00138 //////////////////////////////////////////////////////////////////// 00139 bool WebcamVideoCursorOpenCV:: 00140 get_frame_data(const unsigned char *&r, 00141 const unsigned char *&g, 00142 const unsigned char *&b, 00143 int &x_pitch, int &y_pitch) { 00144 nassertr(ready(), false); 00145 00146 IplImage *image = cvQueryFrame(_capture); 00147 if (image == NULL) { 00148 return false; 00149 } 00150 00151 r = (const unsigned char *)image->imageData; 00152 g = r + 1; 00153 b = g + 1; 00154 x_pitch = 3; 00155 y_pitch = image->widthStep; 00156 00157 if (image->dataOrder == 1) { 00158 // Separate channel images. That means a block of r, followed by 00159 // a block of g, followed by a block of b. 00160 x_pitch = 1; 00161 g = r + image->height * y_pitch; 00162 b = g + image->height * y_pitch; 00163 } 00164 00165 if (image->origin == 0) { 00166 // The image data starts with the top row and ends with the bottom 00167 // row--the opposite of Texture::_ram_data's storage convention. 00168 // Therefore, we must increment the initial pointers to the last 00169 // row, and count backwards. 00170 r += (image->height - 1) * y_pitch; 00171 g += (image->height - 1) * y_pitch; 00172 b += (image->height - 1) * y_pitch; 00173 y_pitch = -y_pitch; 00174 } 00175 00176 return true; 00177 } 00178 00179 #endif