Examples

The following is a list of examples and their purpose. These examples exist in C and Python3.

The standard installation path for examples is /usr/share/theimagingsource/tiscamera/examples.

It may be neccessary to install additional development packages when using pre-compiled tiscamera packages. See Dependencies.

Build Instructions

Instructions to build applications using tiscamera.

Show sample code
 1LIBS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-1.0 --libs)
 2LIBS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-video-1.0 --libs)
 3LIBS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gobject-introspection-1.0 --libs)
 4LIBS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config tcam --libs)
 5
 6# to build within the source tree
 7# enable the following lines
 8# and source build directory ./env.sh
 9# LIBS+=-L./../../build/libs
10
11CFLAGS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-1.0 --cflags)
12CFLAGS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-video-1.0 --cflags)
13CFLAGS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gobject-introspection-1.0 --cflags)
14CFLAGS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config tcam --cflags)
15
16# CFLAGS+=-I../../libs/tcam-property/src
17# CFLAGS+=-I../../src/gstreamer-1.0/tcamsrc
18
19.PHONY: all clean
20
21EXECS = 00-list-devices \
22	01-list-properties \
23	02-set-properties \
24	03-live-stream \
25	04-list-formats \
26	05-set-format \
27	06-softwaretrigger \
28	07-appsink \
29	08-save-stream \
30	09-device-lost \
31	10-metadata \
32	11-json-state \
33	12-tcam-properties \
34	13-gstquery
35
36all: $(EXECS)
37
38
39$(EXECS): %: %.c
40	$(CC) -g -DGST_DISABLE_DEPRECATED -Wall -Wextra -O0 $(CFLAGS) -o $@ $< $(LIBS)
41
42clean:
43	$(RM) *.o
44	$(RM) $(EXECS)

00 - list-devices

Shows what cameras there are and how to identify them.

Show sample code
  1
  2/* This example will show you how to list information about the available devices */
  3
  4#include <gst/gst.h>
  5#include <stdio.h> /* printf and putchar */
  6
  7
  8void print_device(GstDevice* device)
  9{
 10
 11    GstStructure* struc = gst_device_get_properties(device);
 12
 13    printf("\tmodel:\t%s\tserial:\t%s\ttype:\t%s\n",
 14           gst_structure_get_string(struc, "model"),
 15           gst_structure_get_string(struc, "serial"),
 16           gst_structure_get_string(struc, "type"));
 17
 18    gst_structure_free(struc);
 19
 20}
 21
 22
 23gboolean bus_function(GstBus* bus __attribute__((unused)), GstMessage* message, gpointer user_data __attribute__((unused)))
 24{
 25    GstDevice* device;
 26
 27    switch (GST_MESSAGE_TYPE(message))
 28    {
 29        case GST_MESSAGE_DEVICE_ADDED:
 30        {
 31            gst_message_parse_device_added(message, &device);
 32
 33            printf("NEW device\n");
 34            print_device(device);
 35            gst_object_unref(device);
 36            break;
 37        }
 38        case GST_MESSAGE_DEVICE_REMOVED:
 39        {
 40            // this can also be used as an alternative to device-lost signals
 41            gst_message_parse_device_removed(message, &device);
 42            printf("REMOVED Device\n");
 43            print_device(device);
 44            gst_object_unref(device);
 45            break;
 46        }
 47        /*
 48        // not used by tiscamera
 49        // requires gstreamer 1.16
 50        case GST_MESSAGE_DEVICE_CHANGED:
 51        */
 52        default:
 53        {
 54            break;
 55        }
 56    }
 57
 58    // this means we want to continue
 59    // to listen to device events
 60    // to stop listening return G_SOURCE_REMOVE;
 61    return G_SOURCE_CONTINUE;
 62}
 63
 64
 65int main(int argc, char* argv[])
 66{
 67    /* this line sets the gstreamer default logging level
 68       it can be removed in normal applications
 69       gstreamer logging can contain verry useful information
 70       when debugging your application
 71       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 72       for further details
 73    */
 74    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 75
 76    gst_init(&argc, &argv); // init gstreamer
 77
 78    // The device monitor listens to device activities for us
 79    GstDeviceMonitor* monitor = gst_device_monitor_new();
 80    // We are only interested in devices that are in the categories
 81    // Video and Source && tcam
 82    gst_device_monitor_add_filter(monitor, "Video/Source/tcam", NULL);
 83
 84    //
 85    // static query
 86    // list all devices that are available right now
 87    //
 88
 89    GList* devices = gst_device_monitor_get_devices(monitor);
 90
 91    for (GList* elem = devices; elem; elem = elem->next)
 92    {
 93        GstDevice* device = (GstDevice*) elem->data;
 94
 95        print_device(device);
 96    }
 97
 98    g_list_free_full(devices, gst_object_unref);
 99
100    //
101    // dynamic listing
102    // notify us on all device changes (add/remove/changed)
103    // all devices will appear once as ADDED
104    //
105
106    GstBus* bus = gst_device_monitor_get_bus(monitor);
107    gst_bus_add_watch(bus, bus_function, NULL);
108    gst_object_unref(bus);
109
110    // actually start the dynamic monitoring
111    gst_device_monitor_start(monitor);
112
113    printf("Now listening to device changes. Disconnect your camera to see a remove event. Connect it to see a connect event. Press Ctrl-C to end.\n");
114
115    // This is simply used to wait for events or the user to end this script
116    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
117    g_main_loop_run(loop);
118    g_main_loop_unref(loop);
119
120    // has to be called when gst_device_monitor_start has been called
121    gst_device_monitor_stop(monitor);
122
123    // cleanup
124    gst_object_unref(monitor);
125
126    return 0;
127}

01 - list-properties

Shows the properties of a camera and their settings (range, current value, etc.).

Show sample code
  1
  2/* This example will show you how to list the available properties */
  3
  4#include "tcam-property-1.0.h" /* gobject introspection interface */
  5
  6#include <gst/gst.h>
  7#include <stdio.h> /* printf and putchar */
  8#include <string.h>
  9#include <unistd.h>
 10
 11void print_flags(TcamPropertyBase* prop)
 12{
 13    printf("Available: ");
 14    GError* err = NULL;
 15    gboolean av = tcam_property_base_is_available(prop, &err);
 16    if (av)
 17    {
 18        printf("yes");
 19    }
 20    else
 21    {
 22        printf("no");
 23    }
 24
 25    printf("\tLocked: ");
 26
 27    gboolean lo = tcam_property_base_is_locked(prop, &err);
 28
 29    if (lo)
 30    {
 31        printf("yes");
 32    }
 33    else
 34    {
 35        printf("no");
 36    }
 37}
 38
 39
 40void list_properties(GstElement* source)
 41{
 42
 43    GError* err = NULL;
 44    GSList* names =  tcam_property_provider_get_tcam_property_names(TCAM_PROPERTY_PROVIDER(source), &err);
 45
 46    for (unsigned int i = 0; i < g_slist_length(names); ++i)
 47    {
 48        char* name = (char*)g_slist_nth(names, i)->data;
 49
 50        TcamPropertyBase* base_property = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source), name, &err);
 51
 52        TcamPropertyType type = tcam_property_base_get_property_type(base_property);
 53
 54        switch(type)
 55        {
 56            case TCAM_PROPERTY_TYPE_INTEGER:
 57            {
 58                TcamPropertyInteger* integer = TCAM_PROPERTY_INTEGER(base_property);
 59
 60                gint64 def = tcam_property_integer_get_default(integer, &err);
 61
 62                gint64 min;
 63                gint64 max;
 64                gint64 step;
 65                tcam_property_integer_get_range(integer, &min, &max, &step, &err);
 66
 67                if (err)
 68                {
 69                    printf("%s\n", err->message);
 70                    g_error_free(err);
 71                    err = NULL;
 72                    break;
 73                }
 74
 75                gint64 value = tcam_property_integer_get_value(integer, &err);
 76
 77                if (err)
 78                {
 79                    printf("%s\n", err->message);
 80                    g_error_free(err);
 81                    err = NULL;
 82                    break;
 83                }
 84
 85                const char* unit = "";
 86                const char* tmp_unit = tcam_property_integer_get_unit(integer);
 87
 88                if (tmp_unit)
 89                {
 90                    unit = tmp_unit;
 91                }
 92
 93                printf("%s\ttype: Integer\t"
 94                       "Display Name: \"%s\" "
 95                       "Category: %s\n"
 96                       "\t\t\tDescription: %s\n"
 97                       "\t\t\tUnit: %s\n"
 98                       "\t\t\tVisibility: %s\n"
 99                       "\t\t\tPresentation: %s\n\t\t\t",
100                       name,
101                       tcam_property_base_get_display_name(base_property),
102                       tcam_property_base_get_category(base_property),
103                       tcam_property_base_get_description(base_property),
104                       unit,
105                       g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)),
106                       g_enum_to_string(tcam_property_intrepresentation_get_type(), tcam_property_integer_get_representation(integer)));
107                print_flags(base_property);
108                printf("\n\n"
109                       "\t\t\tDefault: %ld\n"
110                       "\t\t\tValue: %ld"
111                       "\n\n", def, value);
112
113                break;
114
115            }
116            case TCAM_PROPERTY_TYPE_FLOAT:
117            {
118                TcamPropertyFloat* f = TCAM_PROPERTY_FLOAT(base_property);
119
120                gdouble def = tcam_property_float_get_default(f, &err);
121;
122                gdouble min;
123                gdouble max;
124                gdouble step;
125                tcam_property_float_get_range(f, &min, &max, &step, &err);
126
127                if (err)
128                {
129                    printf("%s\n", err->message);
130                    g_error_free(err);
131                    err = NULL;
132                    break;
133                }
134
135                gdouble value = tcam_property_float_get_value(f, &err);
136
137                if (err)
138                {
139                    printf("%s\n", err->message);
140                    g_error_free(err);
141                    err = NULL;
142                    break;
143                }
144
145
146                const char* unit = "";
147                const char* tmp_unit = tcam_property_float_get_unit(f);
148
149                if (tmp_unit)
150                {
151                    unit = tmp_unit;
152                }
153
154                printf("%s\ttype: Float\t"
155                       "Display Name: \"%s\" "
156                       "Category: %s\n"
157                       "\t\t\tDescription: %s\n"
158                       "\t\t\tUnit: %s\n"
159                       "\t\t\tVisibility: %s\n"
160                       "\t\t\tPresentation: %s\n\t\t\t",
161                       name,
162                       tcam_property_base_get_display_name(base_property),
163                       tcam_property_base_get_category(base_property),
164                       tcam_property_base_get_description(base_property),
165                       unit,
166                       g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)),
167                       g_enum_to_string(tcam_property_intrepresentation_get_type(), tcam_property_float_get_representation(f)));
168                print_flags(base_property);
169                printf("\n\n"
170                       "\t\t\tDefault: %f\n"
171                       "\t\t\tValue: %f"
172                       "\n\n", def, value);
173
174                break;
175            }
176            case TCAM_PROPERTY_TYPE_ENUMERATION:
177            {
178                TcamPropertyEnumeration* e = TCAM_PROPERTY_ENUMERATION(base_property);
179
180                const char* value = tcam_property_enumeration_get_value(e, &err);
181
182                if (err)
183                {
184                    printf("%s\n", err->message);
185                    g_error_free(err);
186                    err = NULL;
187                    break;
188                }
189
190                const char* def = tcam_property_enumeration_get_default(e, &err);
191
192                if (err)
193                {
194                    printf("%s\n", err->message);
195                    g_error_free(err);
196                    err = NULL;
197                    break;
198                }
199
200                printf("%s\ttype: Enumeration\t"
201                       "Display Name: \"%s\" "
202                       "Category: %s\n"
203                       "\t\t\tDescription: %s\n"
204                       "\t\t\tVisibility: %s\n"
205                       "\t\t\t",
206                       name, tcam_property_base_get_display_name(base_property),
207                       tcam_property_base_get_category(base_property),
208                       tcam_property_base_get_description(base_property),
209                       g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)));
210                print_flags(base_property);
211                printf("\n\n"
212                       "\t\t\tEntries:");
213
214                GSList* enum_entries = tcam_property_enumeration_get_enum_entries(e, &err);
215
216                if (err)
217                {
218                    printf("%s\n", err->message);
219                    g_error_free(err);
220                    break;
221                }
222
223                if (enum_entries)
224                {
225                    for (GSList* entry = enum_entries; entry != NULL; entry = entry->next)
226                    {
227                        printf(" %s", (const char*)entry->data);
228                    }
229
230                    g_slist_free_full(enum_entries, g_free);
231                }
232                printf("\n\t\t\tDefault: %s\n"
233                       "\t\t\tValue: %s\n\n\n", def, value);
234
235                break;
236            }
237            case TCAM_PROPERTY_TYPE_BOOLEAN:
238            {
239                TcamPropertyBoolean* b = TCAM_PROPERTY_BOOLEAN(base_property);
240                gboolean value = tcam_property_boolean_get_value(b, &err);
241                gboolean def = tcam_property_boolean_get_default(b, &err);
242
243                if (err)
244                {
245                    printf("%s\n", err->message);
246                    g_error_free(err);
247                    err = NULL;
248                    break;
249                }
250
251                const char* val_str = "false";
252                const char* def_str = "false";
253
254                if (value)
255                {
256                    val_str = "true";
257                }
258
259                if (def)
260                {
261                    def_str = "true";
262                }
263
264                printf("%s\ttype: Boolean\t"
265                       "Display Name: \"%s\" "
266                       "Category: %s\n"
267                       "\t\t\tDescription: %s\n"
268                       "\t\t\t",
269                       name,
270                       tcam_property_base_get_display_name(base_property),
271                       tcam_property_base_get_category(base_property),
272                       tcam_property_base_get_description(base_property)
273                    );
274                print_flags(base_property);
275                printf("\n\n\t\t\tDefault: %s\n"
276                       "\t\t\tValue: %s\n\n\n",
277                       def_str, val_str);
278
279                break;
280            }
281            case TCAM_PROPERTY_TYPE_COMMAND:
282            {
283                printf("%s\ttype: Command\t"
284                       "Display Name: \"%s\" "
285                       "Category: %s\n"
286                       "\t\t\tDescription: %s\n"
287                       "\t\t\t",
288                       name,
289                       tcam_property_base_get_display_name(base_property),
290                       tcam_property_base_get_category(base_property),
291                       tcam_property_base_get_description(base_property));
292                print_flags(base_property);
293                printf("\n\n\n");
294                        break;
295            }
296            default:
297            {
298                break;
299            }
300            printf("\n\n\n");
301        }
302        g_object_unref(base_property);
303    }
304    g_slist_free_full(names, g_free);
305}
306
307
308int main(int argc, char* argv[])
309{
310    /* this line sets the gstreamer default logging level
311       it can be removed in normal applications
312       gstreamer logging can contain verry useful information
313       when debugging your application
314       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
315       for further details
316    */
317    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
318
319    gst_init(&argc, &argv); // init gstreamer
320
321    GError* err = NULL;
322
323    // this is a placeholder definition
324    // normally your pipeline would be defined here
325    GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
326
327    if (pipeline == NULL)
328    {
329        printf("Unable to create pipeline: %s\n", err->message);
330        g_free(err);
331        return 1;
332    }
333
334    /* get the tcambin to retrieve device information */
335    GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
336
337    const char* serial = NULL; // set this if you do not want the first found device
338
339    if (serial != NULL)
340    {
341        GValue val = {};
342        g_value_init(&val, G_TYPE_STRING);
343        g_value_set_static_string(&val, serial);
344
345        g_object_set_property(G_OBJECT(source), "serial", &val);
346    }
347
348    // in the READY state the camera will always be initialized
349    gst_element_set_state(pipeline, GST_STATE_READY);
350
351    list_properties(source);
352
353    // cleanup
354    gst_element_set_state(pipeline, GST_STATE_NULL);
355
356    gst_object_unref(source);
357    gst_object_unref(pipeline);
358
359    return 0;
360}

02 - set-properties

Shows how to set a specific property.

Show sample code
  1
  2/* This example will show you how to set properties for a certain camera */
  3
  4#include "tcam-property-1.0.h" /* gobject introspection interface */
  5
  6#include <gst/gst.h>
  7#include <stdio.h> /* printf and putchar */
  8
  9
 10void print_enum_property(GstElement* source, const char* name)
 11{
 12    /* this is only a sample not all properties will be set here */
 13
 14    GError* err = NULL;
 15    TcamPropertyBase* property_base = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source),
 16                                                                               name,
 17                                                                               &err);
 18
 19    if (err)
 20    {
 21        printf("Error while retrieving property: %s\n", err->message);
 22        g_error_free(err);
 23        err = NULL;
 24    }
 25
 26    if (tcam_property_base_get_property_type(property_base) != TCAM_PROPERTY_TYPE_ENUMERATION)
 27    {
 28        printf("%s has wrong type. This should not happen.\n", name);
 29    }
 30    else
 31    {
 32        TcamPropertyEnumeration* property_enum = TCAM_PROPERTY_ENUMERATION(property_base);
 33        const char* value = tcam_property_enumeration_get_value(property_enum, &err);
 34
 35        if (err)
 36        {
 37            printf("Error while retrieving property: %s\n", err->message);
 38            g_error_free(err);
 39            err = NULL;
 40        }
 41        else
 42        {
 43            printf("%s: %s\n", name, value);
 44        }
 45    }
 46    g_object_unref(property_base);
 47}
 48
 49
 50void set_enum_property(GstElement* source, const char* name, const char* value)
 51{
 52    GError* err = NULL;
 53    TcamPropertyBase* property_base = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source),
 54                                                                               name,
 55                                                                               &err);
 56
 57    if (err)
 58    {
 59        printf("Error while retrieving property: %s\n", err->message);
 60        g_error_free(err);
 61        err = NULL;
 62    }
 63
 64    if (tcam_property_base_get_property_type(property_base) != TCAM_PROPERTY_TYPE_ENUMERATION)
 65    {
 66        printf("ExposureAuto has wrong type. This should not happen.\n");
 67    }
 68    else
 69    {
 70        TcamPropertyEnumeration* enum_property = TCAM_PROPERTY_ENUMERATION(property_base);
 71
 72        tcam_property_enumeration_set_value(enum_property, value, &err);
 73
 74        if (err)
 75        {
 76            printf("Error while setting property: %s\n", err->message);
 77            g_error_free(err);
 78            err = NULL;
 79        }
 80        else
 81        {
 82            printf("Set %s to %s\n", name, value);
 83        }
 84    }
 85    g_object_unref(property_base);
 86}
 87
 88
 89
 90int main(int argc, char* argv[])
 91{
 92    /* this line sets the gstreamer default logging level
 93       it can be removed in normal applications
 94       gstreamer logging can contain verry useful information
 95       when debugging your application
 96       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 97       for further details
 98    */
 99    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
100
101    gst_init(&argc, &argv); // init gstreamer
102
103    GError* err = NULL;
104
105    // this is a placeholder definition
106    // normally your pipeline would be defined here
107    GstElement* pipeline = gst_parse_launch("tcambin name=source  ! fakesink", &err);
108
109    if (pipeline == NULL)
110    {
111        printf("Unable to create pipeline: %s\n", err->message);
112        g_free(err);
113        err = NULL;
114        return 1;
115    }
116
117    /* create a tcambin to retrieve device information */
118    GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
119
120    const char* serial = NULL;
121
122    if (serial != NULL)
123    {
124        GValue val = {};
125        g_value_init(&val, G_TYPE_STRING);
126        g_value_set_static_string(&val, serial);
127
128        g_object_set_property(G_OBJECT(source), "serial", &val);
129    }
130
131    gst_element_set_state(pipeline, GST_STATE_READY);
132
133    /* Device is now in a state for interactions */
134
135    /*
136      We print the properties for a before/after comparison,
137     */
138    printf("Values before we change them:\n\n");
139
140    print_enum_property(source, "ExposureAuto");
141    print_enum_property(source, "GainAuto");
142
143    /*
144      We set the properties to other values
145     */
146    printf("\nChanging:\n\n");
147
148    set_enum_property(source, "ExposureAuto", "Off");
149    set_enum_property(source, "GainAuto", "Off");
150
151    /* alternatively you can get/set directly on the TCAM_PROPERTY_PROVIDER */
152    /* for this you need to know the type of the property you want to get/set */
153
154    /* tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "ExposureAuto", "Off"); */
155    /* tcam_property_provider_set_tcam_integer(TCAM_PROPERTY_PROVIDER(source), "Brightness", 200); */
156    /* tcam_property_provider_set_tcam_float(TCAM_PROPERTY_PROVIDER(source), "ExposureTime", 30000.0); */
157
158    printf("\nValues after we changed them:\n\n");
159
160    /*
161      second print for the before/after comparison
162     */
163    print_enum_property(source, "ExposureAuto");
164    print_enum_property(source, "GainAuto");
165
166    /* cleanup, reset state */
167    gst_element_set_state(source, GST_STATE_NULL);
168
169    gst_object_unref(source);
170
171    return 0;
172}

03 - live-stream

Delivers live-image stream from the camera.

Show sample code
 1
 2/* This example will show you how to start a live stream from your camera */
 3
 4#include <gst/gst.h>
 5#include <stdio.h> /* printf and putchar */
 6
 7
 8int main(int argc, char* argv[])
 9{
10    /* this line sets the gstreamer default logging level
11       it can be removed in normal applications
12       gstreamer logging can contain verry useful information
13       when debugging your application
14       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
15       for further details
16    */
17    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
18
19    gst_init(&argc, &argv); // init gstreamer
20
21    const char* serial = NULL; // set this if you do not want the first found device
22
23    GError* err = NULL;
24
25    GstElement* pipeline =
26        gst_parse_launch("tcambin name=source ! videoconvert ! ximagesink sync=false", &err);
27
28    if (err)
29    {
30        printf("%s\n", err->message);
31        g_error_free(err);
32        err = NULL;
33    }
34
35    /* test for error */
36    if (pipeline == NULL)
37    {
38        printf("Could not create pipeline. Cause: %s\n", err->message);
39        return 1;
40    }
41
42    if (serial != NULL)
43    {
44        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
45        GValue val = {};
46        g_value_init(&val, G_TYPE_STRING);
47        g_value_set_static_string(&val, serial);
48
49        g_object_set_property(G_OBJECT(source), "serial", &val);
50
51        gst_object_unref(source);
52    }
53
54    gst_element_set_state(pipeline, GST_STATE_PLAYING);
55
56    printf("Press enter to stop the stream.\n");
57    getchar();
58
59    gst_element_set_state(pipeline, GST_STATE_NULL);
60
61    gst_object_unref(pipeline);
62
63    return 0;
64}

04 - list-format

Lists what formats the camera offers.

Show sample code
  1
  2/* This example will show you how to list the formats your device offers */
  3
  4#include "tcam-property-1.0.h" /* gobject introspection interface */
  5
  6#include <gst/gst.h>
  7#include <stdio.h> /* printf and putchar */
  8
  9
 10int main(int argc, char* argv[])
 11{
 12    /* this line sets the gstreamer default logging level
 13       it can be removed in normal applications
 14       gstreamer logging can contain verry useful information
 15       when debugging your application
 16       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 17       for further details
 18    */
 19    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 20
 21    gst_init(&argc, &argv); // init gstreamer
 22
 23    // set this if you do not want the first found device
 24    char* serial = NULL;
 25
 26    /* create a tcambin to retrieve device information */
 27    GstElement* source = gst_element_factory_make("tcambin", "source");
 28
 29    if (serial != NULL)
 30    {
 31        GValue val = {};
 32        g_value_init(&val, G_TYPE_STRING);
 33        g_value_set_static_string(&val, serial);
 34
 35        g_object_set_property(G_OBJECT(source), "serial", &val);
 36    }
 37
 38    /* Setting the state to ready ensures that all resources
 39       are initialized and that we really get all format capabilities */
 40    gst_element_set_state(source, GST_STATE_READY);
 41
 42    GstPad* pad = gst_element_get_static_pad(source, "src");
 43
 44    GstCaps* caps = gst_pad_query_caps(pad, NULL);
 45
 46    printf("================ %s\n", gst_caps_to_string(caps));
 47
 48    for (unsigned int i = 0; i < gst_caps_get_size(caps); ++i)
 49    {
 50        GstStructure* structure = gst_caps_get_structure(caps, i);
 51
 52        /*
 53          for a simple display the following line can be used
 54          printf("%s\n", gst_structure_to_string(structure));
 55        */
 56
 57        const char* name = gst_structure_get_name(structure);
 58
 59        // this is only required when dealing
 60        // with FPD/MiPi cameras on tegra systems
 61        // must not be freed
 62        GstCapsFeatures* features = gst_caps_get_features(caps, i);
 63
 64        if (features)
 65        {
 66            if (gst_caps_features_contains(features, "memory:NVMM"))
 67            {
 68                // do something with this information
 69                printf("NVMM ");
 70            }
 71        }
 72
 73        if (gst_structure_get_field_type(structure, "format") == G_TYPE_STRING)
 74        {
 75            const char* format = gst_structure_get_string(structure, "format");
 76
 77            printf("%s %s - ", name, format);
 78        }
 79        else if (gst_structure_get_field_type(structure, "format") == GST_TYPE_LIST)
 80        {
 81            printf("%s { ", name);
 82
 83            const GValue* val = gst_structure_get_value(structure, "format");
 84
 85            for (unsigned int x = 0; x < gst_value_list_get_size(val); ++x)
 86            {
 87                const GValue* format = gst_value_list_get_value(val, x);
 88
 89                printf("%s ", g_value_get_string(format));
 90            }
 91
 92
 93            printf("} - ");
 94        }
 95        else
 96        {
 97            printf("format handling not implemented for unexpected type: %s\n",
 98                   G_VALUE_TYPE_NAME(gst_structure_get_field_type(structure, "format")));
 99            continue;
100        }
101
102        GType width_type = gst_structure_get_field_type(structure, "width");
103
104        if (width_type == GST_TYPE_INT_RANGE)
105        {
106            int width_min =
107                gst_value_get_int_range_min(gst_structure_get_value(structure, "width"));
108            int width_max =
109                gst_value_get_int_range_max(gst_structure_get_value(structure, "width"));
110
111
112            printf("width: [%d-%d]", width_min, width_max);
113        }
114        else
115        {
116            int width;
117            gboolean ret = gst_structure_get_int(structure, "width", &width);
118
119            if (!ret)
120            {
121                printf("Unable to query width\n");
122                continue;
123            }
124
125            printf("%d", width);
126        }
127
128        printf(" X ");
129
130        GType height_type = gst_structure_get_field_type(structure, "height");
131
132        if (height_type == GST_TYPE_INT_RANGE)
133        {
134            int height_min =
135                gst_value_get_int_range_min(gst_structure_get_value(structure, "height"));
136            int height_max =
137                gst_value_get_int_range_max(gst_structure_get_value(structure, "height"));
138
139
140            printf("height: [%d-%d]", height_min, height_max);
141        }
142        else
143        {
144            int height;
145            gboolean ret = gst_structure_get_int(structure, "height", &height);
146
147            if (!ret)
148            {
149                printf("Unable to query height\n");
150                continue;
151            }
152
153            printf("%d", height);
154        }
155
156        printf(" - ");
157
158        const GValue* framerate = gst_structure_get_value(structure, "framerate");
159
160        if (G_VALUE_TYPE(framerate) == GST_TYPE_LIST)
161        {
162            for (unsigned int x = 0; x < gst_value_list_get_size(framerate); ++x)
163            {
164                const GValue* val = gst_value_list_get_value(framerate, x);
165
166                if (G_VALUE_TYPE(val) == GST_TYPE_FRACTION)
167                {
168                    int num = gst_value_get_fraction_numerator(val);
169                    int den = gst_value_get_fraction_denominator(val);
170
171                    printf("%d/%d ", num, den);
172                }
173                else
174                {
175                    printf(
176                        "Handling of framerate handling not implemented for non fraction types.\n");
177                    break;
178                }
179            }
180        }
181        else if (G_VALUE_TYPE(framerate) == GST_TYPE_FRACTION_RANGE)
182        {
183            const GValue* framerate_min = gst_value_get_fraction_range_min(framerate);
184            const GValue* framerate_max = gst_value_get_fraction_range_max(framerate);
185
186            printf("%d/%d - %d/%d",
187                   gst_value_get_fraction_numerator(framerate_min),
188                   gst_value_get_fraction_denominator(framerate_min),
189                   gst_value_get_fraction_numerator(framerate_max),
190                   gst_value_get_fraction_denominator(framerate_max));
191        }
192        else
193        {
194            printf("Unable to interpret framerate type\n");
195            continue;
196        }
197
198        // we printed all information for a format decription
199        // print a new line to keep everything user readable
200        printf("\n");
201    }
202
203    gst_caps_unref(caps);
204    gst_object_unref(pad);
205
206    gst_element_set_state(source, GST_STATE_NULL);
207
208    gst_object_unref(source);
209
210    return 0;
211}

05 - set format

Sets the camera to a specific format.

Show sample code
  1
  2/*
  3  This example will show you how to start a live stream from your camera
  4  with a specific format
  5 */
  6
  7#include "tcam-property-1.0.h" /* gobject introspection interface */
  8
  9#include <gst/gst.h>
 10#include <stdio.h> /* printf and putchar */
 11
 12
 13int main(int argc, char* argv[])
 14{
 15    /* this line sets the gstreamer default logging level
 16       it can be removed in normal applications
 17       gstreamer logging can contain verry useful information
 18       when debugging your application
 19       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 20       for further details
 21    */
 22    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 23
 24    gst_init(&argc, &argv); // init gstreamer
 25
 26    const char* serial = NULL; // set this if you do not want the first found device
 27
 28    GError* err = NULL;
 29    const char* pipeline_desc =
 30        "tcambin name=source ! capsfilter name=filter ! videoconvert ! ximagesink";
 31
 32    GstElement* pipeline = gst_parse_launch(pipeline_desc, &err);
 33
 34    /* test for error */
 35    if (pipeline == NULL)
 36    {
 37        printf("Could not create pipeline. Cause: %s\n", err->message);
 38        return 1;
 39    }
 40
 41    if (serial != NULL)
 42    {
 43        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
 44        GValue val = {};
 45        g_value_init(&val, G_TYPE_STRING);
 46        g_value_set_static_string(&val, serial);
 47
 48        g_object_set_property(G_OBJECT(source), "serial", &val);
 49
 50        gst_object_unref(source);
 51    }
 52
 53
 54    GstCaps* caps = gst_caps_new_empty();
 55
 56    GstStructure* structure = gst_structure_from_string("video/x-raw", NULL);
 57    gst_structure_set(structure,
 58                      "format",
 59                      G_TYPE_STRING,
 60                      "BGRx",
 61                      "width",
 62                      G_TYPE_INT,
 63                      640,
 64                      "height",
 65                      G_TYPE_INT,
 66                      480,
 67                      "framerate",
 68                      GST_TYPE_FRACTION,
 69                      15,
 70                      1,
 71                      NULL);
 72
 73    gst_caps_append_structure(caps, structure);
 74
 75    GstElement* capsfilter = gst_bin_get_by_name(GST_BIN(pipeline), "filter");
 76
 77    if (capsfilter == NULL)
 78    {
 79        printf("Could not retrieve capsfilter from pipeline.");
 80        return 1;
 81    }
 82
 83    g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
 84    gst_object_unref(capsfilter);
 85    gst_caps_unref(caps);
 86
 87    /*
 88      to statically create caps you can reduce the whole procedure to
 89      GstCaps* caps = gst_caps_from_string("video/x-raw,format=BGRx,width=640,height=480,framerate=30/1");
 90
 91      gst_parse_lauch allows you to use strings for caps descriptions.
 92      That means everything until now can be done with:
 93
 94      GstElement* pipeline = gst_parse_launch("tcambin name=source ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1 ! videoconvert ! ximagesink", &err);
 95
 96    */
 97
 98
 99    gst_element_set_state(pipeline, GST_STATE_PLAYING);
100
101    printf("Press enter to stop the stream.\n");
102    getchar();
103
104    gst_element_set_state(pipeline, GST_STATE_NULL);
105
106    gst_object_unref(pipeline);
107
108    return 0;
109}

06 - softwaretrigger

Triggers single images - instead of a continuous image stream.

Show sample code
  1
  2/* This example will show you how to trigger images */
  3
  4#include <gst/gst.h>
  5#include <stdio.h> /* printf */
  6#include <tcam-property-1.0.h>
  7#include <unistd.h> /* sleep  */
  8
  9
 10int main(int argc, char* argv[])
 11{
 12    /* this line sets the gstreamer default logging level
 13       it can be removed in normal applications
 14       gstreamer logging can contain verry useful information
 15       when debugging your application
 16       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 17       for further details
 18    */
 19    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 20
 21    gst_init(&argc, &argv); // init gstreamer
 22
 23    const char* serial = NULL; // the serial number of the camera we want to use
 24
 25    GError* err = NULL;
 26
 27    GstElement* pipeline =
 28        gst_parse_launch("tcambin name=source ! video/x-raw,format=BGRx ! videoconvert ! ximagesink ", &err);
 29
 30    /* test for error */
 31    if (pipeline == NULL)
 32    {
 33        printf("Could not create pipeline. Cause: %s\n", err->message);
 34        return 1;
 35    }
 36
 37    GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
 38
 39    if (serial != NULL)
 40    {
 41        GValue val = {};
 42        g_value_init(&val, G_TYPE_STRING);
 43        g_value_set_static_string(&val, serial);
 44
 45        g_object_set_property(G_OBJECT(source), "serial", &val);
 46
 47        g_value_unset(&val);
 48    }
 49
 50    gst_element_set_state(pipeline, GST_STATE_PLAYING);
 51
 52    /*
 53      This sleep exists only to ensure
 54      that a live image exists before trigger mode is activated.
 55      for all other purposes this can be removed.
 56     */
 57    sleep(2);
 58
 59    tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "TriggerMode", "On", &err);
 60
 61    if (err)
 62    {
 63        printf("Error while setting trigger mode: %s\n", err->message);
 64        g_error_free(err);
 65        err = NULL;
 66    }
 67
 68    while (0 == 0)
 69    {
 70        printf("Press 'q' then 'enter' to stop the stream.\n");
 71        printf("Press 'Enter' to trigger a new image.\n");
 72
 73        char c = getchar();
 74
 75        if (c == 'q')
 76        {
 77            break;
 78        }
 79
 80        tcam_property_provider_set_tcam_command(TCAM_PROPERTY_PROVIDER(source), "TriggerSoftware", &err);
 81        if (err)
 82        {
 83            printf("!!! Could not trigger. !!!\n");
 84            printf("Error while setting trigger: %s\n", err->message);
 85            g_error_free(err);
 86            err = NULL;
 87        }
 88        else
 89        {
 90            printf("=== Triggered image. ===\n");
 91        }
 92    }
 93
 94    /* deactivate trigger mode */
 95    /* this is simply to prevent confusion when the camera ist started without wanting to trigger */
 96    tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "TriggerMode", "Off", &err);
 97
 98    // this stops the pipeline and frees all resources
 99    gst_element_set_state(pipeline, GST_STATE_NULL);
100
101    gst_object_unref(source);
102    /* the pipeline automatically handles all elements that have been added to it.
103       thus they do not have to be cleaned up manually */
104    gst_object_unref(pipeline);
105
106    return 0;
107}

07 - appsink

Receives images in an application instead of just showing them.

Show sample code
  1
  2/*
  3  This example will show you how to receive data
  4  from gstreamer in your application
  5  and how to get the actual image data
  6*/
  7
  8#include <gst/gst.h>
  9#include <gst/video/video.h>
 10#include <stdio.h>
 11#include <stdlib.h>
 12#include <string.h>
 13#include <unistd.h>
 14
 15
 16/*
 17  This function will be called in a separate thread when our appsink
 18  says there is data for us. user_data has to be defined
 19  when calling g_signal_connect. It can be used to pass objects etc.
 20  from your other function to the callback.
 21
 22  user_data can point to additional data for your usage
 23            marked as unused to prevent compiler warnings
 24*/
 25static GstFlowReturn callback(GstElement* sink, void* user_data __attribute__((unused)))
 26{
 27    GstSample* sample = NULL;
 28    /* Retrieve the buffer */
 29    g_signal_emit_by_name(sink, "pull-sample", &sample, NULL);
 30
 31    if (sample)
 32    {
 33        // we have a valid sample
 34        // do things with the image here
 35        static guint framecount = 0;
 36        int pixel_data = -1;
 37
 38        GstBuffer* buffer = gst_sample_get_buffer(sample);
 39        GstMapInfo info; // contains the actual image
 40        if (gst_buffer_map(buffer, &info, GST_MAP_READ))
 41        {
 42            GstVideoInfo* video_info = gst_video_info_new();
 43            if (!gst_video_info_from_caps(video_info, gst_sample_get_caps(sample)))
 44            {
 45                // Could not parse video info (should not happen)
 46                g_warning("Failed to parse video info");
 47                return GST_FLOW_ERROR;
 48            }
 49
 50            // pointer to the image data
 51
 52            // unsigned char* data = info.data;
 53
 54            // Get the pixel value of the center pixel
 55
 56            // int stride = video_info->finfo->bits / 8;
 57            // unsigned int pixel_offset = video_info->width / 2 * stride
 58            //                             + video_info->width * video_info->height / 2 * stride;
 59
 60            // this is only one pixel
 61            // when dealing with formats like BGRx
 62            // pixel_data will consist out of
 63            // pixel_offset   => B
 64            // pixel_offset+1 => G
 65            // pixel_offset+2 => R
 66            // pixel_offset+3 => x
 67
 68            // pixel_data = info.data[pixel_offset];
 69
 70            gst_buffer_unmap(buffer, &info);
 71            gst_video_info_free(video_info);
 72        }
 73
 74        GstClockTime timestamp = GST_BUFFER_PTS(buffer);
 75        g_print("Captured frame %d, Pixel Value=%03d Timestamp=%" GST_TIME_FORMAT "            \r",
 76                framecount,
 77                pixel_data,
 78                GST_TIME_ARGS(timestamp));
 79        framecount++;
 80
 81
 82        // delete our reference so that gstreamer can handle the sample
 83        gst_sample_unref(sample);
 84    }
 85    return GST_FLOW_OK;
 86}
 87
 88
 89int main(int argc, char* argv[])
 90{
 91    /* this line sets the gstreamer default logging level
 92       it can be removed in normal applications
 93       gstreamer logging can contain verry useful information
 94       when debugging your application
 95       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 96       for further details
 97    */
 98    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 99
100    gst_init(&argc, &argv);
101
102    const char* serial = NULL; // the serial number of the camera we want to use
103
104    const char* pipeline_str = "tcambin name=source ! videoconvert ! appsink name=sink";
105
106    GError* err = NULL;
107    GstElement* pipeline = gst_parse_launch(pipeline_str, &err);
108
109    /* test for error */
110    if (pipeline == NULL)
111    {
112        printf("Could not create pipeline. Cause: %s\n", err->message);
113        return 1;
114    }
115
116    if (serial != NULL)
117    {
118        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
119
120        GValue val = {};
121        g_value_init(&val, G_TYPE_STRING);
122        g_value_set_static_string(&val, serial);
123
124        g_object_set_property(G_OBJECT(source), "serial", &val);
125        gst_object_unref(source);
126    }
127
128    /* retrieve the appsink from the pipeline */
129    GstElement* sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
130
131    // tell appsink to notify us when it receives an image
132    g_object_set(G_OBJECT(sink), "emit-signals", TRUE, NULL);
133
134    // tell appsink what function to call when it notifies us
135    g_signal_connect(sink, "new-sample", G_CALLBACK(callback), NULL);
136
137    gst_object_unref(sink);
138
139    gst_element_set_state(pipeline, GST_STATE_PLAYING);
140
141    g_print("Press 'enter' to stop the stream.\n");
142    /* wait for user input to end the program */
143    getchar();
144
145    // this stops the pipeline and frees all resources
146    gst_element_set_state(pipeline, GST_STATE_NULL);
147
148    /*
149      the pipeline automatically handles
150      all elements that have been added to it.
151      thus they do not have to be cleaned up manually
152    */
153    gst_object_unref(pipeline);
154
155    return 0;
156}

08 - save-stream

Stores a stream in a file.

Show sample code
 1
 2/* This example will show you how to save a videostream into a file */
 3
 4#include <gst/gst.h>
 5#include <stdio.h>
 6#include <string.h>
 7
 8int main(int argc, char* argv[])
 9{
10    /* this line sets the gstreamer default logging level
11       it can be removed in normal applications
12       gstreamer logging can contain verry useful information
13       when debugging your application
14       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
15       for further details
16    */
17    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
18
19    gst_init(&argc, &argv); // init gstreamer
20
21    const char* serial = NULL; // the serial number of the camera we want to use
22
23    GError* err = NULL;
24
25
26    GstElement* pipeline =
27        gst_parse_launch("tcambin name=bin"
28                         " ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
29                         " ! tee name=t"
30                         " ! queue"
31                         " ! videoconvert"
32                         " ! ximagesink"
33                         " t."
34                         " ! queue"
35                         " ! videoconvert"
36                         " ! avimux"
37                         " ! filesink name=fsink",
38                         &err);
39    /*
40      to save a video without live view reduce the pipeline to the following:
41
42      GstElement* pipeline = Gst.parse_launch("tcambin name=bin"
43                                              " ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
44                                              " ! videoconvert"
45                                              " ! avimux"
46                                              " ! filesink name=fsink", &err);
47
48    */
49
50    if (serial != NULL)
51    {
52        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "bin");
53        GValue val = {};
54        g_value_init(&val, G_TYPE_STRING);
55        g_value_set_static_string(&val, serial);
56
57        g_object_set_property(G_OBJECT(source), "serial", &val);
58        gst_object_unref(source);
59    }
60
61    const char* file_location = "/tmp/tiscamera-save-stream.avi";
62
63    GstElement* fsink = gst_bin_get_by_name(GST_BIN(pipeline), "fsink");
64
65    g_object_set(G_OBJECT(fsink), "location", file_location, NULL);
66
67    gst_element_set_state(pipeline, GST_STATE_PLAYING);
68
69    printf("Press Enter to stop the recording\n");
70    getchar();
71
72    // this stops the pipeline and frees all resources
73    gst_element_set_state(pipeline, GST_STATE_NULL);
74
75    gst_object_unref(fsink);
76
77    /* the pipeline automatically handles all elements that have been added to it.
78       thus they do not have to be cleaned up manually */
79    gst_object_unref(pipeline);
80
81    printf("Stream saved to: %s\n", file_location);
82
83    return 0;
84}

09 - device-lost

Receives device-lost and other messages and react to them.

Show sample code
  1
  2/* This example will show you how to start a live stream from your camera */
  3
  4#include <gst/gst.h>
  5#include <stdio.h> /* printf and putchar */
  6#include <unistd.h> /* usleep */
  7
  8
  9static GMainLoop* loop;
 10
 11
 12static gboolean starts_with(const char* a, const char* b)
 13{
 14    if (strncmp(a, b, strlen(b)) == 0)
 15    {
 16        return 1;
 17    }
 18    return 0;
 19}
 20
 21
 22static gboolean bus_callback(GstBus* bus __attribute__((unused)), GstMessage* message, gpointer data __attribute__((unused)))
 23{
 24    g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(message));
 25
 26    switch (GST_MESSAGE_TYPE(message))
 27    {
 28        case GST_MESSAGE_ERROR:
 29        {
 30            GError* err;
 31            gchar* debug;
 32
 33            gst_message_parse_error(message, &err, &debug);
 34            g_print("Error: %s \n", err->message);
 35
 36            if (starts_with(err->message, "Device lost ("))
 37            {
 38                char* s_str = strstr(err->message, "(");
 39                const char* serial = strtok(s_str, "()");
 40                printf("Device lost came from device with serial = %s\n", serial);
 41
 42                // device lost handling should be initiated here
 43                // this example simply stops playback
 44                g_main_loop_quit(loop);
 45            }
 46
 47            g_error_free(err);
 48            g_free(debug);
 49
 50            break;
 51        }
 52        case GST_MESSAGE_INFO:
 53        {
 54            break;
 55        }
 56        case GST_MESSAGE_EOS:
 57        {
 58            /* end-of-stream */
 59            g_main_loop_quit(loop);
 60            break;
 61        }
 62        default:
 63        {
 64            /* unhandled message */
 65            break;
 66        }
 67    }
 68    return TRUE;
 69}
 70
 71
 72int main(int argc, char* argv[])
 73{
 74    /* this line sets the gstreamer default logging level
 75       it can be removed in normal applications
 76       gstreamer logging can contain verry useful information
 77       when debugging your application
 78       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 79       for further details
 80    */
 81    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 82
 83    gst_init(&argc, &argv); // init gstreamer
 84
 85    const char* serial = NULL; // set this if you do not want the first found device
 86
 87    GError* err = NULL;
 88
 89    GstElement* pipeline =
 90        gst_parse_launch("tcambin name=source ! videoconvert ! ximagesink", &err);
 91
 92    /* test for error */
 93    if (pipeline == NULL)
 94    {
 95        printf("Could not create pipeline. Cause: %s\n", err->message);
 96        return 1;
 97    }
 98
 99    if (serial != NULL)
100    {
101        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
102        GValue val = {};
103        g_value_init(&val, G_TYPE_STRING);
104        g_value_set_static_string(&val, serial);
105
106        g_object_set_property(G_OBJECT(source), "serial", &val);
107        gst_object_unref(source);
108    }
109
110    GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
111
112    gst_bus_add_watch(bus, bus_callback, NULL);
113
114    gst_object_unref(bus);
115
116
117    gst_element_set_state(pipeline, GST_STATE_PLAYING);
118
119    printf("Disconnect your camera to trigger a device lost or press enter to stop the stream.\n");
120
121    // we work with a event loop to be automatically
122    // notified when a new messages occur.
123    loop = g_main_loop_new(NULL, FALSE);
124    g_main_loop_run(loop);
125
126    g_main_loop_unref(loop);
127    gst_element_set_state(pipeline, GST_STATE_NULL);
128
129    gst_object_unref(pipeline);
130
131    return 0;
132}

10 - metadata

Read meta information like is-damaged, camera capture time, etc.

Show sample code
  1
  2/* This example will show you how to receive data from gstreamer in your application
  3   and how to get the actual iamge data */
  4
  5#include "gstmetatcamstatistics.h"
  6#include "tcam-property-1.0.h" /* gobject introspection interface */
  7
  8#include <gst/gst.h>
  9#include <gst/video/video.h>
 10#include <stdio.h>
 11#include <stdlib.h>
 12#include <string.h>
 13#include <unistd.h>
 14
 15
 16static gboolean meta_struc_print(GQuark field_id, const GValue* value, gpointer user_data  __attribute__((unused)))
 17{
 18    // GQuark is a gobject internal ID for strings
 19    // we call the function g_quark_to_string to get the name of the field
 20    // value is a simple, generic value
 21    // user_data can contain things you need for further processing
 22
 23    printf("%s: ", g_quark_to_string(field_id));
 24
 25    if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN)
 26    {
 27        gboolean val = g_value_get_boolean(value);
 28        if (val)
 29        {
 30            printf(" true\n");
 31        }
 32        else
 33        {
 34            printf(" false\n");
 35        }
 36    }
 37    else if (G_VALUE_TYPE(value) == G_TYPE_DOUBLE)
 38    {
 39        double val = g_value_get_double(value);
 40        printf("%f\n", val);
 41    }
 42    else if (G_VALUE_TYPE(value) == G_TYPE_UINT64)
 43    {
 44        guint64 val = g_value_get_uint64(value);
 45        printf("%lu\n", val);
 46    }
 47    else
 48    {
 49        printf("value type not implemented\n");
 50    }
 51
 52    return TRUE;
 53}
 54
 55/*
 56  This function will be called in a separate thread when our appsink
 57  says there is data for us. user_data has to be defined when calling g_signal_connect.
 58 */
 59static GstFlowReturn callback(GstElement* sink, void* user_data  __attribute__((unused)))
 60{
 61    printf("new sample\n");
 62
 63    GstSample* sample = NULL;
 64    /* Retrieve the buffer */
 65    g_signal_emit_by_name(sink, "pull-sample", &sample, NULL);
 66
 67    if (sample)
 68    {
 69        static guint framecount = 0;
 70
 71        framecount++;
 72
 73        GstBuffer* buffer = gst_sample_get_buffer(sample);
 74
 75        // if you need the associated caps
 76        // GstCaps* c = gst_sample_get_caps(sample);
 77
 78        GstMeta* meta = gst_buffer_get_meta(buffer, g_type_from_name("TcamStatisticsMetaApi"));
 79
 80        if (meta)
 81        {
 82            printf("We have meta\n");
 83        }
 84        else
 85        {
 86            g_warning("No meta data available\n");
 87        }
 88
 89        GstStructure* struc = ((TcamStatisticsMeta*)meta)->structure;
 90
 91        // this prints all contained fields
 92        gst_structure_foreach(struc, meta_struc_print, NULL);
 93
 94        // to only print selective fields
 95        // read the documentation
 96        // https://www.theimagingsource.com/documentation/tiscamera/tcam-gstreamer.html#metadata
 97        // concerning available fields and call them manually by name
 98
 99        /*
100          guint64 frame_count = 0;
101          gst_structure_get_uint64(struc, "frame_count", &frame_count);
102          printf("frame_count: %ul\n", frame_count);
103        */
104
105        // delete our reference so that gstreamer can handle the sample
106        gst_sample_unref(sample);
107    }
108    return GST_FLOW_OK;
109}
110
111
112int main(int argc, char* argv[])
113{
114    /* this line sets the gstreamer default logging level
115       it can be removed in normal applications
116       gstreamer logging can contain verry useful information
117       when debugging your application
118       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
119       for further details
120    */
121    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
122
123    gst_init(&argc, &argv);
124
125    const char* serial = NULL; // set this if you do not want the first found device
126
127    GError* err = NULL;
128
129    // some conversion elements will drop the metadata
130    // for the sake of this example we will retrieve buffers
131    // directly from the src
132    const char* pipeline_str = "tcamsrc name=source ! appsink name=sink";
133
134    GstElement* pipeline = gst_parse_launch(pipeline_str, &err);
135
136    /* test for error */
137    if (pipeline == NULL)
138    {
139        printf("Could not create pipeline. Cause: %s\n", err->message);
140        return 1;
141    }
142
143    if (serial != NULL)
144    {
145        GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
146        GValue val = {};
147        g_value_init(&val, G_TYPE_STRING);
148        g_value_set_static_string(&val, serial);
149
150        g_object_set_property(G_OBJECT(source), "serial", &val);
151        gst_object_unref(source);
152    }
153
154    /* retrieve the appsink from the pipeline */
155    GstElement* sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
156
157    // tell appsink to notify us when it receives an image
158    g_object_set(G_OBJECT(sink), "emit-signals", TRUE, NULL);
159
160    // tell appsink what function to call when it notifies us
161    g_signal_connect(sink, "new-sample", G_CALLBACK(callback), NULL);
162
163    gst_object_unref(sink);
164
165    gst_element_set_state(pipeline, GST_STATE_PLAYING);
166
167    g_print("Press 'enter' to stop the stream.\n");
168    /* wait for user input to end the program */
169    getchar();
170
171    // this stops the pipeline and frees all resources
172    gst_element_set_state(pipeline, GST_STATE_NULL);
173
174    /*
175      the pipeline automatically handles
176      all elements that have been added to it.
177      thus they do not have to be cleaned up manually
178    */
179    gst_object_unref(pipeline);
180
181    return 0;
182}

11 - json-state

Save and load JSON device state.

Show sample code
  1
  2/* This example will show you how to get/set the JSON property description for a certain camera */
  3
  4#include "tcam-property-1.0.h" /* gobject introspection interface */
  5
  6#include <gst/gst.h>
  7#include <stdio.h> /* printf and putchar */
  8
  9
 10gboolean block_until_playing(GstElement* pipeline)
 11{
 12    while (TRUE)
 13    {
 14        GstState state;
 15        GstState pending;
 16
 17        // wait 0.1 seconds for something to happen
 18        GstStateChangeReturn ret = gst_element_get_state(pipeline, &state, &pending, 100000000);
 19
 20        if (ret == GST_STATE_CHANGE_SUCCESS)
 21        {
 22            return TRUE;
 23        }
 24        else if (ret == GST_STATE_CHANGE_FAILURE)
 25        {
 26            printf("Failed to change state %s %s %s\n",
 27                   gst_element_state_change_return_get_name(ret),
 28                   gst_element_state_get_name(state),
 29                   gst_element_state_get_name(pending));
 30
 31            return FALSE;
 32        }
 33    }
 34}
 35
 36
 37int main(int argc, char* argv[])
 38{
 39    /* this line sets the gstreamer default logging level
 40       it can be removed in normal applications
 41       gstreamer logging can contain verry useful information
 42       when debugging your application
 43       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 44       for further details
 45    */
 46    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 47
 48    gst_init(&argc, &argv); // init gstreamer
 49
 50    GError* err = NULL;
 51
 52    // this is a placeholder definition
 53    // normally your pipeline would be defined here
 54    GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
 55
 56    if (pipeline == NULL)
 57    {
 58        printf("Unable to create pipeline: %s\n", err->message);
 59        g_free(err);
 60        return 1;
 61    }
 62
 63    GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
 64
 65    const char* serial = NULL;
 66
 67    if (serial != NULL)
 68    {
 69        GValue val = {};
 70        g_value_init(&val, G_TYPE_STRING);
 71        g_value_set_static_string(&val, serial);
 72
 73        g_object_set_property(G_OBJECT(source), "serial", &val);
 74    }
 75
 76    // in the READY state the camera will always be initialized
 77    // in the PLAYING state additional properties may appear from gstreamer elements
 78    gst_element_set_state(source, GST_STATE_PLAYING);
 79
 80    // helper function to ensure we have the right state
 81    // alternatively wait for the first image
 82    if (!block_until_playing(pipeline))
 83    {
 84        printf("Unable to start pipeline. \n");
 85    }
 86
 87    // Device is now in a state for interactions
 88    GValue state = G_VALUE_INIT;
 89    g_value_init(&state, G_TYPE_STRING);
 90
 91    //We print the properties for a before/after comparison,
 92    g_object_get_property(G_OBJECT(source), "tcam-properties-json", &state);
 93
 94    printf("State of device is:\n%s", g_value_get_string(&state));
 95
 96    // Change JSON description here
 97    // not part of this example
 98
 99    // second print for the before/after comparison
100    g_object_set_property(G_OBJECT(source), "tcam-properties-json", &state);
101
102    //reread state to see if anything changed
103    g_object_get_property(G_OBJECT(source), "tcam-properties-json", &state);
104
105    printf("State of device is:\n%s", g_value_get_string(&state));
106
107    // cleanup, reset state
108    gst_element_set_state(source, GST_STATE_NULL);
109
110    gst_object_unref(source);
111    gst_object_unref(pipeline);
112    g_value_unset(&state);
113
114    return 0;
115}

12 - tcam-properties

Save and load properties via GstStructure.

Show sample code
  1
  2/* This example will show you how to get/set the properties through a description string */
  3
  4#include <gst/gst.h>
  5#include <stdio.h> /* printf and putchar */
  6
  7
  8gboolean block_until_state_change_done (GstElement* pipeline)
  9{
 10    while (TRUE)
 11    {
 12        GstState state;
 13        GstState pending;
 14
 15        // wait 0.1 seconds for something to happen
 16        GstStateChangeReturn ret = gst_element_get_state(pipeline, &state, &pending, 100000000);
 17
 18        if (ret == GST_STATE_CHANGE_SUCCESS || ret == GST_STATE_CHANGE_NO_PREROLL)
 19        {
 20            return TRUE;
 21        }
 22        else if (ret == GST_STATE_CHANGE_FAILURE)
 23        {
 24            printf("Failed to change state %s %s %s\n",
 25                   gst_element_state_change_return_get_name(ret),
 26                   gst_element_state_get_name(state),
 27                   gst_element_state_get_name(pending));
 28
 29            return FALSE;
 30        }
 31    }
 32}
 33
 34
 35static void print_current_properties (GstElement* source)
 36{
 37    // Initialize the GValue
 38    GValue current_properties = G_VALUE_INIT;
 39    g_value_init(&current_properties, GST_TYPE_STRUCTURE);
 40
 41    // Get the GObject property
 42    g_object_get_property(G_OBJECT(source), "tcam-properties", &current_properties);
 43
 44    // get a string to print the current property state
 45    char* string = gst_structure_to_string(gst_value_get_structure(&current_properties));
 46    printf("Current properties:\n%s\n", string );
 47    g_free(string); // free the string
 48
 49    g_value_unset( &current_properties );  // free the GstStructure in the GValue
 50}
 51
 52
 53int main (int argc, char* argv[])
 54{
 55    /* this line sets the gstreamer default logging level
 56       it can be removed in normal applications
 57       gstreamer logging can contain very useful information
 58       when debugging your application
 59       # see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 60       for further details
 61    */
 62    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 63
 64    gst_init(&argc, &argv); // init gstreamer
 65
 66    GError* err = NULL;
 67
 68    // this is a placeholder definition
 69    // normally your pipeline would be defined here
 70    GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
 71
 72    if (pipeline == NULL)
 73    {
 74        printf("Unable to create pipeline: %s\n", err->message);
 75        g_free(err);
 76        return 1;
 77    }
 78
 79    GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
 80
 81    const char* serial = NULL;
 82
 83    if (serial != NULL)
 84    {
 85        GValue val = G_VALUE_INIT;
 86        g_value_init(&val, G_TYPE_STRING);
 87        g_value_set_static_string(&val, serial);
 88
 89        g_object_set_property(G_OBJECT(source), "serial", &val);
 90    }
 91
 92    // in the READY state the camera will always be initialized
 93    gst_element_set_state(source, GST_STATE_READY);
 94
 95    // helper function to wait for async state change to be done
 96    if (!block_until_state_change_done(pipeline))
 97    {
 98        printf("Unable to start pipeline. \n");
 99        return 2;
100    }
101
102    print_current_properties( source );
103
104    // Create a new structure
105    GstStructure* new_property_struct = gst_structure_new_empty("tcam");
106
107    // Change 2 properties so that we can see a 'difference'
108    gst_structure_set(new_property_struct,
109                      "ExposureAuto", G_TYPE_STRING, "Off",
110                      "ExposureTime", G_TYPE_DOUBLE, 35000.0,
111                      NULL );
112
113    GValue new_state = G_VALUE_INIT;
114    g_value_init(&new_state, GST_TYPE_STRUCTURE);
115    gst_value_set_structure( &new_state, new_property_struct);
116
117    // Set the new property settings
118    g_object_set_property(G_OBJECT(source), "tcam-properties", &new_state);
119
120    g_value_unset(&new_state);
121    gst_structure_free(new_property_struct);
122
123    // Print the property settings after the change above
124    print_current_properties(source);
125
126    // cleanup, reset state
127    gst_element_set_state(source, GST_STATE_NULL);
128
129    gst_object_unref(source);
130    gst_object_unref(pipeline);
131
132    return 0;
133}

13 - GstQuery

Shows how to use GstQuery for GstCaps verification.

Show sample code
  1
  2/*
  3  This example will show you how to query the tcamsrc
  4  - to verify potential framerates
  5  - to verify potential caps
  6 */
  7
  8#include <gst/gst.h>
  9#include <stdio.h> /* printf and putchar */
 10
 11
 12int main(int argc, char* argv[])
 13{
 14    /* this line sets the gstreamer default logging level
 15       it can be removed in normal applications
 16       gstreamer logging can contain verry useful information
 17       when debugging your application
 18       see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
 19       for further details
 20    */
 21    gst_debug_set_default_threshold(GST_LEVEL_WARNING);
 22
 23    gst_init(&argc, &argv); // init gstreamer
 24
 25    GError* err = NULL;
 26    const char* pipeline_desc = "tcambin name=bin ! videoconvert ! ximagesink";
 27
 28    GstElement* pipeline = gst_parse_launch(pipeline_desc, &err);
 29
 30    /* test for error */
 31    if (pipeline == NULL)
 32    {
 33        printf("Could not create pipeline. Cause: %s\n", err->message);
 34        return 1;
 35    }
 36    GstElement* tcambin = gst_bin_get_by_name(GST_BIN(pipeline), "bin");
 37
 38    gst_element_set_state(pipeline, GST_STATE_READY);
 39
 40
 41    /* retrieve the source
 42       these queries have to be performed on the source
 43       as the tcambin might alter the query
 44       which we do not want
 45    */
 46    GstElement* source = gst_bin_get_by_name(GST_BIN(tcambin), "tcambin-source");
 47
 48    GstCaps* framerate_query_caps =
 49        gst_caps_from_string("video/x-bayer,format=rggb,width=640,height=480");
 50
 51    // if you have a mono camera try these instead
 52    // GstCaps* framerate_query_caps =
 53    //        gst_caps_from_string("video/x-raw,format=GRAY8,width=640,height=480");
 54
 55    GstQuery* framerate_query = gst_query_new_caps(framerate_query_caps);
 56
 57    gst_caps_unref(framerate_query_caps);
 58
 59    if (gst_element_query(source, framerate_query))
 60    {
 61        // no transfer, nothing has to be freed
 62        GstCaps* query_result_caps = NULL;
 63        gst_query_parse_caps_result(framerate_query, &query_result_caps);
 64
 65        char* result_caps_string = gst_caps_to_string(query_result_caps);
 66        printf("Camera supports these framerates: %s\n", result_caps_string);
 67        g_free(result_caps_string);
 68    }
 69
 70    gst_query_unref(framerate_query);
 71
 72    /*
 73      verify specific caps
 74      for this all needed fields have to be set(format, width, height and framerate)
 75    */
 76
 77    GstCaps* accept_query_caps =
 78        gst_caps_from_string("video/x-bayer,format=rggb,width=640,height=480,framerate=30/1");
 79
 80    GstQuery* accept_query = gst_query_new_accept_caps(accept_query_caps);
 81
 82    gst_caps_unref(accept_query_caps);
 83
 84    if (gst_element_query(source, accept_query))
 85    {
 86        gboolean accepts_caps;
 87        gst_query_parse_accept_caps_result(accept_query, &accepts_caps);
 88
 89        if (accepts_caps)
 90        {
 91            printf("Caps are accepted\n");
 92        }
 93        else
 94        {
 95            printf("Caps are not accepted\n");
 96        }
 97    }
 98
 99    gst_query_unref(accept_query);
100
101    gst_object_unref(source);
102    gst_object_unref(tcambin);
103
104    gst_element_set_state(pipeline, GST_STATE_NULL);
105
106    gst_object_unref(pipeline);
107
108    return 0;
109}

Further Examples

For extended examples, look through the examples repository.

https://github.com/TheImagingSource/Linux-tiscamera-Programming-Samples

It contains examples on how to interact with OpenCV, ROS, GUI toolkits and much more.