aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hansverk@cisco.com>2018-08-21 16:21:21 +0200
committerHans Verkuil <hansverk@cisco.com>2018-08-21 16:21:21 +0200
commit58ff042ceb22f5a7865bb4c195fa231284cac417 (patch)
tree3e7b9e91d0ee4d0bb3d7a1416bb34f4541d4911a
parent015ca7524748fa7cef296102c68b631b078b63c6 (diff)
qvidcap: add histogram supporthisto
Press 'S' to see histogram information of the current frame. Signed-off-by: Hans Verkuil <hansverk@cisco.com>
-rw-r--r--utils/qvidcap/capture-win-gl.cpp184
-rw-r--r--utils/qvidcap/capture-win-gl.h4
-rw-r--r--utils/qvidcap/qvidcap.1.in7
-rw-r--r--utils/qvidcap/qvidcap.cpp7
4 files changed, 202 insertions, 0 deletions
diff --git a/utils/qvidcap/capture-win-gl.cpp b/utils/qvidcap/capture-win-gl.cpp
index 4ef7d276..ce206f77 100644
--- a/utils/qvidcap/capture-win-gl.cpp
+++ b/utils/qvidcap/capture-win-gl.cpp
@@ -195,6 +195,7 @@ CaptureGLWin::CaptureGLWin(QScrollArea *sa, QWidget *parent) :
m_singleStep(false),
m_singleStepStart(0),
m_singleStepNext(false),
+ m_showHistogram(false),
m_screenTextureCount(0),
m_program(0),
m_curSize(),
@@ -627,6 +628,9 @@ void CaptureGLWin::keyPressEvent(QKeyEvent *event)
checkSubMenuItem(m_quantMenu, m_overrideQuantization);
updateShader();
return;
+ case Qt::Key_S:
+ m_showHistogram = true;
+ return;
case Qt::Key_X:
cycleMenu(m_overrideXferFunc, m_origXferFunc,
xfer_funcs, hasShift, hasCtrl);
@@ -1456,6 +1460,181 @@ void CaptureGLWin::tpgUpdateFrame()
m_updateShader = true;
}
+static unsigned components[4][256];
+
+static void countPlane(unsigned plane, const __u8 *p, unsigned size, unsigned step)
+{
+ for (unsigned i = 0; i < size; i += step, p += step)
+ components[plane][*p]++;
+}
+
+void CaptureGLWin::showHistogram()
+{
+ const __u8 *p = m_curData[0];
+ unsigned size = m_curSize[0];
+ unsigned halfsize = size / 2;
+ bool has_alpha = false;
+ unsigned min_cnt = m_v4l_fmt.g_width() * m_v4l_fmt.g_height() * m_histThreshold / 100;
+
+ memset(components, 0, sizeof(components));
+
+ switch (m_v4l_fmt.g_pixelformat()) {
+ case V4L2_PIX_FMT_YUYV:
+ countPlane(0, p, size, 2);
+ countPlane(1, p + 1, size - 1, 4);
+ countPlane(2, p + 3, size - 3, 4);
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ countPlane(0, p, size, 2);
+ countPlane(1, p + 3, size - 3, 4);
+ countPlane(2, p + 1, size - 1, 4);
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ countPlane(1, p, size, 4);
+ countPlane(0, p + 1, size - 1, 2);
+ countPlane(2, p + 2, size - 2, 4);
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ countPlane(2, p, size, 4);
+ countPlane(0, p + 1, size - 1, 2);
+ countPlane(1, p + 2, size - 2, 4);
+ break;
+
+ case V4L2_PIX_FMT_NV16:
+ countPlane(0, p, halfsize, 1);
+ p += halfsize;
+ countPlane(1, p, halfsize, 2);
+ countPlane(2, p + 1, halfsize - 1, 2);
+ break;
+ case V4L2_PIX_FMT_NV61:
+ countPlane(0, p, halfsize, 1);
+ p += halfsize;
+ countPlane(2, p, halfsize, 2);
+ countPlane(1, p + 1, halfsize - 1, 2);
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV16M:
+ countPlane(0, p, size, 1);
+ countPlane(1, m_curData[1], m_curSize[1], 2);
+ countPlane(2, m_curData[1] + 1, m_curSize[1] - 1, 2);
+ break;
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61M:
+ countPlane(0, p, size, 1);
+ countPlane(2, m_curData[1], m_curSize[1], 2);
+ countPlane(1, m_curData[1] + 1, m_curSize[1] - 1, 2);
+ break;
+
+ case V4L2_PIX_FMT_NV12:
+ countPlane(0, p, size / 3 * 2, 1);
+ p += size / 3 * 2;
+ size /= 3;
+ countPlane(1, p, size, 2);
+ countPlane(2, p + 1, size - 1, 2);
+ break;
+ case V4L2_PIX_FMT_NV21:
+ countPlane(0, p, size / 3 * 2, 1);
+ p += size / 3 * 2;
+ size /= 3;
+ countPlane(2, p, size, 2);
+ countPlane(1, p + 1, size - 1, 2);
+ break;
+
+ case V4L2_PIX_FMT_NV24:
+ countPlane(0, p, size / 3, 1);
+ p += size / 3;
+ size -= size / 3;
+ countPlane(1, p, size, 2);
+ countPlane(2, p + 1, size - 1, 2);
+ break;
+ case V4L2_PIX_FMT_NV42:
+ countPlane(0, p, size / 3, 1);
+ p += size / 3;
+ size -= size / 3;
+ countPlane(2, p, size, 2);
+ countPlane(1, p + 1, size - 1, 2);
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_HSV24:
+ countPlane(0, p, size, 3);
+ countPlane(1, p + 1, size - 1, 3);
+ countPlane(2, p + 2, size - 2, 3);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ countPlane(2, p, size, 3);
+ countPlane(1, p + 1, size - 1, 3);
+ countPlane(0, p + 2, size - 2, 3);
+ break;
+ case V4L2_PIX_FMT_ARGB32:
+ countPlane(3, p, size, 4);
+ has_alpha = true;
+ /* fall-through */
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_XRGB32:
+ case V4L2_PIX_FMT_HSV32:
+ countPlane(0, p + 1, size - 1, 4);
+ countPlane(1, p + 2, size - 2, 4);
+ countPlane(2, p + 3, size - 3, 4);
+ break;
+ case V4L2_PIX_FMT_ABGR32:
+ countPlane(3, p + 3, size - 3, 4);
+ has_alpha = true;
+ /* fall-through */
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_XBGR32:
+ countPlane(0, p + 2, size - 2, 4);
+ countPlane(1, p + 1, size - 1, 4);
+ countPlane(2, p, size, 4);
+ break;
+ default:
+ fprintf(stderr, "Histogram is not supported for format '%s' %s\n",
+ fcc2s(m_v4l_fmt.g_pixelformat()).c_str(),
+ pixfmt2s(m_v4l_fmt.g_pixelformat()).c_str());
+ return;
+ }
+
+ switch (m_v4l_fmt.g_pixelformat()) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61M:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ printf("\n Y U V");
+ break;
+
+ case V4L2_PIX_FMT_HSV24:
+ case V4L2_PIX_FMT_HSV32:
+ printf("\n H S V");
+ break;
+ default:
+ printf("\n R G B");
+ break;
+ }
+ if (has_alpha)
+ printf(" A");
+ printf("\n");
+ for (unsigned i = 0; i < 256; i++) {
+ if (components[0][i] <= min_cnt && components[1][i] <= min_cnt &&
+ components[2][i] <= min_cnt && components[3][i] <= min_cnt)
+ continue;
+ printf("%3d/0x%02x: %9u %9u %9u",
+ i, i, components[0][i], components[1][i], components[2][i]);
+ if (has_alpha)
+ printf(" %9u", components[3][i]);
+ printf("\n");
+ }
+}
+
void CaptureGLWin::initializeGL()
{
initializeOpenGLFunctions();
@@ -1544,6 +1723,11 @@ void CaptureGLWin::paintGL()
if (!supportedFmt(m_v4l_fmt.g_pixelformat()))
return;
+ if (m_showHistogram) {
+ m_showHistogram = false;
+ showHistogram();
+ }
+
switch (m_v4l_fmt.g_pixelformat()) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
diff --git a/utils/qvidcap/capture-win-gl.h b/utils/qvidcap/capture-win-gl.h
index d446c1ff..54aea966 100644
--- a/utils/qvidcap/capture-win-gl.h
+++ b/utils/qvidcap/capture-win-gl.h
@@ -83,6 +83,7 @@ public:
void setOverrideHeight(__u32 h);
void setCount(unsigned cnt) { m_cnt = cnt; }
void setReportTimings(bool report) { m_reportTimings = report; }
+ void setHistThreshold(unsigned threshold) { m_histThreshold = threshold; }
void setVerbose(bool verbose) { m_verbose = verbose; }
void setOverridePixelFormat(__u32 fmt) { m_overridePixelFormat = fmt; }
void setOverrideField(__u32 field) { m_overrideField = field; }
@@ -136,6 +137,7 @@ private:
void configureTexture(size_t idx);
void initImageFormat();
void updateOrigValues();
+ void showHistogram();
void updateShader();
void changeShader();
@@ -175,6 +177,7 @@ private:
unsigned m_imageSize;
bool m_verbose;
bool m_reportTimings;
+ unsigned m_histThreshold;
bool m_is_sdtv;
v4l2_std_id m_std;
bool m_is_rgb;
@@ -209,6 +212,7 @@ private:
bool m_singleStep;
unsigned m_singleStepStart;
bool m_singleStepNext;
+ bool m_showHistogram;
QTimer *m_timer;
int m_screenTextureCount;
diff --git a/utils/qvidcap/qvidcap.1.in b/utils/qvidcap/qvidcap.1.in
index bc1d1113..2201a6a8 100644
--- a/utils/qvidcap/qvidcap.1.in
+++ b/utils/qvidcap/qvidcap.1.in
@@ -66,6 +66,10 @@ Be more verbose
\fB\-R\fR, \fB\-\-raw\fR
Open device in raw mode
.TP
+\fB\-\-hist\-threshold\fR=\fI<perc>\fR
+Histogram threshold: only show component values when used
+in <perc> percent of all pixels (default=0).
+.TP
\fB\--opengl\fR
Force openGL to display the video
.TP
@@ -193,6 +197,9 @@ Cycle forwards through all the supported quantization ranges.
With Shift pressed: cycle backwards.
With Ctrl pressed: restore the original quantization range.
.TP
+\fIS\fR
+Show histogram statistics.
+.TP
\fIRight-Click\fR
Open menu.
.TP
diff --git a/utils/qvidcap/qvidcap.cpp b/utils/qvidcap/qvidcap.cpp
index d29b4405..bf3a2009 100644
--- a/utils/qvidcap/qvidcap.cpp
+++ b/utils/qvidcap/qvidcap.cpp
@@ -64,6 +64,8 @@ static void usage()
" -t, --timings report frame render timings\n"
" -v, --verbose be more verbose\n"
" -R, --raw open device in raw mode\n"
+ " --hist-threshold=<perc> histogram threshold: only show component values when used\n"
+ " in <perc> percent of all pixels (default=0)\n"
"\n"
" --opengl force openGL to display the video\n"
" --opengles force openGL ES to display the video\n"
@@ -437,6 +439,7 @@ int main(int argc, char **argv)
unsigned v4l2_bufs = 4;
bool single_step = false;
unsigned single_step_start = 1;
+ unsigned hist_threshold = 0;
int port = 0;
bool info_option = false;
bool report_timings = false;
@@ -648,6 +651,9 @@ int main(int argc, char **argv)
} else if (isOptArg(args[i], "--buffers", "-b")) {
if (!processOption(args, i, v4l2_bufs))
return 0;
+ } else if (isOptArg(args[i], "--hist-threshold")) {
+ if (!processOption(args, i, hist_threshold))
+ return 0;
} else if (isOption(args[i], "--single-step", "-s")) {
single_step = true;
single_step_start = 1;
@@ -737,6 +743,7 @@ int main(int argc, char **argv)
win.setFps(fps);
win.setFormat(format);
win.setReportTimings(report_timings);
+ win.setHistThreshold(hist_threshold);
win.setCount(test ? test : cnt);
if (mode == AppModeTest) {
win.setModeTest(test);

Privacy Policy