static gboolean
gst_phoenixsrc_stop (GstBaseSrc * src)
{
  GstPhoenixSrc *phoenixsrc = GST_PHOENIX_SRC (src);

  GST_DEBUG_OBJECT (phoenixsrc, "stop");

  if (phoenixsrc->hCamera) {
    /* Stop the acquisition */
    /* TODO: should we use PHX_STOP (finished current image) instead? */
    PHX_Acquire (phoenixsrc->hCamera, PHX_ABORT, NULL);

    /* Deallocates hardware and software resources, setting handle to null */
    PHX_CameraRelease (&phoenixsrc->hCamera);
  }

  phoenixsrc->dropped_frame_count = 0;
  /*phoenixsrc->last_time_code = -1; */

  return TRUE;
}
static GstFlowReturn
gst_phoenixsrc_create (GstPushSrc * src, GstBuffer ** buf)
{
  GstPhoenixSrc *phoenixsrc = GST_PHOENIX_SRC (src);
  etStat eStat = PHX_OK;        /* Phoenix status variable */
  ui32 dwParamValue = 0;        /* Phoenix Get/Set intermediate variable */
  stImageBuff phx_buffer;
  guint dropped_frame_count = 0;
  guint new_dropped_frames;
  gint i;
  guint n;
  GstMapInfo minfo;

  /* Start acquisition */
  if (!phoenixsrc->acq_started) {
    /* make class instance pointer available to the callback, and flush cache */
    PHX_ParameterSet (phoenixsrc->hCamera,
        PHX_EVENT_CONTEXT | PHX_CACHE_FLUSH, (void *) phoenixsrc);

    /* Now start our capture */
    eStat = PHX_Acquire (phoenixsrc->hCamera, PHX_START, (void *) phx_callback);
    if (PHX_OK != eStat) {
      GST_ELEMENT_ERROR (phoenixsrc, RESOURCE, FAILED,
          (("Failed to start acquisition.")), (NULL));
      return GST_FLOW_ERROR;    /* TODO: make sure _stop is called if this happens to release resources */
    }
    phoenixsrc->acq_started = TRUE;
  }

  /* about to read/write variables modified by phx_callback */
  g_mutex_lock (&phoenixsrc->mutex);

  /* wait for callback (we should always get at least a timeout( */
  g_cond_wait (&phoenixsrc->cond, &phoenixsrc->mutex);

  if (phoenixsrc->fifo_overflow_occurred) {
    /* TODO: we could offer to try and ABORT then re-START capture */
    GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
        (("Acquisition failure due to FIFO overflow.")), (NULL));
    g_mutex_unlock (&phoenixsrc->mutex);
    return GST_FLOW_ERROR;
  }

  if (phoenixsrc->timeout_occurred) {
    /* TODO: we could offer to try and ABORT then re-START capture */
    GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
        (("Acquisition failure due to timeout.")), (NULL));
    g_mutex_unlock (&phoenixsrc->mutex);
    return GST_FLOW_ERROR;
  }

  if (!phoenixsrc->buffer_ready) {
    GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
        (("You should not see this error, something very bad happened.")),
        (NULL));
    g_mutex_unlock (&phoenixsrc->mutex);
    return GST_FLOW_ERROR;
  }

  GST_LOG_OBJECT (phoenixsrc,
      "Processing new buffer %d (Frame start: %d), ready-processed = %d",
      phoenixsrc->buffer_ready_count, phoenixsrc->frame_start_count,
      phoenixsrc->buffer_ready_count - phoenixsrc->buffer_processed_count);
  phoenixsrc->buffer_ready = FALSE;

  /* frame_start is always >= buffer_ready */
  dropped_frame_count =
      phoenixsrc->frame_start_count - phoenixsrc->buffer_ready_count;

  g_mutex_unlock (&phoenixsrc->mutex);

  eStat = PHX_Acquire (phoenixsrc->hCamera, PHX_BUFFER_GET, &phx_buffer);
  if (PHX_OK != eStat) {
    GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
        (("Failed to get buffer.")), (NULL));
    return GST_FLOW_ERROR;
  }

  /* TODO: use allocator or use from Phoenix pool */
  *buf = gst_buffer_new_and_alloc (phoenixsrc->height * phoenixsrc->gst_stride);

  /* Copy image to buffer from surface TODO: use orc_memcpy */
  gst_buffer_map (*buf, &minfo, GST_MAP_WRITE);
  GST_LOG_OBJECT (phoenixsrc,
      "GstBuffer size=%d, gst_stride=%d, phx_stride=%d", minfo.size,
      phoenixsrc->gst_stride, phoenixsrc->phx_stride);
  for (i = 0; i < phoenixsrc->height; i++) {
    memcpy (minfo.data + i * phoenixsrc->gst_stride,
        ((guint8 *) phx_buffer.pvAddress) + i * phoenixsrc->phx_stride,
        phoenixsrc->gst_stride);
  }
  gst_buffer_unmap (*buf, &minfo);

  /* Having processed the data, release the buffer ready for further image data */
  eStat = PHX_Acquire (phoenixsrc->hCamera, PHX_BUFFER_RELEASE, NULL);
  phoenixsrc->buffer_processed_count++;

  /* check for dropped frames (can only detect more than one) */
  new_dropped_frames = dropped_frame_count - phoenixsrc->dropped_frame_count;
  if (new_dropped_frames > 0) {
    phoenixsrc->dropped_frame_count = dropped_frame_count;
    GST_WARNING ("Dropped %d frames (%d total)", new_dropped_frames,
        phoenixsrc->dropped_frame_count);
    /* TODO: emit message here about dropped frames */
  }

  /* use time from capture board */
  n = (phoenixsrc->buffer_processed_count -
      1) % phoenixsrc->num_capture_buffers;
  GST_BUFFER_TIMESTAMP (*buf) = phoenixsrc->frame_start_times[n];
  GST_BUFFER_DURATION (*buf) =
      GST_CLOCK_DIFF (phoenixsrc->frame_start_times[n],
      phoenixsrc->frame_end_times[n]);
  GST_BUFFER_OFFSET (*buf) = phoenixsrc->buffer_processed_count - 1;
  GST_BUFFER_OFFSET_END (*buf) = GST_BUFFER_OFFSET (*buf);

  return GST_FLOW_OK;
}
static gboolean
gst_phoenixsrc_start (GstBaseSrc * src)
{
  GstPhoenixSrc *phoenixsrc = GST_PHOENIX_SRC (src);
  etStat eStat = PHX_OK;        /* Status variable */
  etParamValue eParamValue = PHX_INVALID_PARAMVALUE;
  ui32 dwParamValue = 0;
  guint eCamConfig;

  GST_DEBUG_OBJECT (phoenixsrc, "start");

  if (phoenixsrc->config_filepath == NULL) {
    GST_WARNING_OBJECT (phoenixsrc,
        "No config file set, using default 640x480x8bpp");
  } else if (!g_file_test (phoenixsrc->config_filepath, G_FILE_TEST_EXISTS)) {
    GST_ELEMENT_ERROR (phoenixsrc, RESOURCE, NOT_FOUND,
        ("Camera config file does not exist: %s", phoenixsrc->config_filepath),
        (NULL));
    goto Error;
  }

  /* TODO: hacky, use enums or something */
  eCamConfig = PHX_DIGITAL;
  switch (phoenixsrc->board) {
    case 0:
      eCamConfig |= PHX_BOARD_AUTO;
      break;
    case 1:
      eCamConfig |= PHX_BOARD1;
      break;
    case 2:
      eCamConfig |= PHX_BOARD2;
      break;
    case 3:
      eCamConfig |= PHX_BOARD3;
      break;
    case 4:
      eCamConfig |= PHX_BOARD4;
      break;
    case 5:
      eCamConfig |= PHX_BOARD5;
      break;
    case 6:
      eCamConfig |= PHX_BOARD6;
      break;
    case 7:
      eCamConfig |= PHX_BOARD7;
      break;
    default:
      g_assert_not_reached ();
  }

  switch (phoenixsrc->channel) {
    case 0:
      eCamConfig |= PHX_CHANNEL_AUTO;
      break;
    case 1:
      eCamConfig |= PHX_CHANNEL1;
      break;
    case 2:
      eCamConfig |= PHX_CHANNEL2;
      break;
  }

  /* Initialize board */
  eStat =
      PHX_CameraConfigLoad (&phoenixsrc->hCamera, phoenixsrc->config_filepath,
      (etCamConfigLoad) eCamConfig, PHX_ErrHandlerDefault);
  if (eStat != PHX_OK) {
    GST_ELEMENT_ERROR (phoenixsrc, LIBRARY, INIT, (NULL), (NULL));
    goto Error;
  }

  /* capture frames continuously */
  eParamValue = PHX_ENABLE;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_ACQ_CONTINUOUS, &eParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;

  /* capture in blocking fashion, i.e. don't overwrite un-processed buffers */
  eParamValue = PHX_DISABLE;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_ACQ_BLOCKING, &eParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;

  /* use event counter to count time from start of acquisition */
  eParamValue = PHX_EVENTCOUNT_TIME;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_EVENTCOUNT_SRC, &eParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;
  eParamValue = PHX_EVENTGATE_ACQ;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_EVENTGATE_SRC, &eParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;

  /* Tell Phoenix to use N buffers.  */
  eParamValue = phoenixsrc->num_capture_buffers;
  PHX_ParameterSet (phoenixsrc->hCamera, PHX_ACQ_NUM_IMAGES, &eParamValue);

  /* Setup a one second timeout value (milliseconds) */
  dwParamValue = 1000;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_TIMEOUT_DMA,
      (void *) &dwParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;

  /* The BUFFER_READY interrupt is already enabled by default,
   * but we must enable other interrupts here. */
  eParamValue =
      PHX_INTRPT_TIMEOUT | PHX_INTRPT_FIFO_OVERFLOW | PHX_INTRPT_FRAME_END |
      PHX_INTRPT_FRAME_START;
  eStat =
      PHX_ParameterSet (phoenixsrc->hCamera, PHX_INTRPT_SET,
      (void *) &eParamValue);
  if (PHX_OK != eStat)
    goto ResourceSettingsError;

  return TRUE;

ResourceSettingsError:
  GST_ELEMENT_ERROR (phoenixsrc, RESOURCE, SETTINGS,
      (("Failed to get Phoenix parameters.")), (NULL));

Error:
  /* Now cease all captures */
  if (phoenixsrc->hCamera)
    PHX_Acquire (phoenixsrc->hCamera, PHX_ABORT, NULL);

  /* TODO Free all the user allocated memory */
  //psImageBuff = pasImageBuffs;
  //if ( NULL != pasImageBuffs ) {
  //  while ( NULL != psImageBuff->pvAddress ) {
  //    free( psImageBuff->pvAddress );
  //    psImageBuff++;
  //  }
  //  free( pasImageBuffs );
  //}

  /* Release the Phoenix board */
  if (phoenixsrc->hCamera)
    PHX_CameraRelease (&phoenixsrc->hCamera);

  return FALSE;
}
Example #4
0
/*
phxlive(ForBrief)
Simple live capture application code
*/
int phxliveFrame(
    etCamConfigLoad eCamConfigLoad,    /* Board number, ie 1, 2, or 0 for next available */
    char *pszConfigFileName,            /* Name of config file */
    double exposure_time,
    int gain,
    unsigned short *frame_out          // added by NC to allow output to another window
)
{
    etStat         eStat     = PHX_OK;  /* Status variable */
    etParamValue   eParamValue;         /* Parameter for use with PHX_ParameterSet/Get calls */
    tHandle        hCamera   = 0;       /* Camera Handle  */
    tPHX           hDisplay  = 0;       /* Display handle */
    tPHX           hBuffer1  = 0;       /* First Image buffer handle  */
    tPHX           hBuffer2  = 0;       /* Second Image buffer handle */
    //tPhxLive       sPhxLive;            /* User defined Event Context */
    ui32           nBufferReadyLast = 0;/* Previous BufferReady count value */
    int i,length;

    /* Initialise the user defined Event context structure */
    memset( &sPhxLive, 0, sizeof( tPhxLive ) );

    /* Allocate the board with the config file */
    eStat = PHX_CameraConfigLoad( &hCamera, pszConfigFileName, eCamConfigLoad, PHX_ErrHandlerDefault );
    if ( PHX_OK != eStat ) goto Error;

    /* set camera to live acquisition mode */
    init_camera_internal_trigger(hCamera);
    set_exposure(hCamera, exposure_time);
    set_gain(hCamera, gain);


#ifndef _USE_QT
    // We create our display with a NULL hWnd, this will automatically create an image window. 
    eStat = PDL_DisplayCreate( &hDisplay, NULL, hCamera, PHX_ErrHandlerDefault );
    if ( PHX_OK != eStat ) goto Error;

    // We create two display buffers for our double buffering 
    eStat = PDL_BufferCreate( &hBuffer1, hDisplay, (etBufferMode)PDL_BUFF_SYSTEM_MEM_DIRECT );
    if ( PHX_OK != eStat ) goto Error;
    eStat = PDL_BufferCreate( &hBuffer2, hDisplay, (etBufferMode)PDL_BUFF_SYSTEM_MEM_DIRECT );
    if ( PHX_OK != eStat ) goto Error;

    // Initialise the display, this associates the display buffers with the display 
    eStat =  PDL_DisplayInit( hDisplay );
    if ( PHX_OK != eStat ) goto Error;

    // The above code has created 2 display (acquisition) buffers.
    // Therefore ensure that the Phoenix is configured to use 2 buffers, by overwriting
    // the value already loaded from the config file.
    eParamValue = (etParamValue) 2;
    eStat = PHX_ParameterSet( hCamera, PHX_ACQ_NUM_IMAGES, &eParamValue );
    if ( PHX_OK != eStat ) goto Error;
#endif


    /* Enable FIFO Overflow events */
    eParamValue = PHX_INTRPT_FIFO_OVERFLOW;
    eStat = PHX_ParameterSet( hCamera, PHX_INTRPT_SET, &eParamValue );
    if ( PHX_OK != eStat ) goto Error;

    /* Setup our own event context */
    eStat = PHX_ParameterSet( hCamera, PHX_EVENT_CONTEXT, (void *) &sPhxLive );
    if ( PHX_OK != eStat ) goto Error;


    /* Now start our capture, using the callback method */
    eStat = PHX_Acquire( hCamera, PHX_START, (void*) phxliveFrame_callback );
    if ( PHX_OK != eStat ) goto Error;


    /* Continue processing data until the user presses a key in the console window
    * or Phoenix detects a FIFO overflow
    */
    //printf("Press a key to exit\n");
    /*   while(!PhxCommonKbHit() && !sPhxLive.fFifoOverFlow)*/
    while(!sPhxLive.fFifoOverFlow)
    {
        /* Temporarily sleep, to avoid burning CPU cycles.
        * An alternative method is to wait on a semaphore, which is signalled
        * within the callback function.  This approach would ensure that the
        * data processing would only start when there was data to process
        */
        _PHX_SleepMs(10);

        /* If there are any buffers waiting to display, then process them here */
        if ( nBufferReadyLast != sPhxLive.nBufferReadyCount ) 
        {
            stImageBuff stBuffer; 
            int nStaleBufferCount;

            /* If the processing is too slow to keep up with acquisition,
            * then there may be more than 1 buffer ready to process.
            * The application can either be designed to process all buffers
            * knowing that it will catch up, or as here, throw away all but the
            * latest
            */
            nStaleBufferCount = sPhxLive.nBufferReadyCount - nBufferReadyLast;
            nBufferReadyLast += nStaleBufferCount;

            /* Throw away all but the last image */
            while ( nStaleBufferCount-- > 1 )
            {
                eStat = PHX_Acquire( hCamera, PHX_BUFFER_RELEASE, NULL );
                if ( PHX_OK != eStat ) goto Error;
            }


            /* Get the info for the last acquired buffer */
            eStat = PHX_Acquire( hCamera, PHX_BUFFER_GET, &stBuffer );
            if ( PHX_OK != eStat ) goto Error;

            /* Process the newly acquired buffer,
            * which in this simple example is a call to display the data.
            * For our display function we use the pvContext member variable to
            * pass a display buffer handle.
            * Alternatively the actual video data can be accessed at stBuffer.pvAddress
            */
#ifndef _USE_QT
            PDL_BufferPaint( (tPHX)stBuffer.pvContext );
#elif defined _USE_QT
            // Load a numpy array here!!!!
            for(i = 0; i < 1000000; i++)
            {
                *(frame_out + i) = *((short unsigned int*)(stBuffer.pvAddress) + i);
            }
            //fflush(stdout);
            //length = sizeof(frame_out);
            //write(1, frame_out, length);

#else
            printf("EventCount = %5d\r", sPhxLive.nBufferReadyCount );
#endif

            /* Having processed the data, release the buffer ready for further image data */
            eStat = PHX_Acquire( hCamera, PHX_BUFFER_RELEASE, NULL );
            if ( PHX_OK != eStat ) goto Error;
        }
    }
    printf("\n");


    /* In this simple example we abort the processing loop on an error condition (FIFO overflow).
    * However handling of this condition is application specific, and generally would involve
    * aborting the current acquisition, and then restarting.
    */
    if ( sPhxLive.fFifoOverFlow )
    {
      printf("FIFO OverFlow detected..Aborting\n");
    }
Error:
   /* Now cease all captures */
    if ( hCamera ) PHX_Acquire( hCamera, PHX_ABORT, NULL );

#if defined _PHX_DISPLAY
    /* Free our display double buffering resources */
    if ( hBuffer1 ) PDL_BufferDestroy( (tPHX*) &hBuffer1 );
    if ( hBuffer2 ) PDL_BufferDestroy( (tPHX*) &hBuffer2 );

    /* Destroy our display */
    if ( hDisplay ) PDL_DisplayDestroy( (tPHX*) &hDisplay );
#endif

    /* Release the Phoenix board */
    if ( hCamera ) PHX_CameraRelease( &hCamera );

    printf("Exiting\n");
    return 0;
}