aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2015-05-15 10:54:55 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2015-05-15 10:54:55 +0200
commit6776b22fe173d76659257d09f4fbb5195cd49161 (patch)
treeb93ba7ed6ee38905eb758d05b3ce8c579925c9c0
parentb7a58371955e8580cedd00005bd0b209a105dba4 (diff)
qv4l2: add support for the transfer functionxfer
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--utils/qv4l2/capture-win-gl.cpp78
-rw-r--r--utils/qv4l2/capture-win-gl.h7
-rw-r--r--utils/qv4l2/capture-win-qt.h3
-rw-r--r--utils/qv4l2/capture-win.cpp1
-rw-r--r--utils/qv4l2/capture-win.h3
-rw-r--r--utils/qv4l2/general-tab.cpp37
-rw-r--r--utils/qv4l2/general-tab.h3
-rw-r--r--utils/qv4l2/qv4l2.cpp29
-rw-r--r--utils/qv4l2/qv4l2.h4
-rw-r--r--utils/qv4l2/tpg-tab.cpp15
-rw-r--r--utils/v4l2-compliance/cv4l-helpers.h2
-rw-r--r--utils/v4l2-compliance/v4l-helpers.h30
12 files changed, 155 insertions, 57 deletions
diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp
index c691bfe0..0dae5bd3 100644
--- a/utils/qv4l2/capture-win-gl.cpp
+++ b/utils/qv4l2/capture-win-gl.cpp
@@ -24,33 +24,6 @@
#include <stdio.h>
-/*
- * These two helper defines are taken from code that is not yet merged
- * in the kernel, but since they are very useful I've copied them here
- * for the time being.
- */
-
-/*
- * Determine how YCBCR_ENC_DEFAULT should map to a proper Y'CbCr encoding.
- * This depends on the colorspace.
- */
-#define V4L2_MAP_YCBCR_ENC_DEFAULT(colsp) \
- ((colsp) == V4L2_COLORSPACE_REC709 ? V4L2_YCBCR_ENC_709 : \
- ((colsp) == V4L2_COLORSPACE_BT2020 ? V4L2_YCBCR_ENC_BT2020 : \
- ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_YCBCR_ENC_SMPTE240M : \
- V4L2_YCBCR_ENC_601)))
-
-/*
- * Determine how QUANTIZATION_DEFAULT should map to a proper quantization.
- * This depends on whether the image is RGB or not, the colorspace and the
- * Y'CbCr encoding.
- */
-#define V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, colsp, ycbcr_enc) \
- (((is_rgb) && (colsp) == V4L2_COLORSPACE_BT2020) ? V4L2_QUANTIZATION_LIM_RANGE : \
- (((is_rgb) || (ycbcr_enc) == V4L2_YCBCR_ENC_XV601 || \
- (ycbcr_enc) == V4L2_YCBCR_ENC_XV709 || (colsp) == V4L2_COLORSPACE_JPEG) ? \
- V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE))
-
CaptureWinGL::CaptureWinGL(ApplicationWindow *aw) :
CaptureWin(aw)
{
@@ -119,10 +92,12 @@ bool CaptureWinGL::isSupported()
#endif
}
-void CaptureWinGL::setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv)
+void CaptureWinGL::setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv)
{
#ifdef HAVE_QTGL
- m_videoSurface.setColorspace(colorspace, ycbcr_enc, quantization, is_sdtv);
+ m_videoSurface.setColorspace(colorspace, xfer_func,
+ ycbcr_enc, quantization, is_sdtv);
#endif
}
@@ -161,6 +136,7 @@ CaptureWinGLEngine::CaptureWinGLEngine() :
m_WCrop(0),
m_HCrop(0),
m_colorspace(V4L2_COLORSPACE_REC709),
+ m_xfer_func(V4L2_XFER_FUNC_DEFAULT),
m_ycbcr_enc(V4L2_YCBCR_ENC_DEFAULT),
m_quantization(V4L2_QUANTIZATION_DEFAULT),
m_is_sdtv(false),
@@ -182,7 +158,8 @@ CaptureWinGLEngine::~CaptureWinGLEngine()
clearShader();
}
-void CaptureWinGLEngine::setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv)
+void CaptureWinGLEngine::setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv)
{
bool is_rgb = true;
@@ -235,14 +212,18 @@ void CaptureWinGLEngine::setColorspace(unsigned colorspace, unsigned ycbcr_enc,
colorspace = V4L2_COLORSPACE_REC709;
break;
}
- if (m_colorspace == colorspace && m_ycbcr_enc == ycbcr_enc &&
- m_quantization == quantization && m_is_sdtv == is_sdtv)
+ if (m_colorspace == colorspace && m_xfer_func == xfer_func &&
+ m_ycbcr_enc == ycbcr_enc && m_quantization == quantization &&
+ m_is_sdtv == is_sdtv)
return;
m_colorspace = colorspace;
+ if (xfer_func == V4L2_XFER_FUNC_DEFAULT)
+ xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(colorspace);
if (ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(colorspace);
if (quantization == V4L2_QUANTIZATION_DEFAULT)
quantization = V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, colorspace, ycbcr_enc);
+ m_xfer_func = xfer_func;
m_ycbcr_enc = ycbcr_enc;
m_quantization = quantization;
m_is_sdtv = is_sdtv;
@@ -660,7 +641,7 @@ QString CaptureWinGLEngine::codeYUVNormalize()
{
switch (m_quantization) {
case V4L2_QUANTIZATION_FULL_RANGE:
- return "";
+ return "";
default:
return QString(" y = (255.0 / 219.0) * (y - (16.0 / 255.0));"
" u = (255.0 / 224.0) * u;"
@@ -696,11 +677,11 @@ QString CaptureWinGLEngine::codeYUV2RGB()
" float b = y + 1.8270 * u;"
);
case V4L2_YCBCR_ENC_BT2020:
- // BT.2020 luma coefficients
- return QString(" float r = y + 1.4719 * v;"
- " float g = y - 0.1646 * u - 0.5703 * v;"
- " float b = y + 1.8814 * u;"
- );
+ // BT.2020 luma coefficients
+ return QString(" float r = y + 1.4719 * v;"
+ " float g = y - 0.1646 * u - 0.5703 * v;"
+ " float b = y + 1.8814 * u;"
+ );
case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
// BT.2020_CONST_LUM luma coefficients
return QString(" float b = u <= 0.0 ? y + 1.9404 * u : y + 1.5816 * u;"
@@ -732,15 +713,15 @@ QString CaptureWinGLEngine::codeYUV2RGB()
// colorspace.
QString CaptureWinGLEngine::codeTransformToLinear()
{
- switch (m_colorspace) {
- case V4L2_COLORSPACE_SMPTE240M:
+ switch (m_xfer_func) {
+ case V4L2_XFER_FUNC_SMPTE240M:
// Old obsolete HDTV standard. Replaced by REC 709.
// This is the transfer function for SMPTE 240M
return QString(" r = (r < 0.0913) ? r / 4.0 : pow((r + 0.1115) / 1.1115, 1.0 / 0.45);"
" g = (g < 0.0913) ? g / 4.0 : pow((g + 0.1115) / 1.1115, 1.0 / 0.45);"
" b = (b < 0.0913) ? b / 4.0 : pow((b + 0.1115) / 1.1115, 1.0 / 0.45);"
);
- case V4L2_COLORSPACE_SRGB:
+ case V4L2_XFER_FUNC_SRGB:
// This is used for sRGB as specified by the IEC FDIS 61966-2-1 standard
return QString(" r = (r < -0.04045) ? -pow((-r + 0.055) / 1.055, 2.4) : "
" ((r <= 0.04045) ? r / 12.92 : pow((r + 0.055) / 1.055, 2.4));"
@@ -749,12 +730,13 @@ QString CaptureWinGLEngine::codeTransformToLinear()
" b = (b < -0.04045) ? -pow((-b + 0.055) / 1.055, 2.4) : "
" ((b <= 0.04045) ? b / 12.92 : pow((b + 0.055) / 1.055, 2.4));"
);
- case V4L2_COLORSPACE_ADOBERGB:
+ case V4L2_XFER_FUNC_ADOBERGB:
return QString(" r = pow(r, 2.19921875);"
" g = pow(g, 2.19921875);"
" b = pow(b, 2.19921875);");
- case V4L2_COLORSPACE_REC709:
- case V4L2_COLORSPACE_BT2020:
+ case V4L2_XFER_FUNC_NONE:
+ return "";
+ case V4L2_XFER_FUNC_709:
default:
// All others use the transfer function specified by REC 709
return QString(" r = (r <= -0.081) ? -pow((r - 0.099) / -1.099, 1.0 / 0.45) : "
@@ -819,7 +801,7 @@ QString CaptureWinGLEngine::codeColorspaceConversion()
QString CaptureWinGLEngine::codeTransformToNonLinear()
{
switch (m_displayColorspace) {
- case 0: // Keep as linear RGB
+ case V4L2_COLORSPACE_DEFAULT: // Keep as linear RGB
return "";
case V4L2_COLORSPACE_SMPTE240M:
@@ -1476,7 +1458,7 @@ void CaptureWinGLEngine::shader_RGB(__u32 format)
configureTexture(0);
manualTransform = m_quantization == V4L2_QUANTIZATION_LIM_RANGE ||
- m_colorspace != V4L2_COLORSPACE_SRGB ||
+ m_xfer_func != V4L2_XFER_FUNC_SRGB ||
format == V4L2_PIX_FMT_BGR666;
GLint internalFmt = manualTransform ? GL_RGBA8 : GL_SRGB8_ALPHA8;
@@ -1701,7 +1683,7 @@ void CaptureWinGLEngine::shader_Bayer(__u32 format)
configureTexture(0);
GLint internalFmt = (m_quantization == V4L2_QUANTIZATION_LIM_RANGE ||
- m_colorspace != V4L2_COLORSPACE_SRGB) ?
+ m_xfer_func != V4L2_XFER_FUNC_SRGB) ?
GL_LUMINANCE : GL_SLUMINANCE;
switch (format) {
@@ -1767,7 +1749,7 @@ void CaptureWinGLEngine::shader_Bayer(__u32 format)
if (m_quantization == V4L2_QUANTIZATION_LIM_RANGE)
codeTail += codeRGBNormalize();
if (m_quantization == V4L2_QUANTIZATION_LIM_RANGE ||
- m_colorspace != V4L2_COLORSPACE_SRGB)
+ m_xfer_func != V4L2_XFER_FUNC_SRGB)
codeTail += codeTransformToLinear();
codeTail += codeColorspaceConversion() +
diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h
index 49e16c91..53e58eb6 100644
--- a/utils/qv4l2/capture-win-gl.h
+++ b/utils/qv4l2/capture-win-gl.h
@@ -47,7 +47,8 @@ public:
unsigned char *data3);
bool hasNativeFormat(__u32 format);
void lockSize(QSize size);
- void setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv);
+ void setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv);
void setDisplayColorspace(unsigned colorspace);
void setField(unsigned field);
void setBlending(bool enable) { m_blending = enable; }
@@ -101,6 +102,7 @@ private:
int m_WCrop;
int m_HCrop;
unsigned m_colorspace;
+ unsigned m_xfer_func;
unsigned m_ycbcr_enc;
unsigned m_quantization;
bool m_is_sdtv;
@@ -132,7 +134,8 @@ public:
void stop();
bool hasNativeFormat(__u32 format);
static bool isSupported();
- void setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv);
+ void setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv);
void setField(unsigned field);
void setDisplayColorspace(unsigned colorspace);
void setBlending(bool enable);
diff --git a/utils/qv4l2/capture-win-qt.h b/utils/qv4l2/capture-win-qt.h
index f99245d1..55294cba 100644
--- a/utils/qv4l2/capture-win-qt.h
+++ b/utils/qv4l2/capture-win-qt.h
@@ -36,7 +36,8 @@ public:
void stop();
bool hasNativeFormat(__u32 format);
static bool isSupported() { return true; }
- void setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv) {}
+ void setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv) {}
void setField(unsigned field) {}
void setDisplayColorspace(unsigned colorspace) {}
void setBlending(bool enable) {}
diff --git a/utils/qv4l2/capture-win.cpp b/utils/qv4l2/capture-win.cpp
index 8e2bb361..1cf8e44d 100644
--- a/utils/qv4l2/capture-win.cpp
+++ b/utils/qv4l2/capture-win.cpp
@@ -351,6 +351,7 @@ void CaptureWin::customMenuRequested(QPoint pos)
menu->addAction(m_appWin->m_snapshotAct);
menu->addAction(m_appWin->m_showFramesAct);
menu->addMenu(m_appWin->m_overrideColorspaceMenu);
+ menu->addMenu(m_appWin->m_overrideXferFuncMenu);
menu->addMenu(m_appWin->m_overrideYCbCrEncMenu);
menu->addMenu(m_appWin->m_overrideQuantizationMenu);
menu->addMenu(m_appWin->m_displayColorspaceMenu);
diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h
index dda53933..fcf61b3d 100644
--- a/utils/qv4l2/capture-win.h
+++ b/utils/qv4l2/capture-win.h
@@ -69,7 +69,8 @@ public:
void setPixelAspectRatio(double ratio);
float getHorScaleFactor();
float getVertScaleFactor();
- virtual void setColorspace(unsigned colorspace, unsigned ycbcr_enc, unsigned quantization, bool is_sdtv) = 0;
+ virtual void setColorspace(unsigned colorspace, unsigned xfer_func,
+ unsigned ycbcr_enc, unsigned quantization, bool is_sdtv) = 0;
virtual void setField(unsigned field) = 0;
virtual void setDisplayColorspace(unsigned colorspace) = 0;
virtual void setBlending(bool enable) = 0;
diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp
index 7fe00425..535b5fd2 100644
--- a/utils/qv4l2/general-tab.cpp
+++ b/utils/qv4l2/general-tab.cpp
@@ -85,6 +85,7 @@ GeneralTab::GeneralTab(const QString &device, cv4l_fd *fd, int n, QWidget *paren
m_videoTimings(NULL),
m_pixelAspectRatio(NULL),
m_colorspace(NULL),
+ m_xferFunc(NULL),
m_ycbcrEnc(NULL),
m_quantRange(NULL),
m_cropping(NULL),
@@ -756,6 +757,18 @@ void GeneralTab::formatSection(v4l2_fmtdesc fmt)
addWidget(m_colorspace);
connect(m_colorspace, SIGNAL(activated(int)), SLOT(colorspaceChanged(int)));
+ m_xferFunc = new QComboBox(parentWidget());
+ m_xferFunc->addItem(m_isOutput ? "Default" : "Autodetect", QVariant(V4L2_XFER_FUNC_DEFAULT));
+ m_xferFunc->addItem("Rec. 709", QVariant(V4L2_XFER_FUNC_709));
+ m_xferFunc->addItem("sRGB", QVariant(V4L2_XFER_FUNC_SRGB));
+ m_xferFunc->addItem("Adobe RGB", QVariant(V4L2_XFER_FUNC_ADOBERGB));
+ m_xferFunc->addItem("SMPTE 240M", QVariant(V4L2_XFER_FUNC_SMPTE240M));
+ m_xferFunc->addItem("None", QVariant(V4L2_XFER_FUNC_NONE));
+
+ addLabel("Transfer Function");
+ addWidget(m_xferFunc);
+ connect(m_xferFunc, SIGNAL(activated(int)), SLOT(xferFuncChanged(int)));
+
m_ycbcrEnc = new QComboBox(parentWidget());
m_ycbcrEnc->addItem(m_isOutput ? "Default" : "Autodetect", QVariant(V4L2_YCBCR_ENC_DEFAULT));
m_ycbcrEnc->addItem("ITU-R 601", QVariant(V4L2_YCBCR_ENC_601));
@@ -1370,6 +1383,21 @@ void GeneralTab::colorspaceChanged(int idx)
g_fmt(fmt);
fmt.s_colorspace(m_colorspace->itemData(idx).toInt());
+ fmt.s_xfer_func(m_xferFunc->itemData(m_xferFunc->currentIndex()).toInt());
+ fmt.s_ycbcr_enc(m_ycbcrEnc->itemData(m_ycbcrEnc->currentIndex()).toInt());
+ fmt.s_quantization(m_quantRange->itemData(m_quantRange->currentIndex()).toInt());
+ if (try_fmt(fmt) == 0)
+ s_fmt(fmt);
+ updateVidFormat();
+}
+
+void GeneralTab::xferFuncChanged(int idx)
+{
+ cv4l_fmt fmt;
+
+ g_fmt(fmt);
+ fmt.s_colorspace(m_colorspace->itemData(m_colorspace->currentIndex()).toInt());
+ fmt.s_xfer_func(m_xferFunc->itemData(idx).toInt());
fmt.s_ycbcr_enc(m_ycbcrEnc->itemData(m_ycbcrEnc->currentIndex()).toInt());
fmt.s_quantization(m_quantRange->itemData(m_quantRange->currentIndex()).toInt());
if (try_fmt(fmt) == 0)
@@ -1383,6 +1411,7 @@ void GeneralTab::ycbcrEncChanged(int idx)
g_fmt(fmt);
fmt.s_colorspace(m_colorspace->itemData(m_colorspace->currentIndex()).toInt());
+ fmt.s_xfer_func(m_xferFunc->itemData(m_xferFunc->currentIndex()).toInt());
fmt.s_ycbcr_enc(m_ycbcrEnc->itemData(idx).toInt());
fmt.s_quantization(m_quantRange->itemData(m_quantRange->currentIndex()).toInt());
if (try_fmt(fmt) == 0)
@@ -1396,6 +1425,7 @@ void GeneralTab::quantRangeChanged(int idx)
g_fmt(fmt);
fmt.s_colorspace(m_colorspace->itemData(m_colorspace->currentIndex()).toInt());
+ fmt.s_xfer_func(m_xferFunc->itemData(m_xferFunc->currentIndex()).toInt());
fmt.s_ycbcr_enc(m_ycbcrEnc->itemData(m_ycbcrEnc->currentIndex()).toInt());
fmt.s_quantization(m_quantRange->itemData(idx).toInt());
if (try_fmt(fmt) == 0)
@@ -1406,7 +1436,9 @@ void GeneralTab::quantRangeChanged(int idx)
void GeneralTab::clearColorspace(cv4l_fmt &fmt)
{
if (m_colorspace->currentIndex() == 0)
- fmt.s_colorspace(0);
+ fmt.s_colorspace(V4L2_COLORSPACE_DEFAULT);
+ if (m_xferFunc->currentIndex() == 0)
+ fmt.s_xfer_func(V4L2_XFER_FUNC_DEFAULT);
if (m_ycbcrEnc->currentIndex() == 0)
fmt.s_ycbcr_enc(V4L2_YCBCR_ENC_DEFAULT);
if (m_quantRange->currentIndex() == 0)
@@ -1918,6 +1950,9 @@ void GeneralTab::updateColorspace()
idx = m_colorspace->findData(fmt.g_colorspace());
if (m_colorspace->currentIndex())
m_colorspace->setCurrentIndex(idx >= 0 ? idx : 0);
+ idx = m_xferFunc->findData(fmt.g_xfer_func());
+ if (m_xferFunc->currentIndex())
+ m_xferFunc->setCurrentIndex(idx >= 0 ? idx : 0);
idx = m_ycbcrEnc->findData(fmt.g_ycbcr_enc());
if (m_ycbcrEnc->currentIndex())
m_ycbcrEnc->setCurrentIndex(idx >= 0 ? idx : 0);
diff --git a/utils/qv4l2/general-tab.h b/utils/qv4l2/general-tab.h
index a69b8e93..55ffa180 100644
--- a/utils/qv4l2/general-tab.h
+++ b/utils/qv4l2/general-tab.h
@@ -88,6 +88,7 @@ public:
int getWidth();
unsigned getNumBuffers() const;
QComboBox *m_tpgComboColorspace;
+ QComboBox *m_tpgComboXferFunc;
QComboBox *m_tpgComboYCbCrEnc;
QComboBox *m_tpgComboQuantRange;
@@ -127,6 +128,7 @@ private slots:
void cropChanged();
void composeChanged();
void colorspaceChanged(int);
+ void xferFuncChanged(int);
void ycbcrEncChanged(int);
void quantRangeChanged(int);
@@ -336,6 +338,7 @@ private:
QComboBox *m_videoTimings;
QComboBox *m_pixelAspectRatio;
QComboBox *m_colorspace;
+ QComboBox *m_xferFunc;
QComboBox *m_ycbcrEnc;
QComboBox *m_quantRange;
QComboBox *m_cropping;
diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp
index 08eeeab3..e51a978d 100644
--- a/utils/qv4l2/qv4l2.cpp
+++ b/utils/qv4l2/qv4l2.cpp
@@ -94,6 +94,7 @@ ApplicationWindow::ApplicationWindow() :
m_makeSnapshot = false;
m_singleStep = false;
m_tpgColorspace = 0;
+ m_tpgXferFunc = 0;
m_tpgYCbCrEnc = 0;
m_tpgQuantRange = 0;
m_tpgLimRGBRange = NULL;
@@ -196,6 +197,18 @@ ApplicationWindow::ApplicationWindow() :
addSubMenuItem(grp, menu, "470 System BG", V4L2_COLORSPACE_470_SYSTEM_BG);
connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(overrideColorspaceChanged(QAction *)));
+ m_overrideXferFunc = -1;
+ menu = new QMenu("Override Transfer Function");
+ m_overrideXferFuncMenu = menu;
+ grp = new QActionGroup(menu);
+ addSubMenuItem(grp, menu, "No Override", -1)->setChecked(true);
+ addSubMenuItem(grp, menu, "Rec. 709", V4L2_XFER_FUNC_709);
+ addSubMenuItem(grp, menu, "sRGB", V4L2_XFER_FUNC_SRGB);
+ addSubMenuItem(grp, menu, "Adobe RGB", V4L2_XFER_FUNC_ADOBERGB);
+ addSubMenuItem(grp, menu, "SMPTE 240M", V4L2_XFER_FUNC_SMPTE240M);
+ addSubMenuItem(grp, menu, "None", V4L2_XFER_FUNC_NONE);
+ connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(overrideXferFuncChanged(QAction *)));
+
m_overrideYCbCrEnc = -1;
menu = new QMenu("Override Y'CbCr Encoding");
m_overrideYCbCrEncMenu = menu;
@@ -235,6 +248,7 @@ ApplicationWindow::ApplicationWindow() :
m_capMenu->addAction(m_capStartAct);
m_capMenu->addAction(m_capStepAct);
m_capMenu->addMenu(m_overrideColorspaceMenu);
+ m_capMenu->addMenu(m_overrideXferFuncMenu);
m_capMenu->addMenu(m_overrideYCbCrEncMenu);
m_capMenu->addMenu(m_overrideQuantizationMenu);
m_capMenu->addMenu(m_displayColorspaceMenu);
@@ -311,21 +325,22 @@ void ApplicationWindow::updateColorspace()
return;
int colorspace = m_overrideColorspace;
+ int xferFunc = m_overrideXferFunc;
int ycbcrEnc = m_overrideYCbCrEnc;
int quantRange = m_overrideQuantization;
cv4l_fmt fmt;
- // don't use the wrapped ioctl since it doesn't
- // update colorspace correctly.
- ::ioctl(g_fd(), VIDIOC_G_FMT, &fmt);
+ g_fmt(fmt);
if (colorspace == -1)
colorspace = fmt.g_colorspace();
+ if (xferFunc == -1)
+ xferFunc = fmt.g_xfer_func();
if (ycbcrEnc == -1)
ycbcrEnc = fmt.g_ycbcr_enc();
if (quantRange == -1)
quantRange = fmt.g_quantization();
- m_capture->setColorspace(colorspace, ycbcrEnc, quantRange,
+ m_capture->setColorspace(colorspace, xferFunc, ycbcrEnc, quantRange,
m_genTab ? m_genTab->isSDTV() : true);
}
@@ -335,6 +350,12 @@ void ApplicationWindow::overrideColorspaceChanged(QAction *a)
updateColorspace();
}
+void ApplicationWindow::overrideXferFuncChanged(QAction *a)
+{
+ m_overrideXferFunc = a->data().toInt();
+ updateColorspace();
+}
+
void ApplicationWindow::overrideYCbCrEncChanged(QAction *a)
{
m_overrideYCbCrEnc = a->data().toInt();
diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h
index e2e088bf..3ee490d0 100644
--- a/utils/qv4l2/qv4l2.h
+++ b/utils/qv4l2/qv4l2.h
@@ -127,6 +127,7 @@ private:
bool m_singleStep;
RenderMethod m_renderMethod;
int m_overrideColorspace;
+ int m_overrideXferFunc;
int m_overrideYCbCrEnc;
int m_overrideQuantization;
int m_displayColorspace;
@@ -164,6 +165,7 @@ private slots:
void clearBuffers();
void about();
void overrideColorspaceChanged(QAction *a);
+ void overrideXferFuncChanged(QAction *a);
void overrideYCbCrEncChanged(QAction *a);
void overrideQuantChanged(QAction *a);
void displayColorspaceChanged(QAction *a);
@@ -201,6 +203,7 @@ public:
QAction *m_snapshotAct;
QAction *m_showFramesAct;
QMenu *m_overrideColorspaceMenu;
+ QMenu *m_overrideXferFuncMenu;
QMenu *m_overrideYCbCrEncMenu;
QMenu *m_overrideQuantizationMenu;
QMenu *m_displayColorspaceMenu;
@@ -248,6 +251,7 @@ private:
bool m_tpgFieldAlt;
unsigned m_tpgSizeImage;
QComboBox *m_tpgColorspace;
+ QComboBox *m_tpgXferFunc;
QComboBox *m_tpgYCbCrEnc;
QComboBox *m_tpgQuantRange;
bool m_useTpg;
diff --git a/utils/qv4l2/tpg-tab.cpp b/utils/qv4l2/tpg-tab.cpp
index b2530755..140c2e44 100644
--- a/utils/qv4l2/tpg-tab.cpp
+++ b/utils/qv4l2/tpg-tab.cpp
@@ -163,6 +163,17 @@ void ApplicationWindow::addTpgTab(int m_winWidth)
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("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));
@@ -326,6 +337,7 @@ 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);
@@ -334,11 +346,14 @@ void ApplicationWindow::tpgColorspaceChanged()
colorspace = fmt.g_colorspace();
if (colorspace == 0)
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);
}
diff --git a/utils/v4l2-compliance/cv4l-helpers.h b/utils/v4l2-compliance/cv4l-helpers.h
index 06c72d96..2fee6d75 100644
--- a/utils/v4l2-compliance/cv4l-helpers.h
+++ b/utils/v4l2-compliance/cv4l-helpers.h
@@ -665,6 +665,8 @@ public:
void s_pixelformat(__u32 pixelformat) { v4l_format_s_pixelformat(this, pixelformat); }
unsigned g_colorspace() const { return v4l_format_g_colorspace(this); }
void s_colorspace(unsigned colorspace) { v4l_format_s_colorspace(this, colorspace); }
+ unsigned g_xfer_func() const { return v4l_format_g_xfer_func(this); }
+ void s_xfer_func(unsigned xfer_func) { v4l_format_s_xfer_func(this, xfer_func); }
unsigned g_ycbcr_enc() const { return v4l_format_g_ycbcr_enc(this); }
void s_ycbcr_enc(unsigned ycbcr_enc) { v4l_format_s_ycbcr_enc(this, ycbcr_enc); }
unsigned g_quantization() const { return v4l_format_g_quantization(this); }
diff --git a/utils/v4l2-compliance/v4l-helpers.h b/utils/v4l2-compliance/v4l-helpers.h
index a36ca143..44395c0a 100644
--- a/utils/v4l2-compliance/v4l-helpers.h
+++ b/utils/v4l2-compliance/v4l-helpers.h
@@ -649,6 +649,36 @@ v4l_format_g_colorspace(const struct v4l2_format *fmt)
}
}
+static inline void v4l_format_s_xfer_func(struct v4l2_format *fmt,
+ unsigned xfer_func)
+{
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ fmt->fmt.pix.xfer_func = xfer_func;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ fmt->fmt.pix_mp.xfer_func = xfer_func;
+ break;
+ }
+}
+
+static inline unsigned
+v4l_format_g_xfer_func(const struct v4l2_format *fmt)
+{
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ return fmt->fmt.pix.xfer_func;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return fmt->fmt.pix_mp.xfer_func;
+ default:
+ return 0;
+ }
+}
+
static inline void v4l_format_s_ycbcr_enc(struct v4l2_format *fmt,
unsigned ycbcr_enc)
{

Privacy Policy