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; }
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; } }
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; } }
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; }