Panda3D
webcamVideoCursorOpenCV.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file webcamVideoCursorOpenCV.cxx
10  * @author drose
11  * @date 2010-10-20
12  */
13 
15 
16 #ifdef HAVE_OPENCV
17 
18 #include "webcamVideoOpenCV.h"
19 #include "movieVideoCursor.h"
20 
21 #include "pStatTimer.h"
22 
23 #include <opencv2/highgui/highgui.hpp>
24 
25 TypeHandle WebcamVideoCursorOpenCV::_type_handle;
26 
27 /**
28  *
29  */
30 WebcamVideoCursorOpenCV::
31 WebcamVideoCursorOpenCV(WebcamVideoOpenCV *src) : MovieVideoCursor(src) {
32  _size_x = src->_size_x;
33  _size_y = src->_size_y;
34  _num_components = 3;
35  _length = 1.0E10;
36  _can_seek = false;
37  _can_seek_fast = false;
38  _aborted = false;
39  _streaming = true;
40  _ready = false;
41 
42  _capture = cvCaptureFromCAM(src->_camera_index);
43  if (_capture != nullptr) {
44  _size_x = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
45  _size_y = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
46  _ready = true;
47  }
48 }
49 
50 /**
51  *
52  */
53 WebcamVideoCursorOpenCV::
54 ~WebcamVideoCursorOpenCV() {
55  if (_capture != nullptr) {
56  cvReleaseCapture(&_capture);
57  _capture = nullptr;
58  }
59 }
60 
61 /**
62  *
63  */
64 PT(MovieVideoCursor::Buffer) WebcamVideoCursorOpenCV::
65 fetch_buffer() {
66  if (!_ready) {
67  return nullptr;
68  }
69 
70  PT(Buffer) buffer = get_standard_buffer();
71  unsigned char *dest = buffer->_block;
72  int num_components = get_num_components();
73  nassertr(num_components == 3, nullptr);
74  int dest_x_pitch = num_components; // Assume component_width == 1
75  int dest_y_pitch = _size_x * dest_x_pitch;
76 
77  const unsigned char *r, *g, *b;
78  int x_pitch, y_pitch;
79  if (get_frame_data(r, g, b, x_pitch, y_pitch)) {
80  if (num_components == 3 && x_pitch == 3) {
81  // The easy case--copy the whole thing in, row by row.
82  int copy_bytes = _size_x * dest_x_pitch;
83  nassertr(copy_bytes <= dest_y_pitch && copy_bytes <= abs(y_pitch), nullptr);
84 
85  for (int y = 0; y < _size_y; ++y) {
86  memcpy(dest, r, copy_bytes);
87  dest += dest_y_pitch;
88  r += y_pitch;
89  }
90 
91  } else {
92  // The harder case--interleave in the color channels, pixel by pixel.
93 
94  for (int y = 0; y < _size_y; ++y) {
95  int dx = 0;
96  int sx = 0;
97  for (int x = 0; x < _size_x; ++x) {
98  dest[dx] = r[sx];
99  dest[dx + 1] = g[sx];
100  dest[dx + 2] = b[sx];
101  dx += dest_x_pitch;
102  sx += x_pitch;
103  }
104  dest += dest_y_pitch;
105  r += y_pitch;
106  g += y_pitch;
107  b += y_pitch;
108  }
109  }
110  }
111 
112  return buffer;
113 }
114 
115 /**
116  * Gets the data needed to traverse through the decompressed buffer. Returns
117  * true on success, false on failure.
118  *
119  * In the case of a success indication (true return value), the three pointers
120  * r, g, b are loaded with the addresses of the three components of the
121  * bottom-left pixel of the image. (They will be adjacent in memory in the
122  * case of an interleaved image, and separated in the case of a separate-
123  * channel image.) The x_pitch value is filled with the amount to add to each
124  * pointer to advance to the pixel to the right; and the y_pitch value is
125  * filled with the amount to add to each pointer to advance to the pixel
126  * above. Note that these values may be negative (particularly in the case of
127  * a top-down image).
128  */
129 bool WebcamVideoCursorOpenCV::
130 get_frame_data(const unsigned char *&r,
131  const unsigned char *&g,
132  const unsigned char *&b,
133  int &x_pitch, int &y_pitch) {
134  nassertr(ready(), false);
135 
136  IplImage *image = cvQueryFrame(_capture);
137  if (image == nullptr) {
138  return false;
139  }
140 
141  r = (const unsigned char *)image->imageData;
142  g = r + 1;
143  b = g + 1;
144  x_pitch = 3;
145  y_pitch = image->widthStep;
146 
147  if (image->dataOrder == 1) {
148  // Separate channel images. That means a block of r, followed by a block
149  // of g, followed by a block of b.
150  x_pitch = 1;
151  g = r + image->height * y_pitch;
152  b = g + image->height * y_pitch;
153  }
154 
155  if (image->origin == 0) {
156  // The image data starts with the top row and ends with the bottom row--
157  // the opposite of Texture::_ram_data's storage convention. Therefore, we
158  // must increment the initial pointers to the last row, and count
159  // backwards.
160  r += (image->height - 1) * y_pitch;
161  g += (image->height - 1) * y_pitch;
162  b += (image->height - 1) * y_pitch;
163  y_pitch = -y_pitch;
164  }
165 
166  return true;
167 }
168 
169 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Definition: buffer.h:24
A MovieVideo is actually any source that provides a sequence of video frames.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81