Commit cdc634a1 authored by Thiago Santini's avatar Thiago Santini

Adds additionall configuration options from debugging

When using 640x480 @ 120 FPS and the processing can't keep up with
the frame rate, some glitches start showing in the images; these commit
adds some additional options that were used during test and might be
useful in the future.

I'm not entirely sure where these glitches come from, but it seems they originate
within libuvc.
After tracing it back to this point, increasing
LIBUVC_NUM_TRANSFER_BUFS  seems to get rid of the bug.
However, setting it too high impedes opening all three pupil cameras.

Temporary solution is to make sure processing can keep up with the
framerate (e.g., by downsizing the processing input in EyeRecToo).
parent 21ff0b70
#include "uvccamerasession.h" #include "uvccamerasession.h"
#include <QThread>
#include <QtConcurrent/QtConcurrent>
QMutex UVCCameraSession::sessionMutex; QMutex UVCCameraSession::sessionMutex;
...@@ -27,6 +29,8 @@ void UVCCameraSession::setSurface(QAbstractVideoSurface* surface) ...@@ -27,6 +29,8 @@ void UVCCameraSession::setSurface(QAbstractVideoSurface* surface)
m_surface = surface; m_surface = surface;
} }
// If the following is defined, frame grabbing is performed by the callback thread
//#define BLOCKING_FRAME_GRABBING
void cb(uvc_frame_t *frame, void *ptr) { static_cast<UVCCameraSession*>(ptr)->callback(frame); } void cb(uvc_frame_t *frame, void *ptr) { static_cast<UVCCameraSession*>(ptr)->callback(frame); }
void UVCCameraSession::callback(uvc_frame_t *frame) void UVCCameraSession::callback(uvc_frame_t *frame)
{ {
...@@ -39,7 +43,7 @@ void UVCCameraSession::callback(uvc_frame_t *frame) ...@@ -39,7 +43,7 @@ void UVCCameraSession::callback(uvc_frame_t *frame)
QVideoFrame qFrame; QVideoFrame qFrame;
switch(frame->frame_format) { switch(frame->frame_format) {
case UVC_FRAME_FORMAT_MJPEG: case UVC_FRAME_FORMAT_MJPEG:
qFrame = QVideoFrame( (int) frame->data_bytes, QSize(frame->width, frame->height), -1, QVideoFrame::Format_Jpeg); qFrame = QVideoFrame( (int) frame->data_bytes, QSize(settings.resolution().width(), settings.resolution().height()), 0, QVideoFrame::Format_Jpeg);
qFrame.map(QAbstractVideoBuffer::WriteOnly); qFrame.map(QAbstractVideoBuffer::WriteOnly);
memcpy( qFrame.bits(), frame->data, frame->data_bytes); // copied; safe to retun from callback now memcpy( qFrame.bits(), frame->data, frame->data_bytes); // copied; safe to retun from callback now
qFrame.unmap(); qFrame.unmap();
...@@ -47,20 +51,22 @@ void UVCCameraSession::callback(uvc_frame_t *frame) ...@@ -47,20 +51,22 @@ void UVCCameraSession::callback(uvc_frame_t *frame)
default: default:
return; return;
} }
#ifdef BLOCKING_FRAME_GRABBING
QMutexLocker locker(&frameMutex); m_surface->present( qFrame );
QMetaObject::invokeMethod(this, "presentFrame", Qt::QueuedConnection, Q_ARG(const QVideoFrame&, qFrame), Q_ARG(const qreal, t) ); #else
QMetaObject::invokeMethod(this, "presentFrame", Qt::QueuedConnection, Q_ARG(QVideoFrame, qFrame), Q_ARG(const qreal, t) );
#endif
} }
} }
void UVCCameraSession::presentFrame(const QVideoFrame &frame, const qreal t) void UVCCameraSession::presentFrame(QVideoFrame frame, const qreal t)
{ {
QMutexLocker locker(&frameMutex);
QVideoFrame tmp(frame);
qreal latency = frameReference.elapsed() - t; qreal latency = frameReference.elapsed() - t;
tmp.setMetaData("latency", latency); frame.setMetaData("latency", latency);
if (latency < MAX_LATENCY_MS) frame.map(QAbstractVideoBuffer::ReadOnly);
m_surface->present( tmp ); frame.unmap();
if (latency <= MAX_LATENCY_MS)
m_surface->present(frame);
//else //else
// qWarning() << "Dropping frame (" << latency << "ms old )"; // qWarning() << "Dropping frame (" << latency << "ms old )";
} }
...@@ -115,6 +121,22 @@ bool UVCCameraSession::unload() ...@@ -115,6 +121,22 @@ bool UVCCameraSession::unload()
return true; return true;
} }
void customCallback(UVCCameraSession *session)
{
while (session->streaming) {
if (session->strmh == NULL)
continue;
uvc_frame_t *frame = NULL;
uvc_error_t res;
res = uvc_stream_get_frame(session->strmh, &frame, 0);
if ( res == UVC_SUCCESS && frame != NULL)
session->callback(frame);
else
qWarning() << uvc_strerror(res) << frame;
}
}
//#define USE_CUSTOM_CALLBACK
bool UVCCameraSession::startPreview() bool UVCCameraSession::startPreview()
{ {
uvc_error_t res; uvc_error_t res;
...@@ -142,7 +164,11 @@ bool UVCCameraSession::startPreview() ...@@ -142,7 +164,11 @@ bool UVCCameraSession::startPreview()
return false; return false;
} }
#ifdef USE_CUSTOM_CALLBACK
res = uvc_stream_start(strmh, NULL, (void*) this, bandwidthFactor, 0);
#else
res = uvc_stream_start(strmh, cb, (void*) this, bandwidthFactor, 0); res = uvc_stream_start(strmh, cb, (void*) this, bandwidthFactor, 0);
#endif
if (res != UVC_SUCCESS) { if (res != UVC_SUCCESS) {
qWarning() << "uvc_stream_start" << uvc_strerror(res); qWarning() << "uvc_stream_start" << uvc_strerror(res);
return false; return false;
...@@ -150,6 +176,10 @@ bool UVCCameraSession::startPreview() ...@@ -150,6 +176,10 @@ bool UVCCameraSession::startPreview()
streaming = true; streaming = true;
frameReference.restart(); frameReference.restart();
#ifdef USE_CUSTOM_CALLBACK
QtConcurrent::run(customCallback, this);
#endif
return true; return true;
} }
...@@ -215,6 +245,7 @@ void UVCCameraSession::updateSourceCapabilities() ...@@ -215,6 +245,7 @@ void UVCCameraSession::updateSourceCapabilities()
bool UVCCameraSession::stopPreview() bool UVCCameraSession::stopPreview()
{ {
uvc_error_t res; uvc_error_t res;
streaming = false;
// for some reason libuvc seems to timeout on uvc_stream_stop // for some reason libuvc seems to timeout on uvc_stream_stop
for (unsigned int i=0; i<100;i++) for (unsigned int i=0; i<100;i++)
...@@ -224,7 +255,6 @@ bool UVCCameraSession::stopPreview() ...@@ -224,7 +255,6 @@ bool UVCCameraSession::stopPreview()
qWarning() << "uvc_stream_stop" << uvc_strerror(res); qWarning() << "uvc_stream_stop" << uvc_strerror(res);
uvc_stream_close(strmh); uvc_stream_close(strmh);
streaming = false;
frameReference.invalidate(); frameReference.invalidate();
return true; return true;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// Maximum acceptable latency for calling the surface present method // Maximum acceptable latency for calling the surface present method
#define MAX_LATENCY_MS 100 #define MAX_LATENCY_MS 0
class UVCCameraSession : public QObject class UVCCameraSession : public QObject
{ {
...@@ -47,11 +47,13 @@ public: ...@@ -47,11 +47,13 @@ public:
bool stopPreview(); bool stopPreview();
void callback(uvc_frame_t *frame); void callback(uvc_frame_t *frame);
bool streaming;
uvc_stream_handle_t *strmh;
private Q_SLOTS: private Q_SLOTS:
void presentFrame(const QVideoFrame &frame, const qreal t); void presentFrame(QVideoFrame frame, const qreal t);
private: private:
bool streaming;
float bandwidthFactor; float bandwidthFactor;
QCamera::Status m_status; QCamera::Status m_status;
QAbstractVideoSurface *m_surface; QAbstractVideoSurface *m_surface;
...@@ -60,14 +62,12 @@ private: ...@@ -60,14 +62,12 @@ private:
uvc_device_t *dev; uvc_device_t *dev;
uvc_device_handle_t *devh; uvc_device_handle_t *devh;
uvc_stream_ctrl_t ctrl; uvc_stream_ctrl_t ctrl;
uvc_stream_handle_t *strmh;
// Frame // Frame
QVideoFrame currentFrame; QVideoFrame currentFrame;
unsigned char* yuvBuffer; unsigned char* yuvBuffer;
long unsigned int yuvBufferSize; long unsigned int yuvBufferSize;
QElapsedTimer frameReference; QElapsedTimer frameReference;
QMutex frameMutex;
// capabilities // capabilities
QList<QCameraViewfinderSettings> m_supportedViewfinderSettings; QList<QCameraViewfinderSettings> m_supportedViewfinderSettings;
...@@ -79,6 +79,7 @@ private: ...@@ -79,6 +79,7 @@ private:
bool isPupilFieldCamera(); bool isPupilFieldCamera();
bool isPupilEyeCamera(); bool isPupilEyeCamera();
}; };
QT_END_NAMESPACE QT_END_NAMESPACE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment