我正在Nexus 6上使用适用于Android的camera2 api拍照。从我的代码到达onImageAvailable()到再次调用时,它几乎没有时间。
但是,通过tcp / ip发送我的照片需要大约700毫秒。
private ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader)
{
Image image = mImageReader.acquireLatestImage();
if(image.getPlanes().length == 0)
return;
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
if(buffer == null)
return;
byte[] pictureBytes = new byte[buffer.remaining()];
buffer.get(pictureBytes);
mOutputStream.write((String.valueOf(pictureBytes.length) + "....").getBytes());
// FROM HERE
mOutputStream.write(pictureBytes);
// TO HERE TAKES ~700ms
mOutputStream.flush();
}
我的连接是在另一个线程中创建的,如android所示,使用以下代码:
ServerSocket serverSocket = new ServerSocket(#);
Socket clientSocket = serverSocket.accept();
OutputStream outputStream = clientSocket.getOutputStream();
注意:主线程中的mOutputStream等于outputStream。我将outputStream传递给主线程。
我尝试过使用BufferedOutputStream,实际上速度较慢。
我的手机与其连接的设备之间的链接速度为130Mbps。对于小于2MB的图像,我应该能够每秒发送至少8张图片。
如何减少700毫秒的时间?谢谢!
答案 0 :(得分:0)
如果您使用TCP,即使您与其他设备有130mbps的连接,也无法立即使用所有带宽。这是因为TCP拥塞控制机制称为 slow-start 。
在每个连接开始时,TCP开始时发送少量数据,因为链接的容量未知。在接收到ACK之前发送的此流量由拥塞窗口定义,并且根据配置的MSS(最大段大小),它可以是MSS的2-4倍。确切数量在RFC5681中定义:
If SMSS > 2190 bytes:
IW = 2 * SMSS bytes and MUST NOT be more than 2 segments
If (SMSS > 1095 bytes) and (SMSS <= 2190 bytes):
IW = 3 * SMSS bytes and MUST NOT be more than 3 segments
If SMSS <= 1095 bytes:
IW = 4 * SMSS bytes and MUST NOT be more than 4 segments
在接收到每个ACK之后,拥塞窗口的大小增加了MSS的大小。这实际上意味着窗口大小呈指数增长。即使指数增长使TCP能够非常快地达到最大带宽,但对于相对较小的文件,这种速度还不够快。即使您的连接是100mbps,您也无法每秒发送8张图片,因为传输时间相对较短,并且窗口大小在相当长的传输时间内太小,无法使用完整的可用带宽。
根据往返时间(到服务器和返回),发送前1MB数据甚至可能需要500ms,因此您每秒发送2个或3个以上图像的可能性很小
答案 1 :(得分:-1)
我从Java切换到C#以读取字节。那是主要的瓶颈。我达到3.33 fps;这包括写入磁盘的时间。
但是,我确认这些照片不到2MB。
谢谢大家!