
/**
 * @example camera.c
 * Question: I need to display a live camera image via VNC. Until now I just 
 * grab an image, set the rect to modified and do a 0.1 s sleep to give the 
 * system time to transfer the data.
 * This is obviously a solution which doesn't scale very well to different 
 * connection speeds/cpu horsepowers, so I wonder if there is a way for the 
 * server application to determine if the updates have been sent. This would 
 * cause the live image update rate to always be the maximum the connection 
 * supports while avoiding excessive loads.
 *
 * Thanks in advance,
 *
 *
 * Christian Daschill 
 *
 *
 * Answer: Originally, I thought about using seperate threads and using a
 * mutex to determine when the frame buffer was being accessed by any client
 * so we could determine a safe time to take a picture.  The probem is, we
 * are lock-stepping everything with framebuffer access.  Why not be a
 * single-thread application and in-between rfbProcessEvents perform a
 * camera snapshot.  And this is what I do here.  It guarantees that the
 * clients have been serviced before taking another picture.
 *
 * The downside to this approach is that the more clients you have, there is
 * less time available for you to service the camera equating to reduced
 * frame rate.  (or, your clients are on really slow links). Increasing your
 * systems ethernet transmit queues may help improve the overall performance
 * as the libvncserver should not stall on transmitting to any single
 * client.
 *
 * Another solution would be to provide a seperate framebuffer for each
 * client and use mutexes to determine if any particular client is ready for
 * a snapshot.  This way, your not updating a framebuffer for a slow client
 * while it is being transferred.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rfb/rfb.h>


#define WIDTH  640
#define HEIGHT 480
#define BPP      4

/* 15 frames per second (if we can) */
#define PICTURE_TIMEOUT (1.0/15.0)


/*
 * throttle camera updates
*/
int TimeToTakePicture() {
    static struct timeval now={0,0}, then={0,0};
    double elapsed, dnow, dthen;

    gettimeofday(&now,NULL);

    dnow  = now.tv_sec  + (now.tv_usec /1000000.0);
    dthen = then.tv_sec + (then.tv_usec/1000000.0);
    elapsed = dnow - dthen;

    if (elapsed > PICTURE_TIMEOUT)
      memcpy((char *)&then, (char *)&now, sizeof(struct timeval));
    return elapsed > PICTURE_TIMEOUT;
}



/*
 * simulate grabbing a picture from some device
 */
int TakePicture(unsigned char *buffer)
{
  static int last_line=0, fps=0, fcount=0;
  int line=0;
  int i,j;
  struct timeval now;

  /*
   * simulate grabbing data from a device by updating the entire framebuffer
   */
  
  for(j=0;j<HEIGHT;++j) {
    for(i=0;i<WIDTH;++i) {
      buffer[(j*WIDTH+i)*BPP+0]=(i+j)*128/(WIDTH+HEIGHT); /* red */
      buffer[(j*WIDTH+i)*BPP+1]=i*128/WIDTH; /* green */
      buffer[(j*WIDTH+i)*BPP+2]=j*256/HEIGHT; /* blue */
    }
    buffer[j*WIDTH*BPP+0]=0xff;
    buffer[j*WIDTH*BPP+1]=0xff;
    buffer[j*WIDTH*BPP+2]=0xff;
  }

  /*
   * simulate the passage of time
   *
   * draw a simple black line that moves down the screen. The faster the
   * client, the more updates it will get, the smoother it will look!
   */
  gettimeofday(&now,NULL);
  line = now.tv_usec / (1000000/HEIGHT);
  if (line>HEIGHT) line=HEIGHT-1;
  memset(&buffer[(WIDTH * BPP) * line], 0, (WIDTH * BPP));

  /* frames per second (informational only) */
  fcount++;
  if (last_line > line) {
    fps = fcount;
    fcount = 0;
  }
  last_line = line;
  fprintf(stderr,"%03d/%03d Picture (%03d fps)\r", line, HEIGHT, fps);

  /* success!   We have a new picture! */
  return (1==1);
}




/* 
 * Single-threaded application that interleaves client servicing with taking
 * pictures from the camera.  This way, we do not update the framebuffer
 * while an encoding is working on it too (banding, and image artifacts).
 */
int main(int argc,char** argv)
{                                       
  long usec;
  
  rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP);
  if(!server)
    return 0;
  server->desktopName = "Live Video Feed Example";
  server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP);
  server->alwaysShared=(1==1);

  /* Initialize the server */
  rfbInitServer(server);           

  /* Loop, processing clients and taking pictures */
  while (rfbIsActive(server)) {
    if (TimeToTakePicture())
      if (TakePicture((unsigned char *)server->frameBuffer))
        rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT);
          
    usec = server->deferUpdateTime*1000;
    rfbProcessEvents(server,usec);
  }
  return(0);
}
