IPcapture vs PImage.get()

edited June 2016 in Library Questions

Hi,

I'm using IPcapture with multiple MJPEG streams and buffering frames over time in as many circular buffers as there are cameras. The goal is to then display the streams with a delay.

I can currently connect to the cameras and display their original streams without any problem and my circular buffers also seem to be working properly but something strange happens when I try to copy the frames to the buffers. Here is a simplified version of my sketch which displays the problem:

Note: screen resolution is 1920x1080 and the camera stream is 480x300

import ipcapture.*;

IPCapture cam1;

// Circular buffer
PImage[] cam1_buffer; 

// These determine the size of the circular buffer and help iterate while writing and reading through them
int nFrames = 60;
int iWrite = 0, iRead = 1;

void setup() {
  fullScreen();

  cam1 = new IPCapture(this, "http://192.168.0.172/axis-cgi/mjpg/video.cgi", "root", "root");
  cam1.start();

  cam1_buffer = new PImage[nFrames];
}

void draw() {
   if (cam1.isAvailable()) {
    cam1.read();
    cam1_buffer[iWrite] = cam1.get();
    if(cam1_buffer[0] != null){
      // The original camera image is displayed correctly at 480x300 in the upper left corner          
      image(cam1,0,0); 
      // The buffered frame appears under the original one but it is 1920x1080 and contains 4 stretched copies of the original side by side at the top of the image
      image(cam1_buffer[0],0,300);
    }    
  }

 // Increment write and read counters
  iWrite++;
  iRead++;

  // Start writing over our buffer every time we reach the end
  if(iRead >= nFrames-1){
    iRead = 0;
  }

  if(iWrite >= nFrames-1){
    iWrite = 0;
  }   
}

My understanding is that IPcapture.get(); returns PImages which are the same size as the screen and not the same size as the IPcapture resolution. I haven't found anything in the IPcapture reference on how to force the proper resolution.

Any ideas?

Also is there a way of getting the current stream frame rate? This would allow me to better tune the display delay as the stream frame rate varies over time...

Thanks!

Answers

  • Answer ✓

    Ok, so it turns out the IPcapture object seems to get instanciated with its PImage.pixelWidth and PImage.pixelHeight values equal to the screen's and not the actual MJPEG stream's resolution. However PImage.width and PImage.height do get the proper MJPEG's resolution and this difference seems to cause the resize/stretch/multiple copies problem I had earlier.

    Correcting the pixelWidth and pixelHeight values immediately after cam1.start() so they are equal to the actual camera resolution solves the problem.

    For instance, this works:

    import ipcapture.*;
    
    IPCapture cam1;
    
    // Circular buffer
    PImage[] cam1_buffer; 
    
    // These determine the size of the circular buffer and help iterate while writing and reading through them
    int nFrames = 60;
    int iWrite = 0, iRead = 1;
    
    void setup() {
      fullScreen();
    
      cam1 = new IPCapture(this, "<a href="http://192.168.0.172/axis-cgi/mjpg/video.cgi" target="_blank" rel="nofollow">http://192.168.0.172/axis-cgi/mjpg/video.cgi</a>;", "root", "root");
      cam1.start();
      // If the camera resolution isn't explicitely defined the PImage.get() method will give strange results
      cam1.pixelWidth = 480;
      cam1.pixelHeight = 300;
    
    cam1_buffer = new PImage[nFrames];
    }
    
    void draw() {
      if (cam1.isAvailable()) {
        cam1.read();
        cam1_buffer[iWrite] = cam1.get();
      if(cam1_buffer[0] != null){
      // The original camera image is displayed correctly at 480x300 in the upper left corner          
      image(cam1,0,0); 
      // The buffered frame appears under the original one but it is 1920x1080 and contains 4 stretched copies of the original side by side at the top of the image
      image(cam1_buffer[0],0,300);
      }    
    }
    
    // Increment write and read counters
    iWrite++;
    iRead++;
    
    // Start writing over our buffer every time we reach the end
      if(iRead >= nFrames-1){
        iRead = 0;
      }
    
      if(iWrite >= nFrames-1){
        iWrite = 0;
      }
    }
    
Sign In or Register to comment.