是否有比使用AndroidBitmap_xxx功能更快的视频渲染解决方案?

时间:2012-06-22 23:04:43

标签: android opengl-es bitmap ffmpeg rendering

在我的本机线程中,我有FFMpeg获取并解码帧然后将它们放入队列。

在Java方面,我有一个GLSurfaceView来自Renderer.onDrawFrame我正在调用传递位图的本机代码(我创建的位图只有一次,然后每次都传递它。)

在本机代码中,我得到队列的头部,使用AndroidBitmap_xxx函数将数据复制到java位图,然后在Java端将该位图渲染为纹理。

我想知道有更快的方式来渲染视频吗?我应该完全在本机代码中完成它,如果是的话,为什么它会更快?

编辑:我现在不将RGB帧像素复制到锁定的位图像素,而是将YUV帧直接解码为锁定的位图像素。这使得渲染速度明显加快(因为没有不必要的memcpy了)仍然存在问题。

1 个答案:

答案 0 :(得分:2)

更改纹理中像素的最有效技术称为渲染到纹理,可以通过FBOs在OpenGL / OpenGL ES中完成。在桌面OpenGL上,您可以使用像素缓冲区对象(PBOs)直接在GPU上操作像素数据(但OpenGL ES尚不支持)。

在未扩展的OpenGL上,您可以更改系统内存中的像素,然后使用glTexImage2D / glTexSubImage2D更新纹理 - 但这是效率低下的最后解决方案,应尽可能避免使用。 glTexSubImage2D 通常要快得多,因为它只更新现有纹理内的像素,而glTexImage2D创建全新纹理(作为一个好处,你可以改变纹理的大小和像素格式)。另一方面,glTexSubImage2D只允许更新纹理的一部分。

您说您希望它与OpenGL ES一起使用,因此我建议您执行以下步骤:

  • 用glTexSubImage2D()替换glTexImage2D() - 如果你获得了足够的性能,就让它成为现实;
  • 使用FBO和着色器实现渲染到纹理 - 它将需要 更多的工作来重写你的代码,但会更好 性能

对于FBO,代码可能如下所示:

// setup FBO
glGenFramebuffers( 1, &FFrameBuffer );
glBindFramebuffer( GL_FRAMEBUFFER, FFrameBuffer );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, YourTextureID, 0 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );

// render to FBO
glBindFramebuffer( GL_FRAMEBUFFER, FFrameBuffer );
glViewport( 0, 0, YourTextureWidth, YourTextureHeight );
your rendering code goes here - it will draw directly into the texture
glBindFramebuffer( GL_FRAMEBUFFER, 0 );

// cleanup
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glDeleteFramebuffers( 1, &FFrameBuffer );

请记住,并非所有像素格式都可以呈现。 RGB / RGBA通常很好。