计算机系统应用教程网站

网站首页 > 技术文章 正文

QT5.14使用双通道渲染解决YUV视频流出现花屏及绿屏

btikc 2024-09-02 17:14:13 技术文章 11 ℃ 0 评论

基于多线程离屏渲染YUV后,通过不同的CPU及笔记本机型测试,发现在Intel显卡下会出现视频闪花屏及绿屏等现象,通过对WebRtc代码模块中Opengl渲染YUV数据部分进行分析,发现在采用随机的双Opengl通道YUV数据渲染。

首先在初始化2组纹理存储空间

//定义6个纹理存储ID
static const GLsizei kNumTextureSets = 2;
static const GLsizei kNumTexturesPerSet = 3;
static const GLsizei kNumTextures = kNumTexturesPerSet * kNumTextureSets;

//初始化纹理储存ID
void VideoPlayRender::initTextures()
{
	glGenTextures(kNumTextures, tex_yuv);
	for (GLsizei i = 0; i < kNumTextures; i++) {
		glBindTexture(GL_TEXTURE_2D, tex_yuv[i]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
}

在YUV数据渲染时分配渲染数据存储空间

void VideoPlayRender::render(int width, int height, uint8_t* dataY, uint8_t* dataU, uint8_t* dataV, size_t strideY, size_t strideU, size_t strideV, uint32_t userId)
{
  //查找空闲储存ID
	_currentTextureSet = (_currentTextureSet + 1) % kNumTextureSets;
	m_CurYuv[0] = tex_yuv[_currentTextureSet * kNumTexturesPerSet];
	m_CurYuv[1] = tex_yuv[_currentTextureSet * kNumTexturesPerSet + 1];
	m_CurYuv[2] = tex_yuv[_currentTextureSet * kNumTexturesPerSet + 2];
  //清理空间
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT|);
  //获取绘制窗体
	glViewport(0, 0, width, height);
	glBindTexture(GL_TEXTURE_2D, m_CurYuv[0]);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, dataY);
	glUniform1i(textureUniformY, 0);

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, m_CurYuv[1]);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width >> 1, height >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, dataU);
	glUniform1i(textureUniformU, 1);

	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, m_CurYuv[2]);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width >> 1, height >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, dataV);
	glUniform1i(textureUniformV, 2);
	glFlush(); //离屏渲染必须调用,否则会造成视频异常
}

至此完美解决了部分显卡及机型会出现的花屏及绿屏等问题,其中实现的原理为,当YUV视频数据没有及时更新时,采用上一次渲染好的数据提交给系统刷新进行重复绘制即可,当有新的YUV数据到来时,将当前渲染好的GLuint通道ID通过信号发送到主线程,通过系统显示队里显示即可。

特别注意有时候在界面显示时还没有收到YUV数据时,会出现绿屏现象,这需要根据自己的业务场景,在paintGL中对无数据状态进行保护处理。

void GlVideoWidget::paintGL()
{
	if (m_isYuvUpdate == false)     //还没有YUV数据更新时候,不做重绘处理
	{
		return;
	}
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表