Skip to content

Commit

Permalink
Added virtual function uca_camera_grab_live
Browse files Browse the repository at this point in the history
Nothing special the implementation. Everything is the
same as `uca_camera_grab`.
  • Loading branch information
gabs1234 committed Oct 25, 2023
1 parent bb0929b commit c62bd4b
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
38 changes: 38 additions & 0 deletions plugins/mock/uca-mock-camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,43 @@ uca_mock_camera_grab (UcaCamera *camera, gpointer data, GError **error)
return TRUE;
}

static gboolean
uca_mock_camera_grab_live (UcaCamera *camera, gpointer data, GError **error)
{
UcaMockCameraPrivate *priv;
UcaCameraTriggerSource trigger_source;
gdouble exposure_time;

g_return_val_if_fail (UCA_IS_MOCK_CAMERA(camera), FALSE);

priv = UCA_MOCK_CAMERA_GET_PRIVATE (camera);

g_object_get (G_OBJECT (camera),
"exposure-time", &exposure_time,
"trigger-source", &trigger_source, NULL);

if (trigger_source == UCA_CAMERA_TRIGGER_SOURCE_SOFTWARE)
g_free (g_async_queue_pop (priv->trigger_queue));

if (trigger_source == UCA_CAMERA_TRIGGER_SOURCE_EXTERNAL) {
/* wait for signal to arrive */
g_mutex_lock (&signal_mutex);
g_cond_wait (&signal_cond, &signal_mutex);
g_mutex_unlock (&signal_mutex);
}

g_usleep (G_USEC_PER_SEC * exposure_time);

if (priv->fill_data) {
print_current_frame (priv, priv->dummy_data, FALSE);
g_memmove (data, priv->dummy_data, priv->roi_width * priv->roi_height * priv->bytes);
}

priv->current_frame++;

return TRUE;
}

static gboolean
uca_mock_camera_readout (UcaCamera *camera, gpointer data, guint index, GError **error)
{
Expand Down Expand Up @@ -553,6 +590,7 @@ uca_mock_camera_class_init(UcaMockCameraClass *klass)
camera_class->start_recording = uca_mock_camera_start_recording;
camera_class->stop_recording = uca_mock_camera_stop_recording;
camera_class->grab = uca_mock_camera_grab;
camera_class->grab_live = uca_mock_camera_grab_live;
camera_class->readout = uca_mock_camera_readout;
camera_class->trigger = uca_mock_camera_trigger;

Expand Down
95 changes: 95 additions & 0 deletions src/uca-camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,101 @@ uca_camera_grab (UcaCamera *camera, gpointer data, GError **error)
return result;
}

/**
* uca_camera_grab_live:
* @camera: A #UcaCamera object
* @data: (type gulong): Pointer to suitably sized data buffer. Must not be
* %NULL.
* @error: Location to store a #UcaCameraError error or %NULL
*
* Graba single frame and store the result in @data.
*
* You must have called uca_camera_start_recording() before, otherwise you will
* get a #UCA_CAMERA_ERROR_NOT_RECORDING error. This function does not interfere
* with uca_camera_grab().
*/
gboolean
uca_camera_grab_live (UcaCamera *camera, gpointer data, GError **error)
{
UcaCameraClass *klass;
gboolean result = FALSE;

/* FIXME: this prevents accessing two independent cameras simultanously. */
static GMutex mutex;

g_return_val_if_fail (UCA_IS_CAMERA(camera), FALSE);

klass = UCA_CAMERA_GET_CLASS (camera);

g_return_val_if_fail (klass != NULL, FALSE);
g_return_val_if_fail (klass->grab_live != NULL, FALSE);
g_return_val_if_fail (data != NULL, FALSE);

if (!camera->priv->buffered) {
g_mutex_lock (&mutex);

if (!camera->priv->is_recording && !camera->priv->is_readout) {
g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING,
"Camera is neither recording nor in readout mode");
}
else {
#ifdef WITH_PYTHON_MULTITHREADING
if (Py_IsInitialized ()) {
PyGILState_STATE state = PyGILState_Ensure ();
Py_BEGIN_ALLOW_THREADS

g_mutex_lock (&access_lock);
result = (*klass->grab_live) (camera, data, error);
g_mutex_unlock (&access_lock);

Py_END_ALLOW_THREADS
PyGILState_Release (state);
}
else {
g_mutex_lock (&access_lock);
result = (*klass->grab_live) (camera, data, error);
g_mutex_unlock (&access_lock);
}
#else
g_mutex_lock (&access_lock);
result = (*klass->grab_live) (camera, data, error);
g_mutex_unlock (&access_lock);
#endif
}

g_mutex_unlock (&mutex);
}
else {
gpointer buffer;

if (camera->priv->ring_buffer == NULL)
return FALSE;

/*
* Spin-lock until we can read something. This shouldn't happen to
* often, as buffering is usually used in those cases when the camera is
* faster than the software.
*/
while (!uca_ring_buffer_available (camera->priv->ring_buffer)) {
if (camera->priv->cancelling_grab) {
return FALSE;
}
}

buffer = uca_ring_buffer_get_read_pointer (camera->priv->ring_buffer);

if (buffer == NULL) {
g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM,
"Ring buffer is empty");
}
else {
memcpy (data, buffer, uca_ring_buffer_get_block_size (camera->priv->ring_buffer));
result = TRUE;
}
}
return result;
}

/**
* uca_camera_readout:
* @camera: A #UcaCamera object
Expand Down
5 changes: 5 additions & 0 deletions src/uca-camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct _UcaCameraClass {
void (*trigger) (UcaCamera *camera, GError **error);
void (*write) (UcaCamera *camera, const gchar *name, gpointer data, gsize size, GError **error);
gboolean (*grab) (UcaCamera *camera, gpointer data, GError **error);
gboolean (*grab_live) (UcaCamera *camera, gpointer data, GError **error);
gboolean (*readout) (UcaCamera *camera, gpointer data, guint index, GError **error);
};

Expand Down Expand Up @@ -174,6 +175,10 @@ gboolean uca_camera_grab (UcaCamera *camera,
gpointer data,
GError **error)
__attribute__((nonnull (2)));
gboolean uca_camera_grab_live (UcaCamera *camera,
gpointer data,
GError **error)
__attribute__((nonnull (2)));
gboolean uca_camera_readout (UcaCamera *camera,
gpointer data,
guint index,
Expand Down

0 comments on commit c62bd4b

Please sign in to comment.