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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | LIBS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-1.0 --libs)
LIBS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-video-1.0 --libs)
LIBS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gobject-introspection-1.0 --libs)
LIBS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config tcam --libs)
# to build within the source tree
# enable the following lines
# and source build directory ./env.sh
# LIBS+=-L./../../build/libs
CFLAGS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-1.0 --cflags)
CFLAGS:=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gstreamer-video-1.0 --cflags)
CFLAGS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config gobject-introspection-1.0 --cflags)
CFLAGS+=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config tcam --cflags)
# CFLAGS+=-I../../libs/tcam-property/src
# CFLAGS+=-I../../src/gstreamer-1.0/tcamsrc
.PHONY: all clean
EXECS = 00-list-devices \
01-list-properties \
02-set-properties \
03-live-stream \
04-list-formats \
05-set-format \
06-softwaretrigger \
07-appsink \
08-save-stream \
09-device-lost \
10-metadata \
11-json-state \
12-tcam-properties \
13-gstquery
all: $(EXECS)
$(EXECS): %: %.c
$(CC) -g -DGST_DISABLE_DEPRECATED -Wall -Wextra -O0 $(CFLAGS) -o $@ $< $(LIBS)
clean:
$(RM) *.o
$(RM) $(EXECS)
|
Automatically handled by gobject introspection.
For custom installations set GI_TYPELIB_PATH to where the file Tcam-1.0.typelib is installed.
00 - list-devices¶
Shows what cameras there are and how to identify them.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
/* This example will show you how to list information about the available devices */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
void print_device(GstDevice* device)
{
GstStructure* struc = gst_device_get_properties(device);
printf("\tmodel:\t%s\tserial:\t%s\ttype:\t%s\n",
gst_structure_get_string(struc, "model"),
gst_structure_get_string(struc, "serial"),
gst_structure_get_string(struc, "type"));
gst_structure_free(struc);
}
gboolean bus_function(GstBus* bus __attribute__((unused)), GstMessage* message, gpointer user_data __attribute__((unused)))
{
GstDevice* device;
switch (GST_MESSAGE_TYPE(message))
{
case GST_MESSAGE_DEVICE_ADDED:
{
gst_message_parse_device_added(message, &device);
printf("NEW device\n");
print_device(device);
gst_object_unref(device);
break;
}
case GST_MESSAGE_DEVICE_REMOVED:
{
// this can also be used as an alternative to device-lost signals
gst_message_parse_device_removed(message, &device);
printf("REMOVED Device\n");
print_device(device);
gst_object_unref(device);
break;
}
/*
// not used by tiscamera
// requires gstreamer 1.16
case GST_MESSAGE_DEVICE_CHANGED:
*/
default:
{
break;
}
}
// this means we want to continue
// to listen to device events
// to stop listening return G_SOURCE_REMOVE;
return G_SOURCE_CONTINUE;
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
// The device monitor listens to device activities for us
GstDeviceMonitor* monitor = gst_device_monitor_new();
// We are only interested in devices that are in the categories
// Video and Source && tcam
gst_device_monitor_add_filter(monitor, "Video/Source/tcam", NULL);
//
// static query
// list all devices that are available right now
//
GList* devices = gst_device_monitor_get_devices(monitor);
for (GList* elem = devices; elem; elem = elem->next)
{
GstDevice* device = (GstDevice*) elem->data;
print_device(device);
}
g_list_free_full(devices, gst_object_unref);
//
// dynamic listing
// notify us on all device changes (add/remove/changed)
// all devices will appear once as ADDED
//
GstBus* bus = gst_device_monitor_get_bus(monitor);
gst_bus_add_watch(bus, bus_function, NULL);
gst_object_unref(bus);
// actually start the dynamic monitoring
gst_device_monitor_start(monitor);
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");
// This is simply used to wait for events or the user to end this script
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
// has to be called when gst_device_monitor_start has been called
gst_device_monitor_stop(monitor);
// cleanup
gst_object_unref(monitor);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #!/usr/bin/env python3
#
# This example will show you how to list information about the available devices
#
import sys
import gi
gi.require_version("Gst", "1.0")
gi.require_version("GLib", "2.0")
from gi.repository import GLib, Gst
def print_device(device):
"""
"""
# struc is a Gst.Structure
struc = device.get_properties()
print("\tmodel:\t{}\tserial:\t{}\ttype:\t{}".format(struc.get_string("model"),
struc.get_string("serial"),
struc.get_string("type")))
def bus_function(bus, message, user_data):
"""
Callback for the GstBus watch
"""
if message.type == Gst.MessageType.DEVICE_ADDED:
device = message.parse_device_added()
print("NEW Device")
print_device(device)
elif message.type == Gst.MessageType.DEVICE_REMOVED:
device = message.parse_device_removed()
print("REMOVED Device")
print_device(device)
return True
if __name__ == "__main__":
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
monitor = Gst.DeviceMonitor.new()
monitor.add_filter("Video/Source/tcam")
#
# static query
# list all devices that are available right now
#
for device in monitor.get_devices():
print_device(device)
#
# dynamic listing
# notify us on all device changes (add/remove/changed)
# all devices will appear once as ADDED
#
bus = monitor.get_bus()
bus.add_watch(GLib.PRIORITY_DEFAULT, bus_function, None)
monitor.start()
print("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")
# This is simply used to wait for events or the user to end this script
loop = GLib.MainLoop.new(None, False)
loop.run()
# has to be called when gst_device_monitor_start has been called
monitor.stop()
|
01 - list-properties¶
Shows the properties of a camera and their settings (range, current value, etc.).
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
/* This example will show you how to list the available properties */
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
#include <string.h>
#include <unistd.h>
void print_flags(TcamPropertyBase* prop)
{
printf("Available: ");
GError* err = NULL;
gboolean av = tcam_property_base_is_available(prop, &err);
if (av)
{
printf("yes");
}
else
{
printf("no");
}
printf("\tLocked: ");
gboolean lo = tcam_property_base_is_locked(prop, &err);
if (lo)
{
printf("yes");
}
else
{
printf("no");
}
}
void list_properties(GstElement* source)
{
GError* err = NULL;
GSList* names = tcam_property_provider_get_tcam_property_names(TCAM_PROPERTY_PROVIDER(source), &err);
for (unsigned int i = 0; i < g_slist_length(names); ++i)
{
char* name = (char*)g_slist_nth(names, i)->data;
TcamPropertyBase* base_property = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source), name, &err);
TcamPropertyType type = tcam_property_base_get_property_type(base_property);
switch(type)
{
case TCAM_PROPERTY_TYPE_INTEGER:
{
TcamPropertyInteger* integer = TCAM_PROPERTY_INTEGER(base_property);
gint64 def = tcam_property_integer_get_default(integer, &err);
gint64 min;
gint64 max;
gint64 step;
tcam_property_integer_get_range(integer, &min, &max, &step, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
gint64 value = tcam_property_integer_get_value(integer, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
const char* unit = "";
const char* tmp_unit = tcam_property_integer_get_unit(integer);
if (tmp_unit)
{
unit = tmp_unit;
}
printf("%s\ttype: Integer\t"
"Display Name: \"%s\" "
"Category: %s\n"
"\t\t\tDescription: %s\n"
"\t\t\tUnit: %s\n"
"\t\t\tVisibility: %s\n"
"\t\t\tPresentation: %s\n\t\t\t",
name,
tcam_property_base_get_display_name(base_property),
tcam_property_base_get_category(base_property),
tcam_property_base_get_description(base_property),
unit,
g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)),
g_enum_to_string(tcam_property_intrepresentation_get_type(), tcam_property_integer_get_representation(integer)));
print_flags(base_property);
printf("\n\n"
"\t\t\tDefault: %ld\n"
"\t\t\tValue: %ld"
"\n\n", def, value);
break;
}
case TCAM_PROPERTY_TYPE_FLOAT:
{
TcamPropertyFloat* f = TCAM_PROPERTY_FLOAT(base_property);
gdouble def = tcam_property_float_get_default(f, &err);
;
gdouble min;
gdouble max;
gdouble step;
tcam_property_float_get_range(f, &min, &max, &step, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
gdouble value = tcam_property_float_get_value(f, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
const char* unit = "";
const char* tmp_unit = tcam_property_float_get_unit(f);
if (tmp_unit)
{
unit = tmp_unit;
}
printf("%s\ttype: Float\t"
"Display Name: \"%s\" "
"Category: %s\n"
"\t\t\tDescription: %s\n"
"\t\t\tUnit: %s\n"
"\t\t\tVisibility: %s\n"
"\t\t\tPresentation: %s\n\t\t\t",
name,
tcam_property_base_get_display_name(base_property),
tcam_property_base_get_category(base_property),
tcam_property_base_get_description(base_property),
unit,
g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)),
g_enum_to_string(tcam_property_intrepresentation_get_type(), tcam_property_float_get_representation(f)));
print_flags(base_property);
printf("\n\n"
"\t\t\tDefault: %f\n"
"\t\t\tValue: %f"
"\n\n", def, value);
break;
}
case TCAM_PROPERTY_TYPE_ENUMERATION:
{
TcamPropertyEnumeration* e = TCAM_PROPERTY_ENUMERATION(base_property);
const char* value = tcam_property_enumeration_get_value(e, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
const char* def = tcam_property_enumeration_get_default(e, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
printf("%s\ttype: Enumeration\t"
"Display Name: \"%s\" "
"Category: %s\n"
"\t\t\tDescription: %s\n"
"\t\t\tVisibility: %s\n"
"\t\t\t",
name, tcam_property_base_get_display_name(base_property),
tcam_property_base_get_category(base_property),
tcam_property_base_get_description(base_property),
g_enum_to_string(tcam_property_visibility_get_type() , tcam_property_base_get_visibility(base_property)));
print_flags(base_property);
printf("\n\n"
"\t\t\tEntries:");
GSList* enum_entries = tcam_property_enumeration_get_enum_entries(e, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
break;
}
if (enum_entries)
{
for (GSList* entry = enum_entries; entry != NULL; entry = entry->next)
{
printf(" %s", (const char*)entry->data);
}
g_slist_free_full(enum_entries, g_free);
}
printf("\n\t\t\tDefault: %s\n"
"\t\t\tValue: %s\n\n\n", def, value);
break;
}
case TCAM_PROPERTY_TYPE_BOOLEAN:
{
TcamPropertyBoolean* b = TCAM_PROPERTY_BOOLEAN(base_property);
gboolean value = tcam_property_boolean_get_value(b, &err);
gboolean def = tcam_property_boolean_get_default(b, &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
break;
}
const char* val_str = "false";
const char* def_str = "false";
if (value)
{
val_str = "true";
}
if (def)
{
def_str = "true";
}
printf("%s\ttype: Boolean\t"
"Display Name: \"%s\" "
"Category: %s\n"
"\t\t\tDescription: %s\n"
"\t\t\t",
name,
tcam_property_base_get_display_name(base_property),
tcam_property_base_get_category(base_property),
tcam_property_base_get_description(base_property)
);
print_flags(base_property);
printf("\n\n\t\t\tDefault: %s\n"
"\t\t\tValue: %s\n\n\n",
def_str, val_str);
break;
}
case TCAM_PROPERTY_TYPE_COMMAND:
{
printf("%s\ttype: Command\t"
"Display Name: \"%s\" "
"Category: %s\n"
"\t\t\tDescription: %s\n"
"\t\t\t",
name,
tcam_property_base_get_display_name(base_property),
tcam_property_base_get_category(base_property),
tcam_property_base_get_description(base_property));
print_flags(base_property);
printf("\n\n\n");
break;
}
default:
{
break;
}
printf("\n\n\n");
}
g_object_unref(base_property);
}
g_slist_free_full(names, g_free);
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
GError* err = NULL;
// this is a placeholder definition
// normally your pipeline would be defined here
GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
if (pipeline == NULL)
{
printf("Unable to create pipeline: %s\n", err->message);
g_free(err);
return 1;
}
/* get the tcambin to retrieve device information */
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
const char* serial = NULL; // set this if you do not want the first found device
if (serial != NULL)
{
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
}
// in the READY state the camera will always be initialized
gst_element_set_state(pipeline, GST_STATE_READY);
list_properties(source);
// cleanup
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(source);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | #!/usr/bin/env python3
#
# This example will show you how to list available properties
#
import sys
import gi
gi.require_version("Tcam", "1.0")
gi.require_version("Gst", "1.0")
gi.require_version("GLib", "2.0")
from gi.repository import Tcam, Gst, GLib
def flag_strings(prop):
"""
"""
ret = "Available: "
if prop.is_available():
ret += "yes"
else:
ret += "no"
ret += "\tLocked: "
if prop.is_locked():
ret += "yes"
else:
ret += "no"
return ret
def list_properties(camera):
property_names = camera.get_tcam_property_names()
for name in property_names:
try:
base = camera.get_tcam_property(name)
if base.get_property_type() == Tcam.PropertyType.INTEGER:
default = base.get_default()
mini, maxi, step = base.get_range()
unit = base.get_unit()
if not unit:
unit = ""
print(("{name}\ttype: Integer\tDisplay Name: \"{disp_name}\"\tCategory: {cat}\n"
"\t\t\tDescription: {desc}\n"
"\t\t\tUnit: {unit}\n"
"\t\t\tVisibility: {vis}\n"
"\t\t\tPresentation: {pres}\n"
"\t\t\t{flags}\n\n"
"\t\t\tMin: {mini}\t Max: {maxi}\tStep: {step}\n"
"\t\t\tDefault: {default}\n"
"\t\t\tValue: {val}\n\n").format(name=name,
disp_name=base.get_display_name(),
cat=base.get_category(),
desc=base.get_description(),
unit=unit,
vis=base.get_visibility(),
pres=base.get_representation(),
flags=flag_strings(base),
mini=mini,
maxi=maxi,
step=step,
default=default,
val=base.get_value()))
elif base.get_property_type() == Tcam.PropertyType.FLOAT:
default = base.get_default()
mini, maxi, step = base.get_range()
unit = base.get_unit()
if not unit:
unit = ""
print(("{name}\ttype: Float\tDisplay Name: \"{disp_name}\"\tCategory: {cat}\n"
"\t\t\tDescription: {desc}\n"
"\t\t\tUnit: {unit}\n"
"\t\t\tVisibility: {vis}\n"
"\t\t\tPresentation: {pres}\n"
"\t\t\t{flags}\n\n"
"\t\t\tMin: {mini}\t Max: {maxi}\tStep: {step}\n"
"\t\t\tDefault: {default}\n"
"\t\t\tValue: {val}\n\n").format(name=name,
disp_name=base.get_display_name(),
cat=base.get_category(),
desc=base.get_description(),
unit=unit,
vis=base.get_visibility(),
pres=base.get_representation(),
flags=flag_strings(base),
mini=mini,
maxi=maxi,
step=step,
default=default,
val=base.get_value()))
elif base.get_property_type() == Tcam.PropertyType.ENUMERATION:
print(("{name}\ttype: Enumeration\tDisplay Name: \"{disp_name}\"\tCategory: {cat}\n"
"\t\t\tDescription: {desc}\n"
"\t\t\tVisibility: {vis}\n"
"\t\t\t{flags}\n\n"
"\t\t\tEntries: {entries}\n"
"\t\t\tDefault: {default}\n"
"\t\t\tValue: {val}\n\n").format(name=name,
disp_name=base.get_display_name(),
cat=base.get_category(),
desc=base.get_description(),
vis=base.get_visibility(),
flags=flag_strings(base),
entries=base.get_enum_entries(),
default=base.get_default(),
val=base.get_value()))
elif base.get_property_type() == Tcam.PropertyType.BOOLEAN:
print(("{name}\ttype: Boolean\tDisplay Name: \"{disp_name}\"\tCategory: {cat}\n"
"\t\t\tDescription: {desc}\n"
"\t\t\tVisibility: {vis}\n"
"\t\t\t{flags}\n\n"
"\t\t\tDefault: {default}\n"
"\t\t\tValue: {val}\n\n").format(name=name,
disp_name=base.get_display_name(),
cat=base.get_category(),
desc=base.get_description(),
vis=base.get_visibility(),
flags=flag_strings(base),
default=base.get_default(),
val=base.get_value()))
elif base.get_property_type() == Tcam.PropertyType.COMMAND:
print(("{name}\ttype: Command\tDisplay Name: \"{disp_name}\"\tCategory: {cat}\n"
"\t\t\tDescription: {desc}\n"
"\t\t\tVisibility: {vis}\n"
"\t\t\t{flags}\n\n").format(name=name,
disp_name=base.get_display_name(),
cat=base.get_category(),
desc=base.get_description(),
vis=base.get_visibility(),
flags=flag_strings(base)))
except GLib.Error as err:
print("Error for {}: {}".format(name, err.message))
def block_until_playing(pipeline):
while True:
# wait 0.1 seconds for something to happen
change_return, state, pending = pipeline.get_state(100000000)
if change_return == Gst.StateChangeReturn.SUCCESS:
return True
elif change_return == Gst.StateChangeReturn.FAILURE:
print("Failed to change state {} {} {}".format(change_return,
state,
pending))
return False
def main():
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
pipeline = Gst.parse_launch("tcambin name=source ! fakesink")
if not pipeline:
print("Unable to create pipeline")
return 1
# set this to a specific camera serial if you
# do not want to use the default camera
serial = None
# get the tcambin to retrieve a property list through it
source = pipeline.get_by_name("source")
# serial is defined, thus make the source open that device
if serial is not None:
source.set_property("serial", serial)
# the pipeline/tcamsrc/tcambin element must
# at least be in Gst.State.READY
# for a device to be open.
# with Gst.State.NULL
# no properties will be returned
pipeline.set_state(Gst.State.READY)
list_properties(source)
# This closes the device
# All properties are now invalid
# and have to be deleted
pipeline.set_state(Gst.State.NULL)
return 0
if __name__ == "__main__":
sys.exit(main())
|
02 - set-properties¶
Shows how to set a specific property.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/* This example will show you how to set properties for a certain camera */
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
void print_enum_property(GstElement* source, const char* name)
{
/* this is only a sample not all properties will be set here */
GError* err = NULL;
TcamPropertyBase* property_base = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source),
name,
&err);
if (err)
{
printf("Error while retrieving property: %s\n", err->message);
g_error_free(err);
err = NULL;
}
if (tcam_property_base_get_property_type(property_base) != TCAM_PROPERTY_TYPE_ENUMERATION)
{
printf("%s has wrong type. This should not happen.\n", name);
}
else
{
TcamPropertyEnumeration* property_enum = TCAM_PROPERTY_ENUMERATION(property_base);
const char* value = tcam_property_enumeration_get_value(property_enum, &err);
if (err)
{
printf("Error while retrieving property: %s\n", err->message);
g_error_free(err);
err = NULL;
}
else
{
printf("%s: %s\n", name, value);
}
}
g_object_unref(property_base);
}
void set_enum_property(GstElement* source, const char* name, const char* value)
{
GError* err = NULL;
TcamPropertyBase* property_base = tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(source),
name,
&err);
if (err)
{
printf("Error while retrieving property: %s\n", err->message);
g_error_free(err);
err = NULL;
}
if (tcam_property_base_get_property_type(property_base) != TCAM_PROPERTY_TYPE_ENUMERATION)
{
printf("ExposureAuto has wrong type. This should not happen.\n");
}
else
{
TcamPropertyEnumeration* enum_property = TCAM_PROPERTY_ENUMERATION(property_base);
tcam_property_enumeration_set_value(enum_property, value, &err);
if (err)
{
printf("Error while setting property: %s\n", err->message);
g_error_free(err);
err = NULL;
}
else
{
printf("Set %s to %s\n", name, value);
}
}
g_object_unref(property_base);
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
GError* err = NULL;
// this is a placeholder definition
// normally your pipeline would be defined here
GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
if (pipeline == NULL)
{
printf("Unable to create pipeline: %s\n", err->message);
g_free(err);
err = NULL;
return 1;
}
/* create a tcambin to retrieve device information */
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
const char* serial = NULL;
if (serial != NULL)
{
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
}
gst_element_set_state(pipeline, GST_STATE_READY);
/* Device is now in a state for interactions */
/*
We print the properties for a before/after comparison,
*/
printf("Values before we change them:\n\n");
print_enum_property(source, "ExposureAuto");
print_enum_property(source, "GainAuto");
/*
We set the properties to other values
*/
printf("\nChanging:\n\n");
set_enum_property(source, "ExposureAuto", "Off");
set_enum_property(source, "GainAuto", "Off");
/* alternatively you can get/set directly on the TCAM_PROPERTY_PROVIDER */
/* for this you need to know the type of the property you want to get/set */
/* tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "ExposureAuto", "Off", &err); */
/* tcam_property_provider_set_tcam_integer(TCAM_PROPERTY_PROVIDER(source), "Brightness", 200, &err); */
/* tcam_property_provider_set_tcam_float(TCAM_PROPERTY_PROVIDER(source), "ExposureTime", 30000.0, &err); */
printf("\nValues after we changed them:\n\n");
/*
second print for the before/after comparison
*/
print_enum_property(source, "ExposureAuto");
print_enum_property(source, "GainAuto");
/* cleanup, reset state */
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(source);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | #!/usr/bin/env python3
#
# This example will show you how to set properties
#
import sys
import gi
gi.require_version("Tcam", "1.0")
gi.require_version("Gst", "1.0")
gi.require_version("GLib", "2.0")
from gi.repository import Tcam, Gst, GLib
def print_properties(camera):
"""
Print selected properties
"""
try:
property_exposure_auto = camera.get_tcam_property("ExposureAuto")
print(property_exposure_auto.get_value())
value = camera.get_tcam_enumeration("ExposureAuto")
print(f"Exposure Auto has value: {value}")
value = camera.get_tcam_enumeration("GainAuto")
print("Gain Auto has value: {}".format(value))
value = camera.get_tcam_float("ExposureTime")
print("ExposureTimer has value: {}".format(value))
except GLib.Error as err:
print(f"{err.message}")
def block_until_playing(pipeline):
while True:
# wait 0.1 seconds for something to happen
change_return, state, pending = pipeline.get_state(100000000)
if change_return == Gst.StateChangeReturn.SUCCESS:
return True
elif change_return == Gst.StateChangeReturn.FAILURE:
print("Failed to change state {} {} {}".format(change_return,
state,
pending))
return False
def main():
Gst.init(sys.argv)
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
# Set this to a serial string for a specific camera
serial = None
camera = Gst.ElementFactory.make("tcambin")
if serial:
# This is gstreamer set_property
camera.set_property("serial", serial)
# in the READY state the camera will always be initialized
camera.set_state(Gst.State.READY)
# Print properties for a before/after comparison
print_properties(camera)
# Set properties
try:
camera.set_tcam_enumeration("ExposureAuto", "Off")
camera.set_tcam_enumeration("GainAuto", "Off")
camera.set_tcam_float("ExposureTime", 2000)
except GLib.Error as err:
# if setting properties fail, print the reason
print(f"{err.message}")
print_properties(camera)
# cleanup, reset state
camera.set_state(Gst.State.NULL)
if __name__ == "__main__":
sys.exit(main())
|
03 - live-stream¶
Delivers live-image stream from the camera.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
/* This example will show you how to start a live stream from your camera */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
const char* serial = NULL; // set this if you do not want the first found device
GError* err = NULL;
GstElement* pipeline =
gst_parse_launch("tcambin name=source ! videoconvert ! ximagesink sync=false", &err);
if (err)
{
printf("%s\n", err->message);
g_error_free(err);
err = NULL;
}
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);
printf("Press enter to stop the stream.\n");
getchar();
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #!/usr/bin/env python3
#
# This example will show you how to start a simply live stream
#
import time
import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def main():
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
serial = None
pipeline = Gst.parse_launch("tcambin name=bin "
" ! videoconvert"
" ! ximagesink sync=false")
# retrieve the bin element from the pipeline
camera = pipeline.get_by_name("bin")
# serial is defined, thus make the source open that device
if serial is not None:
camera.set_property("serial", serial)
pipeline.set_state(Gst.State.PLAYING)
print("Press Ctrl-C to stop.")
# We wait with this thread until a
# KeyboardInterrupt in the form of a Ctrl-C
# arrives. This will cause the pipline
# to be set to state NULL
try:
while True:
time.sleep(1)
pipeline.set_state(Gst.State.READY)
pipeline.set_state(Gst.State.PLAYING)
except KeyboardInterrupt:
pass
finally:
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
04 - list-format¶
Lists what formats the camera offers.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
/* This example will show you how to list the formats your device offers */
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
// set this if you do not want the first found device
char* serial = NULL;
/* create a tcambin to retrieve device information */
GstElement* source = gst_element_factory_make("tcambin", "source");
if (serial != NULL)
{
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
}
/* Setting the state to ready ensures that all resources
are initialized and that we really get all format capabilities */
gst_element_set_state(source, GST_STATE_READY);
GstPad* pad = gst_element_get_static_pad(source, "src");
GstCaps* caps = gst_pad_query_caps(pad, NULL);
printf("================ %s\n", gst_caps_to_string(caps));
for (unsigned int i = 0; i < gst_caps_get_size(caps); ++i)
{
GstStructure* structure = gst_caps_get_structure(caps, i);
/*
for a simple display the following line can be used
printf("%s\n", gst_structure_to_string(structure));
*/
const char* name = gst_structure_get_name(structure);
// this is only required when dealing
// with FPD/MiPi cameras on tegra systems
// must not be freed
GstCapsFeatures* features = gst_caps_get_features(caps, i);
if (features)
{
if (gst_caps_features_contains(features, "memory:NVMM"))
{
// do something with this information
printf("NVMM ");
}
}
if (gst_structure_get_field_type(structure, "format") == G_TYPE_STRING)
{
const char* format = gst_structure_get_string(structure, "format");
printf("%s %s - ", name, format);
}
else if (gst_structure_get_field_type(structure, "format") == GST_TYPE_LIST)
{
printf("%s { ", name);
const GValue* val = gst_structure_get_value(structure, "format");
for (unsigned int x = 0; x < gst_value_list_get_size(val); ++x)
{
const GValue* format = gst_value_list_get_value(val, x);
printf("%s ", g_value_get_string(format));
}
printf("} - ");
}
else
{
printf("format handling not implemented for unexpected type: %s\n",
G_VALUE_TYPE_NAME(gst_structure_get_field_type(structure, "format")));
continue;
}
GType width_type = gst_structure_get_field_type(structure, "width");
if (width_type == GST_TYPE_INT_RANGE)
{
int width_min =
gst_value_get_int_range_min(gst_structure_get_value(structure, "width"));
int width_max =
gst_value_get_int_range_max(gst_structure_get_value(structure, "width"));
printf("width: [%d-%d]", width_min, width_max);
}
else
{
int width;
gboolean ret = gst_structure_get_int(structure, "width", &width);
if (!ret)
{
printf("Unable to query width\n");
continue;
}
printf("%d", width);
}
printf(" X ");
GType height_type = gst_structure_get_field_type(structure, "height");
if (height_type == GST_TYPE_INT_RANGE)
{
int height_min =
gst_value_get_int_range_min(gst_structure_get_value(structure, "height"));
int height_max =
gst_value_get_int_range_max(gst_structure_get_value(structure, "height"));
printf("height: [%d-%d]", height_min, height_max);
}
else
{
int height;
gboolean ret = gst_structure_get_int(structure, "height", &height);
if (!ret)
{
printf("Unable to query height\n");
continue;
}
printf("%d", height);
}
printf(" - ");
const GValue* framerate = gst_structure_get_value(structure, "framerate");
if (G_VALUE_TYPE(framerate) == GST_TYPE_LIST)
{
for (unsigned int x = 0; x < gst_value_list_get_size(framerate); ++x)
{
const GValue* val = gst_value_list_get_value(framerate, x);
if (G_VALUE_TYPE(val) == GST_TYPE_FRACTION)
{
int num = gst_value_get_fraction_numerator(val);
int den = gst_value_get_fraction_denominator(val);
printf("%d/%d ", num, den);
}
else
{
printf(
"Handling of framerate handling not implemented for non fraction types.\n");
break;
}
}
}
else if (G_VALUE_TYPE(framerate) == GST_TYPE_FRACTION_RANGE)
{
const GValue* framerate_min = gst_value_get_fraction_range_min(framerate);
const GValue* framerate_max = gst_value_get_fraction_range_max(framerate);
printf("%d/%d - %d/%d",
gst_value_get_fraction_numerator(framerate_min),
gst_value_get_fraction_denominator(framerate_min),
gst_value_get_fraction_numerator(framerate_max),
gst_value_get_fraction_denominator(framerate_max));
}
else
{
printf("Unable to interpret framerate type\n");
continue;
}
// we printed all information for a format decription
// print a new line to keep everything user readable
printf("\n");
}
gst_caps_unref(caps);
gst_object_unref(pad);
gst_element_set_state(source, GST_STATE_NULL);
gst_object_unref(source);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | #!/usr/bin/env python3
#
# This example will show you how to retrieve the available gstreamer
# caps from tcamsrc and how to display print them to stdout.
#
import sys
import gi
import re
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def print_formats(source):
caps = source.get_static_pad("src").query_caps()
for x in range(caps.get_size()):
structure = caps.get_structure(x)
# video/x-raw, video/x-bayer, etc.
name = structure.get_name()
# this is only required when dealing
# with FPD/MiPi cameras on tegra systems
features = caps.get_features(x)
if features:
if features.contains("memory:NVMM"):
print("NVMM ")
try:
fmt = structure.get_value("format")
if isinstance(fmt, str):
print(f"{name} {fmt}", end="")
elif isinstance(fmt, Gst.ValueList):
print(f"{name} {{ ", end="")
for y in range(Gst.ValueList.get_size(fmt)):
val = Gst.ValueList.get_value(fmt, y)
print(f"{val} ", end="")
print("}", end="")
else:
print("==")
except TypeError: # Gst.ValueList
# this means we have multiple formats that all
# have the same width/height/framerate settings
begin = structure.to_string().find("format=(string){")
print(begin)
substr = structure.to_string()[begin:]
values = substr[substr.find("{")+1:substr.find("}")]
print(f"{name} {{ ", end="")
for fmt in values.split(","):
print(f"{fmt} ", end="")
print("}", end="")
# the python gobject introspection wrapper
# can pose problems in older version
# the type Gst.IntRange
# may not be available and thus cause a TypeError
# in such a case we query the string description
# of the Gst.Structure and extract the width/height
try:
if (structure.to_string().find("width=[") != -1
or structure.to_string().find("height=[") != -1):
raise TypeError
width = structure.get_value("width")
height = structure.get_value("height")
print(f" - {width}x{height} - ", end="")
except TypeError:
# width handling
begin = structure.to_string().find("width=(int)[")
substr = structure.to_string()[begin:]
values = substr[substr.find("[")+1:substr.find("]")]
v = re.findall(r'\d+', values)
# assume first entry is smaller
width_min = v[0]
width_max = v[1]
# height handling
begin = structure.to_string().find("height=(int)[")
substr = structure.to_string()[begin:]
values = substr[substr.find("[")+1:substr.find("]")]
v = re.findall(r'\d+', values)
height_min = v[0]
height_max = v[1]
print(f" - {width_min}x{height_min} <=> {width_max}x{height_max} - ", end="")
# the python gobject introspection wrapper
# can pose problems in older version
# the types Gst.Fraction and Gst.FractionRange
# may not be available and thus cause a TypeError
# in such a case we query the string description
# of the Gst.Structure and extract the framerates
try:
framerates = structure.get_value("framerate")
except TypeError:
substr = structure.to_string()[structure.to_string().find("framerate="):]
try:
# try for frame rate lists
field, values, remain = re.split("{|}", substr, maxsplit=3)
rates = [x.strip() for x in values.split(",")]
for r in rates:
print(f"{r} ", end="")
except ValueError: # we have a GstFractionRange
values = substr[substr.find("[")+1:substr.find("]")]
v = re.findall(r'\d+', values)
fps_min_num = v[0]
fps_min_den = v[1]
fps_max_num = v[2]
fps_max_den = v[3]
# framerates are fractions thus one framerate euqals two values
print(f"{fps_min_num}/ {fps_min_den} <=> {fps_max_num}/{fps_max_den}", end="")
# printf line break
print("")
# we are done here
continue
if isinstance(framerates, Gst.ValueList):
# Gst.ValueList.get_size may cause a warning:
# DeprecationWarning: an integer is required (got type float).
# Implicit conversion to integers using __int__ is deprecated,
# and may be removed in a future version of Python.
#
# this is part of the GStreamer python wrapper
# and not tiscamera
size = Gst.ValueList.get_size(framerates)
for y in range(size):
val = Gst.ValueList.get_value(framerates, y)
print("{} ".format(val), end="")
elif isinstance(framerates, Gst.FractionRange):
min_val = Gst.value_get_fraction_range_min(framerates)
max_val = Gst.value_get_fraction_range_max(framerates)
print(f"{min_val} <-> {max_val}")
else:
print(f"framerates not supported {isinstance(framerates)}")
# we are finished
print("")
def main():
"""
main function
initializes GstElement and starts GstCaps query
"""
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
source = Gst.ElementFactory.make("tcambin")
# The tcambin wraps the tcamsrc and offers additional
# formats by implicitly converting
# source = Gst.ElementFactory.make("tcambin")
serial = None
if serial:
source.set_property("serial", serial)
source.set_state(Gst.State.READY)
print_formats(source)
source.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
05 - set format¶
Sets the camera to a specific format.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
/*
This example will show you how to start a live stream from your camera
with a specific format
*/
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
const char* serial = NULL; // set this if you do not want the first found device
GError* err = NULL;
const char* pipeline_desc =
"tcambin name=source ! capsfilter name=filter ! videoconvert ! ximagesink";
GstElement* pipeline = gst_parse_launch(pipeline_desc, &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
GstCaps* caps = gst_caps_new_empty();
GstStructure* structure = gst_structure_from_string("video/x-raw", NULL);
gst_structure_set(structure,
"format",
G_TYPE_STRING,
"BGRx",
"width",
G_TYPE_INT,
640,
"height",
G_TYPE_INT,
480,
"framerate",
GST_TYPE_FRACTION,
15,
1,
NULL);
gst_caps_append_structure(caps, structure);
GstElement* capsfilter = gst_bin_get_by_name(GST_BIN(pipeline), "filter");
if (capsfilter == NULL)
{
printf("Could not retrieve capsfilter from pipeline.");
return 1;
}
g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
gst_object_unref(capsfilter);
gst_caps_unref(caps);
/*
to statically create caps you can reduce the whole procedure to
GstCaps* caps = gst_caps_from_string("video/x-raw,format=BGRx,width=640,height=480,framerate=30/1");
gst_parse_lauch allows you to use strings for caps descriptions.
That means everything until now can be done with:
GstElement* pipeline = gst_parse_launch("tcambin name=source ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1 ! videoconvert ! ximagesink", &err);
*/
gst_element_set_state(pipeline, GST_STATE_PLAYING);
printf("Press enter to stop the stream.\n");
getchar();
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | #!/usr/bin/env python3
#
# This example will show you how to start a simply live stream
#
import time
import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def main():
"""
"""
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
serial = None
pipeline = Gst.parse_launch("tcambin name=bin"
" ! capsfilter name=filter"
" ! videoconvert"
" ! ximagesink")
# serial is defined, thus make the source open that device
if serial:
# retrieve the bin element from the pipeline
camera = pipeline.get_by_name("bin")
camera.set_property("serial", serial)
caps = Gst.Caps.new_empty()
structure = Gst.Structure.new_from_string("video/x-raw")
structure.set_value("width", 640)
structure.set_value("height", 480)
try:
fraction = Gst.Fraction(30, 1)
structure.set_value("framerate", fraction)
except TypeError:
struc_string = structure.to_string()
struc_string += ",framerate={}/{}".format(30, 1)
structure.free()
structure, end = structure.from_string(struc_string)
caps.append_structure(structure)
structure.free()
# structure is not useable from here on
capsfilter = pipeline.get_by_name("filter")
if not capsfilter:
print("Could not retrieve capsfilter from pipeline.")
return 1
capsfilter.set_property("caps", caps)
# to statically create caps you can reduce the whole procedure to
# caps = Gst.Caps.from_string("video/x-raw,format=BGRx,width=640,height=480,framerate=30/1");
#
# Gst.parse_lauch allows you to use strings for caps descriptions.
# That means everything until now can be done with:
#
# pipeline = Gst.parse_launch("tcambin name=source"
# " ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
# " ! videoconvert ! ximagesink");
pipeline.set_state(Gst.State.PLAYING)
print("Press Ctrl-C to stop.")
# We wait with this thread until a
# KeyboardInterrupt in the form of a Ctrl-C
# arrives. This will cause the pipline
# to be set to state NULL
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
pipeline.set_state(Gst.State.NULL)
return 0
if __name__ == "__main__":
sys.exit(main())
|
06 - softwaretrigger¶
Triggers single images - instead of a continuous image stream.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
/* This example will show you how to trigger images */
#include <gst/gst.h>
#include <stdio.h> /* printf */
#include <tcam-property-1.0.h>
#include <unistd.h> /* sleep */
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
const char* serial = NULL; // the serial number of the camera we want to use
GError* err = NULL;
GstElement* pipeline =
gst_parse_launch("tcambin name=source ! video/x-raw,format=BGRx ! videoconvert ! ximagesink ", &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
if (serial != NULL)
{
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
g_value_unset(&val);
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);
/*
This sleep exists only to ensure
that a live image exists before trigger mode is activated.
for all other purposes this can be removed.
*/
sleep(2);
tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "TriggerMode", "On", &err);
if (err)
{
printf("Error while setting trigger mode: %s\n", err->message);
g_error_free(err);
err = NULL;
}
while (0 == 0)
{
printf("Press 'q' then 'enter' to stop the stream.\n");
printf("Press 'Enter' to trigger a new image.\n");
char c = getchar();
if (c == 'q')
{
break;
}
tcam_property_provider_set_tcam_command(TCAM_PROPERTY_PROVIDER(source), "TriggerSoftware", &err);
if (err)
{
printf("!!! Could not trigger. !!!\n");
printf("Error while setting trigger: %s\n", err->message);
g_error_free(err);
err = NULL;
}
else
{
printf("=== Triggered image. ===\n");
}
}
/* deactivate trigger mode */
/* this is simply to prevent confusion when the camera ist started without wanting to trigger */
tcam_property_provider_set_tcam_enumeration(TCAM_PROPERTY_PROVIDER(source), "TriggerMode", "Off", &err);
// this stops the pipeline and frees all resources
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(source);
/* the pipeline automatically handles all elements that have been added to it.
thus they do not have to be cleaned up manually */
gst_object_unref(pipeline);
return 0;
}
|
07 - appsink¶
Receives images in an application instead of just showing them.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
/*
This example will show you how to receive data
from gstreamer in your application
and how to get the actual image data
*/
#include <gst/gst.h>
#include <gst/video/video.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
This function will be called in a separate thread when our appsink
says there is data for us. user_data has to be defined
when calling g_signal_connect. It can be used to pass objects etc.
from your other function to the callback.
user_data can point to additional data for your usage
marked as unused to prevent compiler warnings
*/
static GstFlowReturn callback(GstElement* sink, void* user_data __attribute__((unused)))
{
GstSample* sample = NULL;
/* Retrieve the buffer */
g_signal_emit_by_name(sink, "pull-sample", &sample, NULL);
if (sample)
{
// we have a valid sample
// do things with the image here
static guint framecount = 0;
int pixel_data = -1;
GstBuffer* buffer = gst_sample_get_buffer(sample);
GstMapInfo info; // contains the actual image
if (gst_buffer_map(buffer, &info, GST_MAP_READ))
{
GstVideoInfo* video_info = gst_video_info_new();
if (!gst_video_info_from_caps(video_info, gst_sample_get_caps(sample)))
{
// Could not parse video info (should not happen)
g_warning("Failed to parse video info");
return GST_FLOW_ERROR;
}
// pointer to the image data
// unsigned char* data = info.data;
// Get the pixel value of the center pixel
// int stride = video_info->finfo->bits / 8;
// unsigned int pixel_offset = video_info->width / 2 * stride
// + video_info->width * video_info->height / 2 * stride;
// this is only one pixel
// when dealing with formats like BGRx
// pixel_data will consist out of
// pixel_offset => B
// pixel_offset+1 => G
// pixel_offset+2 => R
// pixel_offset+3 => x
// pixel_data = info.data[pixel_offset];
gst_buffer_unmap(buffer, &info);
gst_video_info_free(video_info);
}
GstClockTime timestamp = GST_BUFFER_PTS(buffer);
g_print("Captured frame %d, Pixel Value=%03d Timestamp=%" GST_TIME_FORMAT " \r",
framecount,
pixel_data,
GST_TIME_ARGS(timestamp));
framecount++;
// delete our reference so that gstreamer can handle the sample
gst_sample_unref(sample);
}
return GST_FLOW_OK;
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv);
const char* serial = NULL; // the serial number of the camera we want to use
const char* pipeline_str = "tcambin name=source ! videoconvert ! appsink name=sink";
GError* err = NULL;
GstElement* pipeline = gst_parse_launch(pipeline_str, &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
/* retrieve the appsink from the pipeline */
GstElement* sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
// tell appsink to notify us when it receives an image
g_object_set(G_OBJECT(sink), "emit-signals", TRUE, NULL);
// tell appsink what function to call when it notifies us
g_signal_connect(sink, "new-sample", G_CALLBACK(callback), NULL);
gst_object_unref(sink);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_print("Press 'enter' to stop the stream.\n");
/* wait for user input to end the program */
getchar();
// this stops the pipeline and frees all resources
gst_element_set_state(pipeline, GST_STATE_NULL);
/*
the pipeline automatically handles
all elements that have been added to it.
thus they do not have to be cleaned up manually
*/
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #!/usr/bin/env python3
#
# This example will show you how to enable trigger-mode
# and how to trigger images with via software trigger.
#
import sys
import gi
import time
gi.require_version("Gst", "1.0")
gi.require_version("GstVideo", "1.0")
from gi.repository import Gst, GstVideo
framecount = 0
def callback(appsink, user_data):
"""
This function will be called in a separate thread when our appsink
says there is data for us. user_data has to be defined
when calling g_signal_connect. It can be used to pass objects etc.
from your other function to the callback.
"""
sample = appsink.emit("pull-sample")
if sample:
caps = sample.get_caps()
gst_buffer = sample.get_buffer()
try:
(ret, buffer_map) = gst_buffer.map(Gst.MapFlags.READ)
video_info = GstVideo.VideoInfo()
video_info.from_caps(caps)
stride = video_info.finfo.bits / 8
pixel_offset = int(video_info.width / 2 * stride +
video_info.width * video_info.height / 2 * stride)
# this is only one pixel
# when dealing with formats like BGRx
# pixel_data will have to consist out of
# pixel_offset => B
# pixel_offset+1 => G
# pixel_offset+2 => R
# pixel_offset+3 => x
pixel_data = buffer_map.data[pixel_offset]
timestamp = gst_buffer.pts
global framecount
output_str = "Captured frame {}, Pixel Value={} Timestamp={}".format(framecount,
pixel_data,
timestamp)
print(output_str, end="\r") # print with \r to rewrite line
framecount += 1
finally:
gst_buffer.unmap(buffer_map)
return Gst.FlowReturn.OK
def main():
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
serial = '01719915'
pipeline = Gst.parse_launch("tcambin name=source"
" ! videoconvert"
" ! appsink name=sink")
# test for error
if not pipeline:
print("Could not create pipeline.")
sys.exit(1)
# The user has not given a serial, so we prompt for one
if serial is not None:
source = pipeline.get_by_name("source")
source.set_property("serial", serial)
sink = pipeline.get_by_name("sink")
# tell appsink to notify us when it receives an image
sink.set_property("emit-signals", True)
user_data = "This is our user data"
# tell appsink what function to call when it notifies us
sink.connect("new-sample", callback, user_data)
pipeline.set_state(Gst.State.PLAYING)
print("Press Ctrl-C to stop.")
# We wait with this thread until a
# KeyboardInterrupt in the form of a Ctrl-C
# arrives. This will cause the pipline
# to be set to state NULL
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
08 - save-stream¶
Stores a stream in a file.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
/* This example will show you how to save a videostream into a file */
#include <gst/gst.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
const char* serial = NULL; // the serial number of the camera we want to use
GError* err = NULL;
GstElement* pipeline =
gst_parse_launch("tcambin name=bin"
" ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
" ! tee name=t"
" ! queue"
" ! videoconvert"
" ! ximagesink"
" t."
" ! queue"
" ! videoconvert"
" ! avimux"
" ! filesink name=fsink",
&err);
/*
to save a video without live view reduce the pipeline to the following:
GstElement* pipeline = Gst.parse_launch("tcambin name=bin"
" ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
" ! videoconvert"
" ! avimux"
" ! filesink name=fsink", &err);
*/
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "bin");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
const char* file_location = "/tmp/tiscamera-save-stream.avi";
GstElement* fsink = gst_bin_get_by_name(GST_BIN(pipeline), "fsink");
g_object_set(G_OBJECT(fsink), "location", file_location, NULL);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
printf("Press Enter to stop the recording\n");
getchar();
// this stops the pipeline and frees all resources
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(fsink);
/* the pipeline automatically handles all elements that have been added to it.
thus they do not have to be cleaned up manually */
gst_object_unref(pipeline);
printf("Stream saved to: %s\n", file_location);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #!/usr/bin/env python3
#
# This example will show you how to save a video stream to a file
#
import time
import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def main():
Gst.init(sys.argv) # init gstreamer
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
serial = None
pipeline = Gst.parse_launch("tcambin name=bin"
" ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
" ! tee name=t"
" ! queue"
" ! videoconvert"
" ! ximagesink"
" t."
" ! queue"
" ! videoconvert"
" ! avimux"
" ! filesink name=fsink")
# to save a video without live view reduce the pipeline to the following:
# pipeline = Gst.parse_launch("tcambin name=bin"
# " ! video/x-raw,format=BGRx,width=640,height=480,framerate=30/1"
# " ! videoconvert"
# " ! avimux"
# " ! filesink name=fsink")
# serial is defined, thus make the source open that device
if serial is not None:
camera = pipeline.get_by_name("bin")
camera.set_property("serial", serial)
file_location = "/tmp/tiscamera-save-stream.avi"
fsink = pipeline.get_by_name("fsink")
fsink.set_property("location", file_location)
pipeline.set_state(Gst.State.PLAYING)
print("Press Ctrl-C to stop.")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
09 - device-lost¶
Receives device-lost and other messages and react to them.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
/* This example will show you how to start a live stream from your camera */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
#include <unistd.h> /* usleep */
static GMainLoop* loop;
static gboolean starts_with(const char* a, const char* b)
{
if (strncmp(a, b, strlen(b)) == 0)
{
return 1;
}
return 0;
}
static gboolean bus_callback(GstBus* bus __attribute__((unused)), GstMessage* message, gpointer data __attribute__((unused)))
{
g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(message));
switch (GST_MESSAGE_TYPE(message))
{
case GST_MESSAGE_ERROR:
{
GError* err;
gchar* debug;
gst_message_parse_error(message, &err, &debug);
g_print("Error: %s \n", err->message);
if (starts_with(err->message, "Device lost ("))
{
char* s_str = strstr(err->message, "(");
const char* serial = strtok(s_str, "()");
printf("Device lost came from device with serial = %s\n", serial);
// device lost handling should be initiated here
// this example simply stops playback
g_main_loop_quit(loop);
}
g_error_free(err);
g_free(debug);
break;
}
case GST_MESSAGE_INFO:
{
break;
}
case GST_MESSAGE_EOS:
{
/* end-of-stream */
g_main_loop_quit(loop);
break;
}
default:
{
/* unhandled message */
break;
}
}
return TRUE;
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
const char* serial = NULL; // set this if you do not want the first found device
GError* err = NULL;
GstElement* pipeline =
gst_parse_launch("tcambin name=source ! videoconvert ! ximagesink", &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_callback, NULL);
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
printf("Disconnect your camera to trigger a device lost or press enter to stop the stream.\n");
// we work with a event loop to be automatically
// notified when a new messages occur.
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #!/usr/bin/env python3
#
# This example will show you how to react to messages on the gstreamer bus.
#
import sys
import re
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib
loop = GLib.MainLoop()
def bus_callback(bus, message, user_data):
"""
Gstreamer Message Types and how to parse
https://lazka.github.io/pgi-docs/Gst-1.0/flags.html#Gst.MessageType
"""
mtype = message.type
if mtype == Gst.MessageType.EOS:
# end-of-stream
loop.quit()
elif mtype == Gst.MessageType.ERROR:
# Handle Errors
err, debug = message.parse_error()
print(err, debug)
if err.message.startswith("Device lost ("):
m = re.search('Device lost \((.*)\)', err.message)
print("Device lost came from device with serial = {}".format(m.group(1)))
# device lost handling should be initiated here
# this example simply stops playback
loop.quit()
elif mtype == Gst.MessageType.WARNING:
# Handle warnings
err, debug = message.parse_warning()
print(err, debug)
return True
def main():
Gst.init(sys.argv)
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
#Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
serial = None
pipeline = Gst.parse_launch("tcambin name=source ! videoconvert ! ximagesink sync=false")
if not pipeline:
print("Could not create pipeline")
sys.exit(1)
if serial:
src = pipeline.get_by_name("source")
src.set_property("serial", serial)
src = None
bus = pipeline.get_bus()
bus.add_signal_watch()
# bus.enable_sync_message_emission()
bus.connect('message', bus_callback, None)
# bus.add_watch(bus_callback, None)
pipeline.set_state(Gst.State.PLAYING)
print("Disconnect your camera to trigger a device lost or press enter to stop the stream.")
# we work with a event loop to be automatically
# be notified when new messages occur.
loop.run()
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
10 - metadata¶
Read meta information like is-damaged, camera capture time, etc.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
/* This example will show you how to receive data from gstreamer in your application
and how to get the actual iamge data */
#include "gstmetatcamstatistics.h"
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <gst/video/video.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static gboolean meta_struc_print(GQuark field_id, const GValue* value, gpointer user_data __attribute__((unused)))
{
// GQuark is a gobject internal ID for strings
// we call the function g_quark_to_string to get the name of the field
// value is a simple, generic value
// user_data can contain things you need for further processing
printf("%s: ", g_quark_to_string(field_id));
if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN)
{
gboolean val = g_value_get_boolean(value);
if (val)
{
printf(" true\n");
}
else
{
printf(" false\n");
}
}
else if (G_VALUE_TYPE(value) == G_TYPE_DOUBLE)
{
double val = g_value_get_double(value);
printf("%f\n", val);
}
else if (G_VALUE_TYPE(value) == G_TYPE_UINT64)
{
guint64 val = g_value_get_uint64(value);
printf("%lu\n", val);
}
else
{
printf("value type not implemented\n");
}
return TRUE;
}
/*
This function will be called in a separate thread when our appsink
says there is data for us. user_data has to be defined when calling g_signal_connect.
*/
static GstFlowReturn callback(GstElement* sink, void* user_data __attribute__((unused)))
{
printf("new sample\n");
GstSample* sample = NULL;
/* Retrieve the buffer */
g_signal_emit_by_name(sink, "pull-sample", &sample, NULL);
if (sample)
{
static guint framecount = 0;
framecount++;
GstBuffer* buffer = gst_sample_get_buffer(sample);
// if you need the associated caps
// GstCaps* c = gst_sample_get_caps(sample);
GstMeta* meta = gst_buffer_get_meta(buffer, g_type_from_name("TcamStatisticsMetaApi"));
if (meta)
{
printf("We have meta\n");
}
else
{
g_warning("No meta data available\n");
}
GstStructure* struc = ((TcamStatisticsMeta*)meta)->structure;
// this prints all contained fields
gst_structure_foreach(struc, meta_struc_print, NULL);
// to only print selective fields
// read the documentation
// https://www.theimagingsource.com/documentation/tiscamera/tcam-gstreamer.html#metadata
// concerning available fields and call them manually by name
/*
guint64 frame_count = 0;
gst_structure_get_uint64(struc, "frame_count", &frame_count);
printf("frame_count: %ul\n", frame_count);
*/
// delete our reference so that gstreamer can handle the sample
gst_sample_unref(sample);
}
return GST_FLOW_OK;
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv);
const char* serial = NULL; // set this if you do not want the first found device
GError* err = NULL;
// some conversion elements will drop the metadata
// for the sake of this example we will retrieve buffers
// directly from the src
const char* pipeline_str = "tcamsrc name=source ! appsink name=sink";
GstElement* pipeline = gst_parse_launch(pipeline_str, &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
if (serial != NULL)
{
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
gst_object_unref(source);
}
/* retrieve the appsink from the pipeline */
GstElement* sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
// tell appsink to notify us when it receives an image
g_object_set(G_OBJECT(sink), "emit-signals", TRUE, NULL);
// tell appsink what function to call when it notifies us
g_signal_connect(sink, "new-sample", G_CALLBACK(callback), NULL);
gst_object_unref(sink);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_print("Press 'enter' to stop the stream.\n");
/* wait for user input to end the program */
getchar();
// this stops the pipeline and frees all resources
gst_element_set_state(pipeline, GST_STATE_NULL);
/*
the pipeline automatically handles
all elements that have been added to it.
thus they do not have to be cleaned up manually
*/
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | #!/usr/bin/env python3
#
# This example will show you how to enable trigger-mode
# and how to trigger images with via software trigger.
#
import sys
import gi
import time
import ctypes
gi.require_version("Gst", "1.0")
gi.require_version("GstVideo", "1.0")
gi.require_version("GObject", "2.0")
gi.require_version("GLib", "2.0")
from gi.repository import Gst, GstVideo, GObject, GLib
# workaround for missing GstMeta apis
# load tiscamera GstMeta library
clib = ctypes.CDLL("libtcamgststatistics.so")
# declare input/output type for our helper function
clib.tcam_statistics_get_structure.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
clib.tcam_statistics_get_structure.restype = ctypes.c_bool
# allocate a c-string with length 320 bytes
# this _should_ be long enough to hold any
# GstStructure string that will be retrieved
# if not change this to a higher number
meta_out_buffer_size = 320
meta_out_buffer = ctypes.create_string_buffer(meta_out_buffer_size)
def get_meta(gst_buffer):
"""
Check Gst.Buffer for a valid Gst.Meta object
and return the contained Gst.Structure
Parameters:
Gst.Buffer
Returns:
Gst.Structure or None in case of error
"""
meta = gst_buffer.get_meta("TcamStatisticsMetaApi")
if not meta:
return None
# fill meta_out_buffer with the result of gst_structure_get_string(meta->structure)
ret = clib.tcam_statistics_get_structure(hash(meta), meta_out_buffer, meta_out_buffer_size)
# ret is a bool indicating successfull string copy
if ret:
# ret is bytecode
# decode it to get a valide str object
# ret.decode("utf-8")
structure_string = ctypes.string_at(meta_out_buffer).decode("utf-8")
struc = Gst.Structure.from_string(structure_string)
# Gst.Structure.from_string returns a tuple
# we only want the actual Gst.Structure
return struc[0]
return None
def callback(appsink, user_data):
"""
This function will be called in a separate thread when our appsink
says there is data for us. user_data has to be defined
when calling g_signal_connect. It can be used to pass objects etc.
from your other function to the callback.
"""
sample = appsink.emit("pull-sample")
if sample:
print("new sample")
# caps = sample.get_caps()
gst_buffer = sample.get_buffer()
tcam_meta = get_meta(gst_buffer)
if tcam_meta:
def print_structure(field_id, value, user_data):
"""
"""
name = GLib.quark_to_string(field_id)
print(f"{name} => {value}")
# return true as we want to continue iterating
return True
# call print structure for all members of the Gst.Structure
tcam_meta.foreach(print_structure, None)
else:
print("No meta")
# empty line for more readability
print("")
return Gst.FlowReturn.OK
def main():
Gst.init(sys.argv)
serial = None
pipeline = Gst.parse_launch("tcambin name=source"
" ! appsink name=sink")
# test for error
if not pipeline:
print("Could not create pipeline.")
sys.exit(1)
# The user has not given a serial, so we prompt for one
if serial is not None:
source = pipeline.get_by_name("source")
source.set_property("serial", serial)
sink = pipeline.get_by_name("sink")
# tell appsink to notify us when it receives an image
sink.set_property("emit-signals", True)
user_data = "This is our user data"
# tell appsink what function to call when it notifies us
sink.connect("new-sample", callback, user_data)
pipeline.set_state(Gst.State.PLAYING)
print("Press Ctrl-C to stop.")
# We wait with this thread until a
# KeyboardInterrupt in the form of a Ctrl-C
# arrives. This will cause the pipline
# to be set to state NULL
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
main()
|
11 - json-state¶
Save and load JSON device state.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
/* This example will show you how to get/set the JSON property description for a certain camera */
#include "tcam-property-1.0.h" /* gobject introspection interface */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
gboolean block_until_playing(GstElement* pipeline)
{
while (TRUE)
{
GstState state;
GstState pending;
// wait 0.1 seconds for something to happen
GstStateChangeReturn ret = gst_element_get_state(pipeline, &state, &pending, 100000000);
if (ret == GST_STATE_CHANGE_SUCCESS)
{
return TRUE;
}
else if (ret == GST_STATE_CHANGE_FAILURE)
{
printf("Failed to change state %s %s %s\n",
gst_element_state_change_return_get_name(ret),
gst_element_state_get_name(state),
gst_element_state_get_name(pending));
return FALSE;
}
}
}
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
GError* err = NULL;
// this is a placeholder definition
// normally your pipeline would be defined here
GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
if (pipeline == NULL)
{
printf("Unable to create pipeline: %s\n", err->message);
g_free(err);
return 1;
}
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
const char* serial = NULL;
if (serial != NULL)
{
GValue val = {};
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
}
// in the READY state the camera will always be initialized
// in the PLAYING state additional properties may appear from gstreamer elements
gst_element_set_state(source, GST_STATE_PLAYING);
// helper function to ensure we have the right state
// alternatively wait for the first image
if (!block_until_playing(pipeline))
{
printf("Unable to start pipeline. \n");
}
// Device is now in a state for interactions
GValue state = G_VALUE_INIT;
g_value_init(&state, G_TYPE_STRING);
//We print the properties for a before/after comparison,
g_object_get_property(G_OBJECT(source), "tcam-properties-json", &state);
printf("State of device is:\n%s", g_value_get_string(&state));
// Change JSON description here
// not part of this example
// second print for the before/after comparison
g_object_set_property(G_OBJECT(source), "tcam-properties-json", &state);
//reread state to see if anything changed
g_object_get_property(G_OBJECT(source), "tcam-properties-json", &state);
printf("State of device is:\n%s", g_value_get_string(&state));
// cleanup, reset state
gst_element_set_state(source, GST_STATE_NULL);
gst_object_unref(source);
gst_object_unref(pipeline);
g_value_unset(&state);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #!/usr/bin/env python3
#
# This example will show you how to set properties
#
import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def block_until_playing(pipeline):
while True:
# wait 0.1 seconds for something to happen
change_return, state, pending = pipeline.get_state(100000000)
if change_return == Gst.StateChangeReturn.SUCCESS:
return True
elif change_return == Gst.StateChangeReturn.FAILURE:
print("Failed to change state {} {} {}".format(change_return,
state,
pending))
return False
def main():
Gst.init(sys.argv)
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain verry useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
pipeline = Gst.parse_launch("tcambin name=source ! fakesink")
if not pipeline:
print("Unable to create pipeline")
return 1
# Set this to a serial string for a specific camera
serial = None
camera = pipeline.get_by_name("source")
if serial:
# This is gstreamer set_property
camera.set_property("serial", serial)
# in the READY state the camera will always be initialized
# in the PLAYING state additional properties may appear from gstreamer elements
pipeline.set_state(Gst.State.PLAYING)
if not block_until_playing(pipeline):
print("Unable to start pipeline")
# Print properties for a before/after comparison
state = camera.get_property("tcam-properties-json")
print(f"State of device is:\n{state}")
# Change JSON description here
# not part of this example
camera.set_property("tcam-properties-json", state)
# Print properties for a before/after comparison
state = camera.get_property("tcam-properties-json")
print(f"State of device is:\n{state}")
# cleanup, reset state
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
sys.exit(main())
|
12 - tcam-properties¶
Save and load properties via GstStructure.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/* This example will show you how to get/set the properties through a description string */
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
gboolean block_until_state_change_done (GstElement* pipeline)
{
while (TRUE)
{
GstState state;
GstState pending;
// wait 0.1 seconds for something to happen
GstStateChangeReturn ret = gst_element_get_state(pipeline, &state, &pending, 100000000);
if (ret == GST_STATE_CHANGE_SUCCESS || ret == GST_STATE_CHANGE_NO_PREROLL)
{
return TRUE;
}
else if (ret == GST_STATE_CHANGE_FAILURE)
{
printf("Failed to change state %s %s %s\n",
gst_element_state_change_return_get_name(ret),
gst_element_state_get_name(state),
gst_element_state_get_name(pending));
return FALSE;
}
}
}
static void print_current_properties (GstElement* source)
{
// Initialize the GValue
GValue current_properties = G_VALUE_INIT;
g_value_init(¤t_properties, GST_TYPE_STRUCTURE);
// Get the GObject property
g_object_get_property(G_OBJECT(source), "tcam-properties", ¤t_properties);
// get a string to print the current property state
char* string = gst_structure_to_string(gst_value_get_structure(¤t_properties));
printf("Current properties:\n%s\n", string );
g_free(string); // free the string
g_value_unset( ¤t_properties ); // free the GstStructure in the GValue
}
int main (int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain very useful information
when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
GError* err = NULL;
// this is a placeholder definition
// normally your pipeline would be defined here
GstElement* pipeline = gst_parse_launch("tcambin name=source ! fakesink", &err);
if (pipeline == NULL)
{
printf("Unable to create pipeline: %s\n", err->message);
g_free(err);
return 1;
}
GstElement* source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
const char* serial = NULL;
if (serial != NULL)
{
GValue val = G_VALUE_INIT;
g_value_init(&val, G_TYPE_STRING);
g_value_set_static_string(&val, serial);
g_object_set_property(G_OBJECT(source), "serial", &val);
}
// in the READY state the camera will always be initialized
gst_element_set_state(source, GST_STATE_READY);
// helper function to wait for async state change to be done
if (!block_until_state_change_done(pipeline))
{
printf("Unable to start pipeline. \n");
return 2;
}
print_current_properties( source );
// Create a new structure
GstStructure* new_property_struct = gst_structure_new_empty("tcam");
// Change 2 properties so that we can see a 'difference'
gst_structure_set(new_property_struct,
"ExposureAuto", G_TYPE_STRING, "Off",
"ExposureTime", G_TYPE_DOUBLE, 35000.0,
NULL );
GValue new_state = G_VALUE_INIT;
g_value_init(&new_state, GST_TYPE_STRUCTURE);
gst_value_set_structure( &new_state, new_property_struct);
// Set the new property settings
g_object_set_property(G_OBJECT(source), "tcam-properties", &new_state);
g_value_unset(&new_state);
gst_structure_free(new_property_struct);
// Print the property settings after the change above
print_current_properties(source);
// cleanup, reset state
gst_element_set_state(source, GST_STATE_NULL);
gst_object_unref(source);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #!/usr/bin/env python3
#
# This example will show you how to get/set the properties through a description string
#
import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def block_until_playing(pipeline):
while True:
# wait 0.1 seconds for something to happen
change_return, state, pending = pipeline.get_state(100000000)
if change_return == Gst.StateChangeReturn.SUCCESS:
return True
elif change_return == Gst.StateChangeReturn.FAILURE:
print("Failed to change state {} {} {}".format(change_return,
state,
pending))
return False
def main():
Gst.init(sys.argv)
# this line sets the gstreamer default logging level
# it can be removed in normal applications
# gstreamer logging can contain very useful information
# when debugging your application
# see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
# for further details
Gst.debug_set_default_threshold(Gst.DebugLevel.WARNING)
pipeline = Gst.parse_launch("tcambin name=source ! fakesink")
if not pipeline:
print("Unable to create pipeline")
return 1
serial = None
source = pipeline.get_by_name("source")
# The user has not given a serial, so we prompt for one
if serial is not None:
source.set_property("serial", serial)
# in the READY state the camera will always be initialized
# in the PLAYING state additional properties may appear from gstreamer elements
pipeline.set_state(Gst.State.PLAYING)
if not block_until_playing(pipeline):
print("Unable to start pipeline")
# Print properties for a before/after comparison
state = source.get_property("tcam-properties")
print(f"State of device is:\n{state.to_string()}")
# Create new structure
# containing changes we want to apply
new_state = Gst.Structure.new_empty("tcam")
new_state.set_value("ExposureAuto", "Off")
new_state.set_value("ExposureTime", 35000.0)
# this can also be done by calling Gst.Structure.from_string()
source.set_property("tcam-properties", new_state)
# Print properties for a before/after comparison
state = source.get_property("tcam-properties")
print(f"New state of device is:\n{state.to_string()}")
# cleanup, reset state
pipeline.set_state(Gst.State.NULL)
if __name__ == "__main__":
sys.exit(main())
|
13 - GstQuery¶
Shows how to use GstQuery for GstCaps verification.
Show sample code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
/*
This example will show you how to query the tcamsrc
- to verify potential framerates
- to verify potential caps
*/
#include <gst/gst.h>
#include <stdio.h> /* printf and putchar */
int main(int argc, char* argv[])
{
/* this line sets the gstreamer default logging level
it can be removed in normal applications
gstreamer logging can contain verry useful information
when debugging your application
see https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html
for further details
*/
gst_debug_set_default_threshold(GST_LEVEL_WARNING);
gst_init(&argc, &argv); // init gstreamer
GError* err = NULL;
const char* pipeline_desc = "tcambin name=bin ! videoconvert ! ximagesink";
GstElement* pipeline = gst_parse_launch(pipeline_desc, &err);
/* test for error */
if (pipeline == NULL)
{
printf("Could not create pipeline. Cause: %s\n", err->message);
return 1;
}
GstElement* tcambin = gst_bin_get_by_name(GST_BIN(pipeline), "bin");
gst_element_set_state(pipeline, GST_STATE_READY);
/* retrieve the source
these queries have to be performed on the source
as the tcambin might alter the query
which we do not want
*/
GstElement* source = gst_bin_get_by_name(GST_BIN(tcambin), "tcambin-source");
GstCaps* framerate_query_caps =
gst_caps_from_string("video/x-bayer,format=rggb,width=640,height=480");
// if you have a mono camera try these instead
// GstCaps* framerate_query_caps =
// gst_caps_from_string("video/x-raw,format=GRAY8,width=640,height=480");
GstQuery* framerate_query = gst_query_new_caps(framerate_query_caps);
gst_caps_unref(framerate_query_caps);
if (gst_element_query(source, framerate_query))
{
// no transfer, nothing has to be freed
GstCaps* query_result_caps = NULL;
gst_query_parse_caps_result(framerate_query, &query_result_caps);
char* result_caps_string = gst_caps_to_string(query_result_caps);
printf("Camera supports these framerates: %s\n", result_caps_string);
g_free(result_caps_string);
}
gst_query_unref(framerate_query);
/*
verify specific caps
for this all needed fields have to be set(format, width, height and framerate)
*/
GstCaps* accept_query_caps =
gst_caps_from_string("video/x-bayer,format=rggb,width=640,height=480,framerate=30/1");
GstQuery* accept_query = gst_query_new_accept_caps(accept_query_caps);
gst_caps_unref(accept_query_caps);
if (gst_element_query(source, accept_query))
{
gboolean accepts_caps;
gst_query_parse_accept_caps_result(accept_query, &accepts_caps);
if (accepts_caps)
{
printf("Caps are accepted\n");
}
else
{
printf("Caps are not accepted\n");
}
}
gst_query_unref(accept_query);
gst_object_unref(source);
gst_object_unref(tcambin);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #!/usr/bin/env python3
#
# This example will show you how to query the tcamsrc
# - to verify potential framerates
# - to verify potential caps
#
import sys
import gi
import time
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def main():
Gst.init(sys.argv)
pipeline = Gst.parse_launch("tcambin name=bin ! videoconvert ! ximagesink ")
pipeline.set_state(Gst.State.READY)
tcambin = pipeline.get_by_name("bin")
# retrieve the source
# these queries have to be performed on the source
# as the tcambin might alter the query
# which we do not want
source = tcambin.get_by_name("tcambin-source")
framerate_query_caps = Gst.Caps.from_string("video/x-bayer,format=rggb,width=640,height=480")
# if you have a mono camera try these instead
# framerate_query_caps = Gst.Caps.from_string("video/x-raw,format=GRAY8.width=640,height=480")
framerate_query = Gst.Query.new_caps(framerate_query_caps)
if source.query(framerate_query):
# the result caps will contain our framerate_query_caps + all potential framerates
supported_framerate_caps = framerate_query.parse_caps_result()
print("Camera supports these framerates: {}".format(supported_framerate_caps.to_string()))
#
# verify specific caps
# for this all needed fields have to be set (format, width, height and framerate)
#
accept_query_caps = Gst.Caps.from_string("video/x-bayer,format=rggb,width=640,height=480,framerate=30/1")
accept_query = Gst.Query.new_accept_caps(accept_query_caps)
if source.query(accept_query):
if accept_query.parse_accept_caps_result():
print("Caps are supported")
else:
print("Caps are not supported")
pipeline.set_state(Gst.State.NULL)
return 0
if __name__ == "__main__":
sys.exit(main())
|
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.