如何让ExtractMpegFramesTest中的saveFrame()方法更高效?

4

[编辑]按照fadden@的建议转换为问答形式。

ExtractMpegFramesTest_egl14.java.txt中,方法saveFrame()有一个循环用于将RGBA重新排序为ARGB以进行位图png压缩(请参见该文件的下面引用),如何优化此过程?

// glReadPixels gives us a ByteBuffer filled with what is essentially big-endian RGBA
// data (i.e. a byte of red, followed by a byte of green...).  We need an int[] filled
// with little-endian ARGB data to feed to Bitmap.
//

...

// So... we set the ByteBuffer to little-endian, which should turn the bulk IntBuffer
// get() into a straight memcpy on most Android devices.  Our ints will hold ABGR data.
// Swapping B and R gives us ARGB.  We need about 30ms for the bulk get(), and another
// 270ms for the color swap.

...

for (int i = 0; i < pixelCount; i++) {
    int c = colors[i];
    colors[i] = (c & 0xff00ff00) | ((c & 0x00ff0000) >> 16) | ((c & 0x000000ff) << 16);
}

2
好主意!在Java中,那个交换循环并不特别快。 - fadden
1
就我个人而言,我认为提出建议的“官方”方式是询问:“我们如何使ExtractMpegFramesTest中的saveFrame()方法更有效率?”,然后回答自己的问题。这样可以鼓励其他人提出他们自己的答案。请参阅http://stackoverflow.com/help/self-answer。 - fadden
重新格式化,谢谢fadden! - miguelao
2个回答

4

原来有一种更快的方法。

按照@elmiguelao的建议,我修改了片段着色器以进行像素交换。这使我可以从saveFrame()中删除交换代码。由于我不再需要在内存中保存像素的临时副本,因此完全消除了int[]缓冲区,并从以下内容切换:

int[] colors = [... copy from mPixelBuf, swap ...]
Bitmap.createBitmap(colors, mWidth, mHeight, Bitmap.Config.ARGB_8888);

转换为:

Bitmap bmp = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(mPixelBuf);

当我这样做时,所有的颜色都变错了。

原来Bitmap#copyPixelsFromBuffer()需要按照RGBA顺序来提供像素,而不是ARGB顺序。从glReadPixels()中出来的值已经是正确的格式。所以通过这种方式,我避免了交换、不必要的复制,并且完全不需要调整片段着色器。


3

[编辑] 根据fadden@的建议,将格式重新排列为问答形式

我想建议在FragmentShader中通过更改以下行来进行此转换:

gl_FragColor = texture2D(sTexture, vTextureCoord);

转换为

gl_FragColor = texture2D(sTexture, vTextureCoord).argb;

这是一种在GPU中重新排序着色器输出通道的高效方式,也可以使用其他方法:.abgr或者.bggr等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接