diff options
Diffstat (limited to 'bin/tools')
-rw-r--r-- | bin/tools/CMakeLists.txt | 40 | ||||
-rw-r--r-- | bin/tools/benchmark.c | 272 | ||||
-rw-r--r-- | bin/tools/config.h.in | 1 | ||||
-rw-r--r-- | bin/tools/gen-doc.c | 224 | ||||
-rw-r--r-- | bin/tools/grab.c | 292 |
5 files changed, 829 insertions, 0 deletions
diff --git a/bin/tools/CMakeLists.txt b/bin/tools/CMakeLists.txt new file mode 100644 index 0000000..a52bb97 --- /dev/null +++ b/bin/tools/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 2.8) + +add_definitions("--std=c99 -Wall") + +# --- Find packages and libraries --------------------------------------------- +find_package(TIFF) + +# --- Build targets ----------------------------------------------------------- +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ) + +set(libs uca) + +if (TIFF_FOUND) + set(HAVE_LIBTIFF "1") + list(APPEND libs ${TIFF_LIBRARIES}) + include_directories(${TIFF_INCLUDE_DIRS}) +endif () + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +# --- gen-doc +add_executable(gen-doc gen-doc.c) +target_link_libraries(gen-doc ${libs}) + +# --- uca-grab +add_executable(uca-grab grab.c) +target_link_libraries(uca-grab + ringbuffer + ${libs}) + +# --- uca-benchmark +add_executable(benchmark benchmark.c) +target_link_libraries(benchmark ${libs}) + +install(TARGETS uca-grab + RUNTIME DESTINATION bin) diff --git a/bin/tools/benchmark.c b/bin/tools/benchmark.c new file mode 100644 index 0000000..0939d78 --- /dev/null +++ b/bin/tools/benchmark.c @@ -0,0 +1,272 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include <glib-object.h> +#include <signal.h> +#include <string.h> +#include <stdlib.h> +#include "uca-camera.h" +#include "uca-plugin-manager.h" + +typedef void (*GrabFrameFunc) (UcaCamera *camera, gpointer buffer, guint n_frames); + +static UcaCamera *camera = NULL; + +static void +sigint_handler(int signal) +{ + g_print ("Closing down libuca\n"); + uca_camera_stop_recording (camera, NULL); + g_object_unref (camera); + exit (signal); +} + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +static void +log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user) +{ + gsize n_written; + GError *error = NULL; + GIOChannel *channel = user; + +#if GLIB_CHECK_VERSION(2, 26, 0) + GTimeZone *tz; + GDateTime *date_time; + gchar *new_message; + + tz = g_time_zone_new_local (); + date_time = g_date_time_new_now (tz); + + new_message = g_strdup_printf ("[%s] %s\n", + g_date_time_format (date_time, "%FT%H:%M:%S%z"), message); + + g_time_zone_unref (tz); + g_date_time_unref (date_time); + + g_io_channel_write_chars (channel, new_message, strlen (new_message), &n_written, &error); + g_assert_no_error (error); + g_free (new_message); +#else + g_io_channel_write_chars (channel, message, strlen (message), &n_written, &error); + g_assert_no_error (error); +#endif + + g_io_channel_flush (channel, &error); + g_assert_no_error (error); +} + +static void +grab_frames_sync (UcaCamera *camera, gpointer buffer, guint n_frames) +{ + GError *error = NULL; + + uca_camera_start_recording (camera, &error); + + for (guint i = 0; i < n_frames; i++) { + if (!uca_camera_grab (camera, buffer, &error)) + g_warning ("Data stream ended"); + + if (error != NULL) { + g_warning ("Error grabbing frame %02i/%i: `%s'", i, n_frames, error->message); + g_error_free (error); + error = NULL; + } + } + + uca_camera_stop_recording (camera, &error); +} + +static void +grab_callback (gpointer data, gpointer user_data) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + guint *n_acquired_frames = user_data; + + g_static_mutex_lock (&mutex); + *n_acquired_frames += 1; + g_static_mutex_unlock (&mutex); +} + +static void +grab_frames_async (UcaCamera *camera, gpointer buffer, guint n_frames) +{ + GError *error = NULL; + guint n_acquired_frames = 0; + + uca_camera_set_grab_func (camera, grab_callback, &n_acquired_frames); + uca_camera_start_recording (camera, &error); + + /* + * Behold! Spinlooping is probably a bad idea but nowadays single core + * machines are relatively rare. + */ + while (n_acquired_frames < n_frames) + ; + + uca_camera_stop_recording (camera, &error); +} + +static void +benchmark_method (UcaCamera *camera, gpointer buffer, GrabFrameFunc func, guint n_runs, guint n_frames, guint n_bytes) +{ + GTimer *timer; + gdouble fps; + gdouble bandwidth; + gdouble total_time = 0.0; + GError *error = NULL; + + g_print ("%-10i%-10i", n_frames, n_runs); + timer = g_timer_new (); + g_assert_no_error (error); + + for (guint run = 0; run < n_runs; run++) { + g_message ("Start run %i of %i", run, n_runs); + g_timer_start (timer); + + func (camera, buffer, n_frames); + + g_timer_stop (timer); + total_time += g_timer_elapsed (timer, NULL); + } + + g_assert_no_error (error); + + fps = n_runs * n_frames / total_time; + bandwidth = n_bytes * fps / 1024 / 1024; + g_print ("%-16.2f%-16.2f\n", fps, bandwidth); + + g_timer_destroy (timer); +} + +static void +benchmark (UcaCamera *camera) +{ + const guint n_runs = 3; + const guint n_frames = 100; + + guint sensor_width; + guint sensor_height; + guint roi_width; + guint roi_height; + guint bits; + guint n_bytes_per_pixel; + guint n_bytes; + gdouble exposure = 0.00001; + gpointer buffer; + + g_object_set (G_OBJECT (camera), + "exposure-time", exposure, + NULL); + + g_object_get (G_OBJECT (camera), + "sensor-width", &sensor_width, + "sensor-height", &sensor_height, + "sensor-bitdepth", &bits, + "roi-width", &roi_width, + "roi-height", &roi_height, + "exposure-time", &exposure, + NULL); + + g_print ("# --- General information ---\n"); + g_print ("# Sensor size: %ix%i\n", sensor_width, sensor_height); + g_print ("# ROI size: %ix%i\n", roi_width, roi_height); + g_print ("# Exposure time: %fs\n", exposure); + g_print ("# Bits: %i\n", bits); + + /* Synchronous frame acquisition */ + g_print ("# %-10s%-10s%-10s%-16s%-16s\n", "type", "n_frames", "n_runs", "frames/s", "MiB/s"); + g_print (" %-10s", "sync"); + + g_message ("Start synchronous benchmark"); + + n_bytes_per_pixel = bits > 8 ? 2 : 1; + n_bytes = roi_width * roi_height * n_bytes_per_pixel; + buffer = g_malloc0(n_bytes); + + benchmark_method (camera, buffer, grab_frames_sync, n_runs, n_frames, n_bytes); + + /* Asynchronous frame acquisition */ + g_object_set (G_OBJECT(camera), + "transfer-asynchronously", TRUE, + NULL); + + g_message ("Start asynchronous benchmark"); + g_print (" %-10s", "async"); + + benchmark_method (camera, buffer, grab_frames_async, n_runs, n_frames, n_bytes); + + g_free (buffer); +} + +int +main (int argc, char *argv[]) +{ + UcaPluginManager *manager; + GIOChannel *log_channel; + GError *error = NULL; + + (void) signal (SIGINT, sigint_handler); + g_type_init(); + + if (argc < 2) { + print_usage(); + return 1; + } + + log_channel = g_io_channel_new_file ("error.log", "a+", &error); + g_assert_no_error (error); + g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); + + if (camera == NULL) { + g_error ("Initialization: %s", error->message); + return 1; + } + + benchmark (camera); + + g_object_unref (camera); + g_io_channel_shutdown (log_channel, TRUE, &error); + g_assert_no_error (error); + + return 0; +} diff --git a/bin/tools/config.h.in b/bin/tools/config.h.in new file mode 100644 index 0000000..aea5237 --- /dev/null +++ b/bin/tools/config.h.in @@ -0,0 +1 @@ +#cmakedefine HAVE_LIBTIFF diff --git a/bin/tools/gen-doc.c b/bin/tools/gen-doc.c new file mode 100644 index 0000000..d27bdd8 --- /dev/null +++ b/bin/tools/gen-doc.c @@ -0,0 +1,224 @@ +/* Copyright (C) 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include <glib-object.h> +#include "uca-plugin-manager.h" +#include "uca-camera.h" + + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: gen-doc [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +static const gchar * +get_flags_description (GParamSpec *pspec) +{ + static const gchar *descriptions[] = { + "", + "Read-only", + "Write-only", + "Read / Write", + "" + }; + + if (pspec->flags >= 3) + return descriptions[3]; + + return descriptions[pspec->flags]; +} + +static void +print_property_toc (GParamSpec **pspecs, guint n_props) +{ + g_print ("<h2>Properties</h2><ul id=\"toc\">"); + + for (guint i = 0; i < n_props; i++) { + GParamSpec *pspec = pspecs[i]; + const gchar *name = g_param_spec_get_name (pspec); + + g_print ("<li><code><a href=#%s>\"%s\"</a></code></li>", name, name); + } + + g_print ("</ul>"); +} + +static void +print_value_info (GParamSpec *pspec) +{ + gchar *default_value = NULL; + GString *range = g_string_new(""); + +#define MAKE_RANGE(spec_type, fmt) \ + { \ + spec_type *spec = (spec_type *) pspec; \ + g_string_printf (range, \ + fmt" ≤ <em>%s</em> ≤ "fmt, \ + spec->minimum, \ + g_param_spec_get_name (pspec), \ + spec->maximum); \ + default_value = g_strdup_printf (fmt, spec->default_value); \ + } + + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + { + GParamSpecBoolean *spec = (GParamSpecBoolean *) pspec; + default_value = spec->default_value ? g_strdup ("<code>TRUE</code>") : g_strdup ("<code>FALSE</code>"); + } + break; + + case G_TYPE_UINT: + MAKE_RANGE (GParamSpecUInt, "%i"); + break; + + case G_TYPE_FLOAT: + MAKE_RANGE (GParamSpecFloat, "%.1e"); + break; + + case G_TYPE_DOUBLE: + MAKE_RANGE (GParamSpecDouble, "%.1e"); + break; + } + +#undef MAKE_RANGE + + if (g_type_is_a (pspec->value_type, G_TYPE_ENUM)) { + GParamSpecEnum *spec = (GParamSpecEnum *) pspec; + + if (spec->enum_class->n_values > 0) { + g_string_printf (range, "<table><tr><th>Enum name</th><th>Value</th>"); + + for (guint i = 0; i < spec->enum_class->n_values; i++) { + GEnumValue *v = &spec->enum_class->values[i]; + g_string_append_printf (range, + "<tr><td><code>%s</code></td><td>%i</td></tr>", + v->value_name, v->value); + } + + g_string_append_printf (range, "</table>"); + } + } + + if (range->len > 0) + g_print ("<p>Possible values: %s</p>", range->str); + + if (default_value != NULL) { + g_print ("<p>Default value: %s</p>", default_value); + g_free (default_value); + } + + g_string_free (range, TRUE); +} + +static void +print_property_descriptions (GParamSpec **pspecs, guint n_props) +{ + g_print ("<h2>Details</h2><dl>"); + + for (guint i = 0; i < n_props; i++) { + GParamSpec *pspec = pspecs[i]; + const gchar *name = g_param_spec_get_name (pspec); + + g_print ("<dt id=\"%s\"><a href=\"#toc\">%s</a></dt>\n", name, name); + g_print ("<dd>"); + g_print ("<pre><code class=\"prop-type\">\"%s\" : %s : %s</code></pre>\n", + name, + g_type_name (pspec->value_type), + get_flags_description (pspec)); + g_print ("<p>%s</p>\n", g_param_spec_get_blurb (pspec)); + print_value_info (pspec); + g_print ("</dd>"); + } + + g_print ("</dl>"); +} + +static void +print_properties (UcaCamera *camera) +{ + GObjectClass *oclass; + GParamSpec **pspecs; + guint n_props; + + oclass = G_OBJECT_GET_CLASS (camera); + pspecs = g_object_class_list_properties (oclass, &n_props); + + print_property_toc (pspecs, n_props); + print_property_descriptions (pspecs, n_props); + + g_free (pspecs); +} + +static const gchar *html_header = "<html><head>\ +<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\" />\ +<link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700|Droid+Serif:400,400italic|Inconsolata' rel='stylesheet' type='text/css'>\ +<title>%s — properties</title></head><body>"; +static const gchar *html_footer = "</body></html>"; + +int main(int argc, char *argv[]) +{ + UcaPluginManager *manager; + UcaCamera *camera; + gchar *name; + GError *error = NULL; + + g_type_init(); + manager = uca_plugin_manager_new (); + + if (argc < 2) { + name = g_strdup ("Basic camera"); + camera = g_object_new (UCA_TYPE_CAMERA, NULL); + } + else { + name = argv[1]; + camera = uca_plugin_manager_get_camera (manager, name, &error, NULL); + } + + if (camera == NULL) { + g_print("Error during initialization: %s\n", error->message); + print_usage(); + return 1; + } + + g_print (html_header, name); + g_print ("<div id=\"header\"><h1 class=\"title\">Property documentation of %s</h1>", name); + print_properties (camera); + g_print ("%s\n", html_footer); + + g_object_unref (camera); + g_object_unref (manager); +} diff --git a/bin/tools/grab.c b/bin/tools/grab.c new file mode 100644 index 0000000..972f000 --- /dev/null +++ b/bin/tools/grab.c @@ -0,0 +1,292 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include "config.h" + +#include <glib-object.h> +#include <stdio.h> +#include <stdlib.h> +#include "uca-plugin-manager.h" +#include "uca-camera.h" +#include "ring-buffer.h" + +#ifdef HAVE_LIBTIFF +#include <tiffio.h> +#endif + + +typedef struct { + gint n_frames; + gdouble duration; + gchar *filename; +} Options; + + +static gchar * +get_camera_list (void) +{ + GList *types; + GString *str; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + types = uca_plugin_manager_get_available_cameras (manager); + str = g_string_new ("[ "); + + if (types != NULL) { + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + + if (g_list_next (it) == NULL) + g_string_append_printf (str, "%s ]", name); + else + g_string_append_printf (str, "%s, ", name); + } + } + else { + g_string_append (str, "]"); + } + + g_object_unref (manager); + return g_string_free (str, FALSE); +} + +static guint +get_bytes_per_pixel (guint bits_per_pixel) +{ + return bits_per_pixel > 8 ? 2 : 1; +} + +#ifdef HAVE_LIBTIFF +static void +write_tiff (RingBuffer *buffer, + Options *opts, + guint width, + guint height, + guint bits_per_pixel) +{ + TIFF *tif; + guint32 rows_per_strip; + guint n_frames; + guint bits_per_sample; + gsize bytes_per_pixel; + + if (opts->filename) + tif = TIFFOpen (opts->filename, "w"); + else + tif = TIFFOpen ("frames.tif", "w"); + + n_frames = ring_buffer_get_num_blocks (buffer); + rows_per_strip = TIFFDefaultStripSize (tif, (guint32) - 1); + bytes_per_pixel = get_bytes_per_pixel (bits_per_pixel); + bits_per_sample = bits_per_pixel > 8 ? 16 : 8; + + /* Write multi page TIFF file */ + TIFFSetField (tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + + for (guint i = 0; i < n_frames; i++) { + gpointer data; + gsize offset = 0; + + data = ring_buffer_get_pointer (buffer, i); + + TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample); + TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rows_per_strip); + TIFFSetField (tif, TIFFTAG_PAGENUMBER, i, n_frames); + + for (guint y = 0; y < height; y++, offset += width * bytes_per_pixel) + TIFFWriteScanline (tif, data + offset, y, 0); + + TIFFWriteDirectory (tif); + } + + TIFFClose (tif); +} +#else +static void +write_raw (RingBuffer *buffer, + Options *opts) +{ + guint n_frames; + gsize size; + + size = ring_buffer_get_block_size (buffer); + n_frames = ring_buffer_get_num_blocks (buffer); + + for (gint i = 0; i < n_frames; i++) { + FILE *fp; + gchar *filename; + gpointer data; + + if (opts->filename) + filename = g_strdup_printf ("%s-%08i.raw", opts->filename, i); + else + filename = g_strdup_printf ("frame-%08i.raw", i); + + fp = fopen(filename, "wb"); + data = ring_buffer_get_pointer (buffer, i); + + fwrite (data, size, 1, fp); + fclose (fp); + g_free (filename); + } +} +#endif + +static GError * +record_frames (UcaCamera *camera, Options *opts) +{ + guint roi_width; + guint roi_height; + guint bits; + guint pixel_size; + gsize size; + gint n_frames; + guint n_allocated; + GTimer *timer; + RingBuffer *buffer; + GError *error = NULL; + gdouble last_printed; + + g_object_get (G_OBJECT (camera), + "roi-width", &roi_width, + "roi-height", &roi_height, + "sensor-bitdepth", &bits, + NULL); + + pixel_size = get_bytes_per_pixel (bits); + size = roi_width * roi_height * pixel_size; + n_allocated = opts->n_frames > 0 ? opts->n_frames : 256; + buffer = ring_buffer_new (size, n_allocated); + timer = g_timer_new(); + + g_print("Start recording: %ix%i at %i bits/pixel\n", + roi_width, roi_height, bits); + + uca_camera_start_recording(camera, &error); + + if (error != NULL) + return error; + + n_frames = 0; + g_timer_start(timer); + last_printed = 0.0; + + while (1) { + gdouble elapsed; + + uca_camera_grab (camera, ring_buffer_get_current_pointer (buffer), &error); + ring_buffer_proceed (buffer); + + if (error != NULL) + return error; + + n_frames++; + elapsed = g_timer_elapsed (timer, NULL); + + if (n_frames == opts->n_frames || (opts->duration > 0.0 && elapsed >= opts->duration)) + break; + + if (elapsed - last_printed >= 1.0) { + g_print ("Recorded %i frames at %.2f frames/s\n", + n_frames, n_frames / elapsed); + last_printed = elapsed; + } + } + + g_print ("Stop recording: %3.2f frames/s\n", + n_frames / g_timer_elapsed (timer, NULL)); + + uca_camera_stop_recording (camera, &error); + +#ifdef HAVE_LIBTIFF + write_tiff (buffer, opts, roi_width, roi_height, bits); +#else + write_raw (buffer, opts); +#endif + + ring_buffer_free (buffer); + g_timer_destroy (timer); + + return error; +} + +int +main (int argc, char *argv[]) +{ + GOptionContext *context; + UcaPluginManager *manager; + UcaCamera *camera; + gchar *cam_list; + GError *error = NULL; + + static Options opts = { + .n_frames = -1, + .duration = -1.0, + .filename = NULL + }; + + static GOptionEntry entries[] = { + { "num-frames", 'n', 0, G_OPTION_ARG_INT, &opts.n_frames, "Number of frames to acquire", "N" }, + { "duration", 'd', 0, G_OPTION_ARG_DOUBLE, &opts.duration, "Duration in seconds", NULL }, + { "output", 'o', 0, G_OPTION_ARG_STRING, &opts.filename, "Output file name", "FILE" }, + { NULL } + }; + + g_type_init(); + + cam_list = get_camera_list (); + context = g_option_context_new (cam_list); + g_option_context_add_main_entries (context, entries, NULL); + g_free (cam_list); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Failed parsing arguments: %s\n", error->message); + exit (1); + } + + if (argc < 2) { + g_print ("%s\n", g_option_context_get_help (context, TRUE, NULL)); + exit (0); + } + + if (opts.n_frames < 0 && opts.duration < 0.0) { + g_print ("You must specify at least one of --num-frames and --output.\n"); + exit (1); + } + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); + + if (camera == NULL) { + g_print ("Error during initialization: %s\n", error->message); + exit (1); + } + + error = record_frames (camera, &opts); + + if (error != NULL) + g_print ("Error: %s\n", error->message); + + g_object_unref (camera); + return error != NULL ? 1 : 0; +} |