2014-02-07 18 views
2

按fadden @建議重新格式化爲問題和答案格式。我們如何使ExtractMpegFramesTest中的saveFrame()方法更高效?

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

FWIW,我認爲提供建議的「官方」方法是詢問「我們如何使ExtractMpegFramesTest中的saveFrame()方法更有效?」,然後回答自己的問題。這樣鼓勵其他人也提出自己的答案。請參閱http://stackoverflow.com/help/self-answer。 – fadden

+0

重新格式化,謝謝fadden! – miguelao

回答

3

它事實證明還有更快的方法。

使用@ elmiguelao答案中的建議,我修改了片段着色器來進行像素交換。這使我可以從saveFrame()中刪除交換代碼。因爲我不再需要在內存中的像素的臨時副本,我消除了int[]緩衝區完全,從這個開關:當我這樣做,所有

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

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

本我的顏色錯了。

事實證明Bitmap#copyPixelsFromBuffer()想要RGBA順序中的像素,而不是 ARGB順序。來自glReadPixels()的值已經以正確的格式顯示。所以通過這樣做,我避免了交換,避免了不必要的副本,並且根本不需要調整片段着色器。

2

[編輯]改編爲問答形式下法登@建議

我想建議這種轉換可以發生在FragmentShader中anging行

gl_FragColor = texture2D(sTexture, vTextureCoord); 

gl_FragColor = texture2D(sTexture, vTextureCoord).argb; 

這是一種高效快捷的GPU着色器的輸出通道重新排序,在其他方面也適用:.abgr甚至.bggr