This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/v4l-utils.git tree:
Subject: qv4l2: add support for V4L2_PIX_FMT_NV16M/61M Author: Hans Verkuil <[email protected]> Date: Mon Mar 31 10:44:59 2014 +0200 Add support for the NV16M and NV61M planar YUV 4:2:2 formats. This is not the prettiest code. Once the (c)v4l-helpers.h are more mature (particularly w.r.t. the v4l2-format handling) the qv4l2 code will switch to that and that should greatly improve the code. For now though it is good to have support for at least one multiplanar format in qv4l2 to help testing the multiplanar API. Signed-off-by: Hans Verkuil <[email protected]> utils/qv4l2/capture-win-gl.cpp | 162 ++++++++++++++++++++++++++++++++++------ utils/qv4l2/capture-win-gl.h | 9 ++- utils/qv4l2/capture-win-qt.cpp | 3 +- utils/qv4l2/capture-win-qt.h | 2 +- utils/qv4l2/capture-win.h | 2 +- utils/qv4l2/general-tab.cpp | 137 +++++++++++++++++++++++---------- utils/qv4l2/general-tab.h | 14 +--- utils/qv4l2/qv4l2.cpp | 154 +++++++++++++++++++++++++++++-------- utils/qv4l2/qv4l2.h | 5 +- utils/qv4l2/v4l2-api.cpp | 62 +++++++++++---- utils/qv4l2/v4l2-api.h | 24 ++----- 11 files changed, 423 insertions(+), 151 deletions(-) --- http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=c66aba761741811d1f2bce6d2ad0be516d61172a diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp index 7127298..5df1c70 100644 --- a/utils/qv4l2/capture-win-gl.cpp +++ b/utils/qv4l2/capture-win-gl.cpp @@ -52,10 +52,11 @@ void CaptureWinGL::resizeEvent(QResizeEvent *event) event->accept(); } -void CaptureWinGL::setFrame(int width, int height, __u32 format, unsigned char *data, const QString &info) +void CaptureWinGL::setFrame(int width, int height, __u32 format, + unsigned char *data, unsigned char *data2, const QString &info) { #ifdef HAVE_QTGL - m_videoSurface.setFrame(width, height, format, data); + m_videoSurface.setFrame(width, height, format, data, data2); #endif m_information.setText(info); } @@ -107,6 +108,7 @@ void CaptureWinGLEngine::stop() // Setting the m_frameData to NULL stops OpenGL // from updating frames on repaint m_frameData = NULL; + m_frameData2 = NULL; } void CaptureWinGLEngine::initializeGL() @@ -136,7 +138,7 @@ void CaptureWinGLEngine::resizeGL(int width, int height) glViewport(0, 0, width, height); } -void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data) +void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data, unsigned char *data2) { if (format != m_frameFormat || width != m_frameWidth || height != m_frameHeight) { m_formatChange = true; @@ -146,6 +148,7 @@ void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned } m_frameData = data; + m_frameData2 = data2 ? data2 : data; updateGL(); } @@ -175,6 +178,8 @@ bool CaptureWinGLEngine::hasNativeFormat(__u32 format) { V4L2_PIX_FMT_VYUY, true }, { V4L2_PIX_FMT_YVU420, true }, { V4L2_PIX_FMT_YUV420, true }, + { V4L2_PIX_FMT_NV16M, true }, + { V4L2_PIX_FMT_NV61M, true }, { 0, false } }; bool haveShaders = m_glfunction.hasOpenGLFeature(QGLFunctions::Shaders); @@ -206,6 +211,11 @@ void CaptureWinGLEngine::changeShader() shader_YUY2(m_frameFormat); break; + case V4L2_PIX_FMT_NV16M: + case V4L2_PIX_FMT_NV61M: + shader_NV16M(m_frameFormat); + break; + case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: shader_YUV(); @@ -303,6 +313,11 @@ void CaptureWinGLEngine::paintGL() render_YUY2(); break; + case V4L2_PIX_FMT_NV16M: + case V4L2_PIX_FMT_NV61M: + render_NV16M(m_frameFormat); + break; + case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: render_YUV(m_frameFormat); @@ -440,39 +455,107 @@ void CaptureWinGLEngine::render_YUV(__u32 format) checkError("YUV paint vtex"); } -void CaptureWinGLEngine::shader_BGR() +QString CaptureWinGLEngine::shader_NV16M_invariant(__u32 format) { - m_screenTextureCount = 1; + switch (format) { + case V4L2_PIX_FMT_NV16M: + return QString("if (mod(xcoord, 2.0) == 0.0) {" + " u = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;" + " v = texture2D(uvtex, vec2(pixelx + texl_w, pixely)).r - 0.5;" + "} else {" + " u = texture2D(uvtex, vec2(pixelx - texl_w, pixely)).r - 0.5;" + " v = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;" + "}" + ); + + case V4L2_PIX_FMT_NV61M: + return QString("if (mod(xcoord, 2.0) == 0.0) {" + " u = texture2D(uvtex, vec2(pixelx + texl_w, pixely)).r - 0.5;" + " v = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;" + "} else {" + " u = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;" + " v = texture2D(uvtex, vec2(pixelx - texl_w, pixely)).r - 0.5;" + "}" + ); + + default: + return QString(); + } +} + +void CaptureWinGLEngine::shader_NV16M(__u32 format) +{ + m_screenTextureCount = 2; glGenTextures(m_screenTextureCount, m_screenTexture); + + glActiveTexture(GL_TEXTURE0); configureTexture(0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_frameWidth, m_frameHeight, 0, - GL_RGB, GL_UNSIGNED_BYTE, NULL); - checkError("BGR shader"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_frameWidth, m_frameHeight, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); + checkError("NV16M shader texture 0"); - bool src_c = m_shaderProgram.addShaderFromSourceCode( - QGLShader::Fragment, - "uniform sampler2D tex;" - "void main()" - "{" - " vec4 color = texture2D(tex, gl_TexCoord[0].xy);" - " gl_FragColor = vec4(color.b, color.g, color.r, 1.0);" - "}" + glActiveTexture(GL_TEXTURE1); + configureTexture(1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_frameWidth, m_frameHeight, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); + checkError("NV16M shader texture 1"); + + QString codeHead = QString("uniform sampler2D ytex;" + "uniform sampler2D uvtex;" + "uniform float texl_w;" + "uniform float tex_w;" + "void main()" + "{" + " vec2 xy = vec2(gl_TexCoord[0].xy);" + " float y = 1.1640625 * (texture2D(ytex, xy).r - 0.0625);" + " float u, v;" + " float pixelx = gl_TexCoord[0].x;" + " float pixely = gl_TexCoord[0].y;" + " float xcoord = floor(pixelx * tex_w);" + ); + + QString codeBody = shader_NV16M_invariant(format); + + QString codeTail = QString(" float r = y + 1.5958 * v;" + " float g = y - 0.39173 * u - 0.81290 * v;" + " float b = y + 2.017 * u;" + " gl_FragColor = vec4(r, g, b, 1.0);" + "}" + ); + + bool src_ok = m_shaderProgram.addShaderFromSourceCode( + QGLShader::Fragment, QString("%1%2%3").arg(codeHead, codeBody, codeTail) ); - if (!src_c) - fprintf(stderr, "OpenGL Error: BGR shader compilation failed.\n"); + + if (!src_ok) + fprintf(stderr, "OpenGL Error: NV16M shader compilation failed.\n"); m_shaderProgram.bind(); } -void CaptureWinGLEngine::render_BGR() +void CaptureWinGLEngine::render_NV16M(__u32 format) { + int idx; + idx = glGetUniformLocation(m_shaderProgram.programId(), "texl_w"); // Texel width + glUniform1f(idx, 1.0 / m_frameWidth); + idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_w"); // Texture width + glUniform1f(idx, m_frameWidth); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]); - GLint Y = m_glfunction.glGetUniformLocation(m_shaderProgram.programId(), "tex"); + GLint Y = m_glfunction.glGetUniformLocation(m_shaderProgram.programId(), "ytex"); glUniform1i(Y, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, - GL_RGB, GL_UNSIGNED_BYTE, m_frameData); - checkError("BGR paint"); + GL_LUMINANCE, GL_UNSIGNED_BYTE, m_frameData); + checkError("NV16M paint ytex"); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_screenTexture[1]); + GLint UV = m_glfunction.glGetUniformLocation(m_shaderProgram.programId(), "uvtex"); + glUniform1i(UV, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, + GL_LUMINANCE, GL_UNSIGNED_BYTE, m_frameData2); + checkError("NV16M paint"); } QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format) @@ -587,4 +670,39 @@ void CaptureWinGLEngine::render_YUY2() GL_RGBA, GL_UNSIGNED_BYTE, m_frameData); checkError("YUY2 paint"); } + +void CaptureWinGLEngine::shader_BGR() +{ + m_screenTextureCount = 1; + glGenTextures(m_screenTextureCount, m_screenTexture); + configureTexture(0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_frameWidth, m_frameHeight, 0, + GL_RGB, GL_UNSIGNED_BYTE, NULL); + checkError("BGR shader"); + + bool src_c = m_shaderProgram.addShaderFromSourceCode( + QGLShader::Fragment, + "uniform sampler2D tex;" + "void main()" + "{" + " vec4 color = texture2D(tex, gl_TexCoord[0].xy);" + " gl_FragColor = vec4(color.b, color.g, color.r, 1.0);" + "}" + ); + if (!src_c) + fprintf(stderr, "OpenGL Error: BGR shader compilation failed.\n"); + + m_shaderProgram.bind(); +} + +void CaptureWinGLEngine::render_BGR() +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]); + GLint Y = m_glfunction.glGetUniformLocation(m_shaderProgram.programId(), "tex"); + glUniform1i(Y, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight, + GL_RGB, GL_UNSIGNED_BYTE, m_frameData); + checkError("BGR paint"); +} #endif diff --git a/utils/qv4l2/capture-win-gl.h b/utils/qv4l2/capture-win-gl.h index 5a7fb3d..ddc8402 100644 --- a/utils/qv4l2/capture-win-gl.h +++ b/utils/qv4l2/capture-win-gl.h @@ -42,7 +42,8 @@ public: ~CaptureWinGLEngine(); void stop(); - void setFrame(int width, int height, __u32 format, unsigned char *data); + void setFrame(int width, int height, __u32 format, + unsigned char *data, unsigned char *data2); bool hasNativeFormat(__u32 format); void setSize(int width, int height); @@ -54,6 +55,8 @@ protected: private: // Colorspace conversion shaders void shader_YUV(); + void shader_NV16M(__u32 format); + QString shader_NV16M_invariant(__u32 format); void shader_BGR(); void shader_YUY2(__u32 format); QString shader_YUY2_invariant(__u32 format); @@ -62,6 +65,7 @@ private: void render_BGR(); void render_YUY2(); void render_YUV(__u32 format); + void render_NV16M(__u32 format); void clearShader(); void changeShader(); @@ -77,6 +81,7 @@ private: GLuint m_screenTexture[MAX_TEXTURES_NEEDED]; QGLFunctions m_glfunction; unsigned char *m_frameData; + unsigned char *m_frameData2; QGLShaderProgram m_shaderProgram; }; @@ -89,7 +94,7 @@ public: ~CaptureWinGL(); void setFrame(int width, int height, __u32 format, - unsigned char *data, const QString &info); + unsigned char *data, unsigned char *data2, const QString &info); void stop(); bool hasNativeFormat(__u32 format); static bool isSupported(); diff --git a/utils/qv4l2/capture-win-qt.cpp b/utils/qv4l2/capture-win-qt.cpp index 19bfbc0..e4ceb0e 100644 --- a/utils/qv4l2/capture-win-qt.cpp +++ b/utils/qv4l2/capture-win-qt.cpp @@ -69,7 +69,8 @@ void CaptureWinQt::resizeEvent(QResizeEvent *event) paintFrame(); } -void CaptureWinQt::setFrame(int width, int height, __u32 format, unsigned char *data, const QString &info) +void CaptureWinQt::setFrame(int width, int height, __u32 format, + unsigned char *data, unsigned char *data2, const QString &info) { m_data = data; diff --git a/utils/qv4l2/capture-win-qt.h b/utils/qv4l2/capture-win-qt.h index b5de499..e0de583 100644 --- a/utils/qv4l2/capture-win-qt.h +++ b/utils/qv4l2/capture-win-qt.h @@ -43,7 +43,7 @@ public: ~CaptureWinQt(); void setFrame(int width, int height, __u32 format, - unsigned char *data, const QString &info); + unsigned char *data, unsigned char *data2, const QString &info); void stop(); bool hasNativeFormat(__u32 format); diff --git a/utils/qv4l2/capture-win.h b/utils/qv4l2/capture-win.h index d6f5d21..4e34464 100644 --- a/utils/qv4l2/capture-win.h +++ b/utils/qv4l2/capture-win.h @@ -65,7 +65,7 @@ public: * @param info A string containing capture information. */ virtual void setFrame(int width, int height, __u32 format, - unsigned char *data, const QString &info) = 0; + unsigned char *data, unsigned char *data2, const QString &info) = 0; /** * @brief Called when the capture stream is stopped. diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 034b434..38a91c2 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -52,6 +52,7 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) m_isVbi(false), m_freqFac(16), m_freqRfFac(16), + m_isPlanar(false), m_videoInput(NULL), m_videoOutput(NULL), m_audioInput(NULL), @@ -121,6 +122,10 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) m_isVbi = caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE); m_isSDR = m_isRadio = caps() & V4L2_CAP_SDR_CAPTURE; } + if (m_querycap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + m_isPlanar = true; + m_buftype = (isPlanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE); if (hasAlsaAudio()) { m_audioInDevice = new QComboBox(parent); @@ -141,7 +146,7 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) setAudioDeviceBufferSize(75); } else { v4l2_fract fract; - if (!v4l2::get_interval(fract)) { + if (!v4l2::get_interval(m_buftype, fract)) { // Default values are for 30 FPS fract.numerator = 33; fract.denominator = 1000; @@ -433,7 +438,7 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) addLabel("Capture Image Formats"); m_vidCapFormats = new QComboBox(parent); m_vidCapFormats->setMinimumContentsLength(20); - if (enum_fmt_cap(fmt, true)) { + if (enum_fmt_cap(fmt, m_buftype, true)) { do { QString s(pixfmt2s(fmt.pixelformat) + " ("); @@ -441,7 +446,7 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) m_vidCapFormats->addItem(s + "Emulated)"); else m_vidCapFormats->addItem(s + (const char *)fmt.description + ")"); - } while (enum_fmt_cap(fmt)); + } while (enum_fmt_cap(fmt, m_buftype)); } addWidget(m_vidCapFormats); connect(m_vidCapFormats, SIGNAL(activated(int)), SLOT(vidCapFormatChanged(int))); @@ -495,7 +500,9 @@ capture_method: addLabel("Capture Method"); m_capMethods = new QComboBox(parent); m_buftype = isSlicedVbi() ? V4L2_BUF_TYPE_SLICED_VBI_CAPTURE : - (isVbi() ? V4L2_BUF_TYPE_VBI_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE); + (isVbi() ? V4L2_BUF_TYPE_VBI_CAPTURE : + (isPlanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE)); if (caps() & V4L2_CAP_STREAMING) { v4l2_requestbuffers reqbuf; @@ -890,12 +897,15 @@ void GeneralTab::vidCapFormatChanged(int idx) { v4l2_fmtdesc desc; - enum_fmt_cap(desc, true, idx); + enum_fmt_cap(desc, m_buftype, true, idx); v4l2_format fmt; - g_fmt_cap(fmt); - fmt.fmt.pix.pixelformat = desc.pixelformat; + g_fmt_cap(m_buftype, fmt); + if (isPlanar()) + fmt.fmt.pix_mp.pixelformat = desc.pixelformat; + else + fmt.fmt.pix.pixelformat = desc.pixelformat; if (try_fmt(fmt)) s_fmt(fmt); @@ -934,10 +944,13 @@ void GeneralTab::vidCapFieldChanged(int idx) { v4l2_format fmt; - g_fmt_cap(fmt); + g_fmt_cap(m_buftype, fmt); for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { if (m_vidCapFields->currentText() == QString(field2s(f))) { - fmt.fmt.pix.field = f; + if (isPlanar()) + fmt.fmt.pix_mp.field = f; + else + fmt.fmt.pix.field = f; s_fmt(fmt); break; } @@ -952,8 +965,11 @@ void GeneralTab::frameWidthChanged() if (!m_frameWidth->isEnabled()) return; - g_fmt_cap(fmt); - fmt.fmt.pix.width = val; + g_fmt_cap(m_buftype, fmt); + if (isPlanar()) + fmt.fmt.pix_mp.width = val; + else + fmt.fmt.pix.width = val; if (try_fmt(fmt)) s_fmt(fmt); @@ -967,8 +983,11 @@ void GeneralTab::frameHeightChanged() if (!m_frameHeight->isEnabled()) return; - g_fmt_cap(fmt); - fmt.fmt.pix.height = val; + g_fmt_cap(m_buftype, fmt); + if (isPlanar()) + fmt.fmt.pix_mp.height = val; + else + fmt.fmt.pix.height = val; if (try_fmt(fmt)) s_fmt(fmt); @@ -982,9 +1001,14 @@ void GeneralTab::frameSizeChanged(int idx) if (enum_framesizes(frmsize, m_pixelformat, idx)) { v4l2_format fmt; - g_fmt_cap(fmt); - fmt.fmt.pix.width = frmsize.discrete.width; - fmt.fmt.pix.height = frmsize.discrete.height; + g_fmt_cap(m_buftype, fmt); + if (isPlanar()) { + fmt.fmt.pix_mp.width = frmsize.discrete.width; + fmt.fmt.pix_mp.height = frmsize.discrete.height; + } else { + fmt.fmt.pix.width = frmsize.discrete.width; + fmt.fmt.pix.height = frmsize.discrete.height; + } if (try_fmt(fmt)) s_fmt(fmt); } @@ -997,7 +1021,7 @@ void GeneralTab::frameIntervalChanged(int idx) if (enum_frameintervals(frmival, m_pixelformat, m_width, m_height, idx) && frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - if (set_interval(frmival.discrete)) + if (set_interval(m_buftype, frmival.discrete)) m_interval = frmival.discrete; } } @@ -1020,7 +1044,9 @@ void GeneralTab::vidOutFormatChanged(int idx) void GeneralTab::vbiMethodsChanged(int idx) { m_buftype = isSlicedVbi() ? V4L2_BUF_TYPE_SLICED_VBI_CAPTURE : - (isVbi() ? V4L2_BUF_TYPE_VBI_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE); + (isVbi() ? V4L2_BUF_TYPE_VBI_CAPTURE : + (isPlanar() ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE)); } void GeneralTab::updateVideoInput() @@ -1270,20 +1296,36 @@ void GeneralTab::updateVidCapFormat() if (isVbi()) return; - g_fmt_cap(fmt); - m_pixelformat = fmt.fmt.pix.pixelformat; - m_width = fmt.fmt.pix.width; - m_height = fmt.fmt.pix.height; + g_fmt_cap(m_buftype, fmt); + if (isPlanar()) { + m_pixelformat = fmt.fmt.pix_mp.pixelformat; + m_width = fmt.fmt.pix_mp.width; + m_height = fmt.fmt.pix_mp.height; + } else { + m_pixelformat = fmt.fmt.pix.pixelformat; + m_width = fmt.fmt.pix.width; + m_height = fmt.fmt.pix.height; + } updateFrameSize(); updateFrameInterval(); - if (enum_fmt_cap(desc, true)) { + if (enum_fmt_cap(desc, m_buftype, true)) { do { - if (desc.pixelformat == fmt.fmt.pix.pixelformat) - break; - } while (enum_fmt_cap(desc)); + if (isPlanar()) { + if (desc.pixelformat == fmt.fmt.pix_mp.pixelformat) + break; + } else { + if (desc.pixelformat == fmt.fmt.pix.pixelformat) + break; + } + } while (enum_fmt_cap(desc, m_buftype)); + } + if (isPlanar()) { + if (desc.pixelformat != fmt.fmt.pix_mp.pixelformat) + return; + } else { + if (desc.pixelformat != fmt.fmt.pix.pixelformat) + return; } - if (desc.pixelformat != fmt.fmt.pix.pixelformat) - return; m_vidCapFormats->setCurrentIndex(desc.index); updateVidCapFields(); } @@ -1294,23 +1336,34 @@ void GeneralTab::updateVidCapFields() v4l2_format tmp; bool first = true; - g_fmt_cap(fmt); + g_fmt_cap(m_buftype, fmt); for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { tmp = fmt; - tmp.fmt.pix.field = f; - if (!s_fmt(tmp) || tmp.fmt.pix.field != f) - continue; - if (first) { - m_vidCapFields->clear(); - first = false; + if (isPlanar()) { + tmp.fmt.pix_mp.field = f; + if (!try_fmt(tmp) || tmp.fmt.pix_mp.field != f) + continue; + if (first) { + m_vidCapFields->clear(); + first = false; + } + m_vidCapFields->addItem(field2s(f)); + if (fmt.fmt.pix_mp.field == f) + m_vidCapFields->setCurrentIndex(m_vidCapFields->count() - 1); + } else { + tmp.fmt.pix.field = f; + if (!try_fmt(tmp) || tmp.fmt.pix.field != f) + continue; + if (first) { + m_vidCapFields->clear(); + first = false; + } + m_vidCapFields->addItem(field2s(f)); + if (fmt.fmt.pix.field == f) + m_vidCapFields->setCurrentIndex(m_vidCapFields->count() - 1); } - m_vidCapFields->addItem(field2s(f)); - if (fmt.fmt.pix.field == f) - m_vidCapFields->setCurrentIndex(m_vidCapFields->count() - 1); } - if (!first) - s_fmt(fmt); } void GeneralTab::updateFrameSize() @@ -1398,7 +1451,7 @@ double GeneralTab::getPixelAspectRatio() switch (m_pixelAspectRatio->currentIndex()) { case 0: - ratio = g_pixel_aspect(); + ratio = g_pixel_aspect(m_buftype); break; case 2: ratio.numerator = 11; @@ -1441,7 +1494,7 @@ void GeneralTab::updateFrameInterval() m_frameInterval->setEnabled(m_has_interval); if (m_has_interval) { m_interval = frmival.discrete; - curr_ok = v4l2::get_interval(curr); + curr_ok = v4l2::get_interval(m_buftype, curr); do { m_frameInterval->addItem(QString("%1 fps") .arg((double)frmival.discrete.denominator / frmival.discrete.numerator)); diff --git a/utils/qv4l2/general-tab.h b/utils/qv4l2/general-tab.h index b58203f..d20f3c4 100644 --- a/utils/qv4l2/general-tab.h +++ b/utils/qv4l2/general-tab.h @@ -69,6 +69,7 @@ public: bool isSDR() const { return m_isSDR; } bool isVbi() const { return m_isVbi; } bool isSlicedVbi() const; + bool isPlanar() const { return m_isPlanar; } __u32 bufType() const { return m_buftype; } inline bool reqbufs_mmap(v4l2_requestbuffers &reqbuf, int count = 0) { return v4l2::reqbufs_mmap(reqbuf, m_buftype, count); @@ -76,18 +77,6 @@ public: inline bool reqbufs_user(v4l2_requestbuffers &reqbuf, int count = 0) { return v4l2::reqbufs_user(reqbuf, m_buftype, count); } - inline bool dqbuf_mmap(v4l2_buffer &buf, bool &again) { - return v4l2::dqbuf_mmap(buf, m_buftype, again); - } - inline bool dqbuf_user(v4l2_buffer &buf, bool &again) { - return v4l2::dqbuf_user(buf, m_buftype, again); - } - inline bool qbuf_mmap(int index) { - return v4l2::qbuf_mmap(index, m_buftype); - } - inline bool qbuf_user(int index, void *ptr, int length) { - return v4l2::qbuf_user(index, m_buftype, ptr, length); - } inline bool streamon() { return v4l2::streamon(m_buftype); } inline bool streamoff() { return v4l2::streamoff(m_buftype); } void setHaveBuffers(bool haveBuffers); @@ -176,6 +165,7 @@ private: bool m_isVbi; double m_freqFac; double m_freqRfFac; + bool m_isPlanar; __u32 m_buftype; __u32 m_audioModes[5]; QString m_device; diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index d54a5e2..bcce927 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -400,7 +400,7 @@ void ApplicationWindow::capVbiFrame() qbuf(buf); return; } - data = (__u8 *)m_buffers[buf.index].start; + data = (__u8 *)m_buffers[buf.index].start[0]; s = buf.bytesused; break; @@ -471,7 +471,7 @@ void ApplicationWindow::capVbiFrame() status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); if (showFrames()) m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), status); + m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL, status); curStatus = statusBar()->currentMessage(); if (curStatus.isEmpty() || curStatus.startsWith("Frame: ")) @@ -483,6 +483,7 @@ void ApplicationWindow::capVbiFrame() void ApplicationWindow::capFrame() { __u32 buftype = m_genTab->bufType(); + v4l2_plane planes[VIDEO_MAX_PLANES]; v4l2_buffer buf; int s = 0; int err = 0; @@ -492,6 +493,7 @@ void ApplicationWindow::capFrame() #endif unsigned char *displaybuf = NULL; + unsigned char *displaybuf2 = NULL; switch (m_capMethod) { case methodRead: @@ -525,6 +527,9 @@ void ApplicationWindow::capFrame() break; case methodMmap: + memset(planes, 0, sizeof(planes)); + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; if (!dqbuf_mmap(buf, buftype, again)) { error("dqbuf"); m_capStartAct->setChecked(false); @@ -545,23 +550,32 @@ void ApplicationWindow::capFrame() if (showFrames()) { if (m_mustConvert) err = v4lconvert_convert(m_convertData, &m_capSrcFormat, &m_capDestFormat, - (unsigned char *)m_buffers[buf.index].start, buf.bytesused, + (unsigned char *)m_buffers[buf.index].start[0], buf.bytesused, m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); if (m_mustConvert && err != -1) displaybuf = m_capImage->bits(); - if (!m_mustConvert) - displaybuf = (unsigned char *)m_buffers[buf.index].start; + if (!m_mustConvert) { + displaybuf = (unsigned char *)m_buffers[buf.index].start[0]; + displaybuf2 = (unsigned char *)m_buffers[buf.index].start[1]; + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + displaybuf += planes[0].data_offset; + displaybuf2 += planes[1].data_offset; + } + } } if (m_makeSnapshot) - makeSnapshot((unsigned char *)m_buffers[buf.index].start, buf.bytesused); + makeSnapshot((unsigned char *)m_buffers[buf.index].start[0], buf.bytesused); if (m_saveRaw.openMode()) - m_saveRaw.write((const char *)m_buffers[buf.index].start, buf.bytesused); + m_saveRaw.write((const char *)m_buffers[buf.index].start[0], buf.bytesused); break; case methodUser: + memset(planes, 0, sizeof(planes)); + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; if (!dqbuf_user(buf, buftype, again)) { - error("dqbuf"); + error("dqbuf1"); m_capStartAct->setChecked(false); return; } @@ -586,8 +600,14 @@ void ApplicationWindow::capFrame() m_capImage->bits(), m_capDestFormat.fmt.pix.sizeimage); if (m_mustConvert && err != -1) displaybuf = m_capImage->bits(); - if (!m_mustConvert) - displaybuf = (unsigned char *)buf.m.userptr; + if (!m_mustConvert) { + displaybuf = (unsigned char *)m_buffers[buf.index].start[0]; + displaybuf2 = (unsigned char *)m_buffers[buf.index].start[1]; + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + displaybuf += planes[0].data_offset; + displaybuf2 += planes[1].data_offset; + } + } } if (m_makeSnapshot) makeSnapshot((unsigned char *)buf.m.userptr, buf.bytesused); @@ -630,7 +650,7 @@ void ApplicationWindow::capFrame() if (showFrames()) m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, displaybuf, status); + m_capDestFormat.fmt.pix.pixelformat, displaybuf, displaybuf2, status); if (m_capMethod == methodMmap || m_capMethod == methodUser) qbuf(buf); @@ -683,6 +703,7 @@ bool ApplicationWindow::startCapture(unsigned buffer_size) } for (m_nbuffers = 0; m_nbuffers < req.count; ++m_nbuffers) { + v4l2_plane planes[VIDEO_MAX_PLANES]; v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); @@ -690,18 +711,32 @@ bool ApplicationWindow::startCapture(unsigned buffer_size) buf.type = buftype; buf.memory = V4L2_MEMORY_MMAP; buf.index = m_nbuffers; + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; if (-1 == ioctl(VIDIOC_QUERYBUF, &buf)) { perror("VIDIOC_QUERYBUF"); goto error; } - m_buffers[m_nbuffers].length = buf.length; - m_buffers[m_nbuffers].start = mmap(buf.length, buf.m.offset); - - if (MAP_FAILED == m_buffers[m_nbuffers].start) { - perror("mmap"); - goto error; + if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { + m_buffers[m_nbuffers].planes = buf.length; + for (unsigned p = 0; p < buf.length; p++) { + m_buffers[m_nbuffers].length[p] = planes[p].length; + m_buffers[m_nbuffers].start[p] = mmap(planes[p].length, planes[p].m.mem_offset); + if (MAP_FAILED == m_buffers[m_nbuffers].start[p]) { + perror("mmap"); + goto error; + } + } + } else { + m_buffers[m_nbuffers].planes = 1; + m_buffers[m_nbuffers].length[0] = buf.length; + m_buffers[m_nbuffers].start[0] = mmap(buf.length, buf.m.offset); + if (MAP_FAILED == m_buffers[m_nbuffers].start[0]) { + perror("mmap"); + goto error; + } } } for (i = 0; i < m_nbuffers; ++i) { @@ -738,13 +773,42 @@ bool ApplicationWindow::startCapture(unsigned buffer_size) } for (m_nbuffers = 0; m_nbuffers < req.count; ++m_nbuffers) { - m_buffers[m_nbuffers].length = buffer_size; - m_buffers[m_nbuffers].start = malloc(buffer_size); + v4l2_plane planes[VIDEO_MAX_PLANES]; + v4l2_buffer buf; + + memset(&buf, 0, sizeof(buf)); + + buf.type = buftype; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = m_nbuffers; + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; - if (!m_buffers[m_nbuffers].start) { - error("Out of memory"); + if (-1 == ioctl(VIDIOC_QUERYBUF, &buf)) { + perror("VIDIOC_QUERYBUF"); goto error; } + + if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { + m_buffers[m_nbuffers].planes = buf.length; + for (unsigned p = 0; p < buf.length; p++) { + m_buffers[m_nbuffers].length[p] = planes[p].length; + m_buffers[m_nbuffers].start[p] = malloc(planes[p].length); + if (m_buffers[m_nbuffers].start[p] == NULL) { + error("Out of memory"); + goto error; + } + } + } else { + m_buffers[m_nbuffers].planes = 1; + m_buffers[m_nbuffers].length[0] = buffer_size; + m_buffers[m_nbuffers].start[0] = malloc(buffer_size); + + if (!m_buffers[m_nbuffers].start[0]) { + error("Out of memory"); + goto error; + } + } } for (i = 0; i < m_nbuffers; ++i) if (!qbuf_user(i, buftype, m_buffers[i].start, m_buffers[i].length)) { @@ -792,8 +856,9 @@ void ApplicationWindow::stopCapture() if (!streamoff(buftype)) perror("VIDIOC_STREAMOFF"); for (i = 0; i < m_nbuffers; ++i) - if (-1 == munmap(m_buffers[i].start, m_buffers[i].length)) - perror("munmap"); + for (unsigned p = 0; p < m_buffers[i].planes; p++) + if (-1 == munmap(m_buffers[i].start[p], m_buffers[i].length[p])) + perror("munmap"); // Free all buffers. reqbufs_mmap(reqbufs, buftype, 1); // videobuf workaround reqbufs_mmap(reqbufs, buftype, 0); @@ -806,7 +871,8 @@ void ApplicationWindow::stopCapture() reqbufs_user(reqbufs, buftype, 1); // videobuf workaround reqbufs_user(reqbufs, buftype, 0); for (i = 0; i < m_nbuffers; ++i) - free(m_buffers[i].start); + for (unsigned p = 0; p < m_buffers[i].planes; p++) + free(m_buffers[i].start[p]); break; } free(m_buffers); @@ -906,6 +972,11 @@ void ApplicationWindow::capStart(bool start) struct v4l2_fract interval; v4l2_pix_format &srcPix = m_capSrcFormat.fmt.pix; v4l2_pix_format &dstPix = m_capDestFormat.fmt.pix; + v4l2_pix_format_mplane &srcMPix = m_capSrcFormat.fmt.pix_mp; + v4l2_pix_format_mplane &dstMPix = m_capDestFormat.fmt.pix_mp; + __u32 buftype = m_genTab->bufType(); + bool isPlanar = m_genTab->isPlanar(); + __u32 width, height, pixfmt; if (!start) { stopCapture(); @@ -964,7 +1035,7 @@ void ApplicationWindow::capStart(bool start) 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_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), NULL, "No frame"); m_capture->resize(m_vbiWidth, m_vbiHeight); if (showFrames()) m_capture->show(); @@ -977,40 +1048,55 @@ void ApplicationWindow::capStart(bool start) return; } - g_fmt_cap(m_capSrcFormat); + g_fmt_cap(buftype, m_capSrcFormat); s_fmt(m_capSrcFormat); if (m_genTab->get_interval(interval)) - set_interval(interval); + set_interval(buftype, interval); - m_frameData = new unsigned char[srcPix.sizeimage]; + if (!isPlanar) + m_frameData = new unsigned char[srcPix.sizeimage]; + else + m_frameData = new unsigned char[srcMPix.plane_fmt[0].sizeimage + srcMPix.plane_fmt[1].sizeimage]; m_capDestFormat = m_capSrcFormat; - dstPix.pixelformat = V4L2_PIX_FMT_RGB24; - if (m_capture->hasNativeFormat(srcPix.pixelformat)) { + if (isPlanar) { + dstMPix.pixelformat = srcMPix.pixelformat; + width = srcMPix.width; + height = srcMPix.height; + pixfmt = srcMPix.pixelformat; + m_mustConvert = false; + } else if (m_capture->hasNativeFormat(srcPix.pixelformat)) { dstPix.pixelformat = srcPix.pixelformat; + width = srcPix.width; + height = srcPix.height; + pixfmt = srcPix.pixelformat; m_mustConvert = false; } else { m_mustConvert = true; + dstPix.pixelformat = V4L2_PIX_FMT_RGB24; v4l2_format copy = m_capSrcFormat; v4lconvert_try_format(m_convertData, &m_capDestFormat, &m_capSrcFormat); // v4lconvert_try_format sometimes modifies the source format if it thinks // that there is a better format available. Restore our selected source // format since we do not want that happening. m_capSrcFormat = copy; + width = dstPix.width; + height = dstPix.height; + pixfmt = dstPix.pixelformat; } // Ensure that the initial image is large enough for native 32 bit per pixel formats - if (dstPix.pixelformat == V4L2_PIX_FMT_RGB32 || dstPix.pixelformat == V4L2_PIX_FMT_BGR32) + if (pixfmt == V4L2_PIX_FMT_RGB32 || pixfmt == V4L2_PIX_FMT_BGR32) dstFmt = QImage::Format_ARGB32; - m_capImage = new QImage(dstPix.width, dstPix.height, dstFmt); + m_capImage = new QImage(width, height, dstFmt); m_capImage->fill(0); updatePixelAspectRatio(); m_capture->setFrame(m_capImage->width(), m_capImage->height(), - m_capDestFormat.fmt.pix.pixelformat, m_capImage->bits(), "No frame"); - m_capture->resize(dstPix.width, dstPix.height); + pixfmt, m_capImage->bits(), NULL, "No frame"); + m_capture->resize(width, height); if (showFrames()) m_capture->show(); diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h index b8cc3b8..21a9d8f 100644 --- a/utils/qv4l2/qv4l2.h +++ b/utils/qv4l2/qv4l2.h @@ -68,8 +68,9 @@ enum RenderMethod { }; struct buffer { - void *start; - size_t length; + unsigned planes; + void *start[VIDEO_MAX_PLANES]; + size_t length[VIDEO_MAX_PLANES]; }; #define CTRL_FLAG_DISABLED (V4L2_CTRL_FLAG_READ_ONLY | \ diff --git a/utils/qv4l2/v4l2-api.cpp b/utils/qv4l2/v4l2-api.cpp index 894a8c1..7b36264 100644 --- a/utils/qv4l2/v4l2-api.cpp +++ b/utils/qv4l2/v4l2-api.cpp @@ -277,10 +277,10 @@ bool v4l2::s_frequency(int val, bool low) return s_frequency(f); } -bool v4l2::g_fmt_cap(v4l2_format &fmt) +bool v4l2::g_fmt_cap(unsigned type, v4l2_format &fmt) { memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.type = type; return ioctl(VIDIOC_G_FMT, &fmt) >= 0; } @@ -307,14 +307,23 @@ bool v4l2::g_fmt_sliced_vbi(v4l2_format &fmt) bool v4l2::try_fmt(v4l2_format &fmt) { - fmt.fmt.pix.field = V4L2_FIELD_ANY; - fmt.fmt.pix.bytesperline = 0; + if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt.fmt.pix_mp.plane_fmt[1].bytesperline = 0; + } else { + fmt.fmt.pix.bytesperline = 0; + } return ioctl("Try Capture Format", VIDIOC_TRY_FMT, &fmt); } bool v4l2::s_fmt(v4l2_format &fmt) { - fmt.fmt.pix.bytesperline = 0; + if (V4L2_TYPE_IS_MULTIPLANAR(fmt.type)) { + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt.fmt.pix_mp.plane_fmt[1].bytesperline = 0; + } else { + fmt.fmt.pix.bytesperline = 0; + } return ioctl("Set Capture Format", VIDIOC_S_FMT, &fmt); } @@ -380,7 +389,7 @@ bool v4l2::enum_dv_timings(v4l2_enum_dv_timings &timings, bool init, int index) return ioctl(VIDIOC_ENUM_DV_TIMINGS, &timings) >= 0; } -bool v4l2::enum_fmt_cap(v4l2_fmtdesc &fmt, bool init, int index) +bool v4l2::enum_fmt_cap(v4l2_fmtdesc &fmt, unsigned type, bool init, int index) { if (init) { memset(&fmt, 0, sizeof(fmt)); @@ -388,7 +397,7 @@ bool v4l2::enum_fmt_cap(v4l2_fmtdesc &fmt, bool init, int index) } else { fmt.index++; } - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.type = type; return ioctl(VIDIOC_ENUM_FMT, &fmt) >= 0; } @@ -452,9 +461,13 @@ bool v4l2::reqbufs_mmap(v4l2_requestbuffers &reqbuf, __u32 buftype, int count) bool v4l2::dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again) { + v4l2_plane *planes = buf.m.planes; + unsigned length = buf.length; int res; memset(&buf, 0, sizeof(buf)); + buf.length = length; + buf.m.planes = planes; buf.type = buftype; buf.memory = V4L2_MEMORY_MMAP; res = ioctl(VIDIOC_DQBUF, &buf); @@ -464,9 +477,13 @@ bool v4l2::dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again) bool v4l2::dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again) { + v4l2_plane *planes = buf.m.planes; + unsigned length = buf.length; int res; memset(&buf, 0, sizeof(buf)); + buf.length = length; + buf.m.planes = planes; buf.type = buftype; buf.memory = V4L2_MEMORY_USERPTR; res = ioctl(VIDIOC_DQBUF, &buf); @@ -481,24 +498,37 @@ bool v4l2::qbuf(v4l2_buffer &buf) bool v4l2::qbuf_mmap(int index, __u32 buftype) { + v4l2_plane planes[VIDEO_MAX_PLANES]; v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = buftype; buf.memory = V4L2_MEMORY_MMAP; buf.index = index; + buf.length = 2; + buf.m.planes = planes; return qbuf(buf); } -bool v4l2::qbuf_user(int index, __u32 buftype, void *ptr, int length) +bool v4l2::qbuf_user(int index, __u32 buftype, void *ptr[], size_t length[]) { + v4l2_plane planes[VIDEO_MAX_PLANES]; v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = buftype; buf.memory = V4L2_MEMORY_USERPTR; - buf.m.userptr = (unsigned long)ptr; - buf.length = length; + if (V4L2_TYPE_IS_MULTIPLANAR(buftype)) { + buf.length = 2; + buf.m.planes = planes; + planes[0].length = length[0]; + planes[0].m.userptr = (unsigned long)ptr[0]; + planes[1].length = length[1]; + planes[1].m.userptr = (unsigned long)ptr[1]; + } else { + buf.m.userptr = (unsigned long)ptr[0]; + buf.length = length[0]; + } buf.index = index; return qbuf(buf); } @@ -596,11 +626,11 @@ bool v4l2::dqevent(v4l2_event &ev) return ioctl(VIDIOC_DQEVENT, &ev) >= 0; } -bool v4l2::set_interval(v4l2_fract interval) +bool v4l2::set_interval(unsigned type, v4l2_fract interval) { v4l2_streamparm parm; - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.type = type; if (ioctl(VIDIOC_G_PARM, &parm) < 0) return false; @@ -612,11 +642,11 @@ bool v4l2::set_interval(v4l2_fract interval) return ioctl("Set FPS", VIDIOC_S_PARM, &parm); } -bool v4l2::get_interval(v4l2_fract &interval) +bool v4l2::get_interval(unsigned type, v4l2_fract &interval) { v4l2_streamparm parm; - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.type = type; if (ioctl(VIDIOC_G_PARM, &parm) >= 0 && (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) { interval = parm.parm.capture.timeperframe; @@ -626,7 +656,7 @@ bool v4l2::get_interval(v4l2_fract &interval) return false; } -v4l2_fract v4l2::g_pixel_aspect() +v4l2_fract v4l2::g_pixel_aspect(unsigned type) { v4l2_cropcap ratio; v4l2_std_id std; @@ -634,7 +664,7 @@ v4l2_fract v4l2::g_pixel_aspect() static const v4l2_fract hz50 = { 11, 12 }; static const v4l2_fract hz60 = { 11, 10 }; - ratio.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ratio.type = type; if (ioctl(VIDIOC_CROPCAP, &ratio) < 0) { if (!g_std(std)) return square; diff --git a/utils/qv4l2/v4l2-api.h b/utils/qv4l2/v4l2-api.h index ad3f15c..485e5d2 100644 --- a/utils/qv4l2/v4l2-api.h +++ b/utils/qv4l2/v4l2-api.h @@ -80,7 +80,7 @@ public: bool g_frequency(v4l2_frequency &freq, unsigned index = 0); bool s_frequency(v4l2_frequency &freq); bool s_frequency(int freq, bool low = false); - bool g_fmt_cap(v4l2_format &fmt); + bool g_fmt_cap(unsigned type, v4l2_format &fmt); bool g_fmt_out(v4l2_format &fmt); bool g_fmt_vbi(v4l2_format &fmt); bool g_fmt_sliced_vbi(v4l2_format &fmt); @@ -92,7 +92,7 @@ public: bool enum_audout(v4l2_audioout &audout, bool init = false); bool enum_std(v4l2_standard &std, bool init = false, int index = 0); bool enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0); - bool enum_fmt_cap(v4l2_fmtdesc &std, bool init = false, int index = 0); + bool enum_fmt_cap(v4l2_fmtdesc &std, unsigned type, bool init = false, int index = 0); bool enum_fmt_out(v4l2_fmtdesc &std, bool init = false, int index = 0); bool enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0); bool enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0); @@ -103,10 +103,10 @@ public: bool dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again); bool qbuf(v4l2_buffer &buf); bool qbuf_mmap(int index, __u32 buftype); - bool qbuf_user(int index, __u32 buftype, void *ptr, int length); + bool qbuf_user(int index, __u32 buftype, void *ptr[], size_t length[]); bool streamon(__u32 buftype); bool streamoff(__u32 buftype); - v4l2_fract g_pixel_aspect(); + v4l2_fract g_pixel_aspect(unsigned type); inline bool reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count = 0) { return reqbufs_mmap(reqbuf, V4L2_BUF_TYPE_VIDEO_CAPTURE, count); @@ -120,12 +120,6 @@ public: inline bool dqbuf_user_cap(v4l2_buffer &buf, bool &again) { return dqbuf_user(buf, V4L2_BUF_TYPE_VIDEO_CAPTURE, again); } - inline bool qbuf_mmap_cap(int index) { - return qbuf_mmap(index, V4L2_BUF_TYPE_VIDEO_CAPTURE); - } - inline bool qbuf_user_cap(int index, void *ptr, int length) { - return qbuf_user(index, V4L2_BUF_TYPE_VIDEO_CAPTURE, ptr, length); - } inline bool streamon_cap() { return streamon(V4L2_BUF_TYPE_VIDEO_CAPTURE); } inline bool streamoff_cap() { return streamoff(V4L2_BUF_TYPE_VIDEO_CAPTURE); } @@ -141,12 +135,6 @@ public: inline bool dqbuf_user_vbi(v4l2_buffer &buf, bool &again) { return dqbuf_user(buf, V4L2_BUF_TYPE_VBI_CAPTURE, again); } - inline bool qbuf_mmap_vbi(int index) { - return qbuf_mmap(index, V4L2_BUF_TYPE_VBI_CAPTURE); - } - inline bool qbuf_user_vbi(int index, void *ptr, int length) { - return qbuf_user(index, V4L2_BUF_TYPE_VBI_CAPTURE, ptr, length); - } inline bool streamon_vbi() { return streamon(V4L2_BUF_TYPE_VBI_CAPTURE); } inline bool streamoff_vbi() { return streamoff(V4L2_BUF_TYPE_VBI_CAPTURE); } @@ -161,8 +149,8 @@ public: bool subscribe_event(v4l2_event_subscription &sub); bool dqevent(v4l2_event &ev); - bool set_interval(v4l2_fract interval); - bool get_interval(v4l2_fract &interval); + bool set_interval(unsigned type, v4l2_fract interval); + bool get_interval(unsigned type, v4l2_fract &interval); private: void clear() { error(QString()); } _______________________________________________ linuxtv-commits mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits
