mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 22:29:24 +02:00
Read the webcam frames in a separate thread, since the call blocks.
This commit is contained in:
parent
3c58f0c0a7
commit
a771f53df3
5 changed files with 104 additions and 50 deletions
|
@ -68,7 +68,7 @@ include(${QT_USE_FILE})
|
|||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
|
||||
|
||||
# run qt moc on qt-enabled headers
|
||||
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h)
|
||||
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h src/Webcam.h)
|
||||
|
||||
# create the executable, make it a bundle on OS X
|
||||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
|
||||
|
|
|
@ -1569,9 +1569,6 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// Update transmitter
|
||||
|
||||
// Get the webcam frame
|
||||
_webcam.grabFrame();
|
||||
|
||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/agents
|
||||
updateAvatar(deltaTime);
|
||||
|
||||
|
@ -2154,26 +2151,28 @@ void Application::displayOverlay() {
|
|||
}
|
||||
|
||||
// render the webcam input frame
|
||||
glBindTexture(GL_TEXTURE_2D, _webcam.getFrameTextureID());
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
const int FRAME_PREVIEW_HEIGHT = 200;
|
||||
int framePreviewWidth = _webcam.getFrameAspectRatio() * FRAME_PREVIEW_HEIGHT;
|
||||
int bottom = _glWidget->height() - 400;
|
||||
int left = _glWidget->width() - framePreviewWidth - 400;
|
||||
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(left, bottom);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(left + framePreviewWidth, bottom);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(left + framePreviewWidth, bottom + FRAME_PREVIEW_HEIGHT);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(left, bottom + FRAME_PREVIEW_HEIGHT);
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (_webcam.getFrameTextureID() != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _webcam.getFrameTextureID());
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
const int FRAME_PREVIEW_HEIGHT = 200;
|
||||
int framePreviewWidth = _webcam.getFrameAspectRatio() * FRAME_PREVIEW_HEIGHT;
|
||||
int bottom = _glWidget->height() - 400;
|
||||
int left = _glWidget->width() - framePreviewWidth - 400;
|
||||
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(left, bottom);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(left + framePreviewWidth, bottom);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(left + framePreviewWidth, bottom + FRAME_PREVIEW_HEIGHT);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(left, bottom + FRAME_PREVIEW_HEIGHT);
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
VoxelSystem* getVoxels() { return &_voxels; }
|
||||
QSettings* getSettings() { return _settings; }
|
||||
Environment* getEnvironment() { return &_environment; }
|
||||
Webcam* getWebcam() { return &_webcam; }
|
||||
bool shouldEchoAudio() { return _echoAudioMode->isChecked(); }
|
||||
|
||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||
|
|
|
@ -11,41 +11,83 @@
|
|||
|
||||
#include <Log.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Webcam.h"
|
||||
|
||||
Webcam::Webcam() {
|
||||
if ((_capture = cvCaptureFromCAM(-1)) == 0) {
|
||||
printLog("Failed to open webcam.\n");
|
||||
return;
|
||||
}
|
||||
class FrameGrabber : public QObject {
|
||||
public:
|
||||
|
||||
// get the dimensions, fps of the frames
|
||||
_frameWidth = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH);
|
||||
_frameHeight = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT);
|
||||
int fps = cvGetCaptureProperty(_capture, CV_CAP_PROP_FPS);
|
||||
printLog("Opened camera [width=%d, height=%d, fps=%d].", _frameWidth, _frameHeight, fps);
|
||||
}
|
||||
FrameGrabber() : _capture(0) { }
|
||||
virtual ~FrameGrabber();
|
||||
|
||||
void Webcam::init() {
|
||||
// initialize the texture that will contain the grabbed frames
|
||||
glGenTextures(1, &_frameTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _frameWidth, _frameHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
protected:
|
||||
|
||||
virtual void timerEvent(QTimerEvent* event);
|
||||
|
||||
private:
|
||||
|
||||
CvCapture* _capture;
|
||||
};
|
||||
|
||||
Webcam::~Webcam() {
|
||||
FrameGrabber::~FrameGrabber() {
|
||||
if (_capture != 0) {
|
||||
cvReleaseCapture(&_capture);
|
||||
}
|
||||
}
|
||||
|
||||
void Webcam::grabFrame() {
|
||||
void FrameGrabber::timerEvent(QTimerEvent* event) {
|
||||
if (_capture == 0) {
|
||||
if ((_capture = cvCaptureFromCAM(-1)) == 0) {
|
||||
printLog("Failed to open webcam.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
IplImage* image = cvQueryFrame(_capture);
|
||||
if (image == 0) {
|
||||
return;
|
||||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _frameWidth, _frameHeight, GL_RGB, GL_UNSIGNED_BYTE, image->imageData);
|
||||
// make sure it's in the format we expect
|
||||
if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U || image->dataOrder != IPL_DATA_ORDER_PIXEL ||
|
||||
image->origin != 0 || image->widthStep != image->width * 3) {
|
||||
printLog("Invalid webcam image format.\n");
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
||||
Q_ARG(QImage, QImage((uchar*)image->imageData, image->width, image->height, QImage::Format_RGB888)));
|
||||
}
|
||||
|
||||
Webcam::Webcam() : _frameTextureID(0) {
|
||||
// the grabber simply runs as fast as possible
|
||||
_grabber = new FrameGrabber();
|
||||
_grabber->startTimer(0);
|
||||
_grabber->moveToThread(&_grabberThread);
|
||||
}
|
||||
|
||||
void Webcam::init() {
|
||||
// start the grabber thread
|
||||
_grabberThread.start();
|
||||
}
|
||||
|
||||
Webcam::~Webcam() {
|
||||
// stop the grabber thread
|
||||
_grabberThread.quit();
|
||||
_grabberThread.wait();
|
||||
|
||||
delete _grabber;
|
||||
}
|
||||
|
||||
void Webcam::setFrame(const QImage& image) {
|
||||
if (_frameTextureID == 0) {
|
||||
glGenTextures(1, &_frameTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _frameWidth = image.width(), _frameHeight = image.height(), 0, GL_BGR,
|
||||
GL_UNSIGNED_BYTE, image.constBits());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _frameWidth, _frameHeight, GL_BGR, GL_UNSIGNED_BYTE, image.constBits());
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,20 @@
|
|||
#ifndef __interface__Webcam__
|
||||
#define __interface__Webcam__
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class QImage;
|
||||
|
||||
struct CvCapture;
|
||||
|
||||
class Webcam {
|
||||
class FrameGrabber;
|
||||
|
||||
class Webcam : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Webcam();
|
||||
|
@ -26,11 +35,14 @@ public:
|
|||
float getFrameAspectRatio() const { return _frameWidth / (float)_frameHeight; }
|
||||
GLuint getFrameTextureID() const { return _frameTextureID; }
|
||||
|
||||
void grabFrame();
|
||||
|
||||
public slots:
|
||||
|
||||
void setFrame(const QImage& image);
|
||||
|
||||
private:
|
||||
|
||||
CvCapture* _capture;
|
||||
QThread _grabberThread;
|
||||
FrameGrabber* _grabber;
|
||||
|
||||
int _frameWidth;
|
||||
int _frameHeight;
|
||||
|
|
Loading…
Reference in a new issue