gboolean
gst_edt_pdv_sink_start (GstBaseSink * basesink)
{
  GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink);

  GST_DEBUG_OBJECT (pdvsink, "Starting");

  pdvsink->dev = pdv_open_channel ("pdv", pdvsink->unit, pdvsink->channel);
  if (pdvsink->dev == NULL) {
    GST_ELEMENT_ERROR (pdvsink, RESOURCE, OPEN_WRITE,
        ("Unable to open unit %d, channel %d", pdvsink->unit, pdvsink->channel),
        (NULL));
    return FALSE;
  }

  if (!pdv_is_simulator (pdvsink->dev)) {
    GST_ELEMENT_ERROR (pdvsink, RESOURCE, OPEN_WRITE,
        ("EDT unit is not a simulator."), (NULL));
    pdv_close (pdvsink->dev);
  }

  /* FIXME: set timeout to wait forever, shouldn't do this of course */
  edt_set_wtimeout (pdvsink->dev, 0);
  edt_set_rtimeout (pdvsink->dev, 0);

  pdv_flush_fifo (pdvsink->dev);

  /* turn off counter data so we can DMA our own image data */
  pdv_cls_set_datacnt (pdvsink->dev, 0);

  pdvsink->cur_buffer = 0;

  return TRUE;
}
gboolean
gst_edt_pdv_sink_stop (GstBaseSink * basesink)
{
  GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink);

  if (pdvsink->dev)
    pdv_close (pdvsink->dev);

  return TRUE;
}
Beispiel #3
0
edt_server::~edt_server()
{
  if (d_pdv_p) {
    pdv_close((PdvDev*)d_pdv_p);
    d_pdv_p = NULL;
  }
  if (d_swap_buffer) {
    delete [] d_swap_buffer;
    d_swap_buffer = NULL;
  }
}
Beispiel #4
0
bool edt_server::open_and_find_parameters(void)
{
  char    errstr[256];
  char    *devname = EDT_INTERFACE;
  int	  unit = 0;
  int	  channel = 0;

  // Try to open the default device name and unit
  d_pdv_p = pdv_open_channel(devname, unit, channel);
  if (d_pdv_p == NULL) {
    fprintf(stderr,"edt_server::open_and_find_parameters: Could not open camera\n");
    sprintf(errstr, "pdv_open_channel(%s%d_%d)", devname, unit, channel);
    pdv_perror(errstr);
    return false;
  }

  // Check the parameters.
  if (pdv_get_depth((PdvDev*)d_pdv_p) != 8) {
    fprintf(stderr,"edt_server::open_and_find_parameters: Can only handle 8-bit cameras\n");
    pdv_close((PdvDev*)d_pdv_p);
    d_pdv_p = NULL;
    return false;
  }
  _num_columns = pdv_get_width((PdvDev*)d_pdv_p);
  _num_rows = pdv_get_height((PdvDev*)d_pdv_p);
  _minX = _minY = 0;
  _maxX = _num_columns-1;
  _maxY = _num_rows-1;
  _binning = 1;

  // Allocate space to swap a line from the buffer
  if ( (d_swap_buffer = new vrpn_uint8[_num_columns]) == NULL) {
    fprintf(stderr,"edt_server::open_and_find_parameters: Out of memory\n");
    pdv_close((PdvDev*)d_pdv_p);
    d_pdv_p = NULL;
    return false;
  }

  /*
   * allocate buffers for optimal pdv ring buffer pipeline (reduce if
   * memory is at a premium)
   */
  pdv_multibuf((PdvDev*)d_pdv_p, d_num_buffers);

  // Clear the timeouts value.
  d_first_timeouts = d_last_timeouts = pdv_timeouts((PdvDev*)d_pdv_p);

  /*
   * prestart the first image or images outside the loop to get the
   * pipeline going. Start multiple images unless force_single set in
   * config file, since some cameras (e.g. ones that need a gap between
   * images or that take a serial command to start every image) don't
   * tolerate queueing of multiple images
   */
  if (((PdvDev*)d_pdv_p)->dd_p->force_single) {
      d_started = 1;
      pdv_start_image((PdvDev*)d_pdv_p);
  } else {
      // Request as many images as buffers, so we are always trying to
      // fill all of them.  If we have gotten all we asked for, we
      // may have missed some.
      d_started = d_num_buffers;
      pdv_start_images((PdvDev*)d_pdv_p, d_started);
  }

  // Read one frame when we start.
  _status = true;
  if (read_image_to_memory()) {
    return true;
  } else {
    pdv_close((PdvDev*)d_pdv_p);
    d_pdv_p = NULL;
    fprintf(stderr, "edt_server::open_and_find_parameters: could not read image to memory\n");
    return false;
  }
}
Beispiel #5
0
bool  edt_server::read_image_to_memory(unsigned minX, unsigned maxX,
							unsigned minY, unsigned maxY,
							double exposure_time_millisecs)
{
  u_char *image_p;
  struct timeval now;

  if (!_status) { return false; }

  //---------------------------------------------------------------------
  // XXX Set the exposure time.

  //---------------------------------------------------------------------
  // Set the size of the window to include all pixels if there were not
  // any binning.  This means adding all but 1 of the binning back at
  // the end to cover the pixels that are within that bin.
  _minX = minX * _binning;
  _maxX = maxX * _binning + (_binning-1);
  _minY = minY * _binning;
  _maxY = maxY * _binning + (_binning-1);

  //---------------------------------------------------------------------
  // If the maxes are greater than the mins, set them to the size of
  // the image.
  if (_maxX < _minX) {
    _minX = 0; _maxX = _num_columns - 1;
  }
  if (_maxY < _minY) {
    _minY = 0; _maxY = _num_rows - 1;
  }

  //---------------------------------------------------------------------
  // Clip collection range to the size of the sensor on the camera.
  if (_minX < 0) { _minX = 0; };
  if (_minY < 0) { _minY = 0; };
  if (_maxX >= _num_columns) { _maxX = _num_columns - 1; };
  if (_maxY >= _num_rows) { _maxY = _num_rows - 1; };

  // If the in-memory buffers have all been filled up, assume
  // that we have missed some unknown number of images.  Save this
  // so that it can be reported if we're sending VRPN messages.
  // Actually, we report this if we drop down to 1 buffer because
  // this was where the version running on one of our computers
  // hit the floor at and started losing frames.
  unsigned outstanding = edt_get_todo((PdvDev*)d_pdv_p) -
                         edt_done_count((PdvDev*)d_pdv_p);
  if ( outstanding <= 1 ) {
    d_missed_some_images = true;
  }

  // Once a second, tell how many buffers have been filled and are waiting
  // for us to process.
  static struct timeval last = { 0, 0 };
  vrpn_gettimeofday(&now, NULL);
  if (now.tv_sec > last.tv_sec) {
    last = now;
    //printf("XXX EDT: %d outstanding buffers\n", outstanding );
  }

  /*
   * get the image and immediately start the next one. Processing
   * can then occur in parallel with the next acquisition
   */
  unsigned int sec_usec[2];
  image_p = pdv_wait_image_timed((PdvDev*)d_pdv_p, sec_usec);
  if (image_p == NULL) {
    fprintf(stderr,"edt_server::read_image_to_memory(): Failed to read image\n");
    pdv_close((PdvDev*)d_pdv_p);
    d_pdv_p = NULL;
    _status = false;
    return false;
  }
  pdv_start_image((PdvDev*)d_pdv_p);
  /*XXX
  if (edt_reg_read((PdvDev*)d_pdv_p, PDV_STAT) & PDV_OVERRUN) {
    XXX_overrun_check; // http://www.edt.com/api/simple__take_8c-source.html
  }
  */

  // XXX We might think that we wanted to use the wait_images functions
  // rather than wait_image, but we do seem to fill up all of the buffers
  // when we can't send data out fast enough.  But it may be worth trying
  // to use it and ask for one at a time, then only start more reads when
  // half of them have been read or something?  And do this using a commend
  // to start multiple reads?  Does it re-start every time we call start?
  // If so, what's the point of multiple buffers in the simple_take.c file?
  // Google search for pdv_wait_image_timed turned up pointers to their docs.

  //---------------------------------------------------------------------
  // Time handling: We let the EDT board tell us what time each image
  // was put into the DMA buffer.  We don't know how this compares to
  // the absolute PC clock time, so we record the offset from the first
  // time we got an image (clock reading and EDT reading), so that the
  // time will be reported relative to the computer's clock.
  // If we don't have a nonzero PC time, this is the first time through,
  // so get both initial times.
  struct timeval edt_now = { sec_usec[0], sec_usec[1] };
  if ( d_pc_time_first_image.tv_sec == 0 ) {
    vrpn_gettimeofday(&d_pc_time_first_image, NULL);
    d_edt_time_first_image = edt_now;
  }
  struct timeval time_offset = vrpn_TimevalDiff(d_pc_time_first_image, d_edt_time_first_image);
  d_timestamp = vrpn_TimevalSum( edt_now, time_offset );

  // XXX The EDT-board time handling seems to be broken, so for now we just
  // put on the current time for the frame.
  vrpn_gettimeofday(&now, NULL);
  d_timestamp = now;

  // Check for timeouts in image transer from the camera into a memory
  // buffer.  This does NOT tell us when we ask for more images than will
  // fit into buffers, but rather when there was a communication error or
  // the system bus was too slow to pull the image off the camera.  We'll
  // need to look at timestamps to determine whether we missed any images
  // due to not having room in the buffers we allocated.

  unsigned timeouts = pdv_timeouts((PdvDev*)d_pdv_p);
  if (timeouts > d_last_timeouts)
  {
      /*
       * pdv_timeout_cleanup helps recover gracefully after a timeout,
       * particularly if multiple buffers were prestarted
       */
      if (d_num_buffers > 1)
      {
	  int     pending = pdv_timeout_cleanup((PdvDev*)d_pdv_p);
	  pdv_start_images((PdvDev*)d_pdv_p, pending);
      }
      d_unreported_timeouts += (timeouts - d_last_timeouts);
      d_last_timeouts = timeouts;
  }

  // If we're supposed to swap every other line, do that here.
  // The image lines are swapped in place.
  if (d_swap_lines) {
    unsigned j;    // Indexes into the lines, skipping every other.

    for (j = 0; j < _num_rows; j += 2) {
      memcpy(d_swap_buffer, image_p + j*_num_columns, _num_columns);
      memcpy(image_p + (j+1)*_num_columns, image_p + j*_num_columns, _num_columns);
      memcpy(image_p + (j+1)*_num_columns, d_swap_buffer, _num_columns);
    }
  }

  // Point to the image in memory.
  d_buffer = image_p;

  return true;
}