10 de octubre de 2014

Streaming Video con Java en Raspberry Pi

Streaming de Video con Java en Raspberry Pi


Hay dos modos de crear streming, uno es capturando las fotos (jpeg) que se toman con raspistill, el otro modo es capturando el vídeo (h264) generado con raspivid, como se observa en el tutorial de:   Streaming Video desde el Raspberry Pi, ahora se va generar este streaming con Java.

Como funciona?

Proyectos necesarios vía GitHub:


git clone https://github.com/andresvelezperez/raspberry-pi.git
Proyecto Maven: StreamingPi
git clone https://github.com/andresvelezperez/java.git
Proyecto Maven: H264J


El server, es un servidor de paquetes UDP (Datagrama) que esta en el proyecto StreamingPi, el cual solo recibe el flujo de datos, dependiendo de la opción que se incluya jpeg o h264 se activa el reproductor correspondiente, para el caso de h264, es un codec escrito en java que es un "port" de la libreria ffmpeg-libavcodec (pero solo la parte de h264). El proyecto original esta en Google Code h264j, pero copie el proyecto y agregue unas mínimas modificaciones para que reciba el streaming de forma directa, proyecto H264J.

Proyecto disponible en:
GitHub: https://github.com/andresvelezperez/java
Original: https://code.google.com/p/h264j/


En el momento el reproductor de fotos/vídeo (jpeg/h264) es básico, solo muestra imágenes, próximamente mas opciones.

Para el lado del cliente, es UDP, solo envía lo que genera los aplicativos raspistill y raspisvid, no se usa el modo normal de "pipe" (|), el api de Java cuenta con con una clase que permite la ejecución de comandos y obtener el "stdout" vía inputStreaming.

Ejemplo:


//command: lista de parametros, primero parametro es el comando a ejecutar.
ProcessBuilder  processBuilder = new ProcessBuilder(command);
//Se incia el proceso y se obtiene el inpuStream de la ejecucion, esto es lo que se envía por UDP.
Process process = processBuilder.start();
InputStream  inputStream = process.getInputStream();

Ver Clase para ver implementación completa: 
org.avpsoft.streaming.net.DatagramCommandClient.java

Uso



Opción con raspistill


Primero ejecutamos el servidor (en windows), quien recibe el streaming:

D:\GitHub\raspberry-pi\StreaminPi>java -cp ./target/StreamingPi-1.0-SNAPSHOT.jar org.avpsoft.streaming.main.Streaming 4445 jpeg

Esto nos abre una ventana, donde se mostrara las imágenes.

Ahora ejecutamos el servidor (Raspberry Pi):

pi@raspberrypi ~ $ java -cp ./StreamingPi-1.0-SNAPSHOT.jar org.avpsoft.streaming.main.Streaming 192.168.1.2 4445 raspistill -n -t 0 -tl 150 -th 0:0:0 -w 640 -h 480 -q 5 -o -

Las primeras dos opciones es la ip del servidor y el puerto son fijas, no puede cambiar el orden.




Ejemplo del "lag" (retraso generado) al usar este metodo, 4 segundos, el mejor tiempo que pude registrar estuvo en 3 segundos.


Opción con raspivid

Se requiere este jar adicional H264J-1.0-SNAPSHOT.jar, para el codec h264.
Primero ejecutamos el servidor (en windows), quien recibe el streaming:

D:\GitHub\raspberry-pi\StreaminPi>java -cp ./*.jar org.avpsoft.streaming.main.Streaming 4445 h264

Esto nos abre una ventana, donde se mostrara las imágenes.

Ahora ejecutamos el servidor (Raspberry Pi):

pi@raspberrypi ~ $ java -cp ./StreamingPi-1.0-SNAPSHOT.jar org.avpsoft.streaming.main.Streaming 192.168.1.2 4445  raspivid -n -t 0 -w 640 -h 480 -fps 10 -o -

Las primeras dos opciones es la ip del servidor y el puerto son fijas, no puede cambiar el orden.






Ejemplo del "lag" (retraso generado) al usar este método, es de menos de 1 segundo, mas o menos 300 milisegundos.

Problemas:

* Debido a que se usa UDP y no TCP, es posible que las imágenes se distorsionen, pero es causado por la fiabilidad de la red, si tiene mala señal WIFI eso pasara.
* Cuando se ejecuta el server con h264, es posible que salga errores, pero el streaming sigue funcionando.
* Para terminan la ejecución use Ctrl+C



12 comentarios:

  1. Andres. Lo primero de todo es darte las gracias por el esfuerzo que supone el trabajo y el publicarlo para que otros podamos aprender.
    No vengo del mundo del software pero estoy haciéndome una aplicación que necesito exactamente lo que has publicado. Mi problema es que no se bajar el proyecto desde el repositorio... ¿como puedo bajármelo?
    un saludo

    ResponderEliminar
    Respuestas
    1. Hola, disculpa la tardanza en responder, pero si ingresas a esta URL: https://github.com/andresvelezperez/raspberry-pi al lado derecho aparece un boton que dice: Download Zip

      o tambien puedes instalar "git" t descargar el codigo de la url del repositorio.

      Eliminar
  2. como bajo el programa a la raspberry pi?

    gracias de nuevo

    ResponderEliminar
    Respuestas
    1. Puedes usar FileZilla para transferir los .jar.

      Eliminar
  3. Muy buenas Andres.
    lo primero es felicitarte el año.
    He visto en tu Web que tienes publicado un montón de formas distintas de hacer streaming con las cámaras de la raspberry.
    Estoy haciendo una aplicación en la que necesito meter en un jpanel el video capturado en streaming desde una cámara pi de raspberry. Cuando empezé pensaba que habria drivers para su funcionamiento, pero no he sido capaz de encontar algo bueno salvo lo tuyo.

    ¿que me aconsejas para meter el video streaming en un jpanel?
    parece que tu aplicación en java es lo más razonable, pero he visto que tienes una gran cantidad de ficheros en cada uno de los proyectos streaming pi y java y la verdad que no he sido capaz de aclararme.

    muchas gracias de antemano.

    ResponderEliminar
    Respuestas
    1. Cordial Saludo

      La clase H264Player que esta en la libreria H264 es la que inicia el panel que muestra el video, para el caso de transmitir fotos, la clase JPEGPlayer que esta en StrammingPi.

      La clase principal es Streaming.java dependendo de lo que se este ejecutando se incia, cliente o servidor, elservidor es el que se ejcuta en windows el que muestra el panel, el cliente es el que se ejecuta en el rpi que no tiene interfaz grafica.

      Eliminar
  4. Andres.

    ya he sido capaz de correr el programa, pero la imagen tiene ruido en exceso y no se debe a que la red alámbrica esté mal.

    ¿tienes idea de por donde puedo mirar para solucionar el problema?

    gracias de antemano

    ResponderEliminar
    Respuestas
    1. Por favor poner URL de imagen del ruido, el ruido por se causado por la red wifi, probar con cable a ver si mejora.

      Eliminar
    2. Andres a mi me sucede lo mismo el video h264 se ve demasiado difuminado, se ve fatal la rpi esta conectada por cable a la red y el pc tb alguna sugerencia??

      Gracia makina

      Eliminar
    3. Posiblemente sea la versión de Java usada, si pueden compartir una imagen que toman, puede ser de utilidad.

      Eliminar
  5. Hola andrés tu programa tiene muy buena pinta pero la imagen recivida en el servido tiene demasiado ruido practicamente no se puede vver da imagenes completamente difuminadas tengo todo conectado x cable y x lo que pones deberia verse mejor alguna ayuda??

    Un Saludo y Gracias Makina

    ResponderEliminar
    Respuestas
    1. Aparte de la versión de Java, puede ser que se pierda muchos paquetes porque el protocolo usado es UDP (próximamente por TCP), pero también se puede jugar con los parámetros que se le pasan a raspivid si es para vídeo. (compartir una imagen).

      Eliminar