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



2 de octubre de 2014

Streaming Video from the Raspberry Pi

Streaming Video desde el Raspberry Pi



A continuacion se menciona las cuatro formas mas usadas para streaming en el Raspberry Pi.


Para habilitar la cámara se debe abrir desde la terminal raspi-config y habilitarla.



Ver:  Enabling the camera

Streaming con VLC

Instalar VLC:  

pi@raspberrypi ~ $ sudo apt-get install vlc

Para su computador descargar la versión que corresponde a su sistema operativo: http://www.videolan.org/

Creando el Streaming

pi@raspberrypi ~ $ raspivid -o - -t 0 -n -w 600 -h 400 -fps 12 | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

Para recibir el streaming, se usara VLC en Windows, al abrir VLC Archivo->"Abrir dispositivo de captura...", en la venta que nos abre, seleccionar la pestaña "Red" se ingresa la URL: rtsp://192.168.1.10:8554/ (cambiar por la ip que tenga su Raspberry Pi).



Resultado del Streaming.


El comando raspivid es el usado para capturar vídeo desde la cámara, opciones usadas:

  • "-o -" causa que la salida sea stdout
  • "-t 0" que grabe indefinidamente
  • "-n" que no muestre imagen por la conexión hdmi.
  • "-w xxx" xxx= ancho del video (64 a 1920)
  • "-h yyy" yyy= alto del video (64 a 1080)
  • "-fps nnn" nnn= Frame por segundos (2 a 90) 

Nota: La combinación de parámetros esta condicionada, video a 1080p30, 720p60 y 640x480p60/90.
Ver Opciones: Camera

Opciones usadas de VLC:

  • "-vvv" Verbose ouput (debug y otros).
  • "stream://"   Captura de vídeo.
  • "--sout "    Salida del stream.

Con esta opcion el retraso (lag) del video es mayor a 6 segundos.


Streaming con MJPG-Streamer


Instalación de MJPG-Streamer

pi@raspberrypi ~ $
pi@raspberrypi ~ $ sudo apt-get install libjpeg8-dev imagemagick libv4l-dev


pi@raspberrypi ~ $ mkdir  mjpg-streamer
pi@raspberrypi ~ $ cd mjpg-streamer
pi@raspberrypi ~/mjpg-streamer $ wget http://sourceforge.net/code-snapshots/svn/m/mj/mjpg-streamer/code/mjpg-streamer-code-182.zip

pi@raspberrypi ~/mjpg-streamer $ unzip mjpg-streamer-code-182.zip
pi@raspberrypi ~/mjpg-streamer $ cd mjpg-streamer-code-182/mjpg-streamer
pi@raspberrypi ~/mjpg-streamer/mjpg-streamer-code-182/mjpg-streamer $ sudo ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h
pi@raspberrypi ~/mjpg-streamer/mjpg-streamer-code-182/mjpg-streamer $ make

Uso:

Consola 2: (se abre otra consola)
pi@raspberrypi ~ $ mkdir /tmp/stream 
pi@raspberrypi ~ $ raspistill --nopreview -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0

Consola 1: (donde se estaba trabjando)
pi@raspberrypi ~/mjpg-streamer/mjpg-streamer-code-182/mjpg-streamer $ ./mjpg_streamer -i "./input_file.so -f /tmp/stream -n pic.jpg" -o "./output_http.so -w ./www"


Abrir el Navegador con esta ruta: http://192.168.1.2:8080/  (La ip es la del Raspberry Pi).






Al lado derecho se tienen las diferentes opciones del Streaming.

Con esta opcion el retraso (lag) del video es mayor a 3 segundos.

Fuente: How to build and run MJPG-Streamer on the Raspberry Pi  y  Step 5: Get the webcam streamer for Raspberry Pi


Streaming con nc & mplayer


Instalación:

NC: NetCat es una herramienta sencilla que permite crear conexiones de red TCP/UDP, sea cliente o server para trasmitir mensajes, en la mayoria de los sistemas Linux trae este comando (hasta el momento no he visto un Linux que no lo traiga). Pero para windows el tema es otro, hay que descargarlo de una fuente fiable o descargar el fuente y compilarlo. He decido por la primera descargarlo de una fuente fiable, asi que me dirige a nmap y descargar nmap para windows, entre sus archivos tiene una version para windows de NetCat. La version usada es nmap-6.47-win32.zip, al descomprimir necesitamos solo tres archivos ncat.exe, libeay32.dll y ssleay32.dll.

mplayer: Es un reproductor multimedia libre, existe version para Windows. Se descarga de: mplayer para windows y el archivo mplayer-svn-37292-x86_64.7z 


Uso:

Primero en la consola cmd de windows no situamos donde se haya descomprimido el archivo de mplayer.
(a esta carpeta copiar los archivos de netcat).

En windows:

D:\mplayer-svn-37291-x86_64>ncat.exe -u -l 5001 | mplayer.exe -fps 60 -cache 1024 -

En el Raspberry Pi:

pi@raspberrypi ~ $ raspivid -n -t 0 -w 640 -h 480 -fps 10 -o - | nc -u 192.168.1.2 5001

La IP que se pone en el Raspberry Pi, es la IP de su computador, ya que el PC actua como server y el Rpi como server.

Al inicio tarda un poco mplayer en abrir la ventana del video, despues de abierta el straming es inmediato.






A diferencia de las otras opciones el retraso (lag) del video es menor a 300 milisegundos.


Fuente: What streaming solution for the Picam has the smallest lag?



Streaming con GSTREAMER


GStreamer: es un framework multimedia libre multiplataforma.

Instalacion:

En windows, se descarga directamente de Download GStreamer o ir directamente a windows y decargar la version que se necesita, para este caso gstreamer-1.0-x86_64-1.4.3.msi

En el Raspberry Pi,

pi@raspberrypi ~ $ sudo apt-get install gstreamer1.0

Algunos tutoriales dicen que hay que agregar un repositorio extra, en este caso no se hizo.

Uso:

En el Raspberry Pi:

pi@raspberrypi ~ $ raspivid -n -t 0 -h 720 -w 1080 -fps 25 -b 2000000 -o - | gst-launch-1.0 -v fdsrc ! h264parse !  rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=192.168.0.200 port=5000

En Windows:

D:\gstreamer\1.0\x86_64\bin>gst-launch-1.0 -v tcpclientsrc host=192.168.0.200 port=5000  ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false

La ip que se ve en los comandos se cambia por la IP que tenga el Raspberry Pi.



Esta opcion como la anterior tienen un retraso (lag) del video menor de 300 milisegundos.


Fuente: Raspberry Pi camera board – Gstreamer


Artículos externos relacionados: