简体   繁体   English

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

[英]Has anyone managed to obtain a YUV_420_888 frame using RenderScript and the new Camera API?

I'm using RenderScript and Allocation to obtain YUV_420_888 frames from the Android Camera2 API, but once I copy the byte[] from the Allocation I receive only the Y plane from the 3 planes which compose the frame, while the U and V planes values are set to 0 in the byte[]. 我正在使用RenderScript和Allocation从Android Camera2 API获取YUV_420_888帧,但是一旦我从分配中复制byte [],我只从组成帧的3个平面接收Y平面,而U和V平面值在字节[]中设置为0。 I'm trying to mimic the onPreviewframe from the previos camera API in order to perform in app processing of the camera frames. 我试图模仿previos相机API中的onPreviewframe,以便在应用程序处理相机帧时执行。 My Allocation is created like: 我的分配创建如下:

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

while my script looks like: 而我的脚本看起来像:

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

rs_allocation my_frame;

The Android sample app HdrViewfinderDemo uses RenderScript to process YUV data from camera2. Android示例应用程序HdrViewfinderDemo使用RenderScript处理来自camera2的YUV数据。

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

Specifically, the ViewfinderProcessor sets up the Allocations, and hdr_merge.rs reads from them. 具体来说, ViewfinderProcessor设置Allocations, hdr_merge.rs从中读取。

Yes I did it, since I couldn't find anything useful. 是的我做到了,因为我找不到任何有用的东西。 But I didn't go the proposed way of defining an allocation to the surface. 但我没有采用建议的方式来定义表面的分配。 Instead I just converted the output of the three image planes to RGB. 相反,我只是将三个图像平面的输出转换为RGB。 The reason for this approach is that I use the YUV420_888 data twofold. 这种方法的原因是我使用YUV420_888数据两倍。 First on a high frequency basis just the intensity values (Y). 首先在高频基础上仅强度值(Y)。 Second, I need to make some color Bitmaps too. 其次,我也需要制作一些彩色位图。 Thus, the following solution. 因此,以下解决方案。 The script takes about 80ms for a 1280x720 YUV_420_888 image, maybe not ultra fast, but ok for my purpose. 对于1280x720 YUV_420_888图像,该脚本大约需要80毫秒,可能不是超快,但我的目的还可以。

UPDATE: I deleted the code here, since I wrote a more general solution here YUV_420_888 -> Bitmap conversion that takes into account pixelStride and rowStride too. 更新:我在这里删除了代码,因为我在这里写了一个更通用的解决方案YUV_420_888 - >位图转换也考虑了pixelStride和rowStride。

I think that you can use an ImageReader to get the frames of you camera into YUV_420_888 我认为您可以使用ImageReader将相机的帧设置为YUV_420_888

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

Then you set an OnImageAvailableListener to the reader : 然后为读者设置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);

Hope that will help you 希望能帮到你

I'm using almost the same method as widea in their answer. 我在答案中使用的方法与widea几乎相同。

The exception you keep getting after ~50 frames might be due to the fact that you're processing all the frames by using acquireNextImage . 在大约50帧之后你得到的例外可能是因为你正在使用acquireNextImage处理所有帧。 The documentation suggest to: 文档建议:

Warning: Consider using acquireLatestImage() instead, as it will automatically release older images, and allow slower-running processing routines to catch up to the newest frame. 警告:请考虑使用acquireLatestImage(),因为它会自动释放较旧的图像,并允许较慢运行的处理例程赶上最新的帧。 [..] [..]

So in case your exception is a IllegalStateException, switching to acquireLatestImage might help. 因此,如果您的异常是IllegalStateException,切换到acquireLatestImage可能会有所帮助。

And make sure you call close() on all images retrieved from ImageReader. 并确保在从ImageReader检索的所有图像上调用close()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM