Intereting Posts
Код буфера обмена Android, который работает на всех уровнях API Как заставить просмотр recycler начинать добавлять элементы из центра? Тестирование Android В приложениях Биллинг реальных покупок В eclipse не удалось ссылаться на проект библиотеки Android в другом проекте Android Touch Calculator в Android Как Android обрабатывает фоновые потоки при выходе из Activity? Как настроить Cordova-android 4.0 с белым списком Есть ли какие-либо преимущества для перехода на Otto из событий Broadcast Начать новую работу и завершить текущий в Android? Обратные вызовы удаленных служб Android Ошибка: пакет com.google.android.gcm не существует – после перехода на Gradle Android Studio: значок приложения не отображается в главном экране или списке приложений. Android получает путь от источника видео от VideoView Android: как сдвинуть высоту выходного звука (в реальном времени) Как я могу использовать новый Xtend-язык Eclipse в своем проекте Android?

Android: потоковая передача камеры как mjpeg

После нескольких дней поиска SO и google я начинаю сдаваться, поэтому я подумал, что могу опубликовать здесь.

Я создаю приложение для Android, которое должно предложить какой-то видеочат. Поскольку это должно быть как можно ближе к реальному времени, я читал о различных протоколах и решил попробовать MJPEG для начинающих (теперь это не касается звука).

Прямо сейчас потоковая передача данных сводит меня с ума. Соединение устанавливается, приложение начинает записывать кадры предварительного просмотра камеры в поток, но ни VLC, ни mplayer не начинают воспроизводить видео. Мониторинг подключения показывает, что данные поступают.

Подключение Этот код выполняется с помощью задачи async, при успешном прослушивании уведомляется слушатель:

try { ServerSocket server = new ServerSocket(8080); socket = server.accept(); server.close(); Log.i(TAG, "New connection to :" + socket.getInetAddress()); stream = new DataOutputStream(socket.getOutputStream()); prepared = true; } catch (IOException e) { Log.e(TAG, e.getMessage(); } 

На моем ПК я http://tabletIP:8080 «mplayer http://tabletIP:8080 », и планшет регистрирует соединение (и, таким образом, запускает мой стример и предварительный просмотр камеры). Это также работает с VLC.

Streaming Это записывает заголовок в поток:

 if (stream != null) { try { // send the header stream.write(("HTTP/1.0 200 OK\r\n" + "Server: iRecon\r\n" + "Connection: close\r\n" + "Max-Age: 0\r\n" + "Expires: 0\r\n" + "Cache-Control: no-cache, private\r\n" + "Pragma: no-cache\r\n" + "Content-Type: multipart/x-mixed-replace; " + "boundary=--" + boundary + "\r\n\r\n").getBytes()); stream.flush(); streaming = true; } catch (IOException e) { notifyOnEncoderError(this, "Error while writing header: " + e.getMessage()); stop(); } } 

После этого потоковая передача запускается через Camera.onPreviewFrame () Обратный вызов:

 @Override public void onPreviewFrame(byte[] data, Camera camera) { frame = data; if (streaming) mHandler.post(this); } @Override public void run() { // TODO: cache not filling? try { // buffer is a ByteArrayOutputStream buffer.reset(); switch (imageFormat) { case ImageFormat.JPEG: // nothing to do, leave it that way buffer.write(frame); break; case ImageFormat.NV16: case ImageFormat.NV21: case ImageFormat.YUY2: case ImageFormat.YV12: new YuvImage(frame, imageFormat, w, h, null).compressToJpeg(area, 100, buffer); break; default: throw new IOException("Error while encoding: unsupported image format"); } buffer.flush(); // write the content header stream.write(("--" + boundary + "\r\n" + "Content-type: image/jpg\r\n" + "Content-Length: " + buffer.size() + "\r\n\r\n").getBytes()); // Should omit the array copy buffer.writeTo(stream); stream.write("\r\n\r\n".getBytes()); stream.flush(); } catch (IOException e) { stop(); notifyOnEncoderError(this, e.getMessage()); } } 

Исключено исключение. MHandler работает в собственном HandlerThread. Просто чтобы убедиться, что я попытался использовать AsyncTask, безрезультатно (кстати, это лучше?).

Закодированные фреймы на стороне Android отлично, я сохранил их в jpg-файлах и мог их открыть.

Я предполагаю, что мне нужно как-то скопировать данные или установить некоторые параметры для сокета или что-то в этом роде, но … ну, я застрял.

Tl; dr: VLC не играет в поток, mplayer говорит, что «кеш не заполняется», проблема, вероятно, в последнем сегменте кода, нужна помощь ~ 🙂

Благодарю вас!

Solutions Collecting From Web of "Android: потоковая передача камеры как mjpeg"

Я понял. Похоже, что мои заголовки http / / content были испорчены. Правильные заголовки должны быть:

 stream.write(("HTTP/1.0 200 OK\r\n" + "Server: iRecon\r\n" + "Connection: close\r\n" + "Max-Age: 0\r\n" + "Expires: 0\r\n" + "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n" + "Pragma: no-cache\r\n" + "Content-Type: multipart/x-mixed-replace; " + "boundary=" + boundary + "\r\n" + "\r\n" + "--" + boundary + "\r\n").getBytes()); 

а также

 stream.write(("Content-type: image/jpeg\r\n" + "Content-Length: " + buffer.size() + "\r\n" + "X-Timestamp:" + timestamp + "\r\n" + "\r\n").getBytes()); buffer.writeTo(stream); stream.write(("\r\n--" + boundary + "\r\n").getBytes()); 

Конечно, где поставить границу – это ваш собственный выбор. Также есть некоторые поля, которые являются необязательными (например, большинство из Cache-Control), но это работает, и до сих пор я был слишком ленив, чтобы их разбить. Важная часть состоит в том, чтобы помнить об очередях ( \r\n thingies) …