open_toontown_panda3d/panda/src/vision/webcamVideoCursorOpenCV.cxx

180 lines
5.7 KiB
C++

// Filename: webcamVideoCursorOpenCV.cxx
// Created by: drose (20Oct10)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "webcamVideoOpenCV.h"
#ifdef HAVE_OPENCV
#include "pStatTimer.h"
TypeHandle WebcamVideoCursorOpenCV::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: WebcamVideoCursorOpenCV::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
WebcamVideoCursorOpenCV::
WebcamVideoCursorOpenCV(WebcamVideoOpenCV *src) : MovieVideoCursor(src) {
_size_x = src->_size_x;
_size_y = src->_size_y;
_num_components = 3;
_length = 1.0E10;
_can_seek = false;
_can_seek_fast = false;
_aborted = false;
_streaming = true;
_ready = false;
_capture = cvCaptureFromCAM(src->_camera_index);
if (_capture != NULL) {
_size_x = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
_size_y = (int)cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
_ready = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: WebcamVideoCursorOpenCV::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
WebcamVideoCursorOpenCV::
~WebcamVideoCursorOpenCV() {
if (_capture != NULL) {
cvReleaseCapture(&_capture);
_capture = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: WebcamVideoCursorOpenCV::fetch_buffer
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(MovieVideoCursor::Buffer) WebcamVideoCursorOpenCV::
fetch_buffer() {
if (!_ready) {
return NULL;
}
PT(Buffer) buffer = get_standard_buffer();
unsigned char *dest = buffer->_block;
int num_components = get_num_components();
nassertr(num_components == 3, NULL);
int dest_x_pitch = num_components; // Assume component_width == 1
int dest_y_pitch = _size_x * dest_x_pitch;
const unsigned char *r, *g, *b;
int x_pitch, y_pitch;
if (get_frame_data(r, g, b, x_pitch, y_pitch)) {
if (num_components == 3 && x_pitch == 3) {
// The easy case--copy the whole thing in, row by row.
int copy_bytes = _size_x * dest_x_pitch;
nassertr(copy_bytes <= dest_y_pitch && copy_bytes <= abs(y_pitch), NULL);
for (int y = 0; y < _size_y; ++y) {
memcpy(dest, r, copy_bytes);
dest += dest_y_pitch;
r += y_pitch;
}
} else {
// The harder case--interleave in the color channels, pixel by
// pixel.
for (int y = 0; y < _size_y; ++y) {
int dx = 0;
int sx = 0;
for (int x = 0; x < _size_x; ++x) {
dest[dx] = r[sx];
dest[dx + 1] = g[sx];
dest[dx + 2] = b[sx];
dx += dest_x_pitch;
sx += x_pitch;
}
dest += dest_y_pitch;
r += y_pitch;
g += y_pitch;
b += y_pitch;
}
}
}
return buffer;
}
////////////////////////////////////////////////////////////////////
// Function: WebcamVideoCursorOpenCV::get_frame_data
// Access: Private
// Description: Gets the data needed to traverse through the
// decompressed buffer. Returns true on success, false
// on failure.
//
// In the case of a success indication (true return
// value), the three pointers r, g, b are loaded with
// the addresses of the three components of the
// bottom-left pixel of the image. (They will be
// adjacent in memory in the case of an interleaved
// image, and separated in the case of a
// separate-channel image.) The x_pitch value is filled
// with the amount to add to each pointer to advance to
// the pixel to the right; and the y_pitch value is
// filled with the amount to add to each pointer to
// advance to the pixel above. Note that these values
// may be negative (particularly in the case of a
// top-down image).
////////////////////////////////////////////////////////////////////
bool WebcamVideoCursorOpenCV::
get_frame_data(const unsigned char *&r,
const unsigned char *&g,
const unsigned char *&b,
int &x_pitch, int &y_pitch) {
nassertr(ready(), false);
IplImage *image = cvQueryFrame(_capture);
if (image == NULL) {
return false;
}
r = (const unsigned char *)image->imageData;
g = r + 1;
b = g + 1;
x_pitch = 3;
y_pitch = image->widthStep;
if (image->dataOrder == 1) {
// Separate channel images. That means a block of r, followed by
// a block of g, followed by a block of b.
x_pitch = 1;
g = r + image->height * y_pitch;
b = g + image->height * y_pitch;
}
if (image->origin == 0) {
// The image data starts with the top row and ends with the bottom
// row--the opposite of Texture::_ram_data's storage convention.
// Therefore, we must increment the initial pointers to the last
// row, and count backwards.
r += (image->height - 1) * y_pitch;
g += (image->height - 1) * y_pitch;
b += (image->height - 1) * y_pitch;
y_pitch = -y_pitch;
}
return true;
}
#endif