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 <QThread>
#include <QtConcurrent/QtConcurrent>
QMutex UVCCameraSession::sessionMutex;
......@@ -27,6 +29,8 @@ void UVCCameraSession::setSurface(QAbstractVideoSurface* 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 UVCCameraSession::callback(uvc_frame_t *frame)
{
......@@ -39,7 +43,7 @@ void UVCCameraSession::callback(uvc_frame_t *frame)
QVideoFrame qFrame;
switch(frame->frame_format) {
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);
memcpy( qFrame.bits(), frame->data, frame->data_bytes); // copied; safe to retun from callback now
qFrame.unmap();
......@@ -47,20 +51,22 @@ void UVCCameraSession::callback(uvc_frame_t *frame)
default:
return;
}
QMutexLocker locker(&frameMutex);
QMetaObject::invokeMethod(this, "presentFrame", Qt::QueuedConnection, Q_ARG(const QVideoFrame&, qFrame), Q_ARG(const qreal, t) );
#ifdef BLOCKING_FRAME_GRABBING
m_surface->present( qFrame );
#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;
tmp.setMetaData("latency", latency);
if (latency < MAX_LATENCY_MS)
m_surface->present( tmp );
frame.setMetaData("latency", latency);
frame.map(QAbstractVideoBuffer::ReadOnly);
frame.unmap();
if (latency <= MAX_LATENCY_MS)
m_surface->present(frame);
//else
// qWarning() << "Dropping frame (" << latency << "ms old )";
}
......@@ -115,6 +121,22 @@ bool UVCCameraSession::unload()
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()
{
uvc_error_t res;
......@@ -142,7 +164,11 @@ bool UVCCameraSession::startPreview()
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);
#endif
if (res != UVC_SUCCESS) {
qWarning() << "uvc_stream_start" << uvc_strerror(res);
return false;
......@@ -150,6 +176,10 @@ bool UVCCameraSession::startPreview()
streaming = true;
frameReference.restart();
#ifdef USE_CUSTOM_CALLBACK
QtConcurrent::run(customCallback, this);
#endif
return true;
}
......@@ -215,6 +245,7 @@ void UVCCameraSession::updateSourceCapabilities()
bool UVCCameraSession::stopPreview()
{
uvc_error_t res;
streaming = false;
// for some reason libuvc seems to timeout on uvc_stream_stop
for (unsigned int i=0; i<100;i++)
......@@ -224,7 +255,6 @@ bool UVCCameraSession::stopPreview()
qWarning() << "uvc_stream_stop" << uvc_strerror(res);
uvc_stream_close(strmh);
streaming = false;
frameReference.invalidate();
return true;
}
......
......@@ -22,7 +22,7 @@
QT_BEGIN_NAMESPACE
// Maximum acceptable latency for calling the surface present method
#define MAX_LATENCY_MS 100
#define MAX_LATENCY_MS 0
class UVCCameraSession : public QObject
{
......@@ -47,11 +47,13 @@ public:
bool stopPreview();
void callback(uvc_frame_t *frame);
bool streaming;
uvc_stream_handle_t *strmh;
private Q_SLOTS:
void presentFrame(const QVideoFrame &frame, const qreal t);
void presentFrame(QVideoFrame frame, const qreal t);
private:
bool streaming;
float bandwidthFactor;
QCamera::Status m_status;
QAbstractVideoSurface *m_surface;
......@@ -60,14 +62,12 @@ private:
uvc_device_t *dev;
uvc_device_handle_t *devh;
uvc_stream_ctrl_t ctrl;
uvc_stream_handle_t *strmh;
// Frame
QVideoFrame currentFrame;
unsigned char* yuvBuffer;
long unsigned int yuvBufferSize;
QElapsedTimer frameReference;
QMutex frameMutex;
// capabilities
QList<QCameraViewfinderSettings> m_supportedViewfinderSettings;
......@@ -79,6 +79,7 @@ private:
bool isPupilFieldCamera();
bool isPupilEyeCamera();
};
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