[PATCH 1/2] qv4l2: change m_scaledFrame to m_scaledSize
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-qt.cpp | 12 ++-- utils/qv4l2/capture-win-qt.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index f746379..82c618c 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -24,8 +24,8 @@ CaptureWinQt::CaptureWinQt() : { CaptureWin::buildWindow(m_videoSurface); - m_scaledFrame.setWidth(0); - m_scaledFrame.setHeight(0); + m_scaledSize.setWidth(0); + m_scaledSize.setHeight(0); } CaptureWinQt::~CaptureWinQt() @@ -39,9 +39,9 @@ void CaptureWinQt::resizeEvent(QResizeEvent *event) return; QPixmap img = QPixmap::fromImage(*m_frame); - m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), QSize(m_frame-width(), m_frame-height())); - img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); m_videoSurface.setPixmap(img); QWidget::resizeEvent(event); } @@ -56,7 +56,7 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * if (m_frame-width() != width || m_frame-height() != height || m_frame-format() != dstFmt) { delete m_frame; m_frame = new QImage(width, height, dstFmt); - m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), QSize(m_frame-width(), m_frame-height())); } @@ -68,7 +68,7 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * m_information.setText(info); QPixmap img = QPixmap::fromImage(*m_frame); - img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); m_videoSurface.setPixmap(img); } diff --git a/utils/qv4l2/capture-win-qt.h b/utils/qv4l2/capture-win-qt.h index 6029109..9faa12f 100644 --- a/utils/qv4l2/capture-win-qt.h +++ b/utils/qv4l2/capture-win-qt.h @@ -48,6 +48,6 @@ private: QImage *m_frame; QLabel m_videoSurface; - QSize m_scaledFrame; + QSize m_scaledSize; }; #endif -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] qv4l2: add cropping and qt opimization
Adds cropping to CaptureWin. It also optimizes Qt renderer to make it perform as expected with cropping and scaling. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 27 +++-- utils/qv4l2/capture-win-gl.h | 1 + utils/qv4l2/capture-win-qt.cpp | 89 -- utils/qv4l2/capture-win-qt.h | 17 +++- utils/qv4l2/capture-win.cpp| 57 ++- utils/qv4l2/capture-win.h | 20 +++--- utils/qv4l2/general-tab.cpp| 57 --- utils/qv4l2/general-tab.h | 5 +++ utils/qv4l2/qv4l2.cpp | 7 utils/qv4l2/qv4l2.h| 1 + 10 files changed, 216 insertions(+), 65 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 27ff3d3..d1828cf 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -261,6 +261,18 @@ void CaptureWinGLEngine::changeShader() glClear(GL_COLOR_BUFFER_BIT); } +void CaptureWinGLEngine::paintFrame() +{ + float crop = (float)CaptureWin::cropHeight(m_frameWidth, m_frameHeight) / m_frameHeight; + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, crop); glVertex2f(0.0, 0); + glTexCoord2f(1.0f, crop); glVertex2f(m_frameWidth, 0); + glTexCoord2f(1.0f, 1.0f - crop); glVertex2f(m_frameWidth, m_frameHeight); + glTexCoord2f(0.0f, 1.0f - crop); glVertex2f(0, m_frameHeight); + glEnd(); +} + void CaptureWinGLEngine::paintGL() { if (m_frameWidth 1 || m_frameHeight 1) { @@ -271,12 +283,7 @@ void CaptureWinGLEngine::paintGL() changeShader(); if (m_frameData == NULL) { - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); - glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); - glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); - glEnd(); + paintFrame(); return; } @@ -329,13 +336,7 @@ void CaptureWinGLEngine::paintGL() checkError(Default paint); break; } - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); - glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); - glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); - glEnd(); + paintFrame(); } void CaptureWinGLEngine::configureTexture(size_t idx) diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 0c3ff8b..5a7fb3d 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -65,6 +65,7 @@ private: void clearShader(); void changeShader(); + void paintFrame(); void configureTexture(size_t idx); void checkError(const char *msg); diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 82c618c..cc21364 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -20,12 +20,19 @@ #include capture-win-qt.h CaptureWinQt::CaptureWinQt() : - m_frame(new QImage(0, 0, QImage::Format_Invalid)) + m_frame(new QImage(0, 0, QImage::Format_Invalid)), + m_data(NULL), + m_supportedFormat(false), + m_filled(false) { CaptureWin::buildWindow(m_videoSurface); m_scaledSize.setWidth(0); m_scaledSize.setHeight(0); + m_crop.crop = 0; + m_crop.height = 0; + m_crop.offset = 0; + m_crop.bytes = 0; } CaptureWinQt::~CaptureWinQt() @@ -33,46 +40,88 @@ CaptureWinQt::~CaptureWinQt() delete m_frame; } -void CaptureWinQt::resizeEvent(QResizeEvent *event) +void CaptureWinQt::resizeScaleCrop() { - if (m_frame-bits() == NULL) - return; - - QPixmap img = QPixmap::fromImage(*m_frame); m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), - QSize(m_frame-width(), m_frame-height())); - img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); - m_videoSurface.setPixmap(img); - QWidget::resizeEvent(event); + QSize(m_frame-width(), m_frame-height())); + + if (!m_crop.bytes || m_crop.crop != cropHeight(m_frame-width(), m_frame-height())) { + m_crop.crop = cropHeight(m_frame-width(), m_frame-height()); + m_crop.height = m_frame-height() - (m_crop.crop * 2); + m_crop.offset = m_crop.crop * (m_frame-depth() / 8) * m_frame-width(); + + // Even though the values above can be valid, it might be that there is no + // data at all. This makes sure that it is. + m_crop.bytes = m_crop.height * m_frame-width
[PATCH 0/2] qv4l2: add cropping and qt opimization
Add cropping to CaptureWin as well as optimizing the Qt renderer. There is also other fixes and tweaks to the code itself. Cropping allows removal of letterboxing from the video display. Qt optimization no longer needs to copy the frame data for every frame and scaling or cropping is only performed when required. This was required to make cropping work efficent and should improve general performance. A consequence is that the Qt renderer has been rewritten. Some of the changes/improvements: - Update, add and fix status tips - Add cropping to CaptureWin - Optimized Qt renderer - Code cleanup Cropping options: - None - Top and Bottom Lines - Widescreen 14:9 - Widescreen 16:9 - Cinema 1.85:1 - Cinema 1.39:1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH FINAL 0/6] qv4l2: cropping, optimization and documentatio
qv4l2: Add cropping to the CaptureWin. In order to make the Qt renderer work with this as well, it had to be optimized to not lose framerate. A basic manpage is added along width fixing the input parameters. New Features/Improvements: - Add cropping to CaptureWin - Qt renderer has been optimized (no longer uses memcpy!) - Add a basic manpage - About window shows version number and ALSA/OpenGL support - Fix program parameters - Fix status hints for some missing GeneralTab elements - Code cleanup and fixes -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH FINAL 1/6] qv4l2: change m_scaledFrame to m_scaledSize
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-qt.cpp | 12 ++-- utils/qv4l2/capture-win-qt.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index f746379..82c618c 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -24,8 +24,8 @@ CaptureWinQt::CaptureWinQt() : { CaptureWin::buildWindow(m_videoSurface); - m_scaledFrame.setWidth(0); - m_scaledFrame.setHeight(0); + m_scaledSize.setWidth(0); + m_scaledSize.setHeight(0); } CaptureWinQt::~CaptureWinQt() @@ -39,9 +39,9 @@ void CaptureWinQt::resizeEvent(QResizeEvent *event) return; QPixmap img = QPixmap::fromImage(*m_frame); - m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), QSize(m_frame-width(), m_frame-height())); - img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); m_videoSurface.setPixmap(img); QWidget::resizeEvent(event); } @@ -56,7 +56,7 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * if (m_frame-width() != width || m_frame-height() != height || m_frame-format() != dstFmt) { delete m_frame; m_frame = new QImage(width, height, dstFmt); - m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), QSize(m_frame-width(), m_frame-height())); } @@ -68,7 +68,7 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * m_information.setText(info); QPixmap img = QPixmap::fromImage(*m_frame); - img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); m_videoSurface.setPixmap(img); } diff --git a/utils/qv4l2/capture-win-qt.h b/utils/qv4l2/capture-win-qt.h index 6029109..9faa12f 100644 --- a/utils/qv4l2/capture-win-qt.h +++ b/utils/qv4l2/capture-win-qt.h @@ -48,6 +48,6 @@ private: QImage *m_frame; QLabel m_videoSurface; - QSize m_scaledFrame; + QSize m_scaledSize; }; #endif -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH FINAL 3/6] qv4l2: fix missing status tips
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/general-tab.cpp | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 3855296..cfc6bcf 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -249,7 +249,9 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_freq = new QLineEdit(parent); m_freq-setValidator(val); m_freq-setWhatsThis(QString(Frequency\nLow: %1\nHigh: %2) - .arg(m_tuner.rangelow / factor).arg(m_tuner.rangehigh / factor)); +.arg(m_tuner.rangelow / factor) +.arg((double)m_tuner.rangehigh / factor, 0, 'f', 2)); + m_freq-setStatusTip(m_freq-whatsThis()); connect(m_freq, SIGNAL(lostFocus()), SLOT(freqChanged())); connect(m_freq, SIGNAL(returnPressed()), SLOT(freqChanged())); updateFreq(); @@ -319,7 +321,9 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_freq = new QLineEdit(parent); m_freq-setValidator(val); m_freq-setWhatsThis(QString(Frequency\nLow: %1\nHigh: %2) - .arg(m_modulator.rangelow / factor).arg(m_modulator.rangehigh / factor)); +.arg(m_tuner.rangelow / factor) +.arg((double)m_tuner.rangehigh / factor, 0, 'f', 2)); + m_freq-setStatusTip(m_freq-whatsThis()); connect(m_freq, SIGNAL(lostFocus()), SLOT(freqChanged())); connect(m_freq, SIGNAL(returnPressed()), SLOT(freqChanged())); updateFreq(); @@ -912,6 +916,7 @@ void GeneralTab::updateAudioInput() what += , has AVL; if (audio.mode V4L2_AUDMODE_AVL) what += , AVL is on; + m_audioInput-setStatusTip(what); m_audioInput-setWhatsThis(what); } @@ -964,6 +969,7 @@ void GeneralTab::updateStandard() (double)vs.frameperiod.numerator / vs.frameperiod.denominator, vs.frameperiod.numerator, vs.frameperiod.denominator, vs.framelines); + m_tvStandard-setStatusTip(what); m_tvStandard-setWhatsThis(what); updateVidCapFormat(); } @@ -1027,6 +1033,7 @@ void GeneralTab::updateTimings() what.sprintf(Video Timings (%u)\n Frame %ux%u\n, p.index, p.timings.bt.width, p.timings.bt.height); + m_videoTimings-setStatusTip(what); m_videoTimings-setWhatsThis(what); updateVidCapFormat(); } -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH FINAL 4/6] qv4l2: fix program input parameters
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 137 -- 1 file changed, 121 insertions(+), 16 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 7e2dba0..a0f21cd 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -1158,33 +1158,138 @@ void ApplicationWindow::closeEvent(QCloseEvent *event) ApplicationWindow *g_mw; +static void usage() +{ + printf( Usage:\n +qv4l2 [-R] [-h] [-d dev] [-r dev] [-V dev]\n + \n -d, --device=dev use device dev as the video device\n + if dev is a number, then /dev/videodev is used\n +-r, --radio-device=dev use device dev as the radio device\n + if dev is a number, then /dev/radiodev is used\n +-V, --vbi-device=dev use device dev as the vbi device\n + if dev is a number, then /dev/vbidev is used\n +-h, --help display this help message\n +-R, --raw open device in raw mode.\n); +} + +static void usageError(const char *msg) +{ + printf(Missing parameter for %s\n, msg); + usage(); +} + +static QString getDeviceName(QString dev, QString name) +{ + bool ok; + name.toInt(ok); + return ok ? QString(%1%2).arg(dev).arg(name) : name; +} + int main(int argc, char **argv) { QApplication a(argc, argv); - QString device = /dev/video0; bool raw = false; - bool help = false; - int i; + QString device; + QString video_device; + QString radio_device; + QString vbi_device; a.setWindowIcon(QIcon(:/qv4l2.png)); g_mw = new ApplicationWindow(); g_mw-setWindowTitle(V4L2 Test Bench); - for (i = 1; i argc; i++) { - const char *arg = a.argv()[i]; - if (!strcmp(arg, -r)) + QStringList args = a.arguments(); + for (int i = 1; i args.size(); i++) { + if (args[i] == -d || args[i] == --device) { + ++i; + if (i = args.size()) { + usageError(-d); + return 0; + } + + video_device = args[i]; + if (video_device.startsWith(-)) { + usageError(-d); + return 0; + } + + } else if (args[i] == -r || args[i] == --radio-device) { + ++i; + if (i = args.size()) { + usageError(-r); + return 0; + } + + radio_device = args[i]; + if (radio_device.startsWith(-)) { + usageError(-r); + return 0; + } + + } else if (args[i] == -V || args[i] == --vbi-device) { + ++i; + if (i = args.size()) { + usageError(-V); + return 0; + } + + vbi_device = args[i]; + if (vbi_device.startsWith(-)) { + usageError(-V); + return 0; + } + + } else if (args[i].startsWith(--device)) { + QStringList param = args[i].split(=); + if (param.size() == 2) { + video_device = param[1]; + } else { + usageError(--device); + return 0; + } + + } else if (args[i].startsWith(--radio-device)) { + QStringList param = args[i].split(=); + if (param.size() == 2) { + radio_device = param[1]; + } else { + usageError(--radio-device); + return 0; + } + + + } else if (args[i].startsWith(--vbi-device)) { + QStringList param = args[i].split(=); + if (param.size() == 2) { + vbi_device = param[1]; + } else { + usageError(--vbi-device); + return 0; + } + + } else if (args[i] == -h || args[i] == --help) { + usage(); + return 0; + + } else if (args[i] == -R || args[i] == --raw) { raw = true; - else if (!strcmp(arg, -h
[PATCH FINAL 2/6] qv4l2: add cropping to CaptureWin and Qt render
Allows for removal of letterboxes from common video formats. The Qt renderer has been rewritten to increase performance required when applying cropping. No longer uses memcpy. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 27 +++-- utils/qv4l2/capture-win-gl.h | 1 + utils/qv4l2/capture-win-qt.cpp | 89 -- utils/qv4l2/capture-win-qt.h | 15 ++- utils/qv4l2/capture-win.cpp| 57 ++- utils/qv4l2/capture-win.h | 73 +- utils/qv4l2/general-tab.cpp| 63 +++--- utils/qv4l2/general-tab.h | 5 +++ utils/qv4l2/qv4l2.cpp | 7 utils/qv4l2/qv4l2.h| 1 + 10 files changed, 270 insertions(+), 68 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 27ff3d3..d1828cf 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -261,6 +261,18 @@ void CaptureWinGLEngine::changeShader() glClear(GL_COLOR_BUFFER_BIT); } +void CaptureWinGLEngine::paintFrame() +{ + float crop = (float)CaptureWin::cropHeight(m_frameWidth, m_frameHeight) / m_frameHeight; + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, crop); glVertex2f(0.0, 0); + glTexCoord2f(1.0f, crop); glVertex2f(m_frameWidth, 0); + glTexCoord2f(1.0f, 1.0f - crop); glVertex2f(m_frameWidth, m_frameHeight); + glTexCoord2f(0.0f, 1.0f - crop); glVertex2f(0, m_frameHeight); + glEnd(); +} + void CaptureWinGLEngine::paintGL() { if (m_frameWidth 1 || m_frameHeight 1) { @@ -271,12 +283,7 @@ void CaptureWinGLEngine::paintGL() changeShader(); if (m_frameData == NULL) { - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); - glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); - glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); - glEnd(); + paintFrame(); return; } @@ -329,13 +336,7 @@ void CaptureWinGLEngine::paintGL() checkError(Default paint); break; } - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); - glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); - glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); - glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); - glEnd(); + paintFrame(); } void CaptureWinGLEngine::configureTexture(size_t idx) diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 0c3ff8b..5a7fb3d 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -65,6 +65,7 @@ private: void clearShader(); void changeShader(); + void paintFrame(); void configureTexture(size_t idx); void checkError(const char *msg); diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 82c618c..d70f317 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -20,12 +20,19 @@ #include capture-win-qt.h CaptureWinQt::CaptureWinQt() : - m_frame(new QImage(0, 0, QImage::Format_Invalid)) + m_frame(new QImage(0, 0, QImage::Format_Invalid)), + m_data(NULL), + m_supportedFormat(false), + m_filled(false) { CaptureWin::buildWindow(m_videoSurface); m_scaledSize.setWidth(0); m_scaledSize.setHeight(0); + m_crop.crop = 0; + m_crop.height = 0; + m_crop.offset = 0; + m_crop.bytes = 0; } CaptureWinQt::~CaptureWinQt() @@ -33,46 +40,88 @@ CaptureWinQt::~CaptureWinQt() delete m_frame; } -void CaptureWinQt::resizeEvent(QResizeEvent *event) +void CaptureWinQt::resizeScaleCrop() { - if (m_frame-bits() == NULL) - return; - - QPixmap img = QPixmap::fromImage(*m_frame); m_scaledSize = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), - QSize(m_frame-width(), m_frame-height())); - img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio); - m_videoSurface.setPixmap(img); - QWidget::resizeEvent(event); + QSize(m_frame-width(), m_frame-height())); + + if (!m_crop.bytes || m_crop.crop != cropHeight(m_frame-width(), m_frame-height())) { + m_crop.crop = cropHeight(m_frame-width(), m_frame-height()); + m_crop.height = m_frame-height() - (m_crop.crop * 2); + m_crop.offset = m_crop.crop * (m_frame-depth() / 8) * m_frame-width(); + + // Even though the values above can be valid, it might be that there is no + // data at all
[PATCH FINAL 5/6] qv4l2: add manpage
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/Makefile.am | 1 + utils/qv4l2/qv4l2.1 | 58 + 2 files changed, 59 insertions(+) create mode 100644 utils/qv4l2/qv4l2.1 diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 58ac097..bdc64fd 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,4 +1,5 @@ bin_PROGRAMS = qv4l2 +man_MANS = qv4l2.1 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 capture-win-gl.cpp capture-win-gl.h alsa_stream.c alsa_stream.h \ diff --git a/utils/qv4l2/qv4l2.1 b/utils/qv4l2/qv4l2.1 new file mode 100644 index 000..c6abe7c --- /dev/null +++ b/utils/qv4l2/qv4l2.1 @@ -0,0 +1,58 @@ +.TH QV4L2 1 August 2013 v4l-utils User Commands +.SH NAME +qv4l2 - A test bench application for video4linux devices +.SH SYNOPSIS +.B qv4l2 +[\fI-R\fR] [\fI-h\fR] [\fI-d dev\fR] [\fI-r dev\fR] [\fI-V dev\fR] +.SH DESCRIPTION +The qv4l2 tool is used to test video4linux capture devices, either video, vbi or radio. +This application can also serve as a generic video/TV viewer application. +.PP +However, it does not (yet) support compressed video streams other than MJPEG +.SH OPTIONS +.TP +\fB\-d\fR, \fB\-\-device\fR=\fIdev\fR +Use device dev as the video device. If dev is a number, then /dev/videodev is used. +.TP +\fB\-r\fR, \fB\-\-radio-device\fR=\fIdev\fR +Use device dev as the radio device. If dev is a number, then /dev/radiodev is used. +.TP +\fB\-V\fR, \fB\-\-vbi-device\fR=\fIdev\fR +Use device dev as the vbi device. If dev is a number, then /dev/vbidev is used. +.TP +\fB\-R\fR, \fB\-\-raw\fR +Open device in raw mode, i.e. without using the libv4l2 wrapper functions. +.TP +\fB\-h\fR, \fB\-\-help\fR +Prints the help message. +.SH HOTKEYS +.SS Main Window +.TP +\fICtrl + O\fR +Open device +.TP +\fICtrl + R\fR +Open device in raw mode +.TP +\fICtrl + W\fR +Close the device +.TP +\fICtrl + V\fR +Start capture +.TP +\fICtrl + F\fR +Resize Capture Window to frame size +.TP +\fICtrl + Q\fR +Exit the application +.SS Capture Window +.TP +\fICtrl + W\fR +Closes the window and stops capture +.TP +\fICtrl + F\fR +Resize Capture Window to frame size +.SH EXIT STATUS +On success, it returns 0. Otherwise, it will return the error code. +.SH BUGS +Report bugs to Hans Verkuil hverk...@xs4all.nl -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH FINAL 6/6] qv4l2: updated about window
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index a0f21cd..056e15d 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -1110,8 +1110,24 @@ void ApplicationWindow::saveRaw(bool checked) void ApplicationWindow::about() { +#ifdef HAVE_ALSA + bool alsa = true; +#else + bool alsa = false; +#endif +#ifdef HAVE_QTGL + bool gl = true; +#else + bool gl = false; +#endif + QMessageBox::about(this, V4L2 Test Bench, - This program allows easy experimenting with video4linux devices.); + QString(This program allows easy experimenting with video4linux devices.\n + v. %1\n\nALSA support : %2\nOpenGL support : %3) + .arg(V4L_UTILS_VERSION) + .arg(alsa ? Present : Not Available) + .arg(gl ? Present : Not Available) + ); } void ApplicationWindow::error(const QString error) -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] qv4l2: fix GeneralTab layout
This moves the layout items for cropping, scaling and ALSA to not interfere with driver specific controls. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/general-tab.cpp | 129 ++-- 1 file changed, 64 insertions(+), 65 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index cfc6bcf..cd00ecd 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -98,6 +98,70 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) if (m_querycap.capabilities V4L2_CAP_DEVICE_CAPS) m_isVbi = caps() (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE); + if (hasAlsaAudio()) { + m_audioInDevice = new QComboBox(parent); + m_audioOutDevice = new QComboBox(parent); + m_audioInDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_audioOutDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + + if (createAudioDeviceList()) { + addLabel(Audio Input Device); + connect(m_audioInDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioInDevice); + + addLabel(Audio Output Device); + connect(m_audioOutDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioOutDevice); + + if (isRadio()) { + setAudioDeviceBufferSize(75); + } else { + v4l2_fract fract; + if (!v4l2::get_interval(fract)) { + // Default values are for 30 FPS + fract.numerator = 33; + fract.denominator = 1000; + } + // Standard capacity is two frames + setAudioDeviceBufferSize((fract.numerator * 2000) / fract.denominator); + } + } else { + delete m_audioInDevice; + delete m_audioOutDevice; + m_audioInDevice = NULL; + m_audioOutDevice = NULL; + } + } + + if (!isRadio() !isVbi()) { + m_pixelAspectRatio = new QComboBox(parent); + m_pixelAspectRatio-addItem(Autodetect); + m_pixelAspectRatio-addItem(Square); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60, Anamorphic); + m_pixelAspectRatio-addItem(PAL/SECAM); + m_pixelAspectRatio-addItem(PAL/SECAM, Anamorphic); + + // Update hints by calling a get + getPixelAspectRatio(); + + addLabel(Pixel Aspect Ratio); + addWidget(m_pixelAspectRatio); + connect(m_pixelAspectRatio, SIGNAL(activated(int)), SLOT(changePixelAspectRatio())); + + m_crop = new QComboBox(parent); + m_crop-addItem(None); + m_crop-addItem(Top and Bottom Line); + m_crop-addItem(Widescreen 14:9); + m_crop-addItem(Widescreen 16:9); + m_crop-addItem(Cinema 1.85:1); + m_crop-addItem(Cinema 2.39:1); + + addLabel(Cropping); + addWidget(m_crop); + connect(m_crop, SIGNAL(activated(int)), SIGNAL(cropChanged())); + } + if (!isRadio() enum_input(vin, true)) { addLabel(Input); m_videoInput = new QComboBox(parent); @@ -148,42 +212,6 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) updateAudioOutput(); } - if (hasAlsaAudio()) { - m_audioInDevice = new QComboBox(parent); - m_audioOutDevice = new QComboBox(parent); - m_audioInDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); - m_audioOutDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); - - if (createAudioDeviceList()) { - addLabel(Audio Input Device); - connect(m_audioInDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); - addWidget(m_audioInDevice); - - addLabel(Audio Output Device); - connect(m_audioOutDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); - addWidget(m_audioOutDevice); - - if (isRadio()) { - setAudioDeviceBufferSize(75); - } else { - v4l2_fract fract; - if (!v4l2::get_interval(fract
[PATCH] qv4l2: fix GeneralTab layout
Cleans up the layout of GeneralTab. Also removes a single debug printout from original ALSA source. The debug was in a corner case and will most likely not be noticed there anyway, but is now removed. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [git:v4l-utils/master] qv4l2: add aspect ratio support
Hi. Bad news. While rebasing my cropping support branch I noticed that Hans has merged in the wrong patch series for the scaling. The one Hans have merged is one of our internal revisions, as only v1 is present on the mailing list. I sent out a full patch series on Tuesday that consists of 9 parts, wheras the part you have merged is only 7 (from YUY2 shader to aspect ratio). B. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 0/9] qv4l2: scaling, pixel aspect ratio and render fixes
The PATCHv2 only rebases for master pull. This adds scaling and aspect ratio support to the qv4l2 CaptureWin. In that regard it fixes a lot of other issues that would otherwise make scaling render incorrectly. It also fixes some issues with the original OpenGL patch series, as well as adding tweaks and improvements left out in the original patches. Some of the changes/improvements: - CaptureWin have scaling support for video frames for all renderers - CaptureWin support pixel aspect ratio scaling - Aspect ratio and scaling can be changed during capture - Reset and disable scaling options - CaptureWin's setMinimumSize is now resize, which resizes the window to the frame size given and minimum size is set automatically - The YUY2 shader programs are rewritten and has the resizing issue fixed - The Show Frames option in Capture menu can be toggled during capture - Added a hotkey: CTRL + F : (size to video 'F'rame) When either the main window or capture window is selected this will reset the scaling to fit the frame size. This option is also available in the Capture menu. Pixel Aspect Ratio Modes: - Autodetect (if not supported this assumes square pixels) - Square - NTSC/PAL-M/PAL-60 - NTSC/PAL-M/PAL-60, Anamorphic - PAL/SECAM - PAL/SECAM, Anamorphic Perfomance: All tests are done using the 3.10 kernel with OpenGL enabled and desktop effects disabled. Testing was done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. FPS for every input for a given number of streams (BGR3, YU12 and YV12 are emulated using the CPU): 1 STREAM 2 STREAMS 3 STREAMS 4 STREAMS RGB3 6060 60 60 BGR3 6060 60 58 YUYV 6060 60 60 YU12 6060 60 60 YV12 6060 60 60 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 3/9] qv4l2: fix black screen with opengl after capture
Fixes the issue when the window was beeing resized/moved and the frame image would become black. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 6 ++ 1 file changed, 6 insertions(+) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 6071410..c8238c5 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -253,6 +253,12 @@ void CaptureWinGLEngine::paintGL() changeShader(); if (m_frameData == NULL) { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); + glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); + glEnd(); return; } -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 2/9] qv4l2: fix YUY2 shader
Fixed the YUY2 shaders to support scaling. The new solution has cleaner shader code and texture upload uses a better format for OpenGL. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 68 ++ 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index c499f1f..6071410 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -1,5 +1,5 @@ /* - * The YUY2 shader code was copied and simplified from face-responder. The code is under public domain: + * The YUY2 shader code is based on face-responder. The code is under public domain: * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master * * All other OpenGL code: @@ -446,47 +446,51 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format) { switch (format) { case V4L2_PIX_FMT_YUYV: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.g - 0.5; + v = luma_chroma.a - 0.5; ); case V4L2_PIX_FMT_YVYU: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.a - 0.5; + v = luma_chroma.g - 0.5; ); case V4L2_PIX_FMT_UYVY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.a - 0.0625) * 1.1643; } + u = luma_chroma.r - 0.5; + v = luma_chroma.b - 0.5; ); case V4L2_PIX_FMT_VYUY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely
[PATCHv2 1/9] qv4l2: generalized opengl include guards
Created a general QtGL makefile condition and using config.h to check in code if QtGL is present. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 6 -- utils/qv4l2/Makefile.am| 4 ++-- utils/qv4l2/capture-win-gl.cpp | 12 ++-- utils/qv4l2/capture-win-gl.h | 6 -- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 4cb6cf2..1e24c91 100644 --- a/configure.ac +++ b/configure.ac @@ -132,7 +132,9 @@ else fi PKG_CHECK_MODULES(QTGL, [QtOpenGL = 4.4 gl], [qt_pkgconfig_gl=true], [qt_pkgconfig_gl=false]) -if test x$qt_pkgconfig_gl = xfalse; then +if test x$qt_pkgconfig_gl = xtrue; then + AC_DEFINE([HAVE_QTGL], [1], [qt has opengl support]) +else AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi @@ -249,9 +251,9 @@ AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes]) AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) -AM_CONDITIONAL([WITH_QV4L2_GL], [test WITH_QV4L2 -a ${qt_pkgconfig_gl} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) +AM_CONDITIONAL([WITH_QTGL], [test ${qt_pkgconfig_gl} = true]) # append -static to libtool compile and link command to enforce static libs AS_IF([test x$enable_libdvbv5 != xyes], [AC_SUBST([ENFORCE_LIBDVBV5_STATIC], [-static])]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 3aed18c..58ac097 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -7,8 +7,8 @@ nodist_qv4l2_SOURCES = moc_qv4l2.cpp moc_general-tab.cpp moc_capture-win.cpp moc qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ ../libmedia_dev/libmedia_dev.la -if WITH_QV4L2_GL -qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL +if WITH_QTGL +qv4l2_CPPFLAGS = $(QTGL_CFLAGS) qv4l2_LDFLAGS = $(QTGL_LIBS) else qv4l2_CPPFLAGS = $(QT_CFLAGS) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 52412c7..c499f1f 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -26,7 +26,7 @@ CaptureWinGL::CaptureWinGL() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWin::buildWindow(m_videoSurface); #endif CaptureWin::setWindowTitle(V4L2 Capture (OpenGL)); @@ -38,14 +38,14 @@ CaptureWinGL::~CaptureWinGL() void CaptureWinGL::stop() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL m_videoSurface.stop(); #endif } void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL m_videoSurface.setFrame(width, height, format, data); #endif m_information.setText(info); @@ -53,7 +53,7 @@ void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char * bool CaptureWinGL::hasNativeFormat(__u32 format) { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL return m_videoSurface.hasNativeFormat(format); #else return false; @@ -62,14 +62,14 @@ bool CaptureWinGL::hasNativeFormat(__u32 format) bool CaptureWinGL::isSupported() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL return true; #else return false; #endif } -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWinGLEngine::CaptureWinGLEngine() : m_frameHeight(0), m_frameWidth(0), diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 08e72b2..6e64269 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -18,10 +18,12 @@ #ifndef CAPTURE_WIN_GL_H #define CAPTURE_WIN_GL_H +#include config.h + #include qv4l2.h #include capture-win.h -#ifdef ENABLE_GL +#ifdef HAVE_QTGL #define GL_GLEXT_PROTOTYPES #include QGLWidget #include QGLShader @@ -88,7 +90,7 @@ public: bool hasNativeFormat(__u32 format); static bool isSupported(); -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWinGLEngine m_videoSurface; #endif }; -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 6/9] qv4l2: add video scaling for CaptureWin
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 26 ++-- utils/qv4l2/capture-win-gl.h | 7 utils/qv4l2/capture-win-qt.cpp | 23 ++- utils/qv4l2/capture-win-qt.h | 5 +++ utils/qv4l2/capture-win.cpp| 93 -- utils/qv4l2/capture-win.h | 14 ++- utils/qv4l2/qv4l2.cpp | 24 --- utils/qv4l2/qv4l2.h| 2 + 8 files changed, 160 insertions(+), 34 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index c8238c5..27ff3d3 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -43,6 +43,15 @@ void CaptureWinGL::stop() #endif } +void CaptureWinGL::resizeEvent(QResizeEvent *event) +{ +#ifdef HAVE_QTGL + QSize margins = getMargins(); + m_videoSurface.setSize(width() - margins.width(), height() - margins.height()); +#endif + event-accept(); +} + void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { #ifdef HAVE_QTGL @@ -109,11 +118,22 @@ void CaptureWinGLEngine::initializeGL() checkError(InitializeGL); } +void CaptureWinGLEngine::setSize(int width, int height) +{ + QSize sizedFrame = CaptureWin::scaleFrameSize(QSize(width, height), QSize(m_frameWidth, m_frameHeight)); + + width = sizedFrame.width(); + height = sizedFrame.height(); + + if (width 0 height 0) { + setMaximumSize(width, height); + resizeGL(width, height); + } +} void CaptureWinGLEngine::resizeGL(int width, int height) { - // Resizing is disabled by setting viewport equal to frame size - glViewport(0, 0, m_frameWidth, m_frameHeight); + glViewport(0, 0, width, height); } void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data) @@ -123,8 +143,6 @@ void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned m_frameWidth = width; m_frameHeight = height; m_frameFormat = format; - - QGLWidget::setMaximumSize(m_frameWidth, m_frameHeight); } m_frameData = data; diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 6e64269..0c3ff8b 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -23,6 +23,8 @@ #include qv4l2.h #include capture-win.h +#include QResizeEvent + #ifdef HAVE_QTGL #define GL_GLEXT_PROTOTYPES #include QGLWidget @@ -42,6 +44,7 @@ public: void stop(); void setFrame(int width, int height, __u32 format, unsigned char *data); bool hasNativeFormat(__u32 format); + void setSize(int width, int height); protected: void paintGL(); @@ -90,6 +93,10 @@ public: bool hasNativeFormat(__u32 format); static bool isSupported(); +protected: + void resizeEvent(QResizeEvent *event); + +private: #ifdef HAVE_QTGL CaptureWinGLEngine m_videoSurface; #endif diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 63c77d5..f746379 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -24,6 +24,8 @@ CaptureWinQt::CaptureWinQt() : { CaptureWin::buildWindow(m_videoSurface); + m_scaledFrame.setWidth(0); + m_scaledFrame.setHeight(0); } CaptureWinQt::~CaptureWinQt() @@ -31,6 +33,19 @@ CaptureWinQt::~CaptureWinQt() delete m_frame; } +void CaptureWinQt::resizeEvent(QResizeEvent *event) +{ + if (m_frame-bits() == NULL) + return; + + QPixmap img = QPixmap::fromImage(*m_frame); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); + img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + m_videoSurface.setPixmap(img); + QWidget::resizeEvent(event); +} + void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { QImage::Format dstFmt; @@ -41,6 +56,8 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * if (m_frame-width() != width || m_frame-height() != height || m_frame-format() != dstFmt) { delete m_frame; m_frame = new QImage(width, height, dstFmt); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); } if (data == NULL || !supported) @@ -49,7 +66,11 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * memcpy(m_frame-bits(), data, m_frame-numBytes()); m_information.setText(info
[PATCHv2 5/9] qv4l2: create function getMargins
Created a function to get the total margins (window frame) in pixels outside the actual video frame beeing displayed. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 14 ++ utils/qv4l2/capture-win.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 2d57909..8722066 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -54,16 +54,22 @@ void CaptureWin::buildWindow(QWidget *videoSurface) vbox-setSpacing(b); } +QSize CaptureWin::getMargins() +{ + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + return QSize(l + r, t + b + m_information.minimumSizeHint().height() + layout()-spacing()); +} + void CaptureWin::setMinimumSize(int minw, int minh) { QDesktopWidget *screen = QApplication::desktop(); QRect resolution = screen-screenGeometry(); QSize maxSize = maximumSize(); - int l, t, r, b; - layout()-getContentsMargins(l, t, r, b); - minw += l + r; - minh += t + b + m_information.minimumSizeHint().height() + layout()-spacing(); + QSize margins = getMargins(); + minw += margins.width(); + minh += margins.height(); if (minw resolution.width()) minw = resolution.width(); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index ca60244..f662bd3 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -78,6 +78,7 @@ public: protected: void closeEvent(QCloseEvent *event); void buildWindow(QWidget *videoSurface); + QSize getMargins(); /** * @brief A label that can is used to display capture information. -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 4/9] qv4l2: show frames option can be toggled during capture
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 84 +++ utils/qv4l2/qv4l2.h | 2 +- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 6f39726..e33254d 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -404,7 +404,7 @@ void ApplicationWindow::capVbiFrame() m_capStartAct-setChecked(false); return; } - if (m_showFrames) { + if (showFrames()) { for (unsigned y = 0; y m_vbiHeight; y++) { __u8 *p = data + y * m_vbiWidth; __u8 *q = m_capImage-bits() + y * m_capImage-bytesPerLine(); @@ -448,7 +448,7 @@ void ApplicationWindow::capVbiFrame() m_tv = tv; } status = QString(Frame: %1 Fps: %2).arg(++m_frame).arg(m_fps); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), status); @@ -491,7 +491,7 @@ void ApplicationWindow::capFrame() if (m_saveRaw.openMode()) m_saveRaw.write((const char *)m_frameData, s); - if (!m_showFrames) + if (!showFrames()) break; if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, @@ -515,7 +515,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)m_buffers[buf.index].start, buf.bytesused, @@ -544,7 +544,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)buf.m.userptr, buf.bytesused, @@ -590,10 +590,10 @@ void ApplicationWindow::capFrame() .arg((m_totalAudioLatency.tv_sec * 1000 + m_totalAudioLatency.tv_usec / 1000) / m_frame)); } #endif - if (displaybuf == NULL m_showFrames) + if (displaybuf == NULL showFrames()) status.append( Error: Unsupported format.); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, displaybuf, status); @@ -776,6 +776,15 @@ void ApplicationWindow::stopCapture() refresh(); } +bool ApplicationWindow::showFrames() +{ + if (m_showFramesAct-isChecked() !m_capture-isVisible()) + m_capture-show(); + if (!m_showFramesAct-isChecked() m_capture-isVisible()) + m_capture-hide(); + return m_showFramesAct-isChecked(); +} + void ApplicationWindow::startOutput(unsigned) { } @@ -849,7 +858,6 @@ void ApplicationWindow::capStart(bool start) m_capImage = NULL; return; } - m_showFrames = m_showFramesAct-isChecked(); m_frame = m_lastFrame = m_fps = 0; m_capMethod = m_genTab-capMethod(); @@ -857,7 +865,6 @@ void ApplicationWindow::capStart(bool start) v4l2_format fmt; v4l2_std_id std; - m_showFrames = false; g_fmt_sliced_vbi(fmt); g_std(std); fmt.fmt.sliced.service_set = (std V4L2_STD_625_50) ? @@ -896,14 +903,14 @@ void ApplicationWindow::capStart(bool start) m_vbiHeight = fmt.fmt.vbi.count[0] + fmt.fmt.vbi.count[1]; m_vbiSize = m_vbiWidth * m_vbiHeight; m_frameData = new unsigned char[m_vbiSize]; - if (m_showFrames) { - m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); - m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); - m_capImage-fill(0); - m_capture-setFrame(m_capImage-width(), m_capImage-height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), No frame); + m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); + m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); + m_capImage-fill(0); + m_capture-setFrame(m_capImage-width(), m_capImage-height
[PATCHv2 9/9] qv4l2: add pixel aspect ratio support for CaptureWin
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 36 ++-- utils/qv4l2/capture-win.h | 6 utils/qv4l2/general-tab.cpp | 68 + utils/qv4l2/general-tab.h | 4 +++ utils/qv4l2/qv4l2.cpp | 22 +++ utils/qv4l2/qv4l2.h | 1 + 6 files changed, 123 insertions(+), 14 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 3abb6cb..7538756 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -30,6 +30,7 @@ #define MIN_WIN_SIZE_HEIGHT 120 bool CaptureWin::m_enableScaling = true; +double CaptureWin::m_pixelAspectRatio = 1.0; CaptureWin::CaptureWin() : m_curWidth(-1), @@ -76,6 +77,14 @@ void CaptureWin::resetSize() resize(w, h); } +int CaptureWin::actualFrameWidth(int width) +{ + if (m_enableScaling) + return (int)((double)width * m_pixelAspectRatio); + + return width; +} + QSize CaptureWin::getMargins() { int l, t, r, b; @@ -108,7 +117,7 @@ void CaptureWin::resize(int width, int height) m_curHeight = height; QSize margins = getMargins(); - width += margins.width(); + width = actualFrameWidth(width) + margins.width(); height += margins.height(); QDesktopWidget *screen = QApplication::desktop(); @@ -130,25 +139,36 @@ void CaptureWin::resize(int width, int height) QSize CaptureWin::scaleFrameSize(QSize window, QSize frame) { - int actualFrameWidth = frame.width();; - int actualFrameHeight = frame.height(); + int actualWidth; + int actualHeight = frame.height(); if (!m_enableScaling) { window.setWidth(frame.width()); window.setHeight(frame.height()); + actualWidth = frame.width(); + } else { + actualWidth = CaptureWin::actualFrameWidth(frame.width()); } double newW, newH; if (window.width() = window.height()) { - newW = (double)window.width() / actualFrameWidth; - newH = (double)window.height() / actualFrameHeight; + newW = (double)window.width() / actualWidth; + newH = (double)window.height() / actualHeight; } else { - newH = (double)window.width() / actualFrameWidth; - newW = (double)window.height() / actualFrameHeight; + newH = (double)window.width() / actualWidth; + newW = (double)window.height() / actualHeight; } double resized = std::min(newW, newH); - return QSize((int)(actualFrameWidth * resized), (int)(actualFrameHeight * resized)); + return QSize((int)(actualWidth * resized), (int)(actualHeight * resized)); +} + +void CaptureWin::setPixelAspectRatio(double ratio) +{ + m_pixelAspectRatio = ratio; + QResizeEvent *event = new QResizeEvent(QSize(width(), height()), QSize(width(), height())); + QCoreApplication::sendEvent(this, event); + delete event; } void CaptureWin::closeEvent(QCloseEvent *event) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 1bfb1e1..e8f0ada 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -76,6 +76,7 @@ public: static bool isSupported() { return false; } void enableScaling(bool enable); + void setPixelAspectRatio(double ratio); static QSize scaleFrameSize(QSize window, QSize frame); public slots: @@ -99,6 +100,11 @@ protected: */ static bool m_enableScaling; + /** +* @note Aspect ratio it taken care of by scaling, frame size is for square pixels only! +*/ + static double m_pixelAspectRatio; + signals: void close(); diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 5cfaf07..c404a3b 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -53,6 +53,7 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_tvStandard(NULL), m_qryStandard(NULL), m_videoTimings(NULL), + m_pixelAspectRatio(NULL), m_qryTimings(NULL), m_freq(NULL), m_vidCapFormats(NULL), @@ -210,6 +211,23 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) connect(m_qryTimings, SIGNAL(clicked()), SLOT(qryTimingsClicked())); } + if (!isRadio() !isVbi()) { + m_pixelAspectRatio = new QComboBox(parent); + m_pixelAspectRatio-addItem(Autodetect); + m_pixelAspectRatio-addItem(Square); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60, Anamorphic); + m_pixelAspectRatio-addItem(PAL/SECAM); + m_pixelAspectRatio-addItem(PAL/SECAM, Anamorphic
[PATCHv2 7/9] qv4l2: added resize to frame size in Capture menu
This will resize the CaptureWin to the original frame size. It also works with maximized windows. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 12 utils/qv4l2/capture-win.h | 3 +++ utils/qv4l2/qv4l2.cpp | 6 -- utils/qv4l2/qv4l2.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 33f7084..3bd6549 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -61,6 +61,18 @@ void CaptureWin::buildWindow(QWidget *videoSurface) vbox-setSpacing(b); } +void CaptureWin::resetSize() +{ + if (isMaximized()) + showNormal(); + + int w = m_curWidth; + int h = m_curHeight; + m_curWidth = -1; + m_curHeight = -1; + resize(w, h); +} + QSize CaptureWin::getMargins() { int l, t, r, b; diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index dd19f2d..eea0335 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -78,6 +78,9 @@ public: void enableScaling(bool enable); static QSize scaleFrameSize(QSize window, QSize frame); +public slots: + void resetSize(); + protected: void closeEvent(QCloseEvent *event); void buildWindow(QWidget *videoSurface); diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 6258a93..3da99da 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -142,11 +142,14 @@ ApplicationWindow::ApplicationWindow() : m_scalingAct-setCheckable(true); m_scalingAct-setChecked(true); connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); + m_resetScalingAct = new QAction(Resize to Frame Size, this); + m_resetScalingAct-setStatusTip(Resizes the capture window to match frame size); QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); captureMenu-addAction(m_showFramesAct); captureMenu-addAction(m_scalingAct); + captureMenu-addAction(m_resetScalingAct); if (CaptureWinGL::isSupported()) { m_renderMethod = QV4L2_RENDER_GL; @@ -211,8 +214,6 @@ void ApplicationWindow::setDevice(const QString device, bool rawOpen) newCaptureWin(); - m_capture-setMinimumSize(150, 50); - QWidget *w = new QWidget(m_tabs); m_genTab = new GeneralTab(device, *this, 4, w); @@ -360,6 +361,7 @@ void ApplicationWindow::newCaptureWin() m_capture-enableScaling(m_scalingAct-isChecked()); connect(m_capture, SIGNAL(close()), this, SLOT(closeCaptureWin())); + connect(m_resetScalingAct, SIGNAL(triggered()), m_capture, SLOT(resetSize())); } void ApplicationWindow::capVbiFrame() diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h index 1402673..179cecb 100644 --- a/utils/qv4l2/qv4l2.h +++ b/utils/qv4l2/qv4l2.h @@ -187,6 +187,7 @@ private: QAction *m_showAllAudioAct; QAction *m_audioBufferAct; QAction *m_scalingAct; + QAction *m_resetScalingAct; QString m_filename; QSignalMapper *m_sigMapper; QTabWidget *m_tabs; -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 8/9] qv4l2: add hotkey for reset scaling to frame size
Adds hotkey CTRL + F for both CaptureWin and main Capture menu. Resets the scaling of CaptureWin to fit frame size. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 3 +++ utils/qv4l2/capture-win.h | 1 + utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 5 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 3bd6549..3abb6cb 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -38,6 +38,8 @@ CaptureWin::CaptureWin() : setWindowTitle(V4L2 Capture); m_hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); connect(m_hotkeyClose, SIGNAL(activated()), this, SLOT(close())); + m_hotkeyScaleReset = new QShortcut(Qt::CTRL+Qt::Key_F, this); + connect(m_hotkeyScaleReset, SIGNAL(activated()), this, SLOT(resetSize())); } CaptureWin::~CaptureWin() @@ -48,6 +50,7 @@ CaptureWin::~CaptureWin() layout()-removeWidget(this); delete layout(); delete m_hotkeyClose; + delete m_hotkeyScaleReset; } void CaptureWin::buildWindow(QWidget *videoSurface) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index eea0335..1bfb1e1 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -104,6 +104,7 @@ signals: private: QShortcut *m_hotkeyClose; + QShortcut *m_hotkeyScaleReset; int m_curWidth; int m_curHeight; }; diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 3da99da..7be9f1a 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -144,6 +144,7 @@ ApplicationWindow::ApplicationWindow() : connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); m_resetScalingAct = new QAction(Resize to Frame Size, this); m_resetScalingAct-setStatusTip(Resizes the capture window to match frame size); + m_resetScalingAct-setShortcut(Qt::CTRL+Qt::Key_F); QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] qv4l2: fix input parameters and missing status tips
- Fixes some of the missing status tips in the general tab. - Fixes the frequency hint, now displaying correct value hints. - Fixes the program parameters. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] qv4l2: fix missing status tips
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/general-tab.cpp | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index c404a3b..2605397 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -236,7 +236,9 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_freq = new QLineEdit(parent); m_freq-setValidator(val); m_freq-setWhatsThis(QString(Frequency\nLow: %1\nHigh: %2) - .arg(m_tuner.rangelow / factor).arg(m_tuner.rangehigh / factor)); +.arg(m_tuner.rangelow / factor) +.arg((double)m_tuner.rangehigh / factor, 0, 'f', 2)); + m_freq-setStatusTip(m_freq-whatsThis()); connect(m_freq, SIGNAL(lostFocus()), SLOT(freqChanged())); connect(m_freq, SIGNAL(returnPressed()), SLOT(freqChanged())); updateFreq(); @@ -306,7 +308,9 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_freq = new QLineEdit(parent); m_freq-setValidator(val); m_freq-setWhatsThis(QString(Frequency\nLow: %1\nHigh: %2) - .arg(m_modulator.rangelow / factor).arg(m_modulator.rangehigh / factor)); +.arg(m_tuner.rangelow / factor) +.arg((double)m_tuner.rangehigh / factor, 0, 'f', 2)); + m_freq-setStatusTip(m_freq-whatsThis()); connect(m_freq, SIGNAL(lostFocus()), SLOT(freqChanged())); connect(m_freq, SIGNAL(returnPressed()), SLOT(freqChanged())); updateFreq(); @@ -899,6 +903,7 @@ void GeneralTab::updateAudioInput() what += , has AVL; if (audio.mode V4L2_AUDMODE_AVL) what += , AVL is on; + m_audioInput-setStatusTip(what); m_audioInput-setWhatsThis(what); } @@ -951,6 +956,7 @@ void GeneralTab::updateStandard() (double)vs.frameperiod.numerator / vs.frameperiod.denominator, vs.frameperiod.numerator, vs.frameperiod.denominator, vs.framelines); + m_tvStandard-setStatusTip(what); m_tvStandard-setWhatsThis(what); updateVidCapFormat(); } @@ -1014,6 +1020,7 @@ void GeneralTab::updateTimings() what.sprintf(Video Timings (%u)\n Frame %ux%u\n, p.index, p.timings.bt.width, p.timings.bt.height); + m_videoTimings-setStatusTip(what); m_videoTimings-setWhatsThis(what); updateVidCapFormat(); } -- 1.8.4.rc1 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] qv4l2: fix input parameters
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 112 ++ 1 file changed, 96 insertions(+), 16 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 892d9c3..644abe6 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -1146,33 +1146,113 @@ void ApplicationWindow::closeEvent(QCloseEvent *event) ApplicationWindow *g_mw; +static void usage() +{ + printf( Usage:\n +qv4l2 [-R] [-h] [-d dev] [-r dev] [-V dev]\n + \n -d, --device=dev use device dev as the video device\n + if dev is a number, then /dev/videodev is used\n +-r, --radio-device=dev use device dev as the radio device\n + if dev is a number, then /dev/radiodev is used\n +-V, --vbi-device=dev use device dev as the vbi device\n + if dev is a number, then /dev/vbidev is used\n +-h, --help display this help message\n +-R, --raw open device in raw mode.\n); +} + +static void usageError(const char *msg) +{ + printf(Missing parameter for %s\n, msg); + usage(); +} + +static QString getDeviceName(QString dev, QString name) +{ + bool ok; + name.toInt(ok); + return ok ? QString(%1%2).arg(dev).arg(name) : name; +} + int main(int argc, char **argv) { QApplication a(argc, argv); - QString device = /dev/video0; bool raw = false; - bool help = false; - int i; + QString device; + QString video_device; + QString radio_device; + QString vbi_device; a.setWindowIcon(QIcon(:/qv4l2.png)); g_mw = new ApplicationWindow(); g_mw-setWindowTitle(V4L2 Test Bench); - for (i = 1; i argc; i++) { - const char *arg = a.argv()[i]; - if (!strcmp(arg, -r)) + QStringList args = a.arguments(); + for (int i = 1; i args.size(); i++) { + + if (args[i] == -d || args[i] == --device) { + ++i; + if (i = args.size()) { + usageError(--device); + return 0; + } + + video_device = args.at(i); + if (video_device.startsWith(-)) { + usageError(--device); + return 0; + } + break; + + } else if (args[i] == -r || args[i] == --radio-device) { + ++i; + if (i = args.size()) { + usageError(--radio-device); + return 0; + } + + radio_device = args.at(i); + if (radio_device.startsWith(-)) { + usageError(--radio-device); + return 0; + } + break; + + } else if (args[i] == -V || args[i] == --vbi-device) { + ++i; + if (i = args.size()) { + usageError(--vbi-device); + return 0; + } + + vbi_device = args.at(i); + if (vbi_device.startsWith(-)) { + usageError(--vbi-device); + return 0; + } + break; + + } else if (args[i] == -h || args[i] == --help) { + usage(); + return 0; + + } else if (args[i] == -R || args[i] == --raw) { raw = true; - else if (!strcmp(arg, -h)) - help = true; - else if (arg[0] != '-') - device = arg; - } - if (help) { - printf(qv4l2 [-r] [-h] [device node]\n\n - -h\tthis help message\n - -r\topen device node in raw mode\n); - return 0; + break; + } else { + printf(Unknown argument %s\n, args[i].toAscii().data()); + return 0; + } } + + if (video_device != NULL) + device = getDeviceName(/dev/video, video_device); + else if (radio_device != NULL) + device = getDeviceName(/dev/radio, radio_device); + else if (vbi_device != NULL) + device = getDeviceName(/dev/vbi, vbi_device); + else + device = /dev/video0; + g_mw-setDevice(device, raw); g_mw-show(); a.connect(a, SIGNAL(lastWindowClosed()), a, SLOT(quit
[PATCHv2 2/5] qv4l2: new ALSA stream source code
Code copied from xawtv3 Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/alsa_stream.c | 645 ++ utils/qv4l2/alsa_stream.h | 5 + 2 files changed, 650 insertions(+) create mode 100644 utils/qv4l2/alsa_stream.c create mode 100644 utils/qv4l2/alsa_stream.h diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c new file mode 100644 index 000..3e33b5e --- /dev/null +++ b/utils/qv4l2/alsa_stream.c @@ -0,0 +1,645 @@ +/* + * ALSA streaming support + * + * Originally written by: + * Copyright (c) by Devin Heitmueller dheitmuel...@kernellabs.com + * for usage at tvtime + * Derived from the alsa-driver test tool latency.c: + *Copyright (c) by Jaroslav Kysela pe...@perex.cz + * + * Copyright (c) 2011 - Mauro Carvalho Chehab mche...@redhat.com + * Ported to xawtv, with bug fixes and improvements + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include config.h + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +#include stdio.h +#include stdlib.h +#include string.h +#include sched.h +#include errno.h +#include getopt.h +#include pthread.h +#include alsa/asoundlib.h +#include sys/time.h +#include math.h +#include alsa_stream.h + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) + +/* Private vars to control alsa thread status */ +static int stop_alsa = 0; + +/* Error handlers */ +snd_output_t *output = NULL; +FILE *error_fp; +int verbose = 0; + +struct final_params { +int bufsize; +int rate; +int latency; +int channels; +}; + +static int setparams_stream(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + snd_pcm_format_t format, + int *channels, + const char *id) +{ +int err; + +err = snd_pcm_hw_params_any(handle, params); +if (err 0) { + fprintf(error_fp, + alsa: Broken configuration for %s PCM: no configurations available: %s\n, + snd_strerror(err), id); + return err; +} + +err = snd_pcm_hw_params_set_access(handle, params, + SND_PCM_ACCESS_RW_INTERLEAVED); +if (err 0) { + fprintf(error_fp, alsa: Access type not available for %s: %s\n, id, + snd_strerror(err)); + return err; +} + +err = snd_pcm_hw_params_set_format(handle, params, format); +if (err 0) { + fprintf(error_fp, alsa: Sample format not available for %s: %s\n, id, + snd_strerror(err)); + return err; +} + +retry: +err = snd_pcm_hw_params_set_channels(handle, params, *channels); +if (err 0) { + if (strcmp(id, capture) == 0 *channels == 2) { + *channels = 1; + goto retry; /* Retry with mono capture */ + } + fprintf(error_fp, alsa: Channels count (%i) not available for %s: %s\n, + *channels, id, snd_strerror(err)); + return err; +} + +return 0; +} + +static void getparams_periods(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + unsigned int *usecs, + unsigned int *count, + const char *id) +{ +unsigned min = 0, max = 0; + +snd_pcm_hw_params_get_periods_min(params, min, 0); +snd_pcm_hw_params_get_periods_max(params, max, 0); +if (min max) { + if (verbose) + fprintf(error_fp, alsa: %s periods range between %u and %u. Want: %u\n, + id, min, max, *count); + if (*count min) + *count = min; + if (*count max) + *count = max; +} + +min = max = 0; +snd_pcm_hw_params_get_period_time_min(params, min, 0); +snd_pcm_hw_params_get_period_time_max(params, max, 0); +if (min max) { + if (verbose) + fprintf(error_fp, alsa: %s period time range between %u and %u. Want: %u\n, + id, min, max, *usecs); + if (*usecs min) + *usecs = min; + if (*usecs max) + *usecs = max; +} +} + +static int setparams_periods(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + unsigned int *usecs, + unsigned int *count
[PATCHv2 1/5] qv4l2: alter capture menu
Corrected Use OpenGL Render to Rendering and removed the separation line. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 4dc5a3e..275b399 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -131,12 +131,11 @@ ApplicationWindow::ApplicationWindow() : QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); captureMenu-addAction(m_showFramesAct); - captureMenu-addSeparator(); if (CaptureWinGL::isSupported()) { m_renderMethod = QV4L2_RENDER_GL; - m_useGLAct = new QAction(Use OpenGL Render, this); + m_useGLAct = new QAction(Use OpenGL Rendering, this); m_useGLAct-setStatusTip(Use GPU with OpenGL for video capture if set.); m_useGLAct-setCheckable(true); m_useGLAct-setChecked(true); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 4/5] qv4l2: add ALSA stream to qv4l2
Changes the ALSA streaming code to work with qv4l2 and allows it to be compiled in. qv4l2 does not use the streaming function yet. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 7 +++ utils/qv4l2/Makefile.am | 8 ++-- utils/qv4l2/alsa_stream.c | 28 utils/qv4l2/alsa_stream.h | 13 ++--- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index d74da61..5a0bb5f 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,13 @@ if test x$qt_pkgconfig_gl = xfalse; then AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi +PKG_CHECK_MODULES(ALSA, [alsa], [alsa_pkgconfig=true], [alsa_pkgconfig=false]) +if test x$alsa_pkgconfig = xtrue; then + AC_DEFINE([HAVE_ALSA], [1], [alsa library is present]) +else + AC_MSG_WARN(ALSA library not available) +fi + AC_SUBST([JPEG_LIBS]) # The dlopen() function is in the C library for *BSD and in diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 22d4c17..3aed18c 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,10 +1,11 @@ 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 capture-win-gl.cpp capture-win-gl.h \ + capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.h alsa_stream.c alsa_stream.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 +qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ + ../libmedia_dev/libmedia_dev.la if WITH_QV4L2_GL qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL @@ -14,6 +15,9 @@ qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) endif +qv4l2_CPPFLAGS += $(ALSA_CFLAGS) +qv4l2_LDFLAGS += $(ALSA_LIBS) -pthread + EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ saveraw.png qv4l2.pro diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c index fbff4cb..dd01d1a 100644 --- a/utils/qv4l2/alsa_stream.c +++ b/utils/qv4l2/alsa_stream.c @@ -26,9 +26,10 @@ * */ -#include config.h +#include config.h -#ifdef HAVE_ALSA_ASOUNDLIB_H +#ifdef HAVE_ALSA +#include alsa_stream.h #include stdio.h #include stdlib.h @@ -40,12 +41,12 @@ #include alsa/asoundlib.h #include sys/time.h #include math.h -#include alsa_stream.h #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) /* Private vars to control alsa thread status */ static int stop_alsa = 0; +static snd_htimestamp_t timestamp; /* Error handlers */ snd_output_t *output = NULL; @@ -202,6 +203,13 @@ static int setparams_set(snd_pcm_t *handle, id, snd_strerror(err)); return err; } + +err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, SND_PCM_TSTAMP_ENABLE); +if (err 0) { + fprintf(error_fp, alsa: Unable to enable timestamps for %s: %s\n, + id, snd_strerror(err)); +} + err = snd_pcm_sw_params(handle, swparams); if (err 0) { fprintf(error_fp, alsa: Unable to set sw params for %s: %s\n, @@ -422,7 +430,8 @@ static int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, static snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len) { snd_pcm_sframes_t r; - +snd_pcm_uframes_t frames; +snd_pcm_htimestamp(handle, frames, timestamp); r = snd_pcm_readi(handle, buf, len); if (r 0 r != -EAGAIN) { r = snd_pcm_recover(handle, r, 0); @@ -453,6 +462,7 @@ static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len) len -= r; snd_pcm_wait(handle, 100); } +return -1; } static int alsa_stream(const char *pdevice, const char *cdevice, int latency) @@ -642,4 +652,14 @@ int alsa_thread_is_running(void) return alsa_is_running; } +void alsa_thread_timestamp(struct timeval *tv) +{ + if (alsa_thread_is_running()) { + tv-tv_sec = timestamp.tv_sec; + tv-tv_usec = timestamp.tv_nsec / 1000; + } else { + tv-tv_sec = 0; + tv-tv_usec = 0; + } +} #endif diff --git a/utils/qv4l2/alsa_stream.h b/utils/qv4l2/alsa_stream.h index c68fd6d..b736ec3 100644 --- a/utils/qv4l2/alsa_stream.h +++ b/utils/qv4l2/alsa_stream.h @@ -1,5 +1,12 @@ -int alsa_thread_startup(const char *pdevice, const char *cdevice, int latency, - FILE *__error_fp, - int __verbose); +#ifndef ALSA_STREAM_H +#define ALSA_STREAM_H + +#include stdio.h +#include
[PATCHv2 5/5] qv4l2: add ALSA audio playback
The qv4l2 test utility now supports ALSA playback of audio. This allows for PCM playback during capture for supported devices. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/general-tab.cpp | 296 +++- utils/qv4l2/general-tab.h | 38 ++ utils/qv4l2/qv4l2.cpp | 141 - utils/qv4l2/qv4l2.h | 9 ++ 4 files changed, 480 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 10b14ca..5cfaf07 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -30,6 +30,16 @@ #include stdio.h #include errno.h +#include QRegExp + +bool GeneralTab::m_fullAudioName = false; + +enum audioDeviceAdd { + AUDIO_ADD_NO, + AUDIO_ADD_READ, + AUDIO_ADD_WRITE, + AUDIO_ADD_READWRITE +}; GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) : QGridLayout(parent), @@ -48,12 +58,16 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_vidCapFormats(NULL), m_frameSize(NULL), m_vidOutFormats(NULL), - m_vbiMethods(NULL) + m_vbiMethods(NULL), + m_audioInDevice(NULL), + m_audioOutDevice(NULL) { + m_device.append(device); setSpacing(3); setSizeConstraint(QLayout::SetMinimumSize); + if (querycap(m_querycap)) { addLabel(Device:); addLabel(device + (useWrapper() ? (wrapped) : ), Qt::AlignLeft); @@ -132,6 +146,42 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) updateAudioOutput(); } + if (hasAlsaAudio()) { + m_audioInDevice = new QComboBox(parent); + m_audioOutDevice = new QComboBox(parent); + m_audioInDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_audioOutDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + + if (createAudioDeviceList()) { + addLabel(Audio Input Device); + connect(m_audioInDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioInDevice); + + addLabel(Audio Output Device); + connect(m_audioOutDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioOutDevice); + + if (isRadio()) { + setAudioDeviceBufferSize(75); + } else { + v4l2_fract fract; + if (!v4l2::get_interval(fract)) { + // Default values are for 30 FPS + fract.numerator = 33; + fract.denominator = 1000; + } + // Standard capacity is two frames + setAudioDeviceBufferSize((fract.numerator * 2000) / fract.denominator); + } + } else { + fprintf(stderr, BANNA\n); + delete m_audioInDevice; + delete m_audioOutDevice; + m_audioInDevice = NULL; + m_audioOutDevice = NULL; + } + } + if (needsStd) { v4l2_std_id tmp; @@ -370,6 +420,180 @@ done: setRowStretch(rowCount() - 1, 1); } +void GeneralTab::showAllAudioDevices(bool use) +{ + QString oldIn(m_audioInDevice-currentText()); + QString oldOut(m_audioOutDevice-currentText()); + + m_fullAudioName = use; + if (oldIn == NULL || oldOut == NULL || !createAudioDeviceList()) + return; + + // Select a similar device as before the listings method change + // check by comparing old selection with any matching in the new list + bool setIn = false, setOut = false; + int listSize = std::max(m_audioInDevice-count(), m_audioOutDevice-count()); + + for (int i = 0; i listSize; i++) { + QString oldInCmp(oldIn.left(std::min(m_audioInDevice-itemText(i).length(), oldIn.length(; + QString oldOutCmp(oldOut.left(std::min(m_audioOutDevice-itemText(i).length(), oldOut.length(; + + if (!setIn i m_audioInDevice-count() +m_audioInDevice-itemText(i).startsWith(oldInCmp)) { + setIn = true; + m_audioInDevice-setCurrentIndex(i); + } + + if (!setOut i m_audioOutDevice-count() +m_audioOutDevice-itemText(i).startsWith(oldOutCmp)) { + setOut = true; + m_audioOutDevice-setCurrentIndex(i); + } + } +} + +bool GeneralTab
[PATCHv2 3/5] qv4l2: fix a bug where the alsa thread never stops
If the output audio device never read the buffer then the alsa thread would continue to fill it up and never stop when the capture stops. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/alsa_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c index 3e33b5e..fbff4cb 100644 --- a/utils/qv4l2/alsa_stream.c +++ b/utils/qv4l2/alsa_stream.c @@ -437,7 +437,7 @@ static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len) { snd_pcm_sframes_t r; -while (1) { +while (!stop_alsa) { r = snd_pcm_writei(handle, buf, len); if (r == len) return 0; -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 0/5] qv4l2: add ALSA audio playback
The qv4l2 test utility now supports ALSA playback of audio. This allows for PCM playback during capture for supported devices. This requires at least the OpenGL patch series' qv4l2: add Capture menu patch. A device must be ALSA compatible in order to be used with the qv4l2. The ALSA implementation requires ALSA on the system. If ALSA support is not present, then this feature will not be compiled in. Changelog v2: - Fixed the A-V average measuring - ALSA is always compiled in but uses include guards from config.h instead Some of the changes/improvements: - Capturing will also capture audio - Added audio controls to the capture menu - Selectable audio devices (can also have no audio) - Automatically find corresponding audio source for a given video device if applicable - Supports both radio, video and audio devices that uses PCM. - Bug fixes Known issues: - Sometimes when generating the audio in and out device lists, it may take some time for the combo boxes to render correctly. - If the audio causes underruns/overruns, try increase the audio buffer. - Not all audio input/output combination will work, depending on system and devices. - The A-V difference in ms is not always correct, but should still help as an indicator -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/9] qv4l2: scaling, pixel aspect ratio and render fixes
The patch series depends on the qv4l2 ALSA and OpenGL patch series. This adds scaling and aspect ratio support to the qv4l2 CaptureWin. In that regard it fixes a lot of other issues that would otherwise make scaling render incorrectly. It also fixes some issues with the original OpenGL patch series, as well as adding tweaks and improvements left out in the original patches. Some of the changes/improvements: - CaptureWin have scaling support for video frames for all renderers - CaptureWin support pixel aspect ratio scaling - Aspect ratio and scaling can be changed during capture - Reset and disable scaling options - CaptureWin's setMinimumSize is now resize, which resizes the window to the frame size given and minimum size is set automatically - The YUY2 shader programs are rewritten and has the resizing issue fixed - The Show Frames option in Capture menu can be toggled during capture - Added a hotkey: CTRL + F : (size to video 'F'rame) When either the main window or capture window is selected this will reset the scaling to fit the frame size. This option is also available in the Capture menu. Pixel Aspect Ratio Modes: - Autodetect (if not supported this assumes square pixels) - Square - NTSC/PAL-M/PAL-60 - NTSC/PAL-M/PAL-60, Anamorphic - PAL/SECAM - PAL/SECAM, Anamorphic Perfomance: All tests are done using the 3.10 kernel with OpenGL enabled and desktop effects disabled. Testing was done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. FPS for every input for a given number of streams (BGR3, YU12 and YV12 are emulated using the CPU): 1 STREAM 2 STREAMS 3 STREAMS 4 STREAMS RGB3 6060 60 60 BGR3 6060 60 58 YUYV 6060 60 60 YU12 6060 60 60 YV12 6060 60 60 Sidenote: - Performing scaling and colorspace conversion for 1080p60 using the CPU can/will give a performance drop in framerate. Recommended to use OpenGL instead. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/9] qv4l2: fix black screen with opengl after capture
Fixes the issue when the window was beeing resized/moved and the frame image would become black. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 6 ++ 1 file changed, 6 insertions(+) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 6071410..c8238c5 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -253,6 +253,12 @@ void CaptureWinGLEngine::paintGL() changeShader(); if (m_frameData == NULL) { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); + glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); + glEnd(); return; } -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/9] qv4l2: show frames option can be toggled during capture
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 79 +++ utils/qv4l2/qv4l2.h | 2 +- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 5510041..ee0c22d 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -404,7 +404,7 @@ void ApplicationWindow::capVbiFrame() m_capStartAct-setChecked(false); return; } - if (m_showFrames) { + if (showFrames()) { for (unsigned y = 0; y m_vbiHeight; y++) { __u8 *p = data + y * m_vbiWidth; __u8 *q = m_capImage-bits() + y * m_capImage-bytesPerLine(); @@ -448,7 +448,7 @@ void ApplicationWindow::capVbiFrame() m_tv = tv; } status = QString(Frame: %1 Fps: %2).arg(++m_frame).arg(m_fps); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), status); @@ -491,7 +491,7 @@ void ApplicationWindow::capFrame() if (m_saveRaw.openMode()) m_saveRaw.write((const char *)m_frameData, s); - if (!m_showFrames) + if (!showFrames()) break; if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, @@ -515,7 +515,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)m_buffers[buf.index].start, buf.bytesused, @@ -544,7 +544,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)buf.m.userptr, buf.bytesused, @@ -590,10 +590,10 @@ void ApplicationWindow::capFrame() .arg((m_totalAudioLatency.tv_sec * 1000 + m_totalAudioLatency.tv_usec / 1000) / m_frame)); } #endif - if (displaybuf == NULL m_showFrames) + if (displaybuf == NULL showFrames()) status.append( Error: Unsupported format.); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, displaybuf, status); @@ -776,6 +776,15 @@ void ApplicationWindow::stopCapture() refresh(); } +bool ApplicationWindow::showFrames() +{ + if (m_showFramesAct-isChecked() !m_capture-isVisible()) + m_capture-show(); + if (!m_showFramesAct-isChecked() m_capture-isVisible()) + m_capture-hide(); + return m_showFramesAct-isChecked(); +} + void ApplicationWindow::startOutput(unsigned) { } @@ -849,7 +858,6 @@ void ApplicationWindow::capStart(bool start) m_capImage = NULL; return; } - m_showFrames = m_showFramesAct-isChecked(); m_frame = m_lastFrame = m_fps = 0; m_capMethod = m_genTab-capMethod(); @@ -857,7 +865,6 @@ void ApplicationWindow::capStart(bool start) v4l2_format fmt; v4l2_std_id std; - m_showFrames = false; g_fmt_sliced_vbi(fmt); g_std(std); fmt.fmt.sliced.service_set = (std V4L2_STD_625_50) ? @@ -896,14 +903,14 @@ void ApplicationWindow::capStart(bool start) m_vbiHeight = fmt.fmt.vbi.count[0] + fmt.fmt.vbi.count[1]; m_vbiSize = m_vbiWidth * m_vbiHeight; m_frameData = new unsigned char[m_vbiSize]; - if (m_showFrames) { - m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); - m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); - m_capImage-fill(0); - m_capture-setFrame(m_capImage-width(), m_capImage-height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), No frame); + m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); + m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); + m_capImage-fill(0); + m_capture-setFrame(m_capImage-width(), m_capImage-height
[PATCH 2/9] qv4l2: fix YUY2 shader
Fixed the YUY2 shaders to support scaling. The new solution has cleaner shader code and texture upload uses a better format for OpenGL. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 68 ++ 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index c499f1f..6071410 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -1,5 +1,5 @@ /* - * The YUY2 shader code was copied and simplified from face-responder. The code is under public domain: + * The YUY2 shader code is based on face-responder. The code is under public domain: * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master * * All other OpenGL code: @@ -446,47 +446,51 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format) { switch (format) { case V4L2_PIX_FMT_YUYV: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.g - 0.5; + v = luma_chroma.a - 0.5; ); case V4L2_PIX_FMT_YVYU: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.a - 0.5; + v = luma_chroma.g - 0.5; ); case V4L2_PIX_FMT_UYVY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.a - 0.0625) * 1.1643; } + u = luma_chroma.r - 0.5; + v = luma_chroma.b - 0.5; ); case V4L2_PIX_FMT_VYUY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely
[PATCH 1/9] qv4l2: generalized opengl include guards
Created a general QtGL makefile condition and using config.h to check in code if QtGL is present. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 6 -- utils/qv4l2/Makefile.am| 4 ++-- utils/qv4l2/capture-win-gl.cpp | 12 ++-- utils/qv4l2/capture-win-gl.h | 6 -- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 5a0bb5f..e83baa4 100644 --- a/configure.ac +++ b/configure.ac @@ -132,7 +132,9 @@ else fi PKG_CHECK_MODULES(QTGL, [QtOpenGL = 4.4 gl], [qt_pkgconfig_gl=true], [qt_pkgconfig_gl=false]) -if test x$qt_pkgconfig_gl = xfalse; then +if test x$qt_pkgconfig_gl = xtrue; then + AC_DEFINE([HAVE_QTGL], [1], [qt has opengl support]) +else AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi @@ -249,9 +251,9 @@ AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes]) AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) -AM_CONDITIONAL([WITH_QV4L2_GL], [test WITH_QV4L2 -a ${qt_pkgconfig_gl} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) +AM_CONDITIONAL([WITH_QTGL], [test ${qt_pkgconfig_gl} = true]) # append -static to libtool compile and link command to enforce static libs AS_IF([test x$enable_libdvbv5 != xyes], [AC_SUBST([ENFORCE_LIBDVBV5_STATIC], [-static])]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 3aed18c..58ac097 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -7,8 +7,8 @@ nodist_qv4l2_SOURCES = moc_qv4l2.cpp moc_general-tab.cpp moc_capture-win.cpp moc qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ ../libmedia_dev/libmedia_dev.la -if WITH_QV4L2_GL -qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL +if WITH_QTGL +qv4l2_CPPFLAGS = $(QTGL_CFLAGS) qv4l2_LDFLAGS = $(QTGL_LIBS) else qv4l2_CPPFLAGS = $(QT_CFLAGS) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 52412c7..c499f1f 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -26,7 +26,7 @@ CaptureWinGL::CaptureWinGL() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWin::buildWindow(m_videoSurface); #endif CaptureWin::setWindowTitle(V4L2 Capture (OpenGL)); @@ -38,14 +38,14 @@ CaptureWinGL::~CaptureWinGL() void CaptureWinGL::stop() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL m_videoSurface.stop(); #endif } void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL m_videoSurface.setFrame(width, height, format, data); #endif m_information.setText(info); @@ -53,7 +53,7 @@ void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char * bool CaptureWinGL::hasNativeFormat(__u32 format) { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL return m_videoSurface.hasNativeFormat(format); #else return false; @@ -62,14 +62,14 @@ bool CaptureWinGL::hasNativeFormat(__u32 format) bool CaptureWinGL::isSupported() { -#ifdef ENABLE_GL +#ifdef HAVE_QTGL return true; #else return false; #endif } -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWinGLEngine::CaptureWinGLEngine() : m_frameHeight(0), m_frameWidth(0), diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 08e72b2..6e64269 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -18,10 +18,12 @@ #ifndef CAPTURE_WIN_GL_H #define CAPTURE_WIN_GL_H +#include config.h + #include qv4l2.h #include capture-win.h -#ifdef ENABLE_GL +#ifdef HAVE_QTGL #define GL_GLEXT_PROTOTYPES #include QGLWidget #include QGLShader @@ -88,7 +90,7 @@ public: bool hasNativeFormat(__u32 format); static bool isSupported(); -#ifdef ENABLE_GL +#ifdef HAVE_QTGL CaptureWinGLEngine m_videoSurface; #endif }; -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/9] qv4l2: add video scaling for CaptureWin
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 26 ++-- utils/qv4l2/capture-win-gl.h | 7 utils/qv4l2/capture-win-qt.cpp | 23 ++- utils/qv4l2/capture-win-qt.h | 5 +++ utils/qv4l2/capture-win.cpp| 93 -- utils/qv4l2/capture-win.h | 14 ++- utils/qv4l2/qv4l2.cpp | 22 -- utils/qv4l2/qv4l2.h| 2 + 8 files changed, 159 insertions(+), 33 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index c8238c5..27ff3d3 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -43,6 +43,15 @@ void CaptureWinGL::stop() #endif } +void CaptureWinGL::resizeEvent(QResizeEvent *event) +{ +#ifdef HAVE_QTGL + QSize margins = getMargins(); + m_videoSurface.setSize(width() - margins.width(), height() - margins.height()); +#endif + event-accept(); +} + void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { #ifdef HAVE_QTGL @@ -109,11 +118,22 @@ void CaptureWinGLEngine::initializeGL() checkError(InitializeGL); } +void CaptureWinGLEngine::setSize(int width, int height) +{ + QSize sizedFrame = CaptureWin::scaleFrameSize(QSize(width, height), QSize(m_frameWidth, m_frameHeight)); + + width = sizedFrame.width(); + height = sizedFrame.height(); + + if (width 0 height 0) { + setMaximumSize(width, height); + resizeGL(width, height); + } +} void CaptureWinGLEngine::resizeGL(int width, int height) { - // Resizing is disabled by setting viewport equal to frame size - glViewport(0, 0, m_frameWidth, m_frameHeight); + glViewport(0, 0, width, height); } void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data) @@ -123,8 +143,6 @@ void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned m_frameWidth = width; m_frameHeight = height; m_frameFormat = format; - - QGLWidget::setMaximumSize(m_frameWidth, m_frameHeight); } m_frameData = data; diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 6e64269..0c3ff8b 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -23,6 +23,8 @@ #include qv4l2.h #include capture-win.h +#include QResizeEvent + #ifdef HAVE_QTGL #define GL_GLEXT_PROTOTYPES #include QGLWidget @@ -42,6 +44,7 @@ public: void stop(); void setFrame(int width, int height, __u32 format, unsigned char *data); bool hasNativeFormat(__u32 format); + void setSize(int width, int height); protected: void paintGL(); @@ -90,6 +93,10 @@ public: bool hasNativeFormat(__u32 format); static bool isSupported(); +protected: + void resizeEvent(QResizeEvent *event); + +private: #ifdef HAVE_QTGL CaptureWinGLEngine m_videoSurface; #endif diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 63c77d5..f746379 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -24,6 +24,8 @@ CaptureWinQt::CaptureWinQt() : { CaptureWin::buildWindow(m_videoSurface); + m_scaledFrame.setWidth(0); + m_scaledFrame.setHeight(0); } CaptureWinQt::~CaptureWinQt() @@ -31,6 +33,19 @@ CaptureWinQt::~CaptureWinQt() delete m_frame; } +void CaptureWinQt::resizeEvent(QResizeEvent *event) +{ + if (m_frame-bits() == NULL) + return; + + QPixmap img = QPixmap::fromImage(*m_frame); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); + img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + m_videoSurface.setPixmap(img); + QWidget::resizeEvent(event); +} + void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { QImage::Format dstFmt; @@ -41,6 +56,8 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * if (m_frame-width() != width || m_frame-height() != height || m_frame-format() != dstFmt) { delete m_frame; m_frame = new QImage(width, height, dstFmt); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); } if (data == NULL || !supported) @@ -49,7 +66,11 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * memcpy(m_frame-bits(), data, m_frame-numBytes()); m_information.setText(info
[PATCH 8/9] qv4l2: add hotkey for reset scaling to frame size
Adds hotkey CTRL + F for both CaptureWin and main Capture menu. Resets the scaling of CaptureWin to fit frame size. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 3 +++ utils/qv4l2/capture-win.h | 1 + utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 5 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 3bd6549..3abb6cb 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -38,6 +38,8 @@ CaptureWin::CaptureWin() : setWindowTitle(V4L2 Capture); m_hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); connect(m_hotkeyClose, SIGNAL(activated()), this, SLOT(close())); + m_hotkeyScaleReset = new QShortcut(Qt::CTRL+Qt::Key_F, this); + connect(m_hotkeyScaleReset, SIGNAL(activated()), this, SLOT(resetSize())); } CaptureWin::~CaptureWin() @@ -48,6 +50,7 @@ CaptureWin::~CaptureWin() layout()-removeWidget(this); delete layout(); delete m_hotkeyClose; + delete m_hotkeyScaleReset; } void CaptureWin::buildWindow(QWidget *videoSurface) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index eea0335..1bfb1e1 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -104,6 +104,7 @@ signals: private: QShortcut *m_hotkeyClose; + QShortcut *m_hotkeyScaleReset; int m_curWidth; int m_curHeight; }; diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 1a476f0..c94b0a8 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -144,6 +144,7 @@ ApplicationWindow::ApplicationWindow() : connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); m_resetScalingAct = new QAction(Resize to Frame Size, this); m_resetScalingAct-setStatusTip(Resizes the capture window to match frame size); + m_resetScalingAct-setShortcut(Qt::CTRL+Qt::Key_F); QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 7/9] qv4l2: added resize to frame size in Capture menu
This will resize the CaptureWin to the original frame size. It also works with maximized windows. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 12 utils/qv4l2/capture-win.h | 3 +++ utils/qv4l2/qv4l2.cpp | 6 -- utils/qv4l2/qv4l2.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 33f7084..3bd6549 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -61,6 +61,18 @@ void CaptureWin::buildWindow(QWidget *videoSurface) vbox-setSpacing(b); } +void CaptureWin::resetSize() +{ + if (isMaximized()) + showNormal(); + + int w = m_curWidth; + int h = m_curHeight; + m_curWidth = -1; + m_curHeight = -1; + resize(w, h); +} + QSize CaptureWin::getMargins() { int l, t, r, b; diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index dd19f2d..eea0335 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -78,6 +78,9 @@ public: void enableScaling(bool enable); static QSize scaleFrameSize(QSize window, QSize frame); +public slots: + void resetSize(); + protected: void closeEvent(QCloseEvent *event); void buildWindow(QWidget *videoSurface); diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 50ba07a..1a476f0 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -142,11 +142,14 @@ ApplicationWindow::ApplicationWindow() : m_scalingAct-setCheckable(true); m_scalingAct-setChecked(true); connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); + m_resetScalingAct = new QAction(Resize to Frame Size, this); + m_resetScalingAct-setStatusTip(Resizes the capture window to match frame size); QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); captureMenu-addAction(m_showFramesAct); captureMenu-addAction(m_scalingAct); + captureMenu-addAction(m_resetScalingAct); if (CaptureWinGL::isSupported()) { m_renderMethod = QV4L2_RENDER_GL; @@ -211,8 +214,6 @@ void ApplicationWindow::setDevice(const QString device, bool rawOpen) newCaptureWin(); - m_capture-setMinimumSize(150, 50); - QWidget *w = new QWidget(m_tabs); m_genTab = new GeneralTab(device, *this, 4, w); @@ -360,6 +361,7 @@ void ApplicationWindow::newCaptureWin() m_capture-enableScaling(m_scalingAct-isChecked()); connect(m_capture, SIGNAL(close()), this, SLOT(closeCaptureWin())); + connect(m_resetScalingAct, SIGNAL(triggered()), m_capture, SLOT(resetSize())); } void ApplicationWindow::capVbiFrame() diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h index 1402673..179cecb 100644 --- a/utils/qv4l2/qv4l2.h +++ b/utils/qv4l2/qv4l2.h @@ -187,6 +187,7 @@ private: QAction *m_showAllAudioAct; QAction *m_audioBufferAct; QAction *m_scalingAct; + QAction *m_resetScalingAct; QString m_filename; QSignalMapper *m_sigMapper; QTabWidget *m_tabs; -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 9/9] qv4l2: add pixel aspect ratio support for CaptureWin
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 36 ++-- utils/qv4l2/capture-win.h | 6 utils/qv4l2/general-tab.cpp | 68 + utils/qv4l2/general-tab.h | 4 +++ utils/qv4l2/qv4l2.cpp | 21 ++ utils/qv4l2/qv4l2.h | 1 + 6 files changed, 122 insertions(+), 14 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 3abb6cb..7538756 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -30,6 +30,7 @@ #define MIN_WIN_SIZE_HEIGHT 120 bool CaptureWin::m_enableScaling = true; +double CaptureWin::m_pixelAspectRatio = 1.0; CaptureWin::CaptureWin() : m_curWidth(-1), @@ -76,6 +77,14 @@ void CaptureWin::resetSize() resize(w, h); } +int CaptureWin::actualFrameWidth(int width) +{ + if (m_enableScaling) + return (int)((double)width * m_pixelAspectRatio); + + return width; +} + QSize CaptureWin::getMargins() { int l, t, r, b; @@ -108,7 +117,7 @@ void CaptureWin::resize(int width, int height) m_curHeight = height; QSize margins = getMargins(); - width += margins.width(); + width = actualFrameWidth(width) + margins.width(); height += margins.height(); QDesktopWidget *screen = QApplication::desktop(); @@ -130,25 +139,36 @@ void CaptureWin::resize(int width, int height) QSize CaptureWin::scaleFrameSize(QSize window, QSize frame) { - int actualFrameWidth = frame.width();; - int actualFrameHeight = frame.height(); + int actualWidth; + int actualHeight = frame.height(); if (!m_enableScaling) { window.setWidth(frame.width()); window.setHeight(frame.height()); + actualWidth = frame.width(); + } else { + actualWidth = CaptureWin::actualFrameWidth(frame.width()); } double newW, newH; if (window.width() = window.height()) { - newW = (double)window.width() / actualFrameWidth; - newH = (double)window.height() / actualFrameHeight; + newW = (double)window.width() / actualWidth; + newH = (double)window.height() / actualHeight; } else { - newH = (double)window.width() / actualFrameWidth; - newW = (double)window.height() / actualFrameHeight; + newH = (double)window.width() / actualWidth; + newW = (double)window.height() / actualHeight; } double resized = std::min(newW, newH); - return QSize((int)(actualFrameWidth * resized), (int)(actualFrameHeight * resized)); + return QSize((int)(actualWidth * resized), (int)(actualHeight * resized)); +} + +void CaptureWin::setPixelAspectRatio(double ratio) +{ + m_pixelAspectRatio = ratio; + QResizeEvent *event = new QResizeEvent(QSize(width(), height()), QSize(width(), height())); + QCoreApplication::sendEvent(this, event); + delete event; } void CaptureWin::closeEvent(QCloseEvent *event) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 1bfb1e1..e8f0ada 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -76,6 +76,7 @@ public: static bool isSupported() { return false; } void enableScaling(bool enable); + void setPixelAspectRatio(double ratio); static QSize scaleFrameSize(QSize window, QSize frame); public slots: @@ -99,6 +100,11 @@ protected: */ static bool m_enableScaling; + /** +* @note Aspect ratio it taken care of by scaling, frame size is for square pixels only! +*/ + static double m_pixelAspectRatio; + signals: void close(); diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 5cfaf07..c404a3b 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -53,6 +53,7 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_tvStandard(NULL), m_qryStandard(NULL), m_videoTimings(NULL), + m_pixelAspectRatio(NULL), m_qryTimings(NULL), m_freq(NULL), m_vidCapFormats(NULL), @@ -210,6 +211,23 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) connect(m_qryTimings, SIGNAL(clicked()), SLOT(qryTimingsClicked())); } + if (!isRadio() !isVbi()) { + m_pixelAspectRatio = new QComboBox(parent); + m_pixelAspectRatio-addItem(Autodetect); + m_pixelAspectRatio-addItem(Square); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60, Anamorphic); + m_pixelAspectRatio-addItem(PAL/SECAM); + m_pixelAspectRatio-addItem(PAL/SECAM, Anamorphic
[PATCH 5/9] qv4l2: create function getMargins
Created a function to get the total margins (window frame) in pixels outside the actual video frame beeing displayed. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 14 ++ utils/qv4l2/capture-win.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 2d57909..8722066 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -54,16 +54,22 @@ void CaptureWin::buildWindow(QWidget *videoSurface) vbox-setSpacing(b); } +QSize CaptureWin::getMargins() +{ + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + return QSize(l + r, t + b + m_information.minimumSizeHint().height() + layout()-spacing()); +} + void CaptureWin::setMinimumSize(int minw, int minh) { QDesktopWidget *screen = QApplication::desktop(); QRect resolution = screen-screenGeometry(); QSize maxSize = maximumSize(); - int l, t, r, b; - layout()-getContentsMargins(l, t, r, b); - minw += l + r; - minh += t + b + m_information.minimumSizeHint().height() + layout()-spacing(); + QSize margins = getMargins(); + minw += margins.width(); + minh += margins.height(); if (minw resolution.width()) minw = resolution.width(); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index ca60244..f662bd3 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -78,6 +78,7 @@ public: protected: void closeEvent(QCloseEvent *event); void buildWindow(QWidget *videoSurface); + QSize getMargins(); /** * @brief A label that can is used to display capture information. -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/5] qv4l2: add ALSA stream to qv4l2
On Saturday, August 03, 2013 12:19:54 AM you wrote: Hello, diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 22d4c17..eed25b0 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -4,7 +4,8 @@ qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp v4l2-api.cpp capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.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 +qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ + ../libmedia_dev/libmedia_dev.la if WITH_QV4L2_GL qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL @@ -14,6 +15,12 @@ qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) endif +if WITH_QV4L2_ALSA +qv4l2_CPPFLAGS += $(ALSA_CFLAGS) -DENABLE_ALSA I would prefer if you don't add another define to the command line. To check for ALSA support please include config.h and use the flag provided there. That is fine for me. However, this design was to make the alsa code not compile in when not required. While I am at it, should I do the same for OpenGL, that is, remove WITH_QV4L2_GL with a config.h define)? The patch series has already been patched in, but I do have another series that adds features and fixes to the first OpenGL patches. It should not be a problem to change OpenGL accordingly as well. B. Thanks, Gregor -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 1/7] qv4l2: fix YUY2 shader
Fixed the YUY2 shaders to support scaling. The new solution has cleaner shader code and texture upload uses a better format for OpenGL. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 68 ++ 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 52412c7..bae6569 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -1,5 +1,5 @@ /* - * The YUY2 shader code was copied and simplified from face-responder. The code is under public domain: + * The YUY2 shader code is based on face-responder. The code is under public domain: * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master * * All other OpenGL code: @@ -446,47 +446,51 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format) { switch (format) { case V4L2_PIX_FMT_YUYV: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.g - 0.5; + v = luma_chroma.a - 0.5; ); case V4L2_PIX_FMT_YVYU: - return QString(y = (luma_chroma.r - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.a; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).a; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.r - 0.0625) * 1.1643; } else { - u = luma_chroma.a; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).a; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.b - 0.0625) * 1.1643; } + u = luma_chroma.a - 0.5; + v = luma_chroma.g - 0.5; ); case V4L2_PIX_FMT_UYVY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely)); + y = (luma_chroma.a - 0.0625) * 1.1643; } + u = luma_chroma.r - 0.5; + v = luma_chroma.b - 0.5; ); case V4L2_PIX_FMT_VYUY: - return QString(y = (luma_chroma.a - 0.0625) * 1.1643; - if (mod(xcoord, 2.0) == 0.0) { - v = luma_chroma.r; - u = texture2D(tex, vec2(pixelx + texl_w, pixely)).r; + return QString(if (mod(xcoord, 2.0) == 0.0) { + luma_chroma = texture2D(tex, vec2(pixelx, pixely)); + y = (luma_chroma.g - 0.0625) * 1.1643; } else { - u = luma_chroma.r; - v = texture2D(tex, vec2(pixelx - texl_w, pixely)).r; + luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely
[RFC PATCH 4/7] qv4l2: add function getMargins
Created a function to get the total margins (window frame) in pixels outside the actual video frame beeing displayed. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 14 ++ utils/qv4l2/capture-win.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 2d57909..e583900 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -54,16 +54,22 @@ void CaptureWin::buildWindow(QWidget *videoSurface) vbox-setSpacing(b); } +QSize CaptureWin::getMargins() +{ + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + return QSize(l + r, t + b + m_information.minimumSizeHint().height() + layout()-spacing()); +} + void CaptureWin::setMinimumSize(int minw, int minh) { QDesktopWidget *screen = QApplication::desktop(); QRect resolution = screen-screenGeometry(); QSize maxSize = maximumSize(); - int l, t, r, b; - layout()-getContentsMargins(l, t, r, b); - minw += l + r; - minh += t + b + m_information.minimumSizeHint().height() + layout()-spacing(); + QSize margins = getMargins(); + minw += margins.width(); + minh += margins.height(); if (minw resolution.width()) minw = resolution.width(); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index ca60244..6b72e00 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -78,6 +78,8 @@ public: protected: void closeEvent(QCloseEvent *event); void buildWindow(QWidget *videoSurface); + QSize getMargins(); + /** * @brief A label that can is used to display capture information. -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 2/7] qv4l2: fix black screen with opengl after capture
Fixes the issue when the window was beeing resized/moved and the frame image would become black. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 6 ++ 1 file changed, 6 insertions(+) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index bae6569..edae60f 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -253,6 +253,12 @@ void CaptureWinGLEngine::paintGL() changeShader(); if (m_frameData == NULL) { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2f(m_frameWidth, 0); + glTexCoord2f(1.0f, 1.0f); glVertex2f(m_frameWidth, m_frameHeight); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0, m_frameHeight); + glEnd(); return; } -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 7/7] qv4l2: add aspect ratio support
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 24 ++-- utils/qv4l2/capture-win.h | 8 +++- utils/qv4l2/general-tab.cpp | 36 utils/qv4l2/general-tab.h | 3 +++ utils/qv4l2/qv4l2.cpp | 22 +++--- utils/qv4l2/qv4l2.h | 2 +- 6 files changed, 84 insertions(+), 11 deletions(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 435c19b..415829a 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -30,6 +30,7 @@ #define MIN_WIN_SIZE_HEIGHT 120 bool CaptureWin::m_enableScaling = true; +double CaptureWin::m_pixelAspectRatio = 1.0; CaptureWin::CaptureWin() : m_curWidth(-1), @@ -73,6 +74,14 @@ void CaptureWin::resetSize() resize(w, h); } +int CaptureWin::actualFrameWidth(int width) +{ + if (m_enableScaling) + return (int)((double)width * m_pixelAspectRatio); + else + return width; +} + QSize CaptureWin::getMargins() { int l, t, r, b; @@ -94,6 +103,14 @@ void CaptureWin::enableScaling(bool enable) delete event; } +void CaptureWin::setPixelAspectRatio(double ratio) +{ + m_pixelAspectRatio = ratio; + QResizeEvent *event = new QResizeEvent(QSize(width(), height()), QSize(width(), height())); + QCoreApplication::sendEvent(this, event); + delete event; +} + void CaptureWin::resize(int width, int height) { // Dont resize window if the frame size is the same in @@ -105,7 +122,7 @@ void CaptureWin::resize(int width, int height) m_curHeight = height; QSize margins = getMargins(); - width += margins.width(); + width = actualFrameWidth(width) + margins.width(); height += margins.height(); QDesktopWidget *screen = QApplication::desktop(); @@ -127,12 +144,15 @@ void CaptureWin::resize(int width, int height) QSize CaptureWin::scaleFrameSize(QSize window, QSize frame) { - int actualFrameWidth = frame.width();; + int actualFrameWidth; int actualFrameHeight = frame.height(); if (!m_enableScaling) { window.setWidth(frame.width()); window.setHeight(frame.height()); + actualFrameWidth = frame.width(); + } else { + actualFrameWidth = CaptureWin::actualFrameWidth(frame.width()); } double newW, newH; diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 1bfb1e1..eded9e0 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -76,9 +76,10 @@ public: static bool isSupported() { return false; } void enableScaling(bool enable); + void setPixelAspectRatio(double ratio); static QSize scaleFrameSize(QSize window, QSize frame); -public slots: + public slots: void resetSize(); protected: @@ -99,6 +100,11 @@ protected: */ static bool m_enableScaling; + /** +* @note Aspect ratio it taken care of by scaling, frame size is for square pixels only! +*/ + static double m_pixelAspectRatio; + signals: void close(); diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 5996c03..53b7e36 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -53,6 +53,7 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_tvStandard(NULL), m_qryStandard(NULL), m_videoTimings(NULL), + m_pixelAspectRatio(NULL), m_qryTimings(NULL), m_freq(NULL), m_vidCapFormats(NULL), @@ -210,6 +211,20 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) connect(m_qryTimings, SIGNAL(clicked()), SLOT(qryTimingsClicked())); } + if (!isRadio() !isVbi()) { + m_pixelAspectRatio = new QComboBox(parent); + m_pixelAspectRatio-addItem(Autodetect); + m_pixelAspectRatio-addItem(Square); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60); + m_pixelAspectRatio-addItem(NTSC/PAL-M/PAL-60, Anamorphic); + m_pixelAspectRatio-addItem(PAL/SECAM); + m_pixelAspectRatio-addItem(PAL/SECAM, Anamorphic); + + addLabel(Pixel Aspect Ratio); + addWidget(m_pixelAspectRatio); + connect(m_pixelAspectRatio, SIGNAL(activated(int)), SIGNAL(pixelAspectRatioChanged())); + } + if (m_tuner.capability) { QDoubleValidator *val; double factor = (m_tuner.capability V4L2_TUNER_CAP_LOW) ? 16 : 16000; @@ -1105,6 +1120,27 @@ void GeneralTab::updateFrameSize() updateFrameInterval(); } +double GeneralTab::getPixelAspectRatio() +{ + if (m_pixelAspectRatio-currentText().compare(Autodetect) == 0) { + v4l2_cropcap ratio
[RFC PATCH 3/7] qv4l2: show frames option can be toggled during capture
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 77 ++- utils/qv4l2/qv4l2.h | 2 +- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index e078e91..fa1425d 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -404,7 +404,7 @@ void ApplicationWindow::capVbiFrame() m_capStartAct-setChecked(false); return; } - if (m_showFrames) { + if (showFrames()) { for (unsigned y = 0; y m_vbiHeight; y++) { __u8 *p = data + y * m_vbiWidth; __u8 *q = m_capImage-bits() + y * m_capImage-bytesPerLine(); @@ -448,7 +448,7 @@ void ApplicationWindow::capVbiFrame() m_tv = tv; } status = QString(Frame: %1 Fps: %2).arg(++m_frame).arg(m_fps); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), status); @@ -490,7 +490,7 @@ void ApplicationWindow::capFrame() if (m_saveRaw.openMode()) m_saveRaw.write((const char *)m_frameData, s); - if (!m_showFrames) + if (!showFrames()) break; if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, @@ -514,7 +514,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)m_buffers[buf.index].start, buf.bytesused, @@ -544,7 +544,7 @@ void ApplicationWindow::capFrame() if (again) return; - if (m_showFrames) { + if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, m_capSrcFormat, m_capDestFormat, (unsigned char *)buf.m.userptr, buf.bytesused, @@ -592,10 +592,10 @@ void ApplicationWindow::capFrame() .arg((m_totalAudioLatency.tv_sec * 1000 + m_totalAudioLatency.tv_usec / 1000) / m_frame)); } #endif - if (displaybuf == NULL m_showFrames) + if (displaybuf == NULL showFrames()) status.append( Error: Unsupported format.); - if (m_showFrames) + if (showFrames()) m_capture-setFrame(m_capImage-width(), m_capImage-height(), m_capDestFormat.fmt.pix.pixelformat, displaybuf, status); @@ -778,6 +778,13 @@ void ApplicationWindow::stopCapture() refresh(); } +bool ApplicationWindow::showFrames() +{ + if (m_showFramesAct-isChecked() !m_capture-isVisible()) + m_capture-show(); + return m_showFramesAct-isChecked(); +} + void ApplicationWindow::startOutput(unsigned) { } @@ -851,7 +858,6 @@ void ApplicationWindow::capStart(bool start) m_capImage = NULL; return; } - m_showFrames = m_showFramesAct-isChecked(); m_frame = m_lastFrame = m_fps = 0; m_capMethod = m_genTab-capMethod(); @@ -859,7 +865,6 @@ void ApplicationWindow::capStart(bool start) v4l2_format fmt; v4l2_std_id std; - m_showFrames = false; g_fmt_sliced_vbi(fmt); g_std(std); fmt.fmt.sliced.service_set = (std V4L2_STD_625_50) ? @@ -898,14 +903,14 @@ void ApplicationWindow::capStart(bool start) m_vbiHeight = fmt.fmt.vbi.count[0] + fmt.fmt.vbi.count[1]; m_vbiSize = m_vbiWidth * m_vbiHeight; m_frameData = new unsigned char[m_vbiSize]; - if (m_showFrames) { - m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); - m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); - m_capImage-fill(0); - m_capture-setFrame(m_capImage-width(), m_capImage-height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits(), No frame); + m_capture-setMinimumSize(m_vbiWidth, m_vbiHeight); + m_capImage = new QImage(m_vbiWidth, m_vbiHeight, dstFmt); + m_capImage-fill(0); + m_capture-setFrame(m_capImage-width(), m_capImage-height(), + m_capDestFormat.fmt.pix.pixelformat, m_capImage-bits
[RFC PATCH 6/7] qv4l2: add hotkey for reset scaling to frame size
Adds hotkey CTRL + F for both CaptureWin and main Capture menu. Resets the scaling of CaptureWin to fit frame size. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 3 +++ utils/qv4l2/capture-win.h | 1 + utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 5 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 4c5dd57..435c19b 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -38,6 +38,8 @@ CaptureWin::CaptureWin() : setWindowTitle(V4L2 Capture); m_hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); connect(m_hotkeyClose, SIGNAL(activated()), this, SLOT(close())); + m_hotkeyScaleReset = new QShortcut(Qt::CTRL+Qt::Key_F, this); + connect(m_hotkeyScaleReset, SIGNAL(activated()), this, SLOT(resetSize())); } CaptureWin::~CaptureWin() @@ -48,6 +50,7 @@ CaptureWin::~CaptureWin() layout()-removeWidget(this); delete layout(); delete m_hotkeyClose; + delete m_hotkeyScaleReset; } void CaptureWin::buildWindow(QWidget *videoSurface) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index eea0335..1bfb1e1 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -104,6 +104,7 @@ signals: private: QShortcut *m_hotkeyClose; + QShortcut *m_hotkeyScaleReset; int m_curWidth; int m_curHeight; }; diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 6b64892..92a415f 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -144,6 +144,7 @@ ApplicationWindow::ApplicationWindow() : connect(m_scalingAct, SIGNAL(toggled(bool)), this, SLOT(enableScaling(bool))); m_resetScalingAct = new QAction(Resize to Frame Size, this); m_resetScalingAct-setStatusTip(Resizes the capture window to match frame size); + m_resetScalingAct-setShortcut(Qt::CTRL+Qt::Key_F); QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 5/7] qv4l2: add video scaling for CaptureWin
Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 26 -- utils/qv4l2/capture-win-gl.h | 8 utils/qv4l2/capture-win-qt.cpp | 24 +- utils/qv4l2/capture-win-qt.h | 5 ++ utils/qv4l2/capture-win.cpp| 106 +++-- utils/qv4l2/capture-win.h | 18 +-- utils/qv4l2/qv4l2.cpp | 27 +-- utils/qv4l2/qv4l2.h| 4 ++ 8 files changed, 181 insertions(+), 37 deletions(-) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index edae60f..628aaec 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -43,6 +43,15 @@ void CaptureWinGL::stop() #endif } +void CaptureWinGL::resizeEvent(QResizeEvent *event) +{ + QSize margins = getMargins(); +#ifdef ENABLE_GL + m_videoSurface.setSize(width() - margins.width(), height() - margins.height()); +#endif + event-accept(); +} + void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { #ifdef ENABLE_GL @@ -109,11 +118,22 @@ void CaptureWinGLEngine::initializeGL() checkError(InitializeGL); } +void CaptureWinGLEngine::setSize(int width, int height) +{ + QSize sizedFrame = CaptureWin::scaleFrameSize(QSize(width, height), QSize(m_frameWidth, m_frameHeight)); + + width = sizedFrame.width(); + height = sizedFrame.height(); + + if (width 0 height 0) { + setMaximumSize(width, height); + resizeGL(width, height); + } +} void CaptureWinGLEngine::resizeGL(int width, int height) { - // Resizing is disabled by setting viewport equal to frame size - glViewport(0, 0, m_frameWidth, m_frameHeight); + glViewport(0, 0, width, height); } void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data) @@ -123,8 +143,6 @@ void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned m_frameWidth = width; m_frameHeight = height; m_frameFormat = format; - - QGLWidget::setMaximumSize(m_frameWidth, m_frameHeight); } m_frameData = data; diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 08e72b2..ef06d0b 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -21,6 +21,9 @@ #include qv4l2.h #include capture-win.h +#include QBoxLayout +#include QResizeEvent + #ifdef ENABLE_GL #define GL_GLEXT_PROTOTYPES #include QGLWidget @@ -40,6 +43,7 @@ public: void stop(); void setFrame(int width, int height, __u32 format, unsigned char *data); bool hasNativeFormat(__u32 format); + void setSize(int width, int height); protected: void paintGL(); @@ -88,6 +92,10 @@ public: bool hasNativeFormat(__u32 format); static bool isSupported(); + protected: + void resizeEvent(QResizeEvent *event); + +private: #ifdef ENABLE_GL CaptureWinGLEngine m_videoSurface; #endif diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 63c77d5..0f6964b 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -22,8 +22,9 @@ CaptureWinQt::CaptureWinQt() : m_frame(new QImage(0, 0, QImage::Format_Invalid)) { - CaptureWin::buildWindow(m_videoSurface); + m_scaledFrame.setWidth(0); + m_scaledFrame.setHeight(0); } CaptureWinQt::~CaptureWinQt() @@ -31,6 +32,19 @@ CaptureWinQt::~CaptureWinQt() delete m_frame; } +void CaptureWinQt::resizeEvent(QResizeEvent *event) +{ + if (m_frame-bits() == NULL) + return; + + QPixmap img = QPixmap::fromImage(*m_frame); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); + img = img.scaled(m_scaledFrame.width(), m_scaledFrame.height(), Qt::IgnoreAspectRatio); + m_videoSurface.setPixmap(img); + QWidget::resizeEvent(event); +} + void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) { QImage::Format dstFmt; @@ -41,6 +55,8 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * if (m_frame-width() != width || m_frame-height() != height || m_frame-format() != dstFmt) { delete m_frame; m_frame = new QImage(width, height, dstFmt); + m_scaledFrame = scaleFrameSize(QSize(m_videoSurface.width(), m_videoSurface.height()), + QSize(m_frame-width(), m_frame-height())); } if (data == NULL || !supported) @@ -49,7 +65,11 @@ void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char * memcpy(m_frame-bits
[RFC PATCH 0/7] qv4l2: scaling and pixel aspect ratio
The patch series depends on the qv4l2 ALSA and OpenGL patch series. This adds scaling and aspect ratio support to the qv4l2 CaptureWin. It also fixes some issues with the original OpenGL patch series, as well as adding tweaks and improvements left out in the original patches. Some of the changes/improvements: - CaptureWin have scaling support for video frames for all renderers - CaptureWin support pixel aspect ratio scaling - Aspect ratio and scaling can be changed during capture - CaptureWin's setMinimumSize is now resize, which resizes the window to the frame size given and minimum size is set automatically - The YUY2 shader programs are rewritten and has the resizing issue fixed - The Show Frames option in Capture menu can be toggled during capture - Reset and disable scaling options - Added a hotkey: CTRL + F : (size to video 'F'rame) When either the main window or capture window is selected this will reset the scaling to fit the frame size. This option is also available in the Capture menu. Pixel Aspect Ratio Modes: - Autodetect (if not supported this assumes square pixels) - Square - NTSC/PAL-M/PAL-60 - NTSC/PAL-M/PAL-60, Anamorphic - PAL/SECAM - PAL/SECAM, Anamorphic -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/5] qv4l2: add ALSA audio playback
The qv4l2 test utility now supports ALSA playback of audio. This allows for PCM playback during capture for supported devices. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/general-tab.cpp | 296 +++- utils/qv4l2/general-tab.h | 36 ++ utils/qv4l2/qv4l2.cpp | 143 - utils/qv4l2/qv4l2.h | 7 ++ 4 files changed, 478 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 10b14ca..5996c03 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -30,6 +30,16 @@ #include stdio.h #include errno.h +#include QRegExp + +bool GeneralTab::m_fullAudioName = false; + +enum audioDeviceAdd { + AUDIO_ADD_NO, + AUDIO_ADD_READ, + AUDIO_ADD_WRITE, + AUDIO_ADD_READWRITE +}; GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) : QGridLayout(parent), @@ -48,12 +58,16 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) m_vidCapFormats(NULL), m_frameSize(NULL), m_vidOutFormats(NULL), - m_vbiMethods(NULL) + m_vbiMethods(NULL), + m_audioInDevice(NULL), + m_audioOutDevice(NULL) { + m_device.append(device); setSpacing(3); setSizeConstraint(QLayout::SetMinimumSize); + if (querycap(m_querycap)) { addLabel(Device:); addLabel(device + (useWrapper() ? (wrapped) : ), Qt::AlignLeft); @@ -132,6 +146,42 @@ GeneralTab::GeneralTab(const QString device, v4l2 fd, int n, QWidget *parent) updateAudioOutput(); } + if (hasAlsaAudio()) { + m_audioInDevice = new QComboBox(parent); + m_audioOutDevice = new QComboBox(parent); + m_audioInDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_audioOutDevice-setSizeAdjustPolicy(QComboBox::AdjustToContents); + + if (createAudioDeviceList()) { + addLabel(Audio Input Device); + connect(m_audioInDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioInDevice); + + addLabel(Audio Output Device); + connect(m_audioOutDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioOutDevice); + + if (isRadio()) { + setAudioDeviceBufferSize(75); + } else { + v4l2_fract fract; + if (!v4l2::get_interval(fract)) { + // Default values are for 30 FPS + fract.numerator = 33; + fract.denominator = 1000; + } + // Standard capacity is two frames + setAudioDeviceBufferSize((fract.numerator * 2000) / fract.denominator); + } + } else { + fprintf(stderr, BANNA\n); + delete m_audioInDevice; + delete m_audioOutDevice; + m_audioInDevice = NULL; + m_audioOutDevice = NULL; + } + } + if (needsStd) { v4l2_std_id tmp; @@ -370,6 +420,180 @@ done: setRowStretch(rowCount() - 1, 1); } +void GeneralTab::showAllAudioDevices(bool use) +{ + QString oldIn(m_audioInDevice-currentText()); + QString oldOut(m_audioOutDevice-currentText()); + + m_fullAudioName = use; + if (oldIn == NULL || oldOut == NULL || !createAudioDeviceList()) + return; + + // Select a similar device as before the listings method change + // check by comparing old selection with any matching in the new list + bool setIn = false, setOut = false; + int listSize = std::max(m_audioInDevice-count(), m_audioOutDevice-count()); + + for (int i = 0; i listSize; i++) { + QString oldInCmp(oldIn.left(std::min(m_audioInDevice-itemText(i).length(), oldIn.length(; + QString oldOutCmp(oldOut.left(std::min(m_audioOutDevice-itemText(i).length(), oldOut.length(; + + if (!setIn i m_audioInDevice-count() +m_audioInDevice-itemText(i).startsWith(oldInCmp)) { + setIn = true; + m_audioInDevice-setCurrentIndex(i); + } + + if (!setOut i m_audioOutDevice-count() +m_audioOutDevice-itemText(i).startsWith(oldOutCmp)) { + setOut = true; + m_audioOutDevice-setCurrentIndex(i); + } + } +} + +bool GeneralTab
[PATCH 4/5] qv4l2: fix a bug where the alsa thread never stops
If the output audio device never read the buffer then the alsa thread would continue to fill it up and never stop when the capture stops. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/alsa_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c index 90d3afb..43ecda3 100644 --- a/utils/qv4l2/alsa_stream.c +++ b/utils/qv4l2/alsa_stream.c @@ -436,7 +436,7 @@ static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len) { snd_pcm_sframes_t r; -while (1) { +while (!stop_alsa) { r = snd_pcm_writei(handle, buf, len); if (r == len) return 0; -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/5] qv4l2: new ALSA stream source code
Code copied from xawtv3 Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/alsa_stream.c | 645 ++ utils/qv4l2/alsa_stream.h | 5 + 2 files changed, 650 insertions(+) create mode 100644 utils/qv4l2/alsa_stream.c create mode 100644 utils/qv4l2/alsa_stream.h diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c new file mode 100644 index 000..3e33b5e --- /dev/null +++ b/utils/qv4l2/alsa_stream.c @@ -0,0 +1,645 @@ +/* + * ALSA streaming support + * + * Originally written by: + * Copyright (c) by Devin Heitmueller dheitmuel...@kernellabs.com + * for usage at tvtime + * Derived from the alsa-driver test tool latency.c: + *Copyright (c) by Jaroslav Kysela pe...@perex.cz + * + * Copyright (c) 2011 - Mauro Carvalho Chehab mche...@redhat.com + * Ported to xawtv, with bug fixes and improvements + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include config.h + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +#include stdio.h +#include stdlib.h +#include string.h +#include sched.h +#include errno.h +#include getopt.h +#include pthread.h +#include alsa/asoundlib.h +#include sys/time.h +#include math.h +#include alsa_stream.h + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) + +/* Private vars to control alsa thread status */ +static int stop_alsa = 0; + +/* Error handlers */ +snd_output_t *output = NULL; +FILE *error_fp; +int verbose = 0; + +struct final_params { +int bufsize; +int rate; +int latency; +int channels; +}; + +static int setparams_stream(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + snd_pcm_format_t format, + int *channels, + const char *id) +{ +int err; + +err = snd_pcm_hw_params_any(handle, params); +if (err 0) { + fprintf(error_fp, + alsa: Broken configuration for %s PCM: no configurations available: %s\n, + snd_strerror(err), id); + return err; +} + +err = snd_pcm_hw_params_set_access(handle, params, + SND_PCM_ACCESS_RW_INTERLEAVED); +if (err 0) { + fprintf(error_fp, alsa: Access type not available for %s: %s\n, id, + snd_strerror(err)); + return err; +} + +err = snd_pcm_hw_params_set_format(handle, params, format); +if (err 0) { + fprintf(error_fp, alsa: Sample format not available for %s: %s\n, id, + snd_strerror(err)); + return err; +} + +retry: +err = snd_pcm_hw_params_set_channels(handle, params, *channels); +if (err 0) { + if (strcmp(id, capture) == 0 *channels == 2) { + *channels = 1; + goto retry; /* Retry with mono capture */ + } + fprintf(error_fp, alsa: Channels count (%i) not available for %s: %s\n, + *channels, id, snd_strerror(err)); + return err; +} + +return 0; +} + +static void getparams_periods(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + unsigned int *usecs, + unsigned int *count, + const char *id) +{ +unsigned min = 0, max = 0; + +snd_pcm_hw_params_get_periods_min(params, min, 0); +snd_pcm_hw_params_get_periods_max(params, max, 0); +if (min max) { + if (verbose) + fprintf(error_fp, alsa: %s periods range between %u and %u. Want: %u\n, + id, min, max, *count); + if (*count min) + *count = min; + if (*count max) + *count = max; +} + +min = max = 0; +snd_pcm_hw_params_get_period_time_min(params, min, 0); +snd_pcm_hw_params_get_period_time_max(params, max, 0); +if (min max) { + if (verbose) + fprintf(error_fp, alsa: %s period time range between %u and %u. Want: %u\n, + id, min, max, *usecs); + if (*usecs min) + *usecs = min; + if (*usecs max) + *usecs = max; +} +} + +static int setparams_periods(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + unsigned int *usecs, + unsigned int *count
[PATCH 1/5] qv4l2: alter capture menu
Corrected Use OpenGL Render to Rendering and removed the separation line. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 4dc5a3e..275b399 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -131,12 +131,11 @@ ApplicationWindow::ApplicationWindow() : QMenu *captureMenu = menuBar()-addMenu(Capture); captureMenu-addAction(m_capStartAct); captureMenu-addAction(m_showFramesAct); - captureMenu-addSeparator(); if (CaptureWinGL::isSupported()) { m_renderMethod = QV4L2_RENDER_GL; - m_useGLAct = new QAction(Use OpenGL Render, this); + m_useGLAct = new QAction(Use OpenGL Rendering, this); m_useGLAct-setStatusTip(Use GPU with OpenGL for video capture if set.); m_useGLAct-setCheckable(true); m_useGLAct-setChecked(true); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/5] qv4l2: add ALSA audio playback
The qv4l2 test utility now supports ALSA playback of audio. This allows for PCM playback during capture for supported devices. This requires at least the OpenGL patch series' qv4l2: add Capture menu patch. A device must be ALSA compatible in order to be used with the qv4l2. The ALSA implementation requires ALSA on the system. If ALSA support is not present, then this feature will not be compiled in. Some of the changes/improvements: - Capturing will also capture audio - Added audio controls to the capture menu - Selectable audio devices (can also have no audio) - Automatically find corresponding audio source for a given video device if applicable - Supports both radio, video and audio devices that uses PCM. - Bug fixes Known issues: - Sometimes when generating the audio in and out device lists, it may take some time for the combo boxes to render correctly. - If the audio causes underruns/overruns, try increase the audio buffer. - Not all audio input/output combination will work, depending on system and devices. - The A-V difference in ms is not always correct, but should still help as an indicator -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/5] qv4l2: add ALSA stream to qv4l2
Changes the ALSA streaming code to work with qv4l2 and allows it to be compiled in. qv4l2 does not use the streaming function yet. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 6 ++ utils/qv4l2/Makefile.am | 9 - utils/qv4l2/alsa_stream.c | 21 +++-- utils/qv4l2/alsa_stream.h | 13 ++--- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index d74da61..e12507e 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,11 @@ if test x$qt_pkgconfig_gl = xfalse; then AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi +PKG_CHECK_MODULES(ALSA, [alsa], [alsa_pkgconfig=true], [alsa_pkgconfig=false]) +if test x$alsa_pkgconfig = xfalse; then + AC_MSG_WARN(ALSA library not available) +fi + AC_SUBST([JPEG_LIBS]) # The dlopen() function is in the C library for *BSD and in @@ -243,6 +248,7 @@ AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) AM_CONDITIONAL([WITH_QV4L2_GL], [test WITH_QV4L2 -a ${qt_pkgconfig_gl} = true]) +AM_CONDITIONAL([WITH_QV4L2_ALSA], [test WITH_QV4L2 -a ${alsa_pkgconfig} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 22d4c17..eed25b0 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -4,7 +4,8 @@ qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp v4l2-api.cpp capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.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 +qv4l2_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la ../libv4l2util/libv4l2util.la \ + ../libmedia_dev/libmedia_dev.la if WITH_QV4L2_GL qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL @@ -14,6 +15,12 @@ qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) endif +if WITH_QV4L2_ALSA +qv4l2_CPPFLAGS += $(ALSA_CFLAGS) -DENABLE_ALSA +qv4l2_LDFLAGS += $(ALSA_LIBS) -pthread +qv4l2_SOURCES += alsa_stream.c alsa_stream.h +endif + EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ saveraw.png qv4l2.pro diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c index 3e33b5e..90d3afb 100644 --- a/utils/qv4l2/alsa_stream.c +++ b/utils/qv4l2/alsa_stream.c @@ -26,9 +26,7 @@ * */ -#include config.h - -#ifdef HAVE_ALSA_ASOUNDLIB_H +#include alsa_stream.h #include stdio.h #include stdlib.h @@ -40,12 +38,12 @@ #include alsa/asoundlib.h #include sys/time.h #include math.h -#include alsa_stream.h #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) /* Private vars to control alsa thread status */ static int stop_alsa = 0; +static snd_htimestamp_t timestamp; /* Error handlers */ snd_output_t *output = NULL; @@ -422,7 +420,8 @@ static int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, static snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len) { snd_pcm_sframes_t r; - +snd_pcm_uframes_t frames; +snd_pcm_htimestamp(handle, frames, timestamp); r = snd_pcm_readi(handle, buf, len); if (r 0 r != -EAGAIN) { r = snd_pcm_recover(handle, r, 0); @@ -453,6 +452,7 @@ static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len) len -= r; snd_pcm_wait(handle, 100); } +return -1; } static int alsa_stream(const char *pdevice, const char *cdevice, int latency) @@ -642,4 +642,13 @@ int alsa_thread_is_running(void) return alsa_is_running; } -#endif +void alsa_thread_timestamp(struct timeval *tv) +{ + if (alsa_thread_is_running()) { + tv-tv_sec = timestamp.tv_sec; + tv-tv_usec = timestamp.tv_nsec / 1000; + } else { + tv-tv_sec = 1337; + tv-tv_usec = 0; + } +} diff --git a/utils/qv4l2/alsa_stream.h b/utils/qv4l2/alsa_stream.h index c68fd6d..b74c3aa 100644 --- a/utils/qv4l2/alsa_stream.h +++ b/utils/qv4l2/alsa_stream.h @@ -1,5 +1,12 @@ -int alsa_thread_startup(const char *pdevice, const char *cdevice, int latency, - FILE *__error_fp, - int __verbose); +#ifndef ALSA_STRAM_H +#define ALSA_STRAM_H + +#include stdio.h +#include sys/time.h + +int alsa_thread_startup(const char *pdevice, const char *cdevice
Re: [PATCHv2 FINAL 6/6] qv4l2: add OpenGL rendering
On Tuesday, July 30, 2013 10:15:24 AM you wrote: [PATCHv2 FINAL 6/6] qv4l2: add OpenGL rendering From 505e803da95dd7c4aeb9d7ec4661c83bb743da1e Mon Sep 17 00:00:00 2001 Message-Id: 505e803da95dd7c4aeb9d7ec4661c83bb743da1e.1375355021.git.bwint...@cisco.com From: =?UTF-8?q?B=C3=A5rd=20Eirik=20Winther?= bwint...@cisco.com Date: Thu, 1 Aug 2013 13:02:43 +0200 Subject: [PATCH] qv4l2: fix compile error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a compile error caused when opengl is not available Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win-gl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 807d9e9..52412c7 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -26,7 +26,9 @@ CaptureWinGL::CaptureWinGL() { +#ifdef ENABLE_GL CaptureWin::buildWindow(m_videoSurface); +#endif CaptureWin::setWindowTitle(V4L2 Capture (OpenGL)); } -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 4/6] qv4l2: add Capture menu
Created a new Capture menu that contains both capture controls and audio/video settings for capture. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index bb1d84f..80937db 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -111,10 +111,8 @@ ApplicationWindow::ApplicationWindow() : fileMenu-addAction(openAct); fileMenu-addAction(openRawAct); fileMenu-addAction(closeAct); - fileMenu-addAction(m_capStartAct); fileMenu-addAction(m_snapshotAct); fileMenu-addAction(m_saveRawAct); - fileMenu-addAction(m_showFramesAct); fileMenu-addSeparator(); fileMenu-addAction(quitAct); @@ -128,6 +126,10 @@ ApplicationWindow::ApplicationWindow() : toolBar-addSeparator(); toolBar-addAction(quitAct); + QMenu *captureMenu = menuBar()-addMenu(Capture); + captureMenu-addAction(m_capStartAct); + captureMenu-addAction(m_showFramesAct); + QMenu *helpMenu = menuBar()-addMenu(Help); helpMenu-addAction(About, this, SLOT(about()), Qt::Key_F1); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 1/6] qv4l2: move function ctrlEvent
Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 94 +-- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index de9b154..a8fcc65 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -202,6 +202,53 @@ void ApplicationWindow::openrawdev() setDevice(d.selectedFiles().first(), true); } +void ApplicationWindow::ctrlEvent() +{ + v4l2_event ev; + + while (dqevent(ev)) { + if (ev.type != V4L2_EVENT_CTRL) + continue; + m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; + m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; + m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; + m_ctrlMap[ev.id].step = ev.u.ctrl.step; + m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; + m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); + switch (m_ctrlMap[ev.id].type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_BITMASK: + setVal(ev.id, ev.u.ctrl.value); + break; + case V4L2_CTRL_TYPE_INTEGER64: + setVal64(ev.id, ev.u.ctrl.value64); + break; + default: + break; + } + if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) + continue; + queryctrl(m_ctrlMap[ev.id]); + + struct v4l2_ext_control c; + struct v4l2_ext_controls ctrls; + + c.id = ev.id; + c.size = m_ctrlMap[ev.id].maximum + 1; + c.string = (char *)malloc(c.size); + memset(ctrls, 0, sizeof(ctrls)); + ctrls.count = 1; + ctrls.ctrl_class = 0; + ctrls.controls = c; + if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) + setString(ev.id, c.string); + free(c.string); + } +} + void ApplicationWindow::capVbiFrame() { __u32 buftype = m_genTab-bufType(); @@ -305,53 +352,6 @@ void ApplicationWindow::capVbiFrame() refresh(); } -void ApplicationWindow::ctrlEvent() -{ - v4l2_event ev; - - while (dqevent(ev)) { - if (ev.type != V4L2_EVENT_CTRL) - continue; - m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; - m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; - m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; - m_ctrlMap[ev.id].step = ev.u.ctrl.step; - m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; - m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); - switch (m_ctrlMap[ev.id].type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_INTEGER_MENU: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_BITMASK: - setVal(ev.id, ev.u.ctrl.value); - break; - case V4L2_CTRL_TYPE_INTEGER64: - setVal64(ev.id, ev.u.ctrl.value64); - break; - default: - break; - } - if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) - continue; - queryctrl(m_ctrlMap[ev.id]); - - struct v4l2_ext_control c; - struct v4l2_ext_controls ctrls; - - c.id = ev.id; - c.size = m_ctrlMap[ev.id].maximum + 1; - c.string = (char *)malloc(c.size); - memset(ctrls, 0, sizeof(ctrls)); - ctrls.count = 1; - ctrls.ctrl_class = 0; - ctrls.controls = c; - if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) - setString(ev.id, c.string); - free(c.string); - } -} - void ApplicationWindow::capFrame() { __u32 buftype = m_genTab-bufType(); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 3/6] qv4l2: fix minimum size in capture win to frame size
CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 29 + utils/qv4l2/capture-win.h | 1 + 2 files changed, 30 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index a94c73d..68dc9ed 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -21,6 +21,8 @@ #include QImage #include QVBoxLayout #include QCloseEvent +#include QApplication +#include QDesktopWidget #include qv4l2.h #include capture-win.h @@ -45,6 +47,33 @@ CaptureWin::~CaptureWin() delete hotkeyClose; } +void CaptureWin::setMinimumSize(int minw, int minh) +{ + QDesktopWidget *screen = QApplication::desktop(); + QRect resolution = screen-screenGeometry(); + QSize maxSize = maximumSize(); + + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + minw += l + r; + minh += t + b + m_msg-minimumSizeHint().height() + layout()-spacing(); + + if (minw resolution.width()) + minw = resolution.width(); + if (minw 150) + minw = 150; + + if (minh resolution.height()) + minh = resolution.height(); + if (minh 100) + minh = 100; + + QWidget::setMinimumSize(minw, minh); + QWidget::setMaximumSize(minw, minh); + updateGeometry(); + QWidget::setMaximumSize(maxSize.width(), maxSize.height()); +} + void CaptureWin::setImage(const QImage image, const QString status) { m_label-setPixmap(QPixmap::fromImage(image)); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 4115d56..3925757 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -35,6 +35,7 @@ public: CaptureWin(); ~CaptureWin(); + void setMinimumSize(int minw, int minh); void setImage(const QImage image, const QString status); protected: -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 0/6] qv4l2: add OpenGL rendering and window fixes
The qv4l2 test utility now supports OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to perform color space conversion. The OpenGL implementation requires OpenGL and QtOpenGL libraries as well as an OpenGL driver (typically from the graphics driver). If OpenGL support is not present, then the program will fall back to using the CPU to display. Changelog v2 FINAL: - Restructured the patch series - Preview menu is now Capture menu which contains both capture controls and audio/video settings for capture. - Corrected the license description for CaptureWinGL - Add doxygen documentation to capture-win.h Changelog v2: - Cleaned up the capture win code and classes - CaptureWin is now a base class that can be used to implement different ways of displaying video. - setMinimumSize is now more reliable - Small code tweaks and improvements, including cleaner display flow - Changed the OpenGL abbreviation from OGL to GL Some of the changes/improvements: - Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. - OpenGL acceleration for supported systems. - Option to change between GPU or CPU based rendering. - CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. - Added a new menu option 'Preview' for controlling the CaptureWin's behavior. - Added a couple of hotkeys: CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window. It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Known issues: - Repositioning, scaling or switching windows while the capture is recording will reduce the framerate. This is a limitation of Qt and not OpenGL. - Using 4 streams of RGB3 1080p60 can at random times cease to render correctly and reduce the framerate to half. A restart solves this though. - OpenGL is limited to 60fps. Disabling V-sync might allow for faster framerates. - Resizing or scaling is not supported, mainly because the YUY2 shader renders the image incorrectly when the canvas size is not equal to the frame size. - Some of the supported OpenGL formats may use the CPU for colorspace conversion, but this is driver dependant. Supported formats for OpenGL render: - Native supported and accelerated: V4L2_PIX_FMT_RGB32 V4L2_PIX_FMT_BGR32 V4L2_PIX_FMT_RGB24 V4L2_PIX_FMT_BGR24 V4L2_PIX_FMT_RGB565 V4L2_PIX_FMT_RGB555 V4L2_PIX_FMT_YUYV V4L2_PIX_FMT_YVYU V4L2_PIX_FMT_UYVY V4L2_PIX_FMT_VYUY V4L2_PIX_FMT_YVU420 V4L2_PIX_FMT_YUV420 - All formats supported by V4L conversion library, but they will use the CPU to convert to RGB3 before being displayed with OpenGL. Performance: All tests are done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. FPS for every input for a given number of streams: 1 STREAM 2 STREAMS 3 STREAMS 4 STREAMS RGB3 6060 60 60 BGR3 6060 60 50 YUYV 6060 60 48 YU12 6060 60 52 YV12 6060 60 52 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 2/6] qv4l2: add hotkeys for common operations
CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 8 utils/qv4l2/capture-win.h | 4 +++- utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 6798252..a94c73d 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -35,6 +35,14 @@ CaptureWin::CaptureWin() vbox-addWidget(m_label); vbox-addWidget(m_msg); + + hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); + QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close())); +} + +CaptureWin::~CaptureWin() +{ + delete hotkeyClose; } void CaptureWin::setImage(const QImage image, const QString status) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index e861b12..4115d56 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -21,6 +21,7 @@ #define CAPTURE_WIN_H #include QWidget +#include QShortcut #include sys/time.h class QImage; @@ -32,7 +33,7 @@ class CaptureWin : public QWidget public: CaptureWin(); - virtual ~CaptureWin() {} + ~CaptureWin(); void setImage(const QImage image, const QString status); @@ -45,6 +46,7 @@ signals: private: QLabel *m_label; QLabel *m_msg; + QShortcut *hotkeyClose; }; #endif diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index a8fcc65..bb1d84f 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -78,6 +78,7 @@ ApplicationWindow::ApplicationWindow() : m_capStartAct-setStatusTip(Start capturing); m_capStartAct-setCheckable(true); m_capStartAct-setDisabled(true); + m_capStartAct-setShortcut(Qt::CTRL+Qt::Key_V); connect(m_capStartAct, SIGNAL(toggled(bool)), this, SLOT(capStart(bool))); m_snapshotAct = new QAction(QIcon(:/snapshot.png), Make Snapshot, this); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 FINAL 5/6] qv4l2: new modular capture window design
The display of video has been divided into classes to easier implement other ways to render frames on screen. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/Makefile.am| 4 +- utils/qv4l2/capture-win-qt.cpp | 89 +++ utils/qv4l2/capture-win-qt.h | 47 + utils/qv4l2/capture-win.cpp| 45 ++-- utils/qv4l2/capture-win.h | 24 ++- utils/qv4l2/qv4l2.cpp | 94 +++--- utils/qv4l2/qv4l2.h| 1 + 7 files changed, 219 insertions(+), 85 deletions(-) create mode 100644 utils/qv4l2/capture-win-qt.cpp create mode 100644 utils/qv4l2/capture-win-qt.h diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 1f5a49f..9ef8149 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,6 +1,7 @@ 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 @@ -37,5 +38,4 @@ install-data-local: $(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 diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp new file mode 100644 index 000..63c77d5 --- /dev/null +++ b/utils/qv4l2/capture-win-qt.cpp @@ -0,0 +1,89 @@ +/* qv4l2: a control panel controlling v4l2 devices. + * + * Copyright (C) 2006 Hans Verkuil hverk...@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
[PATCHv2 FINAL 6/6] qv4l2: add OpenGL rendering
Adds OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to perform color space conversion. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 8 +- utils/qv4l2/Makefile.am| 8 +- utils/qv4l2/capture-win-gl.cpp | 553 + utils/qv4l2/capture-win-gl.h | 96 +++ utils/qv4l2/capture-win-qt.h | 1 + utils/qv4l2/capture-win.h | 39 +++ utils/qv4l2/qv4l2.cpp | 54 +++- utils/qv4l2/qv4l2.h| 10 + 8 files changed, 765 insertions(+), 4 deletions(-) create mode 100644 utils/qv4l2/capture-win-gl.cpp create mode 100644 utils/qv4l2/capture-win-gl.h diff --git a/configure.ac b/configure.ac index e249546..d74da61 100644 --- a/configure.ac +++ b/configure.ac @@ -128,7 +128,12 @@ if test x$qt_pkgconfig = xtrue; then AC_SUBST(UIC) AC_SUBST(RCC) else - AC_MSG_WARN(Qt4 is not available) + AC_MSG_WARN(Qt4 or higher is not available) +fi + +PKG_CHECK_MODULES(QTGL, [QtOpenGL = 4.4 gl], [qt_pkgconfig_gl=true], [qt_pkgconfig_gl=false]) +if test x$qt_pkgconfig_gl = xfalse; then + AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi AC_SUBST([JPEG_LIBS]) @@ -237,6 +242,7 @@ AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes]) AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) +AM_CONDITIONAL([WITH_QV4L2_GL], [test WITH_QV4L2 -a ${qt_pkgconfig_gl} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 9ef8149..22d4c17 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,12 +1,18 @@ 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 \ + capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.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 + +if WITH_QV4L2_GL +qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL +qv4l2_LDFLAGS = $(QTGL_LIBS) +else qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) +endif EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp new file mode 100644 index 000..807d9e9 --- /dev/null +++ b/utils/qv4l2/capture-win-gl.cpp @@ -0,0 +1,553 @@ +/* + * The YUY2 shader code was copied and simplified from face-responder. The code is under public domain: + * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master + * + * All other OpenGL code: + * + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include capture-win-gl.h + +#include stdio.h + +CaptureWinGL::CaptureWinGL() +{ + CaptureWin::buildWindow(m_videoSurface); + CaptureWin::setWindowTitle(V4L2 Capture (OpenGL)); +} + +CaptureWinGL::~CaptureWinGL() +{ +} + +void CaptureWinGL::stop() +{ +#ifdef ENABLE_GL + m_videoSurface.stop(); +#endif +} + +void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) +{ +#ifdef ENABLE_GL + m_videoSurface.setFrame(width, height, format, data); +#endif + m_information.setText(info); +} + +bool CaptureWinGL::hasNativeFormat(__u32 format) +{ +#ifdef ENABLE_GL + return m_videoSurface.hasNativeFormat(format); +#else + return false; +#endif +} + +bool CaptureWinGL::isSupported() +{ +#ifdef ENABLE_GL
Re: [PATCHv2 FINAL 0/6] qv4l2: add OpenGL rendering and window fixes
On Tuesday, July 30, 2013 10:12:33 AM you wrote: Em Tue, 30 Jul 2013 10:15:18 +0200 Bård Eirik Winther bwint...@cisco.com escreveu: ... Performance: All tests are done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. I did a quick test here with a radeon HD 7750 GPU on a i7-3770 CPU, using an UVC camera at VGA resolution and nouveau driver (Kernel 3.10.3). qv4l2 CPU usage dropped from 13% to 3,75%. It sounds a nice improvement! That is good to hear. My results where achived using the 3.9 and 3.10 kernels although I belive that the hardware and opengl driver affects performance the most. With such a good hardware and relatively low resolution, you wont see that much of a differance :-), but it is a nice improvement indeed. Anyway, nice to get additional tests! -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] qv4l2: Fixed a bug in the v4l2-api
Fixed a bug where the get_interval in v4l2-api where it would test for a compatibility flag irrelevant to the feature support and resulting return false. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] qv4l2: Fixed a bug in the v4l2-api
The get_interval would return false even if devices had support for this Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/v4l2-api.cpp | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/utils/qv4l2/v4l2-api.cpp b/utils/qv4l2/v4l2-api.cpp index 9c37be3..7a438af 100644 --- a/utils/qv4l2/v4l2-api.cpp +++ b/utils/qv4l2/v4l2-api.cpp @@ -613,13 +613,11 @@ bool v4l2::set_interval(v4l2_fract interval) bool v4l2::get_interval(v4l2_fract interval) { v4l2_streamparm parm; - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(VIDIOC_G_PARM, parm) = 0 - (parm.parm.capture.capability V4L2_CAP_TIMEPERFRAME)) { - interval = parm.parm.capture.timeperframe; - return true; -} - return false; + if (ioctl(VIDIOC_G_PARM, parm) 0) + return false; + + interval = parm.parm.capture.timeperframe; + return interval.numerator interval.denominator; } -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 0/5] qv4l2: add OpenGL render and window fixes
The qv4l2 test utility now supports OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to perform color space conversion. The OpenGL implementation requires OpenGL and QtOpenGL libraries as well as an OpenGL driver (typically from the graphics driver). If OpenGL support is not present, then the program will fall back to using the CPU to display. Changelog v2: - Cleaned up the capture win code and classes - CaptureWin is now a base class that can be used to implement different ways of displaying video. - setMinimumSize is now more reliable - Small code tweaks and improvements, including cleaner display flow - Changed the OpenGL abbreviation from OGL to GL Some of the changes/improvements: - Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. - OpenGL acceleration for supported systems. - Option to change between GPU or CPU based rendering. - CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. - Added a new menu option 'Preview' for controlling the CaptureWin's behavior. - Added a couple of hotkeys: CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window. It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Known issues: - Repositioning, scaling or switching windows while the capture is recording will reduce the framerate. This is a limitation of Qt and not OpenGL. - Using 4 streams of RGB3 1080p60 can at random times cease to render correctly and reduce the framerate to half. A restart solves this though. - OpenGL is limited to 60fps. Disabling V-sync might allow for faster framerates. - Resizing or scaling is not supported, mainly because the YUY2 shader renders the image incorrectly when the canvas size is not equal to the frame size. - Some of the supported OpenGL formats may use the CPU for colorspace conversion, but this is driver dependant. Supported formats for OpenGL render: - Native supported and accelerated: V4L2_PIX_FMT_RGB32 V4L2_PIX_FMT_BGR32 V4L2_PIX_FMT_RGB24 V4L2_PIX_FMT_BGR24 V4L2_PIX_FMT_RGB565 V4L2_PIX_FMT_RGB555 V4L2_PIX_FMT_YUYV V4L2_PIX_FMT_YVYU V4L2_PIX_FMT_UYVY V4L2_PIX_FMT_VYUY V4L2_PIX_FMT_YVU420 V4L2_PIX_FMT_YUV420 - All formats supported by V4L conversion library, but they will use the CPU to convert to RGB3 before being displayed with OpenGL. Performance: All tests are done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. FPS for every input for a given number of streams: 1 STREAM 2 STREAMS 3 STREAMS 4 STREAMS RGB3 6060 60 60 BGR3 6060 60 50 YUYV 6060 60 48 YU12 6060 60 52 YV12 6060 60 52 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 4/5] qv4l2: new modular capture window design
The display of video has been divided into classes to easier implement other ways to render frames on screen. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/Makefile.am| 4 +- utils/qv4l2/capture-win-qt.cpp | 89 utils/qv4l2/capture-win-qt.h | 48 utils/qv4l2/capture-win.cpp| 45 ++- utils/qv4l2/capture-win.h | 25 ++- utils/qv4l2/qv4l2.cpp | 100 - utils/qv4l2/qv4l2.h| 1 + 7 files changed, 226 insertions(+), 86 deletions(-) create mode 100644 utils/qv4l2/capture-win-qt.cpp create mode 100644 utils/qv4l2/capture-win-qt.h diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 1f5a49f..9ef8149 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,6 +1,7 @@ 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 @@ -37,5 +38,4 @@ install-data-local: $(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 diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp new file mode 100644 index 000..63c77d5 --- /dev/null +++ b/utils/qv4l2/capture-win-qt.cpp @@ -0,0 +1,89 @@ +/* qv4l2: a control panel controlling v4l2 devices. + * + * Copyright (C) 2006 Hans Verkuil hverk...@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
[PATCHv2 5/5] qv4l2: add OpenGL video display and render
Adds OpenGL-accelerated display of video for the qv4l2 test utility. This allows for using the graphics card to render the video content to screen and to perform color space conversion. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac | 8 +- utils/qv4l2/Makefile.am| 8 +- utils/qv4l2/capture-win-gl.cpp | 556 + utils/qv4l2/capture-win-gl.h | 103 utils/qv4l2/qv4l2.cpp | 52 +++- utils/qv4l2/qv4l2.h| 10 + 6 files changed, 733 insertions(+), 4 deletions(-) create mode 100644 utils/qv4l2/capture-win-gl.cpp create mode 100644 utils/qv4l2/capture-win-gl.h diff --git a/configure.ac b/configure.ac index e249546..d74da61 100644 --- a/configure.ac +++ b/configure.ac @@ -128,7 +128,12 @@ if test x$qt_pkgconfig = xtrue; then AC_SUBST(UIC) AC_SUBST(RCC) else - AC_MSG_WARN(Qt4 is not available) + AC_MSG_WARN(Qt4 or higher is not available) +fi + +PKG_CHECK_MODULES(QTGL, [QtOpenGL = 4.4 gl], [qt_pkgconfig_gl=true], [qt_pkgconfig_gl=false]) +if test x$qt_pkgconfig_gl = xfalse; then + AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi AC_SUBST([JPEG_LIBS]) @@ -237,6 +242,7 @@ AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes]) AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) +AM_CONDITIONAL([WITH_QV4L2_GL], [test WITH_QV4L2 -a ${qt_pkgconfig_gl} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 9ef8149..22d4c17 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -1,12 +1,18 @@ 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 \ + capture-win-qt.cpp capture-win-qt.h capture-win-gl.cpp capture-win-gl.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 + +if WITH_QV4L2_GL +qv4l2_CPPFLAGS = $(QTGL_CFLAGS) -DENABLE_GL +qv4l2_LDFLAGS = $(QTGL_LIBS) +else qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) +endif EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp new file mode 100644 index 000..d5c1d54 --- /dev/null +++ b/utils/qv4l2/capture-win-gl.cpp @@ -0,0 +1,556 @@ +/* + * The YUY2 shader code was copied and simplified from face-responder. The code is under public domain: + * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master + * + * Copyright (C) 2012 Nathan Harward + * + * All other OpenGL code: + * + * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include capture-win-gl.h + +#include stdio.h + +CaptureWinGL::CaptureWinGL() +{ + CaptureWin::buildWindow(m_videoSurface); + CaptureWin::setWindowTitle(V4L2 Capture (OpenGL)); +} + +CaptureWinGL::~CaptureWinGL() +{ +} + +void CaptureWinGL::stop() +{ +#ifdef ENABLE_GL + m_videoSurface.stop(); +#endif +} + +void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString info) +{ +#ifdef ENABLE_GL + m_videoSurface.setFrame(width, height, format, data); +#endif + m_information.setText(info); +} + +bool CaptureWinGL::hasNativeFormat(__u32 format) +{ +#ifdef ENABLE_GL + return m_videoSurface.hasNativeFormat(format); +#else + return false; +#endif +} + +bool CaptureWinGL::isSupported() +{ +#ifdef ENABLE_GL
[PATCHv2 3/5] qv4l2: fix minimum size in capture win to frame size
CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 29 + utils/qv4l2/capture-win.h | 1 + 2 files changed, 30 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index a94c73d..68dc9ed 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -21,6 +21,8 @@ #include QImage #include QVBoxLayout #include QCloseEvent +#include QApplication +#include QDesktopWidget #include qv4l2.h #include capture-win.h @@ -45,6 +47,33 @@ CaptureWin::~CaptureWin() delete hotkeyClose; } +void CaptureWin::setMinimumSize(int minw, int minh) +{ + QDesktopWidget *screen = QApplication::desktop(); + QRect resolution = screen-screenGeometry(); + QSize maxSize = maximumSize(); + + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + minw += l + r; + minh += t + b + m_msg-minimumSizeHint().height() + layout()-spacing(); + + if (minw resolution.width()) + minw = resolution.width(); + if (minw 150) + minw = 150; + + if (minh resolution.height()) + minh = resolution.height(); + if (minh 100) + minh = 100; + + QWidget::setMinimumSize(minw, minh); + QWidget::setMaximumSize(minw, minh); + updateGeometry(); + QWidget::setMaximumSize(maxSize.width(), maxSize.height()); +} + void CaptureWin::setImage(const QImage image, const QString status) { m_label-setPixmap(QPixmap::fromImage(image)); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 4115d56..3925757 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -35,6 +35,7 @@ public: CaptureWin(); ~CaptureWin(); + void setMinimumSize(int minw, int minh); void setImage(const QImage image, const QString status); protected: -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 1/5] qv4l2: move function ctrlEvent
Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 94 +-- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index de9b154..a8fcc65 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -202,6 +202,53 @@ void ApplicationWindow::openrawdev() setDevice(d.selectedFiles().first(), true); } +void ApplicationWindow::ctrlEvent() +{ + v4l2_event ev; + + while (dqevent(ev)) { + if (ev.type != V4L2_EVENT_CTRL) + continue; + m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; + m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; + m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; + m_ctrlMap[ev.id].step = ev.u.ctrl.step; + m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; + m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); + switch (m_ctrlMap[ev.id].type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_BITMASK: + setVal(ev.id, ev.u.ctrl.value); + break; + case V4L2_CTRL_TYPE_INTEGER64: + setVal64(ev.id, ev.u.ctrl.value64); + break; + default: + break; + } + if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) + continue; + queryctrl(m_ctrlMap[ev.id]); + + struct v4l2_ext_control c; + struct v4l2_ext_controls ctrls; + + c.id = ev.id; + c.size = m_ctrlMap[ev.id].maximum + 1; + c.string = (char *)malloc(c.size); + memset(ctrls, 0, sizeof(ctrls)); + ctrls.count = 1; + ctrls.ctrl_class = 0; + ctrls.controls = c; + if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) + setString(ev.id, c.string); + free(c.string); + } +} + void ApplicationWindow::capVbiFrame() { __u32 buftype = m_genTab-bufType(); @@ -305,53 +352,6 @@ void ApplicationWindow::capVbiFrame() refresh(); } -void ApplicationWindow::ctrlEvent() -{ - v4l2_event ev; - - while (dqevent(ev)) { - if (ev.type != V4L2_EVENT_CTRL) - continue; - m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; - m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; - m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; - m_ctrlMap[ev.id].step = ev.u.ctrl.step; - m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; - m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); - switch (m_ctrlMap[ev.id].type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_INTEGER_MENU: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_BITMASK: - setVal(ev.id, ev.u.ctrl.value); - break; - case V4L2_CTRL_TYPE_INTEGER64: - setVal64(ev.id, ev.u.ctrl.value64); - break; - default: - break; - } - if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) - continue; - queryctrl(m_ctrlMap[ev.id]); - - struct v4l2_ext_control c; - struct v4l2_ext_controls ctrls; - - c.id = ev.id; - c.size = m_ctrlMap[ev.id].maximum + 1; - c.string = (char *)malloc(c.size); - memset(ctrls, 0, sizeof(ctrls)); - ctrls.count = 1; - ctrls.ctrl_class = 0; - ctrls.controls = c; - if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) - setString(ev.id, c.string); - free(c.string); - } -} - void ApplicationWindow::capFrame() { __u32 buftype = m_genTab-bufType(); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 2/5] qv4l2: add hotkeys for common operations
CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 8 utils/qv4l2/capture-win.h | 4 +++- utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 6798252..a94c73d 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -35,6 +35,14 @@ CaptureWin::CaptureWin() vbox-addWidget(m_label); vbox-addWidget(m_msg); + + hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); + QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close())); +} + +CaptureWin::~CaptureWin() +{ + delete hotkeyClose; } void CaptureWin::setImage(const QImage image, const QString status) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index e861b12..4115d56 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -21,6 +21,7 @@ #define CAPTURE_WIN_H #include QWidget +#include QShortcut #include sys/time.h class QImage; @@ -32,7 +33,7 @@ class CaptureWin : public QWidget public: CaptureWin(); - virtual ~CaptureWin() {} + ~CaptureWin(); void setImage(const QImage image, const QString status); @@ -45,6 +46,7 @@ signals: private: QLabel *m_label; QLabel *m_msg; + QShortcut *hotkeyClose; }; #endif diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index a8fcc65..bb1d84f 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -78,6 +78,7 @@ ApplicationWindow::ApplicationWindow() : m_capStartAct-setStatusTip(Start capturing); m_capStartAct-setCheckable(true); m_capStartAct-setDisabled(true); + m_capStartAct-setShortcut(Qt::CTRL+Qt::Key_V); connect(m_capStartAct, SIGNAL(toggled(bool)), this, SLOT(capStart(bool))); m_snapshotAct = new QAction(QIcon(:/snapshot.png), Make Snapshot, this); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] qv4l2: add OpenGL video render
On Wednesday, July 17, 2013 01:03:44 PM you wrote: Hi Bård, On Tuesday 16 July 2013 14:59:04 Bard Eirik Winther wrote: On Tuesday, July 16, 2013 02:01:45 PM you wrote: Hi Bård, Thank you for the patches. On Tuesday 16 July 2013 13:24:08 Bård Eirik Winther wrote: The qv4l2 test utility now supports OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to performing color space conversion. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac| 8 +- utils/qv4l2/Makefile.am | 9 +- utils/qv4l2/capture-win.cpp | 559 +++-- utils/qv4l2/capture-win.h | 81 ++- utils/qv4l2/qv4l2.cpp | 173 +++--- utils/qv4l2/qv4l2.h | 8 + 6 files changed, 782 insertions(+), 56 deletions(-) Is there a chance you could split the OpenGL code to separate classes, in a separate source file ? This would allow implementing other renderers, such as KMS planes on embedded devices. Hi. Do you mean to separate the GL class only or all the different shaders/renderes as well? Basically, what would be nice to get is an easy way to extend qv4l2 with different renderers. OpenGL is fine on the desktop, but for embedded devices a KMS planes backend would work best given the mess that the embedded GPU situation is. Instead of adding #ifdef ENABLE_OGL and if (use_ogl) through the code, abstracting the rendering code in a separate base class that renderers could inherit from would make the code simpler to read, maintain and extend. I haven't looked at the details so I'm not sure how much work that would be, but if the effort is reasonable I think it would be a nice improvement. I belive I have found a workable solution that should not take that much of time to implement. The current interface for adding more render/display options is simply to extend this class: class CaptureCanvas { public: CaptureCanvas(){} virtual ~CaptureCanvas(); virtual void setFrame(int width, int height, unsigned char *data, __u32 format); virtual void start(); virtual void stop(); virtual void hasNativeFormat(__u32 format); virtual static bool isSupportedRender(); }; It should cover any needs for display afaik, but then again I do not know every system that exists which might require more interaction. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] qv4l2: fix CaptureWin mimimum size to match video fram size
CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 26 ++ utils/qv4l2/capture-win.h | 1 + 2 files changed, 27 insertions(+) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index a94c73d..7ac3fa1 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -21,6 +21,8 @@ #include QImage #include QVBoxLayout #include QCloseEvent +#include QApplication +#include QDesktopWidget #include qv4l2.h #include capture-win.h @@ -36,6 +38,10 @@ CaptureWin::CaptureWin() vbox-addWidget(m_label); vbox-addWidget(m_msg); + int l, t, r, b; + vbox-getContentsMargins(l, t, r, b); + vbox-setSpacing(b); + hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close())); } @@ -45,6 +51,26 @@ CaptureWin::~CaptureWin() delete hotkeyClose; } +void CaptureWin::setMinimumSize(int minw, int minh) +{ + QDesktopWidget *screen = QApplication::desktop(); + QRect resolution = screen-screenGeometry(); + + int l, t, r, b; + layout()-getContentsMargins(l, t, r, b); + minw += l + r; + minh += t + b + m_msg-minimumSizeHint().height() + layout()-spacing(); + + if (minw resolution.width()) + minw = resolution.width(); + + if (minh resolution.height()) + minh = resolution.height(); + + QWidget::setMinimumSize(minw, minh); + resize(minw, minh); +} + void CaptureWin::setImage(const QImage image, const QString status) { m_label-setPixmap(QPixmap::fromImage(image)); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index 4115d56..3de3447 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -35,6 +35,7 @@ public: CaptureWin(); ~CaptureWin(); + virtual void setMinimumSize(int minw, int minh); void setImage(const QImage image, const QString status); protected: -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] qv4l2: add hotkeys for common operations
CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/capture-win.cpp | 8 utils/qv4l2/capture-win.h | 4 +++- utils/qv4l2/qv4l2.cpp | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 6798252..a94c73d 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -35,6 +35,14 @@ CaptureWin::CaptureWin() vbox-addWidget(m_label); vbox-addWidget(m_msg); + + hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); + QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close())); +} + +CaptureWin::~CaptureWin() +{ + delete hotkeyClose; } void CaptureWin::setImage(const QImage image, const QString status) diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index e861b12..4115d56 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -21,6 +21,7 @@ #define CAPTURE_WIN_H #include QWidget +#include QShortcut #include sys/time.h class QImage; @@ -32,7 +33,7 @@ class CaptureWin : public QWidget public: CaptureWin(); - virtual ~CaptureWin() {} + ~CaptureWin(); void setImage(const QImage image, const QString status); @@ -45,6 +46,7 @@ signals: private: QLabel *m_label; QLabel *m_msg; + QShortcut *hotkeyClose; }; #endif diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index a8fcc65..bb1d84f 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -78,6 +78,7 @@ ApplicationWindow::ApplicationWindow() : m_capStartAct-setStatusTip(Start capturing); m_capStartAct-setCheckable(true); m_capStartAct-setDisabled(true); + m_capStartAct-setShortcut(Qt::CTRL+Qt::Key_V); connect(m_capStartAct, SIGNAL(toggled(bool)), this, SLOT(capStart(bool))); m_snapshotAct = new QAction(QIcon(:/snapshot.png), Make Snapshot, this); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/4] qv4l2: add OpenGL video render
The qv4l2 test utility now supports OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to performing color space conversion. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- configure.ac| 8 +- utils/qv4l2/Makefile.am | 9 +- utils/qv4l2/capture-win.cpp | 559 ++-- utils/qv4l2/capture-win.h | 81 ++- utils/qv4l2/qv4l2.cpp | 173 +++--- utils/qv4l2/qv4l2.h | 8 + 6 files changed, 782 insertions(+), 56 deletions(-) diff --git a/configure.ac b/configure.ac index e249546..97a0dfc 100644 --- a/configure.ac +++ b/configure.ac @@ -128,7 +128,12 @@ if test x$qt_pkgconfig = xtrue; then AC_SUBST(UIC) AC_SUBST(RCC) else - AC_MSG_WARN(Qt4 is not available) + AC_MSG_WARN(Qt4 or higher is not available) +fi + +PKG_CHECK_MODULES(QTOGL, [QtOpenGL = 4.4 gl], [qt_pkgconfig_ogl=true], [qt_pkgconfig_ogl=false]) +if test x$qt_pkgconfig_ogl = xfalse; then + AC_MSG_WARN(Qt4 OpenGL or higher is not available) fi AC_SUBST([JPEG_LIBS]) @@ -237,6 +242,7 @@ AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes]) AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno]) AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4lutils != xno]) AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno]) +AM_CONDITIONAL([WITH_QV4L2_OGL_COMPILE], [test WITH_QV4L2 -a ${qt_pkgconfig_ogl} = true]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno]) diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am index 1f5a49f..86bf786 100644 --- a/utils/qv4l2/Makefile.am +++ b/utils/qv4l2/Makefile.am @@ -4,8 +4,14 @@ qv4l2_SOURCES = qv4l2.cpp general-tab.cpp ctrl-tab.cpp vbi-tab.cpp v4l2-api.cpp 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 + +if WITH_QV4L2_OGL_COMPILE +qv4l2_CPPFLAGS = $(QTOGL_CFLAGS) -DENABLE_OGL +qv4l2_LDFLAGS = $(QTOGL_LIBS) +else qv4l2_CPPFLAGS = $(QT_CFLAGS) qv4l2_LDFLAGS = $(QT_LIBS) +endif EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \ video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \ @@ -37,5 +43,4 @@ install-data-local: $(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 diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp index 7ac3fa1..132d23d 100644 --- a/utils/qv4l2/capture-win.cpp +++ b/utils/qv4l2/capture-win.cpp @@ -16,6 +16,7 @@ * 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 QLabel #include QImage @@ -24,23 +25,12 @@ #include QApplication #include QDesktopWidget -#include qv4l2.h #include capture-win.h -CaptureWin::CaptureWin() +CaptureWin::CaptureWin(bool useOGL) { - QVBoxLayout *vbox = new QVBoxLayout(this); - - setWindowTitle(V4L2 Capture); - m_label = new QLabel(); - m_msg = new QLabel(No frame); - - vbox-addWidget(m_label); - vbox-addWidget(m_msg); - - int l, t, r, b; - vbox-getContentsMargins(l, t, r, b); - vbox-setSpacing(b); + m_enableOGL = useOGL; + buildCanvas(); hotkeyClose = new QShortcut(Qt::CTRL+Qt::Key_W, this); QObject::connect(hotkeyClose, SIGNAL(activated()), this, SLOT(close())); @@ -49,6 +39,48 @@ CaptureWin::CaptureWin() CaptureWin::~CaptureWin() { delete hotkeyClose; + clearCanvas(); +} + +void CaptureWin::clearCanvas() +{ + if (layout() != NULL) { + if (m_enableOGL) { +#ifdef ENABLE_OGL + delete m_canvas; +#endif + } else { + delete m_videoSurface; + } + + delete m_information; + layout()-removeWidget(this); + delete layout(); + + } +} + +void CaptureWin::buildCanvas() +{ + QVBoxLayout *vbox = new
[PATCH 0/4] OpenGL render for qv4l2
qv4l2: The qv4l2 test utility now supports OpenGL-accelerated display of video. This allows for using the graphics card to render the video content to screen and to performing color space conversion. The OpenGL implementation requires the QtOpenGL library as well as an OpenGL driver. If OpenGL support is not present, then the program will fall back to using the CPU to display. Some of the changes/improvements: - Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. - OpenGL acceleration for supported systems. - Option to change between GPU or CPU based rendering. - CaptureWin's setMinimumSize() sets the minimum size for the video frame viewport and not for the window itself. If the minimum size is larger than the monitor resolution, it will reduce the minimum size to match this. - Added a new menu option 'Preview' for controlling the CaptureWin's behavior. - Added a couple of hotkeys: CTRL + V : When main window is selected start capture. This gives an option other than the button to start recording, as this is a frequent operation when using the utility. CTRL + W : When CaptureWin is selected close capture window. It makes it easier to deal with high resolutions video on small screen, especially when the window close button may be outside the monitor when repositioning the window. Known issues: - Repositioning, scaling or switching windows while the capture is recording will reduce the framerate. This is a limitation of Qt and not OpenGL. - Using 4 streams of RGB3 1080p60 can at random times cease to render correctly and reduce the framerate to half. A restart solves this though. - OpenGL is limited to 60fps. Disabling V-sync might allow for faster framerates. - Resizing or scaling is not supported, mainly because the YUY2 shader renders the image incorrectly when the canvas size is not equal to the frame size. Supported formats for OpenGL render: - Native supported and accelerated: V4L2_PIX_FMT_RGB32 V4L2_PIX_FMT_BGR32 V4L2_PIX_FMT_RGB24 V4L2_PIX_FMT_BGR24 V4L2_PIX_FMT_RGB565 V4L2_PIX_FMT_RGB555 V4L2_PIX_FMT_YUYV V4L2_PIX_FMT_YVYU V4L2_PIX_FMT_UYVY V4L2_PIX_FMT_VYUY V4L2_PIX_FMT_YVU420 V4L2_PIX_FMT_YUV420 - All formats supported by V4L conversion library, but they will use the CPU to convert to RGB3 before being displayed with OpenGL. Performance: All tests are done on an Intel i7-2600S (with Turbo Boost disabled) using the integrated Intel HD 2000 graphics processor. The mothreboard is an ASUS P8H77-I with 2x2GB CL 9-9-9-24 DDR3 RAM. The capture card is a Cisco test card with 4 HDMI inputs connected using PCIe2.0x8. All video input streams used for testing are progressive HD (1920x1080) with 60fps. FPS for every input for a given number of streams: 1 STREAM 2 STREAMS 3 STREAMS 4 STREAMS RGB3 6060 60 60 BGR3 6060 60 50 YUYV 6060 60 48 YU12 6060 60 52 YV12 6060 60 52 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/4] qv4l2: move function ctrlEvent
Moved the ctrlEvent() function in qv4l2.cpp to be grouped with GUI function and to group capFrame() and capVbiFrame() together. Signed-off-by: Bård Eirik Winther bwint...@cisco.com --- utils/qv4l2/qv4l2.cpp | 94 +-- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index de9b154..a8fcc65 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -202,6 +202,53 @@ void ApplicationWindow::openrawdev() setDevice(d.selectedFiles().first(), true); } +void ApplicationWindow::ctrlEvent() +{ + v4l2_event ev; + + while (dqevent(ev)) { + if (ev.type != V4L2_EVENT_CTRL) + continue; + m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; + m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; + m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; + m_ctrlMap[ev.id].step = ev.u.ctrl.step; + m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; + m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); + switch (m_ctrlMap[ev.id].type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_BITMASK: + setVal(ev.id, ev.u.ctrl.value); + break; + case V4L2_CTRL_TYPE_INTEGER64: + setVal64(ev.id, ev.u.ctrl.value64); + break; + default: + break; + } + if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) + continue; + queryctrl(m_ctrlMap[ev.id]); + + struct v4l2_ext_control c; + struct v4l2_ext_controls ctrls; + + c.id = ev.id; + c.size = m_ctrlMap[ev.id].maximum + 1; + c.string = (char *)malloc(c.size); + memset(ctrls, 0, sizeof(ctrls)); + ctrls.count = 1; + ctrls.ctrl_class = 0; + ctrls.controls = c; + if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) + setString(ev.id, c.string); + free(c.string); + } +} + void ApplicationWindow::capVbiFrame() { __u32 buftype = m_genTab-bufType(); @@ -305,53 +352,6 @@ void ApplicationWindow::capVbiFrame() refresh(); } -void ApplicationWindow::ctrlEvent() -{ - v4l2_event ev; - - while (dqevent(ev)) { - if (ev.type != V4L2_EVENT_CTRL) - continue; - m_ctrlMap[ev.id].flags = ev.u.ctrl.flags; - m_ctrlMap[ev.id].minimum = ev.u.ctrl.minimum; - m_ctrlMap[ev.id].maximum = ev.u.ctrl.maximum; - m_ctrlMap[ev.id].step = ev.u.ctrl.step; - m_ctrlMap[ev.id].default_value = ev.u.ctrl.default_value; - m_widgetMap[ev.id]-setDisabled(m_ctrlMap[ev.id].flags CTRL_FLAG_DISABLED); - switch (m_ctrlMap[ev.id].type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_INTEGER_MENU: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_BITMASK: - setVal(ev.id, ev.u.ctrl.value); - break; - case V4L2_CTRL_TYPE_INTEGER64: - setVal64(ev.id, ev.u.ctrl.value64); - break; - default: - break; - } - if (m_ctrlMap[ev.id].type != V4L2_CTRL_TYPE_STRING) - continue; - queryctrl(m_ctrlMap[ev.id]); - - struct v4l2_ext_control c; - struct v4l2_ext_controls ctrls; - - c.id = ev.id; - c.size = m_ctrlMap[ev.id].maximum + 1; - c.string = (char *)malloc(c.size); - memset(ctrls, 0, sizeof(ctrls)); - ctrls.count = 1; - ctrls.ctrl_class = 0; - ctrls.controls = c; - if (!ioctl(VIDIOC_G_EXT_CTRLS, ctrls)) - setString(ev.id, c.string); - free(c.string); - } -} - void ApplicationWindow::capFrame() { __u32 buftype = m_genTab-bufType(); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html