diff options
author | Hans Verkuil <hansverk@cisco.com> | 2018-08-21 16:21:21 +0200 |
---|---|---|
committer | Hans Verkuil <hansverk@cisco.com> | 2018-08-21 16:21:21 +0200 |
commit | 58ff042ceb22f5a7865bb4c195fa231284cac417 (patch) | |
tree | 3e7b9e91d0ee4d0bb3d7a1416bb34f4541d4911a | |
parent | 015ca7524748fa7cef296102c68b631b078b63c6 (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.cpp | 184 | ||||
-rw-r--r-- | utils/qvidcap/capture-win-gl.h | 4 | ||||
-rw-r--r-- | utils/qvidcap/qvidcap.1.in | 7 | ||||
-rw-r--r-- | utils/qvidcap/qvidcap.cpp | 7 |
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); |