summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfred <fred@home.lan>2011-04-22 23:45:46 (GMT)
committer fred <fred@home.lan>2011-04-22 23:45:46 (GMT)
commit9be6947d00722cabfcb779eca527e25a692f3258 (patch)
tree8d8e770cc6199353dad81fa6afb245f76e2f9d7d
parente5664d8352555bf6c05954a04a67a3df1692bb94 (diff)
Added the ability to change the V4L2 devices resolution
- Created a QqComboRes class. - In Layer class, added the types VIDEOLAYER and V4L2LAYER. - In v4l2_layer.h and .cpp, created a Res class containing the available resolutions. - In QqWidget conctructor, determines if the layer is a v4l2 layer, added a combobox with the different resolutions if it is. - In a Qfreej menu, added the full screen function.
-rw-r--r--qt/Makefile.am4
-rw-r--r--qt/Qfreej.pro6
-rw-r--r--qt/QqWidget.cpp10
-rw-r--r--qt/QqWidget.h3
-rw-r--r--qt/TODO11
-rw-r--r--qt/qfreej.cpp8
-rw-r--r--qt/qfreej.h1
-rw-r--r--qt/qqcombores.cpp36
-rw-r--r--qt/qqcombores.h29
-rw-r--r--src/include/layer.h2
-rw-r--r--src/include/v4l2_layer.h26
-rw-r--r--src/theorautils.cpp2
-rw-r--r--src/v4l2_layer.cpp335
-rw-r--r--src/video_layer.cpp2
14 files changed, 447 insertions, 28 deletions
diff --git a/qt/Makefile.am b/qt/Makefile.am
index 4710fe4..3a98516 100644
--- a/qt/Makefile.am
+++ b/qt/Makefile.am
@@ -26,7 +26,8 @@ BUILT_SOURCES = ui_qfreej.h \
moc_qJackClient.cpp \
moc_qOpacity.cpp \
moc_qLogging.cpp \
- moc_qEncoder.cpp
+ moc_qEncoder.cpp \
+ moc_qqcombores.cpp
SOURCES = main.cpp \
@@ -42,6 +43,7 @@ SOURCES = main.cpp \
qOpacity.cpp \
qEncoder.cpp \
qLogging.cpp \
+ qqcombores.cpp \
$(BUILT_SOURCES)
diff --git a/qt/Qfreej.pro b/qt/Qfreej.pro
index 0d71763..5fdffd1 100644
--- a/qt/Qfreej.pro
+++ b/qt/Qfreej.pro
@@ -19,7 +19,8 @@ SOURCES += main.cpp \
qJackClient.cpp \
qOpacity.cpp \
qEncoder.cpp \
- qLogging.cpp
+ qLogging.cpp \
+ qqcombores.cpp
HEADERS += qfreej.h \
QqComboBlit.h \
@@ -32,7 +33,8 @@ SOURCES += main.cpp \
qJackClient.h \
qOpacity.h \
qEncoder.h \
- qLogging.h
+ qLogging.h \
+ qqcombores.h
#FORMS += qfreej.ui
CONFIG += qt debug
LIBS += -lfreej
diff --git a/qt/QqWidget.cpp b/qt/QqWidget.cpp
index 7ab0048..acc2b8d 100644
--- a/qt/QqWidget.cpp
+++ b/qt/QqWidget.cpp
@@ -92,13 +92,19 @@ QqWidget::QqWidget(Context *freej, QqTabWidget* tabWidget, Qfreej* qfreej, QStri
layoutV = new QVBoxLayout;
layoutH = new QHBoxLayout;
+ QVBoxLayout *layV = new QVBoxLayout;
QqComboBlit *blt = new QqComboBlit(this);
blt->addLayer(qLayer);
+ layV->addWidget(blt);
+ qDebug() << "++ type :" << qLayer->type;
+ if (qLayer->type == 4) { //V4L2LAYER
+ m_comboRes = new QqComboRes ((V4L2CamLayer *)qLayer, this);
+ layV->addWidget(m_comboRes);
+ }
-
- layoutH->addWidget(blt);
+ layoutH->addLayout(layV);
QqComboFilter *filter = new QqComboFilter(freej, qLayer, this);
filter->setToolTip("filters to be applied");
diff --git a/qt/QqWidget.h b/qt/QqWidget.h
index b52bd72..006362d 100644
--- a/qt/QqWidget.h
+++ b/qt/QqWidget.h
@@ -16,8 +16,10 @@
#include <FakeWindow.h>
#include <QqTabWidget.h>
#include <generator_layer.h>
+#include <qqcombores.h>
class Qfreej;
+class QqComboRes;
class QqWidget : public QWidget
@@ -71,5 +73,6 @@ private:
QDoubleSpinBox *m_angleBox;
double m_angle;
QqTabWidget *m_tabWidg;
+ QqComboRes *m_comboRes;
};
#endif // QQWIDGET_H
diff --git a/qt/TODO b/qt/TODO
index 88b64c2..7548a33 100644
--- a/qt/TODO
+++ b/qt/TODO
@@ -1,9 +1,9 @@
//move main window in accordance with the size
//resize ViewPort in accordance to the biggest layer .... (not sure it is good thing)
-//be able to record all marked opened layers with the same quality .... a challenge :)
+//be able to record all marked opened layers with the initial quality.
//devide the fake size window by two .... not sure :)
//insert STRING filters parameters
-//add a x:x ratio button, resizing to the closest width and lenght to obtain this ratio
+//add an x:x ratio button, resizing to the closest width and lenght to obtain this ratio
//create a console for messages comming from func() warning() notice() act(). see Logger class
//see to integrate ogg skeleton config on the graphic interface
//there is a delay between audio and video if you open a video before creating
@@ -15,8 +15,9 @@ the QJackClient of the time you waited to open the QJackClient .... see if a fix
//see if possible to manage an audio layer
//be able to change v4l2 resolution from the graphic interface and to disable it for some bad v4l2 devices
//try to suppress the drift taken when applying an effect
-//streaming a/v, when stopping audio, the stream is corrupted and the client stops (oggmux_flush)
//needs to launch QJackClient before start streaming when you want audio.
//needs to re-launch streaming when disconnect and reconnect the jack input port
-//try to see why there is around 100 us more in between each call to the fps class (40100 instead od 40000 for 25fps)
-//merge with mastr branch ..... mainly for qt config modif \ No newline at end of file
+//have to supress the other mutex
+//[!] nanosleep returned an error, not performing delay! message on the second TextLayer
+//maybe fixed//there is around 1100 normal streaming with fps modified and 200 sec more without ... find why it stops
+//try to improve fullscreen mode.
diff --git a/qt/qfreej.cpp b/qt/qfreej.cpp
index 858ff16..a7bf8d8 100644
--- a/qt/qfreej.cpp
+++ b/qt/qfreej.cpp
@@ -69,6 +69,9 @@ Qfreej::Qfreej(QWidget *parent) :
QAction *actionOpa = menuOpacity->addAction("&Opacity");
connect(actionOpa, SIGNAL(triggered()), this, SLOT(changeOpacity()));
+ QAction *actionFullScreen = menuOpacity->addAction("&Full screen");
+ connect(actionFullScreen, SIGNAL(triggered()), this, SLOT(setFullScreen()));
+
menuGenerator = menuFichier->addMenu("&Generators");
QAction *actionLog = menuFichier->addAction("&Logs");
@@ -114,6 +117,11 @@ void Qfreej::changeOpacity()
m_Opacity->show();
}
+void Qfreej::setFullScreen()
+{
+ screen->fullscreen();
+}
+
void Qfreej::closeEvent(QCloseEvent *event)
{
event->accept();
diff --git a/qt/qfreej.h b/qt/qfreej.h
index cc726f6..03cba38 100644
--- a/qt/qfreej.h
+++ b/qt/qfreej.h
@@ -53,6 +53,7 @@ public slots:
void jackConnect();
void encConnect();
void showLogs();
+ void setFullScreen();
protected:
void closeEvent(QCloseEvent*);
diff --git a/qt/qqcombores.cpp b/qt/qqcombores.cpp
new file mode 100644
index 0000000..45082d1
--- /dev/null
+++ b/qt/qqcombores.cpp
@@ -0,0 +1,36 @@
+#include <qqcombores.h>
+#include <sstream>
+#include <string>
+#include <QDebug>
+#include <iostream>
+#include <FakeWindow.h>
+
+QqComboRes::QqComboRes(V4L2CamLayer *lay, QqWidget *parent) :
+ QWidget(parent)
+{
+ m_QqWidget = parent;
+ m_resBox = new QComboBox(this);
+ m_resBox->setToolTip("V4L2 resolution");
+ m_res = lay->getRes();
+ m_lay = lay;
+ QStringList res;
+
+ QString qx, qy, qres;
+ qDebug() << "++ nb:" << m_res->getNb();
+ for (int i = 0; i < m_res->getNb(); i++){
+ qx.setNum (m_res->getX(i));
+ qy.setNum (m_res->getY(i));
+ qDebug() << "++ x:" << m_res->getX(i) << " y:" << m_res->getY(i) << " i:" << i;
+ qres.clear();
+ qres = qx + "x" + qy;
+ res << qres;
+ }
+ m_resBox->addItems(res);
+ m_resBox->setCurrentIndex(m_res->getCurIdx());
+ connect(m_resBox, SIGNAL(activated(int)), this, SLOT(changeRes(int)));
+}
+
+void QqComboRes::changeRes(int line) {
+ m_lay->chgRes(line, m_res);
+ m_QqWidget->resetZoom();
+} \ No newline at end of file
diff --git a/qt/qqcombores.h b/qt/qqcombores.h
new file mode 100644
index 0000000..b221ccb
--- /dev/null
+++ b/qt/qqcombores.h
@@ -0,0 +1,29 @@
+#ifndef QQCOMBORES_H
+#define QQCOMBORES_H
+
+#include <QWidget>
+#include <QComboBox>
+#include <v4l2_layer.h>
+#include <QqWidget.h>
+
+class QqWidget;
+
+class QqComboRes : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit QqComboRes(V4L2CamLayer *, QqWidget *parent = 0);
+
+
+public slots:
+ void changeRes(int);
+
+private:
+ QComboBox *m_resBox;
+ QqWidget *m_QqWidget;
+ Res *m_res;
+ V4L2CamLayer *m_lay;
+ int m_nbRes;
+};
+
+#endif // QQCOMBORES_H
diff --git a/src/include/layer.h b/src/include/layer.h
index 77e0da6..e307f5a 100644
--- a/src/include/layer.h
+++ b/src/include/layer.h
@@ -90,6 +90,8 @@ class Layer: public Entry, public JSyncThread {
UNKNOWN,
TEXT,
GENERATOR,
+ VIDEOLAYER,
+ V4L2LAYER,
#if defined HAVE_DARWIN && defined WITH_COCOA
GL_COCOA
#endif
diff --git a/src/include/v4l2_layer.h b/src/include/v4l2_layer.h
index 942813a..28c55bc 100644
--- a/src/include/v4l2_layer.h
+++ b/src/include/v4l2_layer.h
@@ -26,6 +26,25 @@
#include <linux/videodev2.h>
+class Res {
+public:
+ Res(int sz);
+ ~Res();
+ bool addRes(int, int, int);
+ int getNb();
+ int getX(int);
+ int getY(int);
+ void setsX(int);
+ int getCurIdx();
+ void chgRes(int);
+
+private:
+ int m_idx, m_curIdx, m_size, m_fd;
+ int (*m_sizes)[2];
+ bool m_dec;
+ struct v4l2_format m_format;
+};
+
class V4L2CamLayer: public Layer {
public:
V4L2CamLayer();
@@ -34,6 +53,8 @@ class V4L2CamLayer: public Layer {
bool open(const char *devfile);
void *feed();
void close();
+ Res *getRes();
+ void chgRes(int, Res *);
protected:
bool _init();
@@ -47,6 +68,9 @@ class V4L2CamLayer: public Layer {
int framenum;
void *frame;
+ int nb_sizes;
+ Res *m_res;
+ struct v4l2_frmsizeenum framesize;
struct v4l2_capability capability;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_input input; ///< info about current video input
@@ -58,7 +82,7 @@ class V4L2CamLayer: public Layer {
void *start;
size_t length;
} *buffers;
-
+ char m_devfile[2048];
// allow to use Factory on this class
FACTORY_ALLOWED;
diff --git a/src/theorautils.cpp b/src/theorautils.cpp
index 3526519..c3dc743 100644
--- a/src/theorautils.cpp
+++ b/src/theorautils.cpp
@@ -391,7 +391,7 @@ void oggmux_init (oggmux_info *info){
if (!vorbis_analysis_init (&info->vd, &info->vi))
{
- std::cerr << "-------- vorbis_analysis_init failed, seems normal !!" << std::endl;
+// std::cerr << "-------- vorbis_analysis_init failed, seems normal !!" << std::endl;
}
vorbis_comment_init (&info->vc);
diff --git a/src/v4l2_layer.cpp b/src/v4l2_layer.cpp
index 352322c..5ef9966 100644
--- a/src/v4l2_layer.cpp
+++ b/src/v4l2_layer.cpp
@@ -40,8 +40,112 @@
#include <v4l2_layer.h>
+#define ARRAY_RESOLUTION_SIZE 30
+
FACTORY_REGISTER_INSTANTIATOR(Layer, V4L2CamLayer, CamLayer, v4l2);
+Res::Res(int sz) {
+ m_size = sz;
+ m_sizes = (int(*)[2]) malloc(sz * sizeof(*m_sizes));
+ m_idx = 0;
+ m_curIdx = 0;
+}
+
+Res::~Res() {
+ if(m_sizes) free(m_sizes);
+}
+
+bool Res::addRes(int x, int y, int type) {
+ if (type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ if (m_idx < (m_size -1)) {
+ m_sizes[m_idx][0] = x;
+ m_sizes[m_idx][1] = y;
+ std::cerr << "--" << m_sizes[m_idx][0] << "x" << y << std::endl;
+ m_idx++;
+ return (true);
+ }
+ else
+ return (false);
+ }
+/* else {
+ if (m_idx > 0) {
+ m_sizes[m_idx][0] = x;
+ m_sizes[m_idx][1] = y;
+ m_idx--;
+ return (true);
+ }
+ else
+ return (false);
+ }*/
+}
+
+int Res::getNb() {
+ return (m_idx);
+}
+
+int Res::getX(int val) {
+ if ((val < m_idx) && (val >= 0))
+ return (m_sizes[val][0]);
+ else {
+ return (0);
+ }
+}
+
+int Res::getY(int val) {
+ if ((val < m_idx) && (val >= 0))
+ return (m_sizes[val][1]);
+ else {
+ return (0);
+ }
+}
+
+void Res::setsX(int x) {
+ for (int i; i < m_idx; i++) {
+ if (x == m_sizes[i][0]) {
+ m_curIdx = i;
+ break;
+ }
+ }
+}
+
+int Res::getCurIdx() {
+ return (m_curIdx);
+}
+
+void Res::chgRes(int line) {
+ if (line < m_idx) {
+ // first, turn off streaming
+/* if(-1 == ioctl(m_fd, VIDIOC_STREAMOFF, &buftype)) {
+ error("VIDIOC_STREAMOFF: %s", errno);
+ }
+ */
+
+ /* Cleanup. */
+/* for (unsigned int i = 0; i < reqbuf.count; i++)
+ munmap (buffers[i].start, buffers[i].length);
+ memset (&m_format, 0, sizeof (m_format));
+ m_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == ioctl (m_fd, VIDIOC_G_FMT, &m_format)) {
+ perror ("VIDIOC_G_FMT");
+ return;
+ }*/
+// memset (&m_format, 0, sizeof (m_format));
+// m_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+/* m_format.fmt.pix.width = m_sizes[line][0];
+ m_format.fmt.pix.height = m_sizes[line][1];
+ m_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ m_format.fmt.pix.field = V4L2_FIELD_ANY;
+ if(0 == ioctl(m_fd, VIDIOC_TRY_FMT, &m_format)) {
+ std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
+ if(-1 == ioctl(m_fd, VIDIOC_S_FMT, &m_format)) {
+ error("VIDIOC_G_FMT: %s", strerror(errno));
+ return;
+ }
+ }*/
+ }
+}
+
V4L2CamLayer::V4L2CamLayer()
:Layer() {
@@ -51,12 +155,13 @@ V4L2CamLayer::V4L2CamLayer()
fd = 0;
frame = NULL;
buffers = NULL;
-
+ nb_sizes = 0;
+ m_res = NULL;
set_name("V4L2");
}
V4L2CamLayer::~V4L2CamLayer() {
-
+ if(m_res) delete(m_res);
if(fd) ::close(fd);
if(buffers) ::free(buffers);
if(frame) ::free(frame);
@@ -72,6 +177,8 @@ bool V4L2CamLayer::open(const char *devfile) {
fd = ::open(devfile,O_RDWR);
}
notice("Video4Linux2 device opened: %s",devfile);
+
+ strcpy (m_devfile, devfile);
// Check that streaming is supported
memset(&capability, 0, sizeof(capability));
@@ -112,15 +219,52 @@ bool V4L2CamLayer::open(const char *devfile) {
standard.index++;
}
- //displays the format description
+ //fills the frame size the format description
memset (&fmtdesc, 0, sizeof (fmtdesc));
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while (0 == ioctl (fd, VIDIOC_ENUM_FMT, &fmtdesc)) {
std::cerr << "----- format description :" << fmtdesc.description << std::endl;
+ if (!m_res)
+ m_res = new Res (ARRAY_RESOLUTION_SIZE);
+ for (int i=0; ;i++){
+ memset(&framesize, 0, sizeof framesize);
+ framesize.pixel_format = fmtdesc.pixelformat;
+ framesize.index = i;
+ int ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &framesize);
+ if (ret < 0)
+ break;
+ if (i != framesize.index)
+ error ("Warning: driver returned wrong frame index "
+ "%u.\n", framesize.index);
+ if (fmtdesc.pixelformat != framesize.pixel_format)
+ error("Warning: driver returned wrong frame pixel "
+ "format %08x.\n", framesize.pixel_format);
+
+ switch (framesize.type) {
+ case V4L2_FRMSIZE_TYPE_DISCRETE:
+ m_res->addRes (framesize.discrete.width, framesize.discrete.height, V4L2_FRMSIZE_TYPE_DISCRETE);
+ break;
+
+ case V4L2_FRMSIZE_TYPE_CONTINUOUS:
+ m_res->addRes (framesize.stepwise.max_width, framesize.stepwise.max_height, V4L2_FRMSIZE_TYPE_CONTINUOUS);
+ m_res->addRes (framesize.stepwise.min_width, framesize.stepwise.min_height, V4L2_FRMSIZE_TYPE_CONTINUOUS);
+ break;
+
+ case V4L2_FRMSIZE_TYPE_STEPWISE:
+ m_res->addRes (framesize.stepwise.max_width, framesize.stepwise.max_height, V4L2_FRMSIZE_TYPE_STEPWISE);
+ m_res->addRes (framesize.stepwise.min_width, framesize.stepwise.min_height, V4L2_FRMSIZE_TYPE_STEPWISE);
+ m_res->addRes (framesize.stepwise.step_width, framesize.stepwise.step_height, V4L2_FRMSIZE_TYPE_STEPWISE);
+ break;
+
+ default:
+ break;
+ }
+ }
fmtdesc.index++;
}
+//gets the current resolution
memset (&format, 0, sizeof (format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -129,19 +273,22 @@ bool V4L2CamLayer::open(const char *devfile) {
return (false);
}
-///////////// does not work with my ricoh and the uvcvideo module .... just comment out if needed
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- format.fmt.pix.width = 352;
- format.fmt.pix.height = 288;
- format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- format.fmt.pix.field = V4L2_FIELD_ANY;
- if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
- std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
- if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
- error("VIDIOC_G_FMT: %s", strerror(errno));
- return(false);
- }
+ if (m_res) {
+ m_res->setsX(format.fmt.pix.width);
}
+///////////// does not work with my ricoh and the uvcvideo module .... just comment out if needed
+// format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+// format.fmt.pix.width = 352;
+// format.fmt.pix.height = 288;
+// format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+// format.fmt.pix.field = V4L2_FIELD_ANY;
+// if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
+// std::cerr << "--- we should be able to setup the resolution :)" << std::endl;
+// if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
+// error("VIDIOC_S_FMT: %s", strerror(errno));
+// return(false);
+// }
+// }
// Need to find out (request?) specific data format (sec 1.10.1)
memset(&format, 0, sizeof(format));
@@ -163,7 +310,7 @@ bool V4L2CamLayer::open(const char *devfile) {
memset (&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
- reqbuf.count = 32;
+ reqbuf.count = 4; //reduced to reduce the display delay (thanks snawrocki)
if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
if (errno == EINVAL)
error("video capturing by mmap-streaming is not supported");
@@ -233,10 +380,15 @@ bool V4L2CamLayer::open(const char *devfile) {
act("%s is supported by V4L2 layer", devfile);
opened = true;
+ type = V4L2LAYER;
return true;
}
+Res *V4L2CamLayer::getRes() {
+ return (m_res);
+}
+
bool V4L2CamLayer::_init() {
// format.fmt.pix.width = geo.w;
@@ -279,6 +431,157 @@ void *V4L2CamLayer::feed() {
return frame;
}
+void V4L2CamLayer::chgRes(int idx, Res *res) {
+ if(!opened) return;
+ this->stop();
+ // first, turn off streaming
+ if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &buftype)) {
+ error("VIDIOC_STREAMOFF: %s", errno);
+ }
+ /* Cleanup. */
+ for (unsigned int i = 0; i < reqbuf.count; i++)
+ munmap (buffers[i].start, buffers[i].length);
+
+ if (-1 == ::close (fd)) {
+ error ("can't close the v4l2 opened device : %s", strerror (errno));
+ this->start();
+ return;
+ }
+ if (-1 == (fd = ::open(m_devfile,O_RDWR|O_NONBLOCK))) {
+ error("error in opening video capture device: %s", m_devfile);
+ this->start();
+ return;
+ } else {
+ ::close(fd);
+ fd = ::open(m_devfile,O_RDWR);
+ }
+
+
+ // Switch to the first video input (example 1-2)
+ int index=0;
+ if(-1 == ioctl(fd, VIDIOC_G_INPUT, &index)) { //gets the current video input
+ error("VIDIOC_G_INPUT: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ // change the resolution
+ memset (&format, 0, sizeof (format));
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) {
+ perror ("VIDIOC_G_FMT");
+ this->start();
+ return;
+ }
+// memset (&format, 0, sizeof (format));
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ format.fmt.pix.width = res->getX(idx);
+ format.fmt.pix.height = res->getY(idx);
+ format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ format.fmt.pix.field = V4L2_FIELD_ANY;
+ if(0 == ioctl(fd, VIDIOC_TRY_FMT, &format)) {
+ if(-1 == ioctl(fd, VIDIOC_S_FMT, &format)) {
+ error("VIDIOC_S_FMT: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ }
+ memset (&format, 0, sizeof (format));
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) {
+ perror ("VIDIOC_G_FMT");
+ this->start();
+ return;
+ }
+ if ((format.fmt.pix.width != res->getX(idx)) || (format.fmt.pix.height != res->getY(idx))) {
+ error ("couldn't change the resolution, still : %dx%d", format.fmt.pix.width, format.fmt.pix.height);
+ this->start();
+ return;
+ }
+ geo.init(format.fmt.pix.width, format.fmt.pix.height, 32);
+ free (frame);
+ frame = malloc(geo.bytesize);
+
+ //////// init buffers
+ memset (&reqbuf, 0, sizeof (reqbuf));
+ reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ reqbuf.memory = V4L2_MEMORY_MMAP;
+ reqbuf.count = 4; //reduced to reduce the display delay (thanks snawrocki)
+ if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
+ if (errno == EINVAL)
+ error("video capturing by mmap-streaming is not supported");
+ else
+ error ("VIDIOC_REQBUFS: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ act("this cam supports %i buffers", reqbuf.count);
+ free (buffers);
+ buffers = (bufs*)calloc (reqbuf.count, sizeof (*buffers));
+
+ if(format.fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) { // YUYV
+ warning("pixel format not recognized, trying anyway as YUYV");
+ warning("the system might become instable...");
+ }
+
+ for (unsigned int i = 0; i < reqbuf.count; i++) {
+
+ memset (&buffer, 0, sizeof (buffer));
+ buffer.type = reqbuf.type;
+ buffer.memory = V4L2_MEMORY_MMAP;
+ buffer.index = i;
+
+ if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
+ error ("VIDIOC_QUERYBUF: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ buffers[i].length = buffer.length; /* remember for munmap() */
+
+ buffers[i].start = mmap (NULL, buffer.length,
+ PROT_READ | PROT_WRITE, /* recommended */
+ MAP_SHARED, /* recommended */
+ fd, buffer.m.offset);
+
+ if (MAP_FAILED == buffers[i].start) {
+ /* If you do not exit here you should unmap() and free()
+ * the buffers mapped so far. */
+ error ("mmap: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ }
+
+ // OK, the memory is mapped, so let's queue up the buffers, turn on
+ // streaming, and do the business
+
+ // queue up all the buffers for the first time
+ for (unsigned int i = 0; i < reqbuf.count; i++) {
+
+ memset (&buffer, 0, sizeof (buffer));
+ buffer.type = reqbuf.type;
+ buffer.memory = V4L2_MEMORY_MMAP;
+ buffer.index = i;
+ buffer.length = buffers[i].length;
+
+ if (-1 == ioctl (fd, VIDIOC_QBUF, &buffer)) {
+ error ("first VIDIOC_QBUF: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ }
+
+ // turn on streaming
+ if(-1 == ioctl(fd, VIDIOC_STREAMON, &buftype)) {
+ error("VIDIOC_STREAMON: %s", strerror(errno));
+ this->start();
+ return;
+ }
+ ////////
+ this->start();
+}
+
void V4L2CamLayer::close() {
if(!opened) return;
// If we've finished, turn off streaming
diff --git a/src/video_layer.cpp b/src/video_layer.cpp
index a127b07..adf663c 100644
--- a/src/video_layer.cpp
+++ b/src/video_layer.cpp
@@ -348,6 +348,8 @@ bool VideoLayer::open(const char *file) {
opened = true;
+ type = VIDEOLAYER;
+
return true;
}