How can we make the saveFrame() method in ExtractMpegFramesTest more efficient?

风流意气都作罢 提交于 2019-11-30 19:14:42

问题


[edit] Reformatting into question and answer format following fadden@ suggestion.

In ExtractMpegFramesTest_egl14.java.txt, method saveFrame(), there is a loop for reordering RGBA into ARGB for Bitmap png compression (see below quotes from that file), how can this be optimised?

// 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);
}

回答1:


It turns out there's an even faster approach.

Using the suggestion in @elmiguelao's answer, I modified the fragment shader to do the pixel swap. This allowed me to remove the swap code from saveFrame(). Since I no longer needed a temporary copy of the pixels in memory, I eliminated the int[] buffer entirely, switching from this:

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

to this:

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

As soon as I did that, all of my colors were wrong.

It turns out that Bitmap#copyPixelsFromBuffer() wants the pixels in RGBA order, not ARGB order. The values coming out of glReadPixels() are already in the right format. So by doing it this way I avoid the swap, avoid an unnecessary copy, and don't need to tweak the fragment shader at all.




回答2:


[edit] Reformatting into question and answer format following fadden@ suggestion

I wanted to suggest that this conversion can happen in the FragmentShader by changing the line

gl_FragColor = texture2D(sTexture, vTextureCoord);

into

gl_FragColor = texture2D(sTexture, vTextureCoord).argb;

which is an efficient shortcut to reorder in GPU the shader's output channels, that works in other ways too: .abgr or even .bggr etc.



来源:https://stackoverflow.com/questions/21634450/how-can-we-make-the-saveframe-method-in-extractmpegframestest-more-efficient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!