我正在使用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;
}
答案 0 :(得分:1)
移动电话上的专用JPEG编码器单元效率很高,但通常不会针对吞吐量进行优化。 (历史上,用户每隔一两秒拍摄一张照片)。在全分辨率下,5X的相机管道不会以高于几FPS的速度生成JPEG。
如果您需要更高的费率,则需要捕获未压缩的YUV。正如CommonsWare所提到的,没有足够的磁盘带宽来将全分辨率的未压缩YUV流式传输到磁盘,因此在内存不足之前只能保留一定数量的帧。
您可以使用libjpeg-turbo或其他一些高效JPEG编码器,看看您可以自己压缩每秒的帧数 - 这可能高于硬件JPEG单元。最大化速率的最简单方法是以30fps捕获YUV,并行运行一些JPEG编码线程。为了获得最大速度,您需要手动编写与JPEG编码器通信的代码,因为您的源数据是YUV,而不是RGB,大多数JPEG编码接口都倾向于接受(尽管通常编码JPEG的颜色空间实际上是YUV以及。)
每当编码器线程完成前一帧时,它就可以抓取来自摄像机的下一帧(您可以维护最新YUV图像的小循环缓冲区以使其更简单)。