[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