有没有人设法使用RenderScript和新的Camera API获得YUV_420_888帧?

时间:2015-06-04 20:14:16

标签: android android-camera android-5.0-lollipop renderscript yuv

我使用RenderScript和Allocation从Android Camera2 API获取YUV_420_888帧,但是一旦我从分配中复制byte [],我只从组成帧的3个平面接收Y平面,而字节[]中的U和V平面值设置为0。我试图模仿previos相机API中的onPreviewframe,以便在应用程序处理相机帧时执行。我的分配创建如下:

Type.Builder yuvTypeBuilderIn = new Type.Builder(rs, Element.YUV(rs));
    yuvTypeBuilderIn.setX(dimensions.getWidth());
    yuvTypeBuilderIn.setY(dimensions.getHeight());
    yuvTypeBuilderIn.setYuvFormat(ImageFormat.YUV_420_888);
    allocation = Allocation.createTyped(rs, yuvTypeBuilderIn.create(),
            Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);

虽然我的脚本看起来像:

#pragma version(1)
#pragma rs java_package_name(my_package)
#pragma rs_fp_relaxed

rs_allocation my_frame;

4 个答案:

答案 0 :(得分:6)

Android示例应用程序HdrViewfinderDemo使用RenderScript处理来自camera2的YUV数据。

https://github.com/googlesamples/android-HdrViewfinder

具体来说,ViewfinderProcessor设置了分配,hdr_merge.rs从中读取。

答案 1 :(得分:3)

是的我做到了,因为我找不到任何有用的东西。但我没有采用建议的方式来定义表面的分配。相反,我只是将三个图像平面的输出转换为RGB。这种方法的原因是我使用YUV420_888数据两倍。首先在高频基础上仅强度值(Y)。其次,我也需要制作一些彩色位图。因此,以下解决方案。 1280x720 YUV_420_888图像的脚本大约需要80ms,可能不是超快,但我的目的还可以。

更新:我在这里删除了代码,因为我在这里写了一个更通用的解决方案YUV_420_888 -> Bitmap conversion,它也考虑了pixelStride和rowStride。

答案 2 :(得分:2)

我认为您可以使用ImageReader将相机的帧渲染到YUV_420_888

reader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(), ImageFormat.YUV_420_888, 2);

然后将OnImageAvailableListener设置为阅读器:

 reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
             int jump = 4; //Le nombre d'image à sauter avant d'en traiter une, pour liberer de la mémoire
             Image readImage = reader.acquireNextImage();

             readImage.getPlane[0] // The Y plane
             readImage.getPlane[1] //The U plane
             readImage.getPlane[2] //The V plane

             readImage.close();
            }
        }, null);

希望能帮到你

答案 3 :(得分:0)

我在答案中使用的方法与widea几乎相同。

大约50帧之后你得到的例外可能是因为你使用acquireNextImage处理所有帧。文档建议:

  

警告:请考虑使用acquireLatestImage(),因为它会自动释放较旧的图像,并允许较慢运行的处理例程赶上最新的帧。 [..]

因此,如果您的异常是IllegalStateException,切换到acquireLatestImage可能会有所帮助。

并确保对从ImageReader检索到的所有图像调用close()。