Renderscript ScriptIntrinsicYuvToRGB和位分配 [英] Renderscript ScriptIntrinsicYuvToRGB and Bitmap allocation

查看:1953
本文介绍了Renderscript ScriptIntrinsicYuvToRGB和位分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我自己的SurfaceView并发送有我已经从previewFrame(字节[]数据,相机摄像头)方法得到的帧。
要做到这一点,我需要从YUV帧CONVER到ARGB并把​​它们画到画布我SurfaceView。

I want to make my own SurfaceView and send there a frames which I've obtained from onPreviewFrame(byte[] data, Camera camera) method. To do it, I need to conver frames from Yuv to ARGB and to draw them to a Canvas to my SurfaceView.

下面是我在previewFrame:

Here is my 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方式:

Here is convertYuvToRgbIntrinsic method:

    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我得到了一些错误:

I think the problem appears because of System.gc() method. Because when I try with 640x480 all okay, but with 1280x720 I obtain some errors:

13 12-30:06:59.063 18034-18178 / youten.redo.y2ndkyuv420sp E / RenderScript:rsAssert失败:CMD-> cmdID< (sizeof的(gPlaybackFuncs)/ sizeof的(无效*)),在框架/ RS / rsThreadIO.cpp 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中:致命的信号11(SIGSEGV)在0x2fa27a84(code = 1),螺纹18178(o.y2ndkyuv420sp)

12-30 13:06:59.063 18034-18178/youten.redo.y2ndkyuv420sp E/RenderScript: rsAssert failed: 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 error con 0x78fb79a0, cmd 2072915616 12-30 13:06:59.063 18034-18178/youten.redo.y2ndkyuv420sp A/libc: Fatal signal 11 (SIGSEGV) at 0x2fa27a84 (code=1), thread 18178 (o.y2ndkyuv420sp)

我明白的System.gc()是一个不好的做法,但在这里做什么来分配内存?
bitmap.recycle();位= NULL;没能解决问题。

I understood that System.gc() is a bad practice, but what to do here to allocate a memory? bitmap.recycle(); bitmap = null; didn't fixes the problem.

推荐答案

我不知道什么触发你的错误,以及如何可能与垃圾收集器。无论如何,1280×720的位图可以很快会耗尽你的记忆力。

I don't know what triggers your error, and how this could be related to garbage collector. At any rate, 1280x720 bitmaps can exhaust your memory quickly.

这是适得其反,重新对每个帧的所有renderscript分配。整点是让所有preparations一次,重复使用。

It is counter-productive to recreate all renderscript allocations for each frame. The whole point is to make all preparations once, and reuse.

附件找到我用的实用功能:

Attached find the utility function I use:

public Bitmap convertYuvImageToBitmap(Context context, YuvImage yuvImage) {

    int w = yuvImage.getWidth();
    int h = yuvImage.getHeight();

    if (rs == null) {
        // once
        rs = RenderScript.create(context);
        yuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }

    if (yuvAllocation == null || yuvAllocation.getBytesSize() < yuvImage.getYuvData().length) {
        yuvType = new Type.Builder(rs, Element.U8(rs)).setX(yuvImage.getYuvData().length);
        yuvAllocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
        Log.w(TAG, "allocate in " + yuvAllocation.getBytesSize() + " " + w + "x" + h);
    }

    if (rgbaAllocation == null || 
            rgbaAllocation.getBytesSize() < rgbaAllocation.getElement().getBytesSize()*w*h) {
        rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(w).setY(h);
        rgbaAllocation = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
        Log.w(TAG, "allocate out " + rgbaAllocation.getBytesSize() + " " + w + "x" + h);
    }

    yuvAllocation.copyFrom(yuvImage.getYuvData());

    yuvToRgb.setInput(yuvAllocation);
    yuvToRgb.forEach(rgbaAllocation);

    if (bmpout == null) {
        bmpout = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    }
    rgbaAllocation.copyTo(bmpout);
    return bmpout;
}

这篇关于Renderscript ScriptIntrinsicYuvToRGB和位分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆