【问题标题】:Using Pixel Buffer Objects (PBO's) on Android在 Android 上使用像素缓冲区对象 (PBO)
【发布时间】:2013-05-06 18:19:05
【问题描述】:

在 Android 上,我正在尝试对相机帧执行一些 OpenGL 处理,在相机预览中显示这些帧,然后将这些帧编码到视频文件中。我正在尝试使用 OpenGL 执行此操作,使用 GLSurfaceView 和 GLSurfaceView.Renderer 以及使用 FFMPEG 进行视频编码。

我已经使用着色器成功处理了图像帧。现在我需要将处理后的帧编码为视频。 GLSurfaceView.Renderer 提供了 onDrawFrame(GL10 ..) 方法。正是在这种方法中,我尝试仅使用 glReadPixels() 读取图像帧,然后将帧放在队列中以编码为视频。就其本身而言, glReadPixels() 太慢了——我的帧速率是个位数。我正在尝试使用 Pixel Buffer Objects 来加快速度。这是行不通的。插上pbo后,帧率不变。这是我第一次使用 OpenGL,我不知道从哪里开始寻找问题。我这样做对吗?谁能给我一些指导?提前致谢。

public class MainRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {

.
.

    public void onDrawFrame ( GL10 gl10 ) {

        //Create a buffer to hold the image frame     
        ByteBuffer byte_buffer = ByteBuffer.allocateDirect(this.width * this.height * 4);
        byte_buffer.order(ByteOrder.nativeOrder());

        //Generate a pointer to the frame buffers
        IntBuffer image_buffers = IntBuffer.allocate(1); 
        GLES20.glGenBuffers(1, image_buffers);

        //Create the buffer
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0));
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, byte_buffer.limit(), byte_buffer, GLES20.GL_STATIC_DRAW);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0));

        //Read the pixel data into the buffer
        gl10.glReadPixels(0, 0, this.width, this.height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, byte_buffer);

        //encode the frame to video
        enQueueForEncoding(byte_buffer);

        //unbind the buffer
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

.
.

}

【问题讨论】:

  • 您检查过 Google Grafika 示例吗?如果这些 OpenGL 实现非常接近您在 Android 上可以达到的最佳状态,也不会感到太惊讶;即github.com/google/grafika/blob/master/src/com/android/grafika/…
  • 对于 glReadPixels 调用,请尝试使用 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, 0);最后通过零,但您需要通过 JNI 执行此操作,因为 java 不允许 null。然后像往常一样使用地图缓冲区。

标签: android opengl-es


【解决方案1】:

我以前从未尝试过这样的事情(opengl+video 编码),但我可以告诉你,从设备内存读取速度很慢。尝试双缓冲,这可能会有所帮助,因为 GPU 可以在 DMA 控制器读回内容时继续渲染到第二个缓冲区。

加载分析器(检查您设备的 GPU 供应商),这可能会给您一些想法。另一件可能有帮助的事情是将内部 pbuffer 格式设置为其他格式,尝试使用较小的数字并删除通道 (alpha)。

编辑:如果您有这种感觉,您可以在 GPU 上对视频进行编码,这将提高您的应用程序的内存和处理能力。

【讨论】:

  • TraxNet,感谢您的回复。我会尝试丢失 Alpha 通道。我相信它会有所帮助,但它不会产生足够大的差异。 GPU 上的编码将是特定于供应商的,不是吗?我需要在不同的设备上运行。
  • 他可能是指使用 RenderScript 来实现 GPU 的副作用。那将是独立于供应商的。
【解决方案2】:

我记得glBufferData() 没有将您的内部缓冲区映射到 GPU 内存,它只是将数据从您的内存复制到缓冲区(初始化)。

要访问由glBufferData() 分配的内存,您应该使用glMapBufferRange()。该函数返回一个您可以读取的 Java Buffer 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2014-07-13
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 2012-01-23
    相关资源
    最近更新 更多