我想製作我自己的SurfaceView併發送一個幀,我已經從onPreviewFrame(byte [] data,Camera camera)方法獲得了這些幀。 要做到這一點,我需要將幀從Yuv轉換爲ARGB,並將它們繪製到我的SurfaceView的畫布上。Renderscript ScriptIntrinsicYuvToRGB和位圖分配
這裏是我的onPreviewFrame:
public void onPreviewFrame(byte[] data, Camera camera) {
if (camera != null) {
camera.addCallbackBuffer(data);
}
// using RenderScript
Bitmap bitmap = RenderScriptFilter.convertYuvToRgbIntrinsic(rs, data, PREVIEW_WIDTH, PREVIEW_HEIGHT);
if (mFilterSurfaceView != null) {
SurfaceHolder holder = mFilterSurfaceView.getHolder();
Canvas canvas = holder.lockCanvas();
// draw bitmap to the canvas
canvas.drawBitmap(bitmap, 0, 0, mPaint);
holder.unlockCanvasAndPost(canvas);
mFrames++;
System.gc();
}
}
};
這裏是convertYuvToRgbIntrinsic方法:
public static Bitmap convertYuvToRgbIntrinsic(RenderScript rs, byte[] data, int w, int h) {
int imageWidth = w ;
int imageHeight = h ;
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs));
// Create the input allocation memory for Renderscript to work with
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs))
.setX(imageWidth)
.setY(imageHeight)
.setYuvFormat(android.graphics.ImageFormat.NV21);
Allocation aIn = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
// Set the YUV frame data into the input allocation
aIn.copyFrom(data);
// Create the output allocation
Type.Builder rgbType = new Type.Builder(rs, Element.RGBA_8888(rs))
.setX(imageWidth)
.setY(imageHeight);
Allocation aOut = Allocation.createTyped(rs, rgbType.create(), Allocation.USAGE_SCRIPT);
yuvToRgbIntrinsic.setInput(aIn);
// Run the script for every pixel on the input allocation and put the result in aOut
yuvToRgbIntrinsic.forEach(aOut);
// Create an output bitmap and copy the result into that bitmap
Bitmap outBitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
aOut.copyTo(outBitmap);
return outBitmap ;
}
我覺得似乎是因爲System.gc()的方法的問題。 因爲當我試着用640×480全沒關係,但與1280×720我得到了一些錯誤:
12-30 13:06:59.063 18034-18178/youten.redo.y2ndkyuv420sp E /的renderScript:rsAssert失敗:CMD- > cmdID <(sizeof(gPlaybackFuncs)/ sizeof(void *)),in frameworks/rs/rsThreadIO.cpp at 156 12-30 13:06:59.063 18034-18178/youten.redo.y2ndkyuv420sp E/RenderScript:playCoreCommands錯誤con 0x78fb79a0,cmd 2072915616 12-30 13:06:59.063 18034-18178/youten.redo.y2ndkyuv420sp A/libc:0x2fa27a84(代碼= 1)的致命信號11(SIGSEGV),線程18178(o.y2ndkyuv420sp)
我明白System.gc()是一個不好的習慣,但是在這裏做什麼來分配內存? bitmap.recycle();位圖=空;沒有解決這個問題。
謝謝!你的代碼運行良好。我已經用Nexus 7進行測試,在1920x1080的內存中保存大約20幀,並且效果很好。早些時候,我在聯想瑜伽標籤2上測試了我的舊代碼,並且拋出了錯誤。所以,似乎這個延遲功能並不適合所有設備。無論如何,使用Renderscript從yuv轉換到rgb要比使用jni更快。 –