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.

  • Anonymous

    I tried using InetAddress so I can send the image to another computer, but I can’t seem to get it to work.

    I keep getting the error “Unexpected token: (” on the ds.send line.

    Are there some libraries that need to be imported first?

  • Anonymous

    I’m not having this problem.  Just replace “localhost” with the  IP address, i.e. “xxx.xxx.xxx” and it should work!

  • Vanstra

    This code is nice. I’ve made a MaxMSP patch for sending a jit.qt.grab videostream over UDP which is showed with the VideoRecieverThread script.

  • Walid Dilaw

    I need an app that woud get a video stream from somewhere else, a local capture, merge both these images, and stream it to the web(with sound from 1 local source).

    You talk about image_streaming here, what about streaming with sound as well? Also, is the PImage/ video? compressed?

    Thanks for your answer, been looking at quite a few possibilities, but i would like to do this in processing. 
    I would really appreciate a couple of advices, since i need this done fast, and i had little luck on stackoverflow, IRC, and forum.processing…

    Thanks for your answer!

  • Titanmak

    Hi, I tried your program, it is Great !
    Now, I am modifying it into a 2-way video streaming!
    but still have some bug in it!
    can I send my file to you to discuss about it??
    my email is : titanmak@gmail.com
     
    thanks so much~

  • Kikuoayumu

    Excute  me
    Do  you  have  streaming  video  with  TCP  in  processing  ?
    P.S.  This  you  UDP  is  very  excellent.
    Thanks  a  lot. 

  • shiffman

    sorry i only have this UDP example

  • Toreesposito

    Dear Shiffman,  
    I’m trying to use it on Ubuntu 11.04 but it doesn’t work. Using GSvideo for linux I’m able to capture the image on the server side but I’m not able to recieve the image on the client side. I have opened the ports but I’m not able to receive the image on client side. The server and client are running on the same PC. If the same code runs on Windows itself work fine. Could you suggest some idea in order to overcome this problem.? Thanks a lot. Salvatore

  • shiffman

    Sorry, i don’t have enough experience with linux to know!  Check all your network and security settings I guess?

  • Koral

    Hello! Shiffman i love your tutorial and examples, they help me a lot, i would like to know if i can do a streaming video where the sender video is in real time and the receiver video wil be one minute period after, it can be posible? Thanks and sorry for my english

  • shiffman

    Yes, you could save the video to a file or an array of PImages for later playback.

  • Koral

     tanks you :)

  • johannes Jørgensen

    i have used your terrific thread example for my slitscan over x screens feedback program. thanx for great code examples!

    https://vimeo.com/52326544

    https://github.com/johannesgj

  • shiffman

    Fantastic, thanks for sharing!

  • Dámaso López

    Hi all,

    I get a same problem, but I can’t look for some of the code because

    the code was compile in C and othet is JAVA and I send 1024 bytes to

    UDP and it respons “Error UDP frame too small:1024″ in the application

    in C.

    I’ll look for Google but I don’t find how solve it.Any idea? In

    whireshark I see that DATA is correct to send 1024 bytes and add 20

    bytes to header, the column Length is 1066 and I don’t understand the

    difference.

    The code is: (JAVA)

    File sound =new File(“k.raw”);

    inputstream in=new fileinputstream(sound);

    bufferedinputstream bis=new bufferedinputstream(in);

    long length=sound.length();

    audioinputstream ais=audioinputstream(bis,format,length);

    byte[] buffer=new byte[1024];

    while((nbyteread=ais.read(buffer,0,buffer.lenght())!=-1){

    bytearrayoutputstream baos=new bytearrayoutputstream();

    objectoutputstream oos=new objectoutputstream(baos);

    oos.write(buffer);

    datagrampacket dp=new

    datagrampacket(baos.tobytearray(),1024,address,port);

    multisocket.send(dp);

    }

  • Dámaso López

    Hi,

    Now, it says “warning:jitter_buffer_get() discarding non-zero start_offset 1023”, I changed buffer 1028 to not 1024 Can you help me, please?

  • suraj s prabhu

    Shiffman,
    I’m a newbie to this software.My need is to stream a live video to a PC which accesses the server I create using a web browser.So can you please help me with it.
    You can contact me on surajsprabhu@gmail.com

  • suraj s prabhu

    I want to make a GUI for streaming video to a local host from a server and to control a robot using the server.

  • Francois Baret

    I tried your codes with Ubuntu and Windows 7 and I got the error message: “Cannot find a class or a type named “DatagramSocket”. Do I miss a library or something?

  • shiffman

    Yes, with Processing 2.0 you’ll need imports for everything. DataGram is in

    import java.net.*;

    For everyhting else just google and find the right Java package to import. I’ll try to post updated versions soon.

  • Dion

    I don’t understand how this can work, using similar code to convert a bufferedimage to jpg took roughly 200 milliseconds on my friends i5. How did this work realtime?