/* * qv4l2 - Test Pattern Generator Tab * * Copyright 2014 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 "qv4l2.h" #include "general-tab.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void ApplicationWindow::addTpgTab(int m_winWidth) { QWidget *t = new QWidget(m_tabs); QVBoxLayout *vbox = new QVBoxLayout(t); QWidget *w = new QWidget(t); QCheckBox *check; QComboBox *combo; QSpinBox *spin; m_col = m_row = 0; m_cols = 4; for (int j = 0; j < m_cols; j++) { m_maxw[j] = 0; } vbox->addWidget(w); QGridLayout *grid = new QGridLayout(w); QLabel *title_tab = new QLabel("Test Pattern Generator", parentWidget()); QFont f = title_tab->font(); f.setBold(true); title_tab->setFont(f); grid->addWidget(title_tab, m_row, m_col, 1, m_cols, Qt::AlignLeft); grid->setRowMinimumHeight(m_row, 25); m_row++; QFrame *m_line = new QFrame(grid->parentWidget()); m_line->setFrameShape(QFrame::HLine); m_line->setFrameShadow(QFrame::Sunken); grid->addWidget(m_line, m_row, m_col, 1, m_cols, Qt::AlignVCenter); m_row++; m_tabs->addTab(t, "Test Pattern Generator"); grid->addWidget(new QWidget(w), grid->rowCount(), 0, 1, m_cols); addLabel(grid, "Test Pattern"); combo = new QComboBox(w); for (int i = 0; tpg_pattern_strings[i]; i++) combo->addItem(tpg_pattern_strings[i]); addWidget(grid, combo); connect(combo, SIGNAL(activated(int)), SLOT(testPatternChanged(int))); m_row++; m_col = 0; addLabel(grid, "Horizontal Movement"); combo = new QComboBox(w); combo->addItem("Move Left Fast"); combo->addItem("Move Left"); combo->addItem("Move Left Slow"); combo->addItem("No Movement"); combo->addItem("Move Right Slow"); combo->addItem("Move Right"); combo->addItem("Move Right Fast"); combo->setCurrentIndex(3); addWidget(grid, combo); connect(combo, SIGNAL(activated(int)), SLOT(horMovementChanged(int))); addLabel(grid, "Video Aspect Ratio"); combo = new QComboBox(w); combo->addItem("Source Width x Height"); combo->addItem("4x3"); combo->addItem("14x9"); combo->addItem("16x9"); combo->addItem("16x9 Anamorphic"); addWidget(grid, combo); connect(combo, SIGNAL(activated(int)), SLOT(videoAspectRatioChanged(int))); addLabel(grid, "Vertical Movement"); combo = new QComboBox(w); combo->addItem("Move Up Fast"); combo->addItem("Move Up"); combo->addItem("Move Up Slow"); combo->addItem("No Movement"); combo->addItem("Move Down Slow"); combo->addItem("Move Down"); combo->addItem("Move Down Fast"); combo->setCurrentIndex(3); addWidget(grid, combo); connect(combo, SIGNAL(activated(int)), SLOT(vertMovementChanged(int))); addLabel(grid, "Show Border"); check = new QCheckBox(w); addWidget(grid, check); connect(check, SIGNAL(stateChanged(int)), SLOT(showBorderChanged(int))); addLabel(grid, "Insert SAV Code in Image"); check = new QCheckBox(w); addWidget(grid, check); connect(check, SIGNAL(stateChanged(int)), SLOT(insSAVChanged(int))); addLabel(grid, "Show Square"); check = new QCheckBox(w); addWidget(grid, check); connect(check, SIGNAL(stateChanged(int)), SLOT(showSquareChanged(int))); addLabel(grid, "Insert EAV Code in Image"); check = new QCheckBox(w); addWidget(grid, check); connect(check, SIGNAL(stateChanged(int)), SLOT(insEAVChanged(int))); addLabel(grid, "Fill Percentage of Frame"); spin = new QSpinBox(w); spin->setRange(0, 100); spin->setValue(100); addWidget(grid, spin); connect(spin, SIGNAL(valueChanged(int)), SLOT(fillPercentageChanged(int))); addLabel(grid, "Colorspace"); m_tpgColorspace = new QComboBox(w); m_tpgColorspace->addItem("Use Format", QVariant(0)); m_tpgColorspace->addItem("SMPTE 170M", QVariant(V4L2_COLORSPACE_SMPTE170M)); m_tpgColorspace->addItem("Rec. 709", QVariant(V4L2_COLORSPACE_REC709)); m_tpgColorspace->addItem("sRGB", QVariant(V4L2_COLORSPACE_SRGB)); m_tpgColorspace->addItem("Adobe RGB", QVariant(V4L2_COLORSPACE_ADOBERGB)); m_tpgColorspace->addItem("BT.2020", QVariant(V4L2_COLORSPACE_BT2020)); m_tpgColorspace->addItem("DCI-P3", QVariant(V4L2_COLORSPACE_DCI_P3)); m_tpgColorspace->addItem("SMPTE 240M", QVariant(V4L2_COLORSPACE_SMPTE240M)); m_tpgColorspace->addItem("470 System M", QVariant(V4L2_COLORSPACE_470_SYSTEM_M)); m_tpgColorspace->addItem("470 System BG", QVariant(V4L2_COLORSPACE_470_SYSTEM_BG)); addWidget(grid, m_tpgColorspace); connect(m_tpgColorspace, SIGNAL(activated(int)), SLOT(tpgColorspaceChanged())); addLabel(grid, "Transfer Function"); m_tpgXferFunc = new QComboBox(w); m_tpgXferFunc->addItem("Use Format", QVariant(V4L2_XFER_FUNC_DEFAULT)); m_tpgXferFunc->addItem("Rec. 709", QVariant(V4L2_XFER_FUNC_709)); m_tpgXferFunc->addItem("sRGB", QVariant(V4L2_XFER_FUNC_SRGB)); m_tpgXferFunc->addItem("Adobe RGB", QVariant(V4L2_XFER_FUNC_ADOBERGB)); m_tpgXferFunc->addItem("DCI-P3", QVariant(V4L2_XFER_FUNC_DCI_P3)); m_tpgXferFunc->addItem("SMPTE 2084", QVariant(V4L2_XFER_FUNC_SMPTE2084)); m_tpgXferFunc->addItem("SMPTE 240M", QVariant(V4L2_XFER_FUNC_SMPTE240M)); m_tpgXferFunc->addItem("None", QVariant(V4L2_XFER_FUNC_NONE)); addWidget(grid, m_tpgXferFunc); connect(m_tpgXferFunc, SIGNAL(activated(int)), SLOT(tpgXferFuncChanged())); addLabel(grid, "Y'CbCr Encoding"); m_tpgYCbCrEnc = new QComboBox(w); m_tpgYCbCrEnc->addItem("Use Format", QVariant(V4L2_YCBCR_ENC_DEFAULT)); m_tpgYCbCrEnc->addItem("ITU-R 601", QVariant(V4L2_YCBCR_ENC_601)); m_tpgYCbCrEnc->addItem("Rec. 709", QVariant(V4L2_YCBCR_ENC_709)); m_tpgYCbCrEnc->addItem("xvYCC 601", QVariant(V4L2_YCBCR_ENC_XV601)); m_tpgYCbCrEnc->addItem("xvYCC 709", QVariant(V4L2_YCBCR_ENC_XV709)); m_tpgYCbCrEnc->addItem("sYCC", QVariant(V4L2_YCBCR_ENC_SYCC)); m_tpgYCbCrEnc->addItem("BT.2020", QVariant(V4L2_YCBCR_ENC_BT2020)); m_tpgYCbCrEnc->addItem("BT.2020 Constant Luminance", QVariant(V4L2_YCBCR_ENC_BT2020_CONST_LUM)); m_tpgYCbCrEnc->addItem("SMPTE 240M", QVariant(V4L2_YCBCR_ENC_SMPTE240M)); addWidget(grid, m_tpgYCbCrEnc); connect(m_tpgYCbCrEnc, SIGNAL(activated(int)), SLOT(tpgColorspaceChanged())); addLabel(grid, "Quantization"); m_tpgQuantRange = new QComboBox(w); m_tpgQuantRange->addItem("Use Format", QVariant(V4L2_QUANTIZATION_DEFAULT)); m_tpgQuantRange->addItem("Full Range", QVariant(V4L2_QUANTIZATION_FULL_RANGE)); m_tpgQuantRange->addItem("Limited Range", QVariant(V4L2_QUANTIZATION_LIM_RANGE)); addWidget(grid, m_tpgQuantRange); connect(m_tpgQuantRange, SIGNAL(activated(int)), SLOT(tpgColorspaceChanged())); addLabel(grid, "Limited RGB Range (16-235)"); m_tpgLimRGBRange = new QCheckBox(w); addWidget(grid, m_tpgLimRGBRange); connect(m_tpgLimRGBRange, SIGNAL(stateChanged(int)), SLOT(limRGBRangeChanged(int))); addLabel(grid, "Alpha Component"); spin = new QSpinBox(w); spin->setRange(0, 255); spin->setValue(0); addWidget(grid, spin); connect(spin, SIGNAL(valueChanged(int)), SLOT(alphaComponentChanged(int))); addLabel(grid, "Apply Alpha To Red Only"); check = new QCheckBox(w); addWidget(grid, check); connect(check, SIGNAL(stateChanged(int)), SLOT(applyToRedChanged(int))); m_row++; m_col = 0; addWidget(grid, new QWidget(w)); grid->setRowStretch(grid->rowCount() - 1, 1); w = new QWidget(t); vbox->addWidget(w); fixWidth(grid); int totalw = 0; int diff = 0; for (int i = 0; i < m_cols; i++) { totalw += m_maxw[i] + m_pxw; } if (totalw > m_winWidth) m_winWidth = totalw; else { diff = m_winWidth - totalw; grid->setHorizontalSpacing(diff/5); } } void ApplicationWindow::testPatternChanged(int val) { tpg_s_pattern(&m_tpg, (tpg_pattern)val); } void ApplicationWindow::horMovementChanged(int val) { tpg_s_mv_hor_mode(&m_tpg, (tpg_move_mode)val); } void ApplicationWindow::vertMovementChanged(int val) { tpg_s_mv_vert_mode(&m_tpg, (tpg_move_mode)val); } void ApplicationWindow::showBorderChanged(int val) { tpg_s_show_border(&m_tpg, val); } void ApplicationWindow::showSquareChanged(int val) { tpg_s_show_square(&m_tpg, val); } void ApplicationWindow::insSAVChanged(int val) { tpg_s_insert_sav(&m_tpg, val); } void ApplicationWindow::insEAVChanged(int val) { tpg_s_insert_eav(&m_tpg, val); } void ApplicationWindow::videoAspectRatioChanged(int val) { tpg_s_video_aspect(&m_tpg, (tpg_video_aspect)val); } void ApplicationWindow::updateLimRGBRange() { if (m_tpgLimRGBRange == NULL) return; v4l2_output out; g_output(out.index); enum_output(out, true, out.index); if (out.capabilities & V4L2_OUT_CAP_STD) { m_tpgLimRGBRange->setChecked(false); } else if (out.capabilities & V4L2_OUT_CAP_DV_TIMINGS) { v4l2_dv_timings timings; g_dv_timings(timings); if (timings.bt.standards & V4L2_DV_BT_STD_CEA861) m_tpgLimRGBRange->setChecked(true); else m_tpgLimRGBRange->setChecked(false); } else { m_tpgLimRGBRange->setChecked(false); } } __u32 ApplicationWindow::tpgDefaultColorspace() { v4l2_dv_timings timings = { 0 }; v4l2_output out; __u32 io_caps; bool dvi_d = false; g_output(out.index); enum_output(out, true, out.index); io_caps = out.capabilities; v4l2_control ctrl = { V4L2_CID_DV_TX_MODE }; if (!g_ctrl(ctrl)) dvi_d = ctrl.value == V4L2_DV_TX_MODE_DVI_D; if (io_caps & V4L2_OUT_CAP_STD) return V4L2_COLORSPACE_SMPTE170M; if (!(io_caps & V4L2_OUT_CAP_DV_TIMINGS)) return V4L2_COLORSPACE_SRGB; g_dv_timings(timings); if (!(timings.bt.standards & V4L2_DV_BT_STD_CEA861) || dvi_d) return V4L2_COLORSPACE_SRGB; if (timings.bt.width == 720 && timings.bt.height <= 576) return V4L2_COLORSPACE_SMPTE170M; return V4L2_COLORSPACE_REC709; } static int combo2int(QComboBox *combo) { return combo->itemData(combo->currentIndex()).toInt(); } void ApplicationWindow::tpgColorspaceChanged() { cv4l_fmt fmt; int colorspace = combo2int(m_tpgColorspace); int xferFunc = combo2int(m_tpgXferFunc); int ycbcrEnc = combo2int(m_tpgYCbCrEnc); int quantization = combo2int(m_tpgQuantRange); g_fmt(fmt); if (colorspace == V4L2_COLORSPACE_DEFAULT) colorspace = fmt.g_colorspace(); if (colorspace == V4L2_COLORSPACE_DEFAULT) colorspace = tpgDefaultColorspace(); if (xferFunc == V4L2_XFER_FUNC_DEFAULT) xferFunc = fmt.g_xfer_func(); if (ycbcrEnc == V4L2_YCBCR_ENC_DEFAULT) ycbcrEnc = fmt.g_ycbcr_enc(); if (quantization == V4L2_QUANTIZATION_DEFAULT) quantization = fmt.g_quantization(); tpg_s_colorspace(&m_tpg, colorspace); tpg_s_xfer_func(&m_tpg, xferFunc); tpg_s_ycbcr_enc(&m_tpg, ycbcrEnc); tpg_s_quantization(&m_tpg, quantization); } void ApplicationWindow::limRGBRangeChanged(int val) { tpg_s_real_rgb_range(&m_tpg, val ? V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL); } void ApplicationWindow::fillPercentageChanged(int val) { tpg_s_perc_fill(&m_tpg, val); } void ApplicationWindow::alphaComponentChanged(int val) { tpg_s_alpha_component(&m_tpg, val); } void ApplicationWindow::applyToRedChanged(int val) { tpg_s_alpha_mode(&m_tpg, val); }