当前位置:   article > 正文

QML用openGL渲染NV12_nv12转rgb的 opengl

nv12转rgb的 opengl

前言

把之前写在windows的播放器移植到了我的安卓手机,就碰到了QOpenGLWidget需要替换的问题。
知乎、CSDN一搜就有渲染YUV420P的代码,git也有。没打招呼不放链接了。
用的是fbo的那个。主要记录下参数和问题。


一、QOpenGLTexture改动

NV12的UV数据是在一起的,所以texture只要创建两个,一个Y,一个UV。
格式套用RGB,RED放Y,GREEN和BLUE放UV:

	...
	mTexY->setFormat(QOpenGLTexture::R8_UNorm);
	...
	mTexUV->setFormat(QOpenGLTexture::RG8_UNorm);
	...
  • 1
  • 2
  • 3
  • 4
  • 5

理所当然后面的都要调整:

	mTexY->setSize(w, h);
    mTexY->allocateStorage(QOpenGLTexture::Red, QOpenGLTexture::UInt8);

    mTexUV->setSize(w/2, h/2);
    mTexUV->allocateStorage(QOpenGLTexture::RG, QOpenGLTexture::UInt8);
  • 1
  • 2
  • 3
  • 4
  • 5
	QOpenGLPixelTransferOptions options;
    options.setImageHeight(data.height);

    options.setRowLength(data.lineSize0);
    mTexY->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, data.data0.data(), &options);

    options.setRowLength(data.lineSize1/2);
    options.setImageHeight(data.height/2);
    mTexUV->setData(QOpenGLTexture::RG, QOpenGLTexture::UInt8, data.data1.data(), &options);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上面lineSize是ffmpeg解码出来的,linesize0和linesize1都是图像的宽。

二、Fragment Src

	const char *fsrc = "\
    varying mediump vec4 textureOut; \
    uniform sampler2D textureY; \
    uniform sampler2D textureUV; \
    void main(void) \
    {\
        vec3 yuv; \
        vec3 rgb; \
        yuv.x = texture2D(textureY, textureOut.st).r - 0.0625; \
        yuv.y = texture2D(textureUV, textureOut.st).r - 0.5; \
        yuv.z = texture2D(textureUV, textureOut.st).g - 0.5; \
        rgb = mat3( 1,       1,         1, \
                    0,       -0.39465,  2.03211, \
                    1.13983, -0.58060,  0) * yuv; \
        gl_FragColor = vec4(rgb, 1); \
    }";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

NV21就把yuv.y和yuv.z的.r .g换一下。

三、 渲染

绘制之前纹理绑定记得改:

	m_program.setUniformValue("textureY",0);
    m_program.setUniformValue("textureUV",1);
  • 1
  • 2

Qt5.12.1没有GL_QUADS了,搜一下这些关键词百度有一个解释绘制过程的文章,看了下画4个点的多边形和4个点的多三角是一样的:

	glDrawArrays(GL_TRIANGLE_FAN,0,4);
  • 1

用这个。


其他问题

原先写好了code怎么也渲染不出来,跟了下打印,发现QML把宽高初始化给OpenGL和ffmpeg了,但是和本身控件大小不一致,就造成了glViewport和解码出来的图都不能渲染。
QML控件初始化完时在那个槽函数重设一下宽高,YUV宽高和OpenGL各个设置的大小都是一致的就没问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46033
推荐阅读
相关标签
  

闽ICP备14008679号