pit offers a node based multimedia pipeline similar to GStreamer. A node can carry audio or video, possibly transforming data before passing it to the next node in the pipeline. In this example we will build a video pipeline that captures frames from a Video for Linux 2 (V4L2) source and stream them to a RTP client, like VLC. The RTSP protocol is implemented entirely in Lua, while RTP and RTCP protocols are implemented in C. This example also demonstrates a way to build reusable object-oriented Lua modules. Instead of going through the source code line by line, I will highlight only the relevant sections. Additional information is present as comments in the main script code at script/testrtp.lua. You need to compile these pit libraries inside the src directory: jpeg-8d, libmedia, libv4l and libstream (be sure to synchronize your git repository first).
General purpose multimedia functions in pit are provided by libmedia, while V4L2 requires its own libv4l library:
camlib = pit.loadlib("libv4l") medialib = pit.loadlib("libmedia")
Our pipeline has four nodes: a camera node acting as a frame source (640×480 @ 15 fps), a rgb node to convert video frames to RGB format, a jpeg node to compress RGB frames to JPEG format (using 50 as compression quality), and a RTP node to actually stream the frames to a remote client. The first argument to this node is the network address to bind to. The second argument is the port number used for RTP. The next port number in sequence (28601) will be used for RTCP:
cam_node = camlib.camera("/dev/video0", 640, 480, 0, 15) rgb_node = medialib.rgb() jpeg_node = medialib.jpeg(50) RTP_PORT = 28600 rtp_node = medialib.rtp("0.0.0.0", RTP_PORT)
Then we connect the nodes to build our pipeline:
medialib.connect(cam_node, rgb_node) medialib.connect(rgb_node, jpeg_node) medialib.connect(jpeg_node, rtp_node)
The pipeline is ready but has not started to process frames yet. The play function on libmedia creates a new thread for running the pipeline. The first parameter is a callback function to be called when processing is terminated for whatever reason (in this example it does nothing). The second parameter is the starting node of the pipeline:
handle = medialib.play(function() end, cam_node)
The RTSP server is implemented in script/rtp.lua. It is loaded and initialized here:
load_module("rtp") RTSP_PORT = 8554 rtp = modules.rtp.new(cam, RTSP_PORT, RTP_PORT) rtp:open()
The cam parameter informs the RTSP modile the video source to be used. When a client connects to the RTSP server, it will inform which RTP/RTCP ports it is going to use. This information is relayed to the rtp node inside the setrtp function:
medialib.option(rtp_node, "host", host) medialib.option(rtp_node, "port", port)
From this point on, each frame received by the rtp node is sent to the connected client using the RTP protocol. This node also receives RTCP packets from the client and prints the contents on the log. When the client terminates the connection, the rtp node turns back into “idle” mode. To run the script, as always, use run:
./run script/testrtp.lua
You will see a lot of log messages telling the model and properties of the V4L2 source, the creation and connection of nodes, and loading of required modules. If everything is correct, near the end of the log you will see two messages:
MAIN RUN: network address 192.168.0.36 STREAM RUN: bound to port 8554
This means that the RTSP server is bound to IPV4 address 192.168.0.36 and port 8554 (in your case, of course, the IP address will vary). To test the server, we can use VLC. Choose “Open Network Stream” from the Media menu and enter the connection URL:
rtsp://192.168.0.36:8554/anything
The media path at the end of the URL is ignored by the server. It will always stream the V4L2 source, no matter which path you pass. When connection is established, you will see periodic RTCP messages on the log. These are QoS messages from VLC informing the server about the quality of the stream. Since VLC will buffer some frames in advance, you will probably notice some latency in the video stream. Note that this example server supports at most one connected client.