[Jderobot-dev] RTSP y MJPEG sin delay en Android
Oscar Garcia
oscar.robotica en linaresdigital.com
Mie Mar 27 23:59:19 CET 2013
El 27/03/13 12:30, Roberto Calvo escribió:
> Cuando queréis mostrar un vídeo por RTSP o MJPEG en Android utilizando
> un VideoView o MediaPlayer, siempre tiene un delay excesivo (en torno a
> 10seg). Parece un delay añadido en código a bajo nivel dificil de
> saltarse.
Esto se debe a la naturaleza de las conexiones TCP y de los códecs
usados en el streaming. En el streaming de vídeo no puede faltar ningún
paquete de datos debido a que se envían fotogramas estimados a partir de
los anteriores en la gran parte del tiempo. La pérdida de un fotograma
estropearía la imagen de vídeo hasta el siguiente fotograma completo
(sin dependencias de los anteriores) recibido.
Para evitar parones debido a que un paquete se ralentice más de lo
normal se suele almacenar en memoria una serie de fotogramas (casi
siempre una o dos secuencias completas de fotograma completo más los
estimados en el tiempo) para minimizar cualquier tipo de parada en la
reproducción. Así que realmente el problema está en el reproductor, una
mínima parte de la culpa está en el transmisor.
> He encontrado un par de opciones que os pueden venir bien si
> necesitáis mostrar video en vuestras apps:
>
> MJPEG:
> En el siguiente enlace podéis encontrar el código para descargar y
> mostrar un video por streaming usando MJPEG. Tiene un delay de 1-2
> segundos y funciona bastante bien. La pega es que tiene que ir sobre
> http y no sobre rtsp
> http://stackoverflow.com/questions/10550139/android-ics-and-mjpeg-using-asynctask
Esta tarde he agregado soporte de vídeo a una implementación remota de
sensores y cámara en Android y este es el resultado:
http://www.youtube.com/watch?v=3UHwSxOfxqw
Subiré el código a mi repositorio en cuanto pueda (mañana temprano salgo
de vacaciones y no es tema de acostarme tarde :).
La gran ventaja de MJPEG es que cada fotograma es un fotograma completo,
no depende del anterior, por lo que no pasa nada si se pierde alguno,
podría enviarse por UDP uno a uno los fotogramas y evitaríamos el
problema de la congestión de una conexión TCP, pero si se usa HTTP como
transporte entonces hay que implementar algo en el transmisor para
detectar que el receptor está bien o está congestionado y debe saltarse
fotogramas.
Como podéis ver en mi implementación hay menos de un segundo de retardo
entre la imagen real y la mostrada en el navegador web. De vez en cuando
hay un parón debido a la pérdida de algún paquete en la red WiFi, por lo
que mi aplicación servidor (que usa un buffer de transmisión muy pequeño
y NIO como API de comunicaciones Java) detecta la congestión rápidamente
y evita seguir haciendo streaming hasta que se recupere el receptor.
En mi implementación de cameraserver en Android no es necesario control
de congestión debido a que el cliente solicita un fotograma y no
solicita el siguiente hasta haber recibido el anterior. Eso es
contraproducente debido a que se está limitando la cantidad de imágenes
por segundo a la latencia de la red y el tiempo de
codificación/decodificación:
http://www.youtube.com/watch?v=_d_8pzFQOZ4
En streaming de fotogramas la ventaja es que puede haber en tránsito más
de un fotograma en un momento dado o estar empezando a llegar un
fotograma en el lado del cliente cuando se empieza a codificar el
siguiente en el lado del servidor.
Si comparamos ambos vídeos, en la página web del vídeo de MJPEG se está
mostrando streaming de imágenes de 640x480 al igual que el segundo
ejemplo (el de la segunda mitad del vídeo de cameraserver, el que va
lento). Es notable la diferencia entre ambos.
Un saludo y que disfrutéis del puente de semana santa.
More information about the Jde-developers
mailing list