我开发了Android应用程序的第一部分,允许通过网络广播视频流。目前,我正在以非常直接的方式发送视频,如下所示:
Socket socket = new Socket(InetAddress.getByName(hostname), port);
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
recorder.setOutputFile(pfd.getFileDescriptor());
但不幸的是,它不是很流畅。我想在通过套接字发送之前缓冲数据流。我尝试的方法之一是使用Android API for recording media在文件中编写流,并使用另一个线程将文件流式传输到计算机上的服务器。
所以我的问题是:如何通过套接字发送仍在编写的文件? 由于BufferedInputStream没有阻止阅读的方法,我试图做这样的事情,但没有任何成功
while (inputStream.available() >= BUFFER_SIZE) {
inputStream.read(buffer);
outputStream.write(buffer);
}
outputStream.flush();
但是当我这样做时,如果网络速度比数据流快,我就会很快离开循环。
有一种'好'的方法吗?我虽然做主动等待,但它不是一个好的解决方案,特别是对于手机。另一种方法是做这样的事情:
while (true) {
while (inputStream.available() < BUFFER_SIZE) {
wait(TIME);
}
inputStream.read(buffer);
outputStream.write(buffer);
}
outputStream.flush();
但对我来说这听起来很脏......是否有更时尚的解决方案?
答案 0 :(得分:1)
在这些情况下,如果只是填充一个字节数组(我的缓冲区),直到我要点击我要传输的数据的末尾,或者缓冲区已满,我会做什么。在这种情况下,缓冲区已准备好传递给我的Socket传输逻辑。不可否认,我不会在视频或音频上执行此操作,但仅限于“常规”数据。
值得注意的是,这将为该数据的接收者提供“janky”用户体验(它可能看起来像网络短时间停止然后再次正常运行...缓冲区用于填充的时间)。因此,如果您必须对视频或音频使用缓冲方法,请注意您决定使用的缓冲区大小。
对于像视频这样的东西,我一直使用基于流的逻辑而不是缓冲,但你显然有一些不同的和有趣的要求。
答案 1 :(得分:0)
我想不出一个漂亮的方法,但是一个选项可能是创建本地套接字对,使用该对的“客户端”作为MediaRecorder输出fd,以及本地服务器之间的缓冲区套接字和远程服务器。这样,您可以在本地服务器上阻塞,直到有数据。
另一种可能性是使用基于文件的管道/ fifo(因此磁盘没有填满),但我不记得Java层是否公开了mkfifo功能。
无论如何,您可能希望查看FileReader,因为读取内容应该阻止。
希望这有帮助,
Phil Lello