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
MovieVideoCursor
A MovieVideo is actually any source that provides a sequence of video frames.
Definition: movieVideoCursor.h:41
movieVideoCursor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
webcamVideoCursorOpenCV.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Buffer
Definition: buffer.h:24
webcamVideoOpenCV.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MovieVideoCursor::Buffer
Definition: movieVideoCursor.h:62