Panda3D
Loading...
Searching...
No Matches
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
25TypeHandle WebcamVideoCursorOpenCV::_type_handle;
26
27/**
28 *
29 */
30WebcamVideoCursorOpenCV::
31WebcamVideoCursorOpenCV(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 */
53WebcamVideoCursorOpenCV::
54~WebcamVideoCursorOpenCV() {
55 if (_capture != nullptr) {
56 cvReleaseCapture(&_capture);
57 _capture = nullptr;
58 }
59}
60
61/**
62 *
63 */
64PT(MovieVideoCursor::Buffer) WebcamVideoCursorOpenCV::
65fetch_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 */
129bool WebcamVideoCursorOpenCV::
130get_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
A MovieVideo is actually any source that provides a sequence of video frames.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.