Отправка буферизованных данных через сокет из Android - PullRequest
1 голос
/ 08 апреля 2011

Я разрабатываю первую часть приложения для 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();

Но это звучит довольно грязно для меня ... Есть ли более изящное решение?

Ответы [ 2 ]

1 голос
/ 08 апреля 2011

Что я делаю в этих ситуациях, если просто заполняю байтовый массив (мой буфер) до тех пор, пока я не достигну конца данных, которые я собираюсь передать, или буфер не заполнится.В этом случае буфер готов к передаче в мою логику передачи Socket.Следует признать, что я не делаю этого на видео или аудио, хотя… только на «обычных» данных.

Что-то, на что стоит обратить внимание, это даст «неудобный» пользовательский опыт получателю этих данных (это может выглядеть каксеть останавливается на короткие промежутки времени, затем снова работает нормально ... время, которое буфер использует для заполнения).Поэтому, если вам нужно использовать буферизованный подход для видео или аудио, будьте осторожны с тем, с каким размером буфера вы решите работать.

Для таких вещей, как видео, я испытывал желание использовать потоковую логику, а не буферизованную, но выпо-видимому, есть разные и интересные требования.

0 голосов
/ 08 апреля 2011

Я не могу придумать красивый способ сделать это, но одним из вариантов может быть создание пары локальных сокетов, использование конца «client» пары в качестве выходного файла MediaRecorder и буфера между локальным серверомсокет и удаленный сервер.Таким образом, вы можете заблокировать локальный сервер до тех пор, пока не появятся данные.

Еще одна возможность - использовать файл-pipe / fifo (чтобы диск не заполнялся), но я не могупомните, если уровень Java предоставляет функциональность mkfifo.

В любом случае вы, вероятно, захотите взглянуть на FileReader , поскольку операции чтения этого блока должны блокироваться.

Надеюсь, это поможет,

Фил Лелло

...