bin_PROGRAMS = qv4l2
qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp v4l2-api.cpp capture-win.cpp \
+ capture-win-qt.cpp capture-win-qt.h \
raw2sliced.cpp qv4l2.h capture-win.h general-tab.h vbi-tab.h v4l2-api.h raw2sliced.h
nodist_qv4l2_SOURCES = moc_qv4l2.cpp moc_general-tab.cpp moc_capture-win.cpp moc_vbi-tab.cpp qrc_qv4l2.cpp
qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la
$(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_24x24.png" "$(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/qv4l2.png"
$(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_32x32.png" "$(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/qv4l2.png"
$(INSTALL_DATA) -D -p "$(srcdir)/qv4l2_64x64.png" "$(DESTDIR)$(datadir)/icons/hicolor/64x64/apps/qv4l2.png"
- $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2.svg" "$(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/qv4l2.svg"
-
+ $(INSTALL_DATA) -D -p "$(srcdir)/qv4l2.svg" "$(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/qv4l2.svg"
\ No newline at end of file
--- /dev/null
+/* qv4l2: a control panel controlling v4l2 devices.
+ *
+ * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "capture-win-qt.h"
+
+CaptureWinQt::CaptureWinQt() :
+ m_frame(new QImage(0, 0, QImage::Format_Invalid))
+{
+
+ CaptureWin::buildWindow(&m_videoSurface);
+}
+
+CaptureWinQt::~CaptureWinQt()
+{
+ delete m_frame;
+}
+
+void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char *data, const QString &info)
+{
+ QImage::Format dstFmt;
+ bool supported = findNativeFormat(format, dstFmt);
+ if (!supported)
+ dstFmt = QImage::Format_RGB888;
+
+ if (m_frame->width() != width || m_frame->height() != height || m_frame->format() != dstFmt) {
+ delete m_frame;
+ m_frame = new QImage(width, height, dstFmt);
+ }
+
+ if (data == NULL || !supported)
+ m_frame->fill(0);
+ else
+ memcpy(m_frame->bits(), data, m_frame->numBytes());
+
+ m_information.setText(info);
+ m_videoSurface.setPixmap(QPixmap::fromImage(*m_frame));
+}
+
+bool CaptureWinQt::hasNativeFormat(__u32 format)
+{
+ QImage::Format fmt;
+ return findNativeFormat(format, fmt);
+}
+
+bool CaptureWinQt::findNativeFormat(__u32 format, QImage::Format &dstFmt)
+{
+ static const struct {
+ __u32 v4l2_pixfmt;
+ QImage::Format qt_pixfmt;
+ } supported_fmts[] = {
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ { V4L2_PIX_FMT_RGB32, QImage::Format_RGB32 },
+ { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
+ { V4L2_PIX_FMT_RGB565X, QImage::Format_RGB16 },
+ { V4L2_PIX_FMT_RGB555X, QImage::Format_RGB555 },
+#else
+ { V4L2_PIX_FMT_BGR32, QImage::Format_RGB32 },
+ { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
+ { V4L2_PIX_FMT_RGB565, QImage::Format_RGB16 },
+ { V4L2_PIX_FMT_RGB555, QImage::Format_RGB555 },
+ { V4L2_PIX_FMT_RGB444, QImage::Format_RGB444 },
+#endif
+ { 0, QImage::Format_Invalid }
+ };
+
+ for (int i = 0; supported_fmts[i].v4l2_pixfmt; i++) {
+ if (supported_fmts[i].v4l2_pixfmt == format) {
+ dstFmt = supported_fmts[i].qt_pixfmt;
+ return true;
+ }
+ }
+ return false;
+}
--- /dev/null
+/* qv4l2: a control panel controlling v4l2 devices.
+ *
+ * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef CAPTURE_WIN_QT_H
+#define CAPTURE_WIN_QT_H
+
+#include "qv4l2.h"
+#include "capture-win.h"
+
+#include <QLabel>
+#include <QImage>
+
+class CaptureWinQt : public CaptureWin
+{
+public:
+ CaptureWinQt();
+ ~CaptureWinQt();
+
+ void setFrame(int width, int height, __u32 format,
+ unsigned char *data, const QString &info);
+
+ bool hasNativeFormat(__u32 format);
+ static bool isSupported() { return true; }
+
+private:
+ bool findNativeFormat(__u32 format, QImage::Format &dstFmt);
+
+ QImage *m_frame;
+ QLabel m_videoSurface;
+};
+#endif
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include <stdio.h>
+
+#include "capture-win.h"
+
+#include <QCloseEvent>
#include <QLabel>
#include <QImage>
#include <QVBoxLayout>
-#include <QCloseEvent>
#include <QApplication>
#include <QDesktopWidget>
-#include "qv4l2.h"
-#include "capture-win.h"
-
CaptureWin::CaptureWin()
{
- QVBoxLayout *vbox = new QVBoxLayout(this);
-
setWindowTitle("V4L2 Capture");
- m_label = new QLabel();
- m_msg = new QLabel("No frame");
+ m_hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this);
+ QObject::connect(m_hotkeyClose, SIGNAL(activated()), this, SLOT(close()));
+}
- vbox->addWidget(m_label);
- vbox->addWidget(m_msg);
+CaptureWin::~CaptureWin()
+{
+ if (layout() == NULL)
+ return;
- hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this);
- QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close()));
+ layout()->removeWidget(this);
+ delete layout();
+ delete m_hotkeyClose;
}
-CaptureWin::~CaptureWin()
+void CaptureWin::buildWindow(QWidget *videoSurface)
{
- delete hotkeyClose;
+ int l, t, r, b;
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ m_information.setText("No Frame");
+ vbox->addWidget(videoSurface, 2000);
+ vbox->addWidget(&m_information, 1, Qt::AlignBottom);
+ vbox->getContentsMargins(&l, &t, &r, &b);
+ vbox->setSpacing(b);
}
void CaptureWin::setMinimumSize(int minw, int minh)
int l, t, r, b;
layout()->getContentsMargins(&l, &t, &r, &b);
minw += l + r;
- minh += t + b + m_msg->minimumSizeHint().height() + layout()->spacing();
+ minh += t + b + m_information.minimumSizeHint().height() + layout()->spacing();
if (minw > resolution.width())
minw = resolution.width();
QWidget::setMaximumSize(maxSize.width(), maxSize.height());
}
-void CaptureWin::setImage(const QImage &image, const QString &status)
-{
- m_label->setPixmap(QPixmap::fromImage(image));
- m_msg->setText(status);
-}
-
void CaptureWin::closeEvent(QCloseEvent *event)
{
QWidget::closeEvent(event);
#ifndef CAPTURE_WIN_H
#define CAPTURE_WIN_H
+#include "qv4l2.h"
+
#include <QWidget>
#include <QShortcut>
-#include <sys/time.h>
-
-class QImage;
-class QLabel;
+#include <QLabel>
class CaptureWin : public QWidget
{
~CaptureWin();
void setMinimumSize(int minw, int minh);
- void setImage(const QImage &image, const QString &status);
+ virtual void setFrame(int width, int height, __u32 format,
+ unsigned char *data, const QString &info) = 0;
+
+ virtual bool hasNativeFormat(__u32 format) = 0;
+ static bool isSupported() { return false; }
protected:
- virtual void closeEvent(QCloseEvent *event);
+ void closeEvent(QCloseEvent *event);
+ void buildWindow(QWidget *videoSurface);
+
+ QLabel m_information;
signals:
void close();
private:
- QLabel *m_label;
- QLabel *m_msg;
- QShortcut *hotkeyClose;
-};
+ QShortcut *m_hotkeyClose;
+};
#endif
#include "general-tab.h"
#include "vbi-tab.h"
#include "capture-win.h"
+#include "capture-win-qt.h"
#include <QToolBar>
#include <QToolButton>
if (!open(device, !rawOpen))
return;
- m_capture = new CaptureWin;
+ m_capture = new CaptureWinQt;
m_capture->setMinimumSize(150, 50);
connect(m_capture, SIGNAL(close()), this, SLOT(closeCaptureWin()));
}
status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps);
if (m_showFrames)
- m_capture->setImage(*m_capImage, status);
+ m_capture->setFrame(m_capImage->width(), m_capImage->height(),
+ m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), status);
+
curStatus = statusBar()->currentMessage();
if (curStatus.isEmpty() || curStatus.startsWith("Frame: "))
statusBar()->showMessage(status);
int err = 0;
bool again;
+ unsigned char *displaybuf = NULL;
+
switch (m_capMethod) {
case methodRead:
s = read(m_frameData, m_capSrcFormat.fmt.pix.sizeimage);
break;
if (m_mustConvert)
err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat,
- m_frameData, s,
- m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
- if (!m_mustConvert || err < 0)
- memcpy(m_capImage->bits(), m_frameData, std::min(s, m_capImage->numBytes()));
+ m_frameData, s,
+ m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
+ if (m_mustConvert && err != -1)
+ displaybuf = m_capImage->bits();
+ if (!m_mustConvert)
+ displaybuf = m_frameData;
break;
case methodMmap:
if (m_showFrames) {
if (m_mustConvert)
- err = v4lconvert_convert(m_convertData,
- &m_capSrcFormat, &m_capDestFormat,
- (unsigned char *)m_buffers[buf.index].start, buf.bytesused,
- m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
- if (!m_mustConvert || err < 0)
- memcpy(m_capImage->bits(),
- (unsigned char *)m_buffers[buf.index].start,
- std::min(buf.bytesused, (unsigned)m_capImage->numBytes()));
+ err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat,
+ (unsigned char *)m_buffers[buf.index].start, buf.bytesused,
+ m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
+ if (m_mustConvert && err != -1)
+ displaybuf = m_capImage->bits();
+ if (!m_mustConvert)
+ displaybuf = (unsigned char *)m_buffers[buf.index].start;
}
if (m_makeSnapshot)
makeSnapshot((unsigned char *)m_buffers[buf.index].start, buf.bytesused);
if (m_saveRaw.openMode())
m_saveRaw.write((const char *)m_buffers[buf.index].start, buf.bytesused);
- qbuf(buf);
break;
case methodUser:
if (m_showFrames) {
if (m_mustConvert)
- err = v4lconvert_convert(m_convertData,
- &m_capSrcFormat, &m_capDestFormat,
- (unsigned char *)buf.m.userptr, buf.bytesused,
- m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
- if (!m_mustConvert || err < 0)
- memcpy(m_capImage->bits(), (unsigned char *)buf.m.userptr,
- std::min(buf.bytesused, (unsigned)m_capImage->numBytes()));
+ err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat,
+ (unsigned char *)buf.m.userptr, buf.bytesused,
+ m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage);
+ if (m_mustConvert && err != -1)
+ displaybuf = m_capImage->bits();
+ if (!m_mustConvert)
+ displaybuf = (unsigned char *)buf.m.userptr;
}
if (m_makeSnapshot)
makeSnapshot((unsigned char *)buf.m.userptr, buf.bytesused);
if (m_saveRaw.openMode())
m_saveRaw.write((const char *)buf.m.userptr, buf.bytesused);
- qbuf(buf);
break;
}
if (err == -1 && m_frame == 0)
m_tv = tv;
}
status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps);
+ if (displaybuf == NULL && m_showFrames)
+ status.append(" Error: Unsupported format.");
if (m_showFrames)
- m_capture->setImage(*m_capImage, status);
+ m_capture->setFrame(m_capImage->width(), m_capImage->height(),
+ m_capDestFormat.fmt.pix.pixelformat, displaybuf, status);
+
+ if (m_capMethod == methodMmap || m_capMethod == methodUser)
+ qbuf(buf);
+
curStatus = statusBar()->currentMessage();
if (curStatus.isEmpty() || curStatus.startsWith("Frame: "))
statusBar()->showMessage(status);
void ApplicationWindow::capStart(bool start)
{
- static const struct {
- __u32 v4l2_pixfmt;
- QImage::Format qt_pixfmt;
- } supported_fmts[] = {
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- { V4L2_PIX_FMT_RGB32, QImage::Format_RGB32 },
- { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
- { V4L2_PIX_FMT_RGB565X, QImage::Format_RGB16 },
- { V4L2_PIX_FMT_RGB555X, QImage::Format_RGB555 },
-#else
- { V4L2_PIX_FMT_BGR32, QImage::Format_RGB32 },
- { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
- { V4L2_PIX_FMT_RGB565, QImage::Format_RGB16 },
- { V4L2_PIX_FMT_RGB555, QImage::Format_RGB555 },
- { V4L2_PIX_FMT_RGB444, QImage::Format_RGB444 },
-#endif
- { 0, QImage::Format_Invalid }
- };
QImage::Format dstFmt = QImage::Format_RGB888;
struct v4l2_fract interval;
v4l2_pix_format &srcPix = m_capSrcFormat.fmt.pix;
m_capture->setMinimumSize(m_vbiWidth, m_vbiHeight);
m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt);
m_capImage->fill(0);
- m_capture->setImage(*m_capImage, "No frame");
+ m_capture->setFrame(m_capImage->width(), m_capImage->height(),
+ m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), "No frame");
m_capture->show();
}
statusBar()->showMessage("No frame");
m_capDestFormat = m_capSrcFormat;
dstPix.pixelformat = V4L2_PIX_FMT_RGB24;
- for (int i = 0; supported_fmts[i].v4l2_pixfmt; i++) {
- if (supported_fmts[i].v4l2_pixfmt == srcPix.pixelformat) {
- dstPix.pixelformat = supported_fmts[i].v4l2_pixfmt;
- dstFmt = supported_fmts[i].qt_pixfmt;
- m_mustConvert = false;
- break;
- }
+ if (m_capture->hasNativeFormat(srcPix.pixelformat)) {
+ dstPix.pixelformat = srcPix.pixelformat;
+ m_mustConvert = false;
}
+
if (m_mustConvert) {
v4l2_format copy = m_capSrcFormat;
m_capture->setMinimumSize(dstPix.width, dstPix.height);
m_capImage = new QImage(dstPix.width, dstPix.height, dstFmt);
m_capImage->fill(0);
- m_capture->setImage(*m_capImage, "No frame");
+ m_capture->setFrame(m_capImage->width(), m_capImage->height(),
+ m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), "No frame");
m_capture->show();
}
#include "v4l2-api.h"
#include "raw2sliced.h"
+#include "capture-win.h"
class QComboBox;
class QSpinBox;