Streaming Raw H.264 From A Raspberry Pi

Introduction

This post explains how to generate a raw H.264 stream on a Raspberry Pi (RPi) and send that stream to other computers on a network. The stream can be played on:

The camera device is a Raspberry Pi running Raspbian connected to a standard camera module. The built in raspivid program will be used to generate a raw H.264 video stream, which will then be sent out over the network as one of the following:

  • TCP/IP stream using netcat
  • HTTP stream using UV4L
  • Multicast stream using multicat (not fully supported)

The viewing device is one or more of these:

  • a Raspberry Pi running Raspbian
  • an Android device running RPiC

Basic Raspberry Pi Setup

All of the following setup descriptions are based on a Raspberry Pi system created using the following steps:

  • install Raspbian Jessie Lite on an SD card (at least 2GB)
  • run sudo raspi-config and do the following:
    • update raspi-config itself
    • expand the file system
    • enable the camera
    • set the device to boot to the console requiring login
    • change the password
    • change the host name
    • reboot
  • sudo apt-get install -y rpi-update
  • sudo rpi-update
  • sudo reboot

Building The hello_video Demo Program

The easiest way to play the raw H.264 stream on a Raspberry Pi is with one of the standard demo programs, hello_video, located in /opt/vc/src/hello_pi. But first, you have to build it with these commands:

  • cd /opt/vc/src/hello_pi
  • make -C libs/ilclient
  • make -C libs/vgfont
  • cd hello_video
  • make
  • cp hello_video.bin ~

This also copies the resulting binary program (hello_video.bin) to your home directory, which is where you should use it from.

The hello_video program reads the raw H.264 stream from stdin and displays it at the coordinates you pass in as parameters, which are usually the top-left and bottom-right coordinates of the entire screen, for example:

./hello_video.bin 0 0 1920 1080

Generating The Stream Using raspivid

The raspivid program is very simple to use, since only one specific version of it is required:

raspivid -n -ih -t 0 -rot 0 -w 1280 -h 720 -fps 15 -b 1000000 -o -

It should be fairly obvious which parameters are the width, height, frame rate and bit rate. You can modify these to suit your needs, but for the purposes of this post, we’ll use the above: 1280×720 video at 15 frames per second with a bit rate of 1MB/s. The other parameters are:

  • -n to not show the video on the Raspberry Pi display
  • -ih to insert H.264 headers into the stream
  • -t 0 to keep streaming forever
  • -rot 0 to not rotate the stream
  • -o – to send the stream to stdout

TCP/IP Streaming Using netcat

This method is by far the simplest, both in terms of setup and overhead. It uses a standard raspivid command and pipes the output into the netcat (nc) program, which sends the stream out over a specific TCP/IP port. For example, to send the stream out over port 5001, you would do:

raspivid -n -ih -t 0 -rot 0 -w 1280 -h 720 -fps 15 -b 1000000 -o - | nc -lkv4 5001

The netcat parameters are:

  • -l 5001 listen on port 5001
  • -k to connect repeatedly
  • -v to produce verbose error messages
  • -4 to use IPv4 addresses only

Unfortunately, netcat can only handle one stream at a time. If you want to handle multiple network streams at the same time you need to replace netcat with ncat, which is part of the nmap package and can be installed with:

  • sudo apt-get install -y nmap

Now just substitute ncat for nc in the above command and multiple devices will be able to view the stream simultaneously:

raspivid -n -ih -t 0 -rot 0 -w 1280 -h 720 -fps 15 -b 1000000 -o - | ncat -lkv4 5001

Regardless of which program you use to send the stream, you only need netcat to receive the stream on another RPi. Just specify the network address and port for the camera device and pipe it into hello_video:

nc 192.168.0.182 5001 | ./hello_video.bin 0 0 1920 1080

HTTP Streaming Using UV4L

This method requires the UV4L software. The full installation instructions for UV4L explain everything you need, but here’s the short version:

  • curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add –
  • edit /etc/apt/sources.list and append this line:
    • deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main
  • sudo apt-get update
  • sudo apt-get install -y uv4l uv4l-raspicam
  • sudo apt-get install uv4l-raspicam-extras
  • sudo apt-get install -y uv4l-webrtc
  • sudo reboot

After the reboot, verify that it’s all working by using a browser to go to port 8080 on the camera device (http://address:8080). This should display the UV4L web interface, which we won’t use at all. The easiest way to configure the UV4L stream is by editing the /etc/uv4l/uv4l-raspicam.conf file. The settings that correspond to the standard raspivid command (described above) are:

  • encoding = h264
  • width = 1280
  • height = 720
  • framerate = 15
  • bitrate = 1000000
  • inline-headers = yes

The default port is 8080, which you may want to modify with this setting:

  • server-option = –port=8080

You should set the passwords for the “admin” and “config” users by modifying these settings:

  • server-option = –admin-password=password
  • server-option = –config-password=password

After any changes to this file, you can restart UV4L with:

  • sudo service uv4l_raspicam restart

To receive the stream on another RPi, use the curl program. Just specify the full HTTP address, port and path for the camera device and pipe it into hello_video. For example, a typical UV4L address, port and path would be:

curl http://192.168.0.183:8080/stream/video.h264 | ./hello_video.bin 0 0 1920 1080

Multicast Streaming Using multicat

Multicast support is not really working! At best you’ll get a thin strip of video at the top of the screen that is slightly recognizable. Furthermore, the only multicast address that seems to work is 224.0.0.1.

This method requires the multicat program, which can be installed with:

  • sudo apt-get install multicat

Use a standard raspivid command and pipe its output into multicat, which broadcasts the stream to a specific multicast address on a specific port. For example, to send the stream to address 224.0.0.1 on port 5001, you would do:

raspivid -n -ih -t 0 -rot 0 -w 1280 -h 720 -fps 15 -b 1000000 -o - | multicat /dev/stdin 224.0.0.1:5001

To receive the broadcast stream on another RPi, once again use the multicat program. Just specify the broadcast address and port for the camera device and pipe it into hello_video:

multicat -X @224.0.0.1:5001 /dev/null | ./hello_video.bin 0 0 1920 1080

Leave a Reply