为什么iMX53上的YUV420到RGB转换速度较慢



我有一个工作链,iMX53上的GPU(AMD Z430)将解码后的视频帧转换为YUV420P格式,转换为RGB565并显示。我唯一担心的是速度,更确切地说是速度不足。输入的视频帧是1920x1088YUV420P,转换时间是40ms,我根本无法让它运行得更快。我试着优化我的着色器,但没有成功。我也尝试过2D色域,它甚至更慢(由于其2D特性,它提供了一些不正确的颜色)。当然,我不是OpenGL ES专家。

这是我的着色器:

static const char *fragment_shader_yuv_src =
"const lowp mat3 rgb_coeff = mat3(1, 1, 1, 0, -0.344, 1.772, 1.402, -0.714, 0);n"
"varying lowp vec2 v_texcoord;n"
"uniform lowp sampler2D s_texture_y;n"
"uniform lowp sampler2D s_texture_u;n"
"uniform lowp sampler2D s_texture_v;n"
"n"
"void main()n"
"{n"
"    lowp vec3 yuv = vec3(texture2D(s_texture_y, v_texcoord).r, texture2D(s_texture_u, v_texcoord).r - 0.5, texture2D(s_texture_v, v_texcoord).r - 0.5);n"
"    gl_FragColor = vec4(rgb_coeff * yuv, 1.0);n"
"}n";
static const char *vertex_shader_yuv_src =
"attribute lowp vec4 position; n"
"attribute lowp vec2 texcoord; n"
"varying lowp vec2 v_texcoord; n"
"                              n"
"void main()                   n"
"{                             n"
"    gl_Position = position;   n"
"    v_texcoord = texcoord.xy; n"
"}                             n";

s_texture_y/u/v包含适当的颜色分量,图像由eglCreateImageKHR(…)分配,并由glEGLImageTargetTexture2DOES(…)指定给纹理。

正如我上面提到的,它是有效的,但速度很慢。我无法决定这是GPU的最大性能,还是我在着色器中做了一些非常错误的事情。。。

(使用有史以来最简单的着色器放大和绘制一个简单的416x416 RGBA32图像也非常慢,~23ms)

有人知道吗,有经验吗?如何优化着色器?

乍一看,着色器的性能看起来还不错。(作为参考,请查看gst-plugins-gl的glupload.c文件,其中OpenGL和OpenGL ES的典型转换都是在着色器中完成的)。

在没有进入平台细节的情况下,性能的缺乏完全可能是由于上传到GPU的惩罚。你试过使用虚拟碎片着色器吗?即:

void main (void)
{
gl_FragColor = vec4 (0.0, 1.0, 0.0, 1.0);
}

同时上传不同分辨率的相框?我的猜测是,即使是很小的帧,你也会受到很大的时间损失~10,20ms,这是因为在注入新数据之前,所有正在进行的计算都需要完成,并且需要刷新管道(即,从GPU的角度来看,上传是一种同步操作)。

如果惩罚很大,你可以尝试使用双上传到GPU(见本文),看看它是否能改善你的特定驱动程序+硬件。

最后,在着色器和glupload.c中,使用3种不同的纹理(每个通道一种)以及使用CPU代码传递的统一纹理对性能没有帮助。你可以尝试两件事:一,用三个通道的YUV背靠背上传一组数据,然后将输出像素到YUV坐标逻辑中,放入着色器本身,类似这样:

void main (void)
{ 
vec2 y_coord = <calculate the position to find the Y component for this pixel>
vec2 u_coord = <calculate the position to find the U component for this pixel>
vec2 v_coord = <calculate the position to find the V component for this pixel>
float y_value = texture2D(s_texture, y_coord).<appropriate channel>
float u_value = texture2D(s_texture, u_coord).<appropriate channel>
float v_value = texture2D(s_texture, v_coord).<appropriate channel>
gl_FragColor = vec4 (rgb_coeff * vec3(y_value, u_value, v_value), 1.0);
}

如果上传不是瓶颈,我可以尝试进一步开发这个着色器。。。

最新更新