相机2,增加FPS

时间:2016-12-14 23:32:52

标签: android jpeg yuv frame-rate camera2

我正在使用Camera 2 API将JPEG图像保存在磁盘上。我目前在我的Nexus 5X上有3-4 fps,我想把它提升到20-30。有可能吗?

将图像格式更改为YUV我设法生成30 fps。是否有可能以这种帧率保存它们,还是应该放弃并使用我的3-4 fps?

显然,如果需要我可以共享代码,但如果每个人都同意这是不可能的,我会放弃。使用NDK(例如libjpeg)是一个选项(但显然我宁愿避免它......)。

由于

编辑:这是我如何将YUV android.media.Image转换为单个字节[]:

private byte[] toByteArray(Image image, File destination) {

    ByteBuffer buffer0 = image.getPlanes()[0].getBuffer();
    ByteBuffer buffer2 = image.getPlanes()[2].getBuffer();
    int buffer0_size = buffer0.remaining();
    int buffer2_size = buffer2.remaining();

    byte[] bytes = new byte[buffer0_size + buffer2_size];

    buffer0.get(bytes, 0, buffer0_size);
    buffer2.get(bytes, buffer0_size, buffer2_size);

    return bytes;
}

编辑2:我发现将YUV图像转换为byte []的另一种方法:

private byte[] toByteArray(Image image, File destination) {

    Image.Plane yPlane = image.getPlanes()[0];
    Image.Plane uPlane = image.getPlanes()[1];
    Image.Plane vPlane = image.getPlanes()[2];

    int ySize = yPlane.getBuffer().remaining();

    // be aware that this size does not include the padding at the end, if there is any
    // (e.g. if pixel stride is 2 the size is ySize / 2 - 1)
    int uSize = uPlane.getBuffer().remaining();
    int vSize = vPlane.getBuffer().remaining();

    byte[] data = new byte[ySize + (ySize/2)];

    yPlane.getBuffer().get(data, 0, ySize);

    ByteBuffer ub = uPlane.getBuffer();
    ByteBuffer vb = vPlane.getBuffer();

    int uvPixelStride = uPlane.getPixelStride(); //stride guaranteed to be the same for u and v planes

    if (uvPixelStride == 1) {

        uPlane.getBuffer().get(data, ySize, uSize);
        vPlane.getBuffer().get(data, ySize + uSize, vSize);
    }
    else {

        // if pixel stride is 2 there is padding between each pixel
        // converting it to NV21 by filling the gaps of the v plane with the u values
        vb.get(data, ySize, vSize);
        for (int i = 0; i < uSize; i += 2) {
            data[ySize + i + 1] = ub.get(i);
        }
    }

    return data;
}

1 个答案:

答案 0 :(得分:1)

移动电话上的专用JPEG编码器单元效率很高,但通常不会针对吞吐量进行优化。 (历史上,用户每隔一两秒拍摄一张照片)。在全分辨率下,5X的相机管道不会以高于几FPS的速度生成JPEG。

如果您需要更高的费率,则需要捕获未压缩的YUV。正如CommonsWare所提到的,没有足够的磁盘带宽来将全分辨率的未压缩YUV流式传输到磁盘,因此在内存不足之前只能保留一定数量的帧。

您可以使用libjpeg-turbo或其他一些高效JPEG编码器,看看您可以自己压缩每秒的帧数 - 这可能高于硬件JPEG单元。最大化速率的最简单方法是以30fps捕获YUV,并行运行一些JPEG编码线程。为了获得最大速度,您需要手动编写与JPEG编码器通信的代码,因为您的源数据是YUV,而不是RGB,大多数JPEG编码接口都倾向于接受(尽管通常编码JPEG的颜色空间实际上是YUV以及。)

每当编码器线程完成前一帧时,它就可以抓取来自摄像机的下一帧(您可以维护最新YUV图像的小循环缓冲区以使其更简单)。