Streaming video with UDP in Processing

UDP Video Streaming from Processing

ITP students Jeff Howard and Alex Vessels are working on a video piece for the upcoming Big Screens show. One of the challenges we’ve always had working on the IAC Video Wall is that the computers that actually drive the wall are locked up in a control room far away from the lobby itself. So any external devices (cameras, sensors, etc.) have to communicate with those machines over the network. For this year’s show, we’ve developed a new solution using UDP streaming to send imagery from a camera to the control room.

This example owes a ton to the Processing UDP Library by Stephane Cousot. I’m using the Java DataGram classes directly instead of the Processing library, but the code draws heavily on techniques from the UDP library.

A couple quick notes about the code.

First, whenever sending data over a network, it’s generally a good idea to try to minimize the amount of data. A 320×240 image has 76,800 pixels, each pixel having 3 bytes (red, green, and blue). That’s 230,400 bytes that need to be sent 30 times per second. It’s do-able, but if we could compress the image first (encoding it as a JPG, for example) before sending, this will save a ton. Encoding a JPG in Java is pretty easy since the ImageIO classes take care of that for you. Assuming you have a PImage variable “img” the code looks something like:

  // We need a buffered image to do the JPG encoding
  int w = img.width;
  int h = img.height;
  BufferedImage b = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
 
  // Transfer pixels from localFrame to the BufferedImage
  img.loadPixels();
  b.setRGB( 0, 0, w, h, img.pixels, 0, w);
 
  // Need these output streams to get image as bytes for UDP
  ByteArrayOutputStream baStream = new ByteArrayOutputStream();
  BufferedOutputStream bos = new BufferedOutputStream(baStream);
 
  // JPG compression into BufferedOutputStream
  // Requires try/catch
  try {
    ImageIO.write(b, "jpg", bos);
  } catch (IOException e) {
    e.printStackTrace();
  }

You might also notice that the above code includes a try/catch statement around the encoding of the JPG. Certain “exceptions” (i.e. errors) in Java require special handling and try/catch is one way of fulfilling that requirement. You’ll see in the example code that try/catch is also required for the UDP communication. For more about exception handling in Processing check out: http://wiki.processing.org/w/Exceptions.

Finally, you’ll also notice in the examples that you are required to specify the IP address you are sending to and the port, i.e.

int clientPort = 9100; 
InetAddress client =  InetAddress.getByName("localhost"); 
ds.send(new DatagramPacket(packet,packet.length,client,clientPort));

The port can be anything (as long as it doesn’t conflict with a port you are using for something else). Generally, 9000 and above is a safe bet. The IP address should be the IP of the machine receiving the video stream. For demonstration purposes, it’s simply “localhost”, i.e. we’re going to send and receive on the same machine.

Finally, the checkForNewImage() function in the VideoReceiver example is blocking, meaning if no data is coming in Processing will stop and wait. So really, it should exist in a separate thread. Stay tuned for an updated threaded version as well as simple thread tutorial!

Update: the thread example is in the download and more here:

http://www.shiffman.net/2010/11/13/processing-and-threads/

Download the code for sending and receiving: image_streaming.zip.

Big Screens, Fall 2008

The Big Screens class has kicked off again for this semester. For all of you marking your calendars, the show will be Friday, Dec 12th, sometime in the evening. The students are proposing their project ideas today and tomorrow.

In preparation for the class, I’ve updated the library with new tutorials and downloads.

http://code.google.com/p/mostpixelsever/

Next week we’ll be running our first tests of content on the wall. Stay tuned! (Photos below from our first visit to IAC on Sept 12th. They were nice enough to set up the giant lobby space as a classroom, complete with IAC paper and pencils.)

IMG_6886  IMG_6888 IMG_6889  IMG_6890

Learning Processing Available Now

nyu bookstore

Just a quick note to let you know that my book, Learning Processing, is now available for purchase. If you are local to NYC, you can buy the book at the NYU bookstore.

Amazon says “out of stock”, but I’m told by the publisher that this is an error and they do, in fact, have copies. Also, at $37.00, this seems to be the cheapest option online that I can find.

All the example code will be available live online at learningprocessing.com by early next week. Feel free to contact me with comments, questions, feedback!

Who is this book for? Check out my earlier post.

Most Pixels Ever v2.0 (UDP)

First, I’m pleased to announce that my students’ work from last year’s Big Screens class is featured in the Processing exhibition.

processing_exhibition

In honor of this achievement as well as this coming fall’s repeat extravaganza, the “Most Pixels Ever” library is moving! I’m slowly getting rid of the old site and shifting over to google code hosting, which has lots of great features for collaborative open source projects.

http://code.google.com/p/mostpixelsever/

Because of the performance issues with v1.0 (especially on windows), I’m rewriting the library to use UDP. So far my tests are promising and it looks like this new version should be speedier and more reliable. Preliminary downloads and source are available on the new site.

Here’s a video of our new test set-up in action at ITP:


http://www.vimeo.com/1517179

Also, I should point out that the library will ultimately be expanded to include several different messaging “modes,” depending on exactly what type of multi-screen application you are building. Right now, the only mode available is overkill mode where the server and client have to shake hands for every single frame rendered.

Finally, there’s a major bug briefly described on the “issues” tab. Am working to fix it now, but if anyone discovers anything, please let me know.