从 Android 通过套接字发送缓冲数据
我开发了 Android 应用程序的第一部分,该应用程序允许通过网络广播视频流。目前,我正在以非常直接的方式发送视频,如下所示:
Socket socket = new Socket(InetAddress.getByName(hostname), port);
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
recorder.setOutputFile(pfd.getFileDescriptor());
但不幸的是,它不是很流畅。我想在通过套接字发送数据流之前对其进行缓冲。我尝试的方法之一是使用 Android API 将流写入文件中记录媒体,并使用另一个线程将文件流式传输到计算机上的服务器。
所以我的问题是:如何通过套接字发送仍在写入的文件? 由于 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();
但这对我来说听起来很脏......有更时尚的解决方案吗?
I develop the first part of an Android application that allows to broadcast video stream through the network. Currently, I'm sending the video in a very direct way, like this:
Socket socket = new Socket(InetAddress.getByName(hostname), port);
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
recorder.setOutputFile(pfd.getFileDescriptor());
But unfortunately, it is not very fluid. I want to buffered the data stream before sending it through the socket. One of the way I tried is to write the stream in a file using the Android API for recording media, and to use another thread to stream the file to the server on a conputer.
So my problem is: how can I send by a socket a file which is still under writing?
As BufferedInputStream has not a blocking method for reading, I tried to do things like this one, but without any success
while (inputStream.available() >= BUFFER_SIZE) {
inputStream.read(buffer);
outputStream.write(buffer);
}
outputStream.flush();
But when i'm doing that, if the network is faster than the datastream, I get quickly out of the loop.
Is there a 'good' way to do that? I though about doing active waiting but it is not a good solution, especially for mobiles. Another way is to do something like this :
while (true) {
while (inputStream.available() < BUFFER_SIZE) {
wait(TIME);
}
inputStream.read(buffer);
outputStream.write(buffer);
}
outputStream.flush();
But it sound quite dirty for me... Is there sleeker solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这些情况下,我要做的就是简单地填充一个字节数组(我的缓冲区),直到我到达要传输的数据的末尾,或者缓冲区已满。在这种情况下,缓冲区已准备好传递给我的套接字传输逻辑。诚然,我不会对视频或音频执行此操作……仅对“常规”数据执行此操作。
值得注意的是,这会给该数据的接收者带来“卡顿”的用户体验(看起来网络可能会短时间停止,然后再次正常运行......缓冲区正在填满的时间)。因此,如果您必须对视频或音频使用缓冲方法,请注意您决定使用的缓冲区大小。
对于视频之类的东西,我的经验是使用基于流的逻辑而不是缓冲的逻辑,但您显然有一些不同且有趣的要求。
What I do in these situations if simply fill up a byte array (my buffer) until either I've hit the end of the data I'm about to transmit, or the buffer is full. In which case the buffer is ready to be passed to my Socket transmission logic. Admittedly, I do not do this on video or audio though … only on “regular” data.
Something worth noting is this will give a "janky" user experience to the recipient of that data (it might look like the network is stopping for short periods then running normally again ... the time the buffer is using to fill up). So if you have to use a buffered approach on either video or audio be careful on what buffer size you decide to work with.
For things like video it's been my experence to use streaming based logic versus buffered, but you apparently have some different and interesting requirements.
我想不出一种很好的方法来做到这一点,但一个选择可能是创建一个本地套接字对,使用该对的“客户端”端作为 MediaRecorder 输出 fd,并在本地服务器套接字和远程服务器。这样,您可以阻塞本地服务器,直到有数据为止。
另一种可能性是使用基于文件的管道/fifo(这样磁盘就不会填满),但我不记得Java层是否公开了mkfifo功能。
无论如何,您可能想看看 FileReader,因为阅读那应该阻止。
希望这有帮助,
菲尔·莱洛
I can't think of a pretty way of doing this, but one option might be to create a local socket pair, use the 'client' end of the pair as the MediaRecorder output fd, and buffer between the local-server socket and the remote-server. This way, you can block on the local-server until there is data.
Another possibility is to use a file-based pipe/fifo (so the disk doesn't fill up), but I can't remember if the Java layer exposes mkfifo functionality.
In any event, you probably want to look at FileReader, since reads on that should block.
Hope this helps,
Phil Lello