3 * Copyright (C) 2018-2019 Igalia S.L.
4 * Copyright (C) 2018 Metrological Group B.V.
5 * Author: Alicia Boya GarcĂa <aboya@igalia.com>
7 * formatting.c: Functions used by validateflow to get string
8 * representations of buffers.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
26 #include "formatting.h"
36 typedef void (*Uint64Formatter) (gchar * dest, guint64 time);
39 format_time (gchar * dest_str, guint64 time)
41 if (GST_CLOCK_TIME_IS_VALID (time)) {
42 sprintf (dest_str, "%" GST_TIME_FORMAT, GST_TIME_ARGS (time));
44 strcpy (dest_str, "none");
49 format_number (gchar * dest_str, guint64 number)
51 sprintf (dest_str, "%" G_GUINT64_FORMAT, number);
55 validate_flow_format_segment (const GstSegment * segment)
57 Uint64Formatter uint64_format;
61 gchar start_str[32], offset_str[32], stop_str[32], time_str[32], base_str[32],
62 position_str[32], duration_str[32];
66 segment->format == GST_FORMAT_TIME ? format_time : format_number;
67 uint64_format (start_str, segment->start);
68 uint64_format (offset_str, segment->offset);
69 uint64_format (stop_str, segment->stop);
70 uint64_format (time_str, segment->time);
71 uint64_format (base_str, segment->base);
72 uint64_format (position_str, segment->position);
73 uint64_format (duration_str, segment->duration);
75 format = g_string_new (gst_format_get_name (segment->format));
76 format = g_string_ascii_up (format);
77 parts[parts_index++] =
78 g_strdup_printf ("format=%s, start=%s, offset=%s, stop=%s", format->str,
79 start_str, offset_str, stop_str);
80 if (segment->rate != 1.0)
81 parts[parts_index++] = g_strdup_printf ("rate=%f", segment->rate);
82 if (segment->applied_rate != 1.0)
83 parts[parts_index++] =
84 g_strdup_printf ("applied_rate=%f", segment->applied_rate);
86 parts[parts_index++] = g_strdup_printf ("flags=0x%02x", segment->flags);
87 parts[parts_index++] =
88 g_strdup_printf ("time=%s, base=%s, position=%s", time_str, base_str,
90 if (GST_CLOCK_TIME_IS_VALID (segment->duration))
91 parts[parts_index++] = g_strdup_printf ("duration=%s", duration_str);
92 parts[parts_index] = NULL;
94 segment_str = g_strjoinv (", ", parts);
96 while (parts_index > 0)
97 g_free (parts[--parts_index]);
98 g_string_free (format, TRUE);
104 structure_only_given_keys (GQuark field_id, GValue * value,
105 gpointer _keys_to_print)
107 const gchar *const *keys_to_print = (const gchar * const *) _keys_to_print;
108 return (!keys_to_print
109 || g_strv_contains (keys_to_print, g_quark_to_string (field_id)));
113 gpointer_free (gpointer pointer_location)
115 g_free (*(void **) pointer_location);
119 validate_flow_format_caps (const GstCaps * caps,
120 const gchar * const *keys_to_print)
123 GArray *structures_strv = g_array_new (TRUE, FALSE, sizeof (gchar *));
126 g_array_set_clear_func (structures_strv, gpointer_free);
128 /* A single GstCaps can contain several caps structures (although only one is
129 * used in most cases). We will print them separated with spaces. */
130 for (i = 0; i < gst_caps_get_size (caps); i++) {
131 GstStructure *structure =
132 gst_structure_copy (gst_caps_get_structure (caps, i));
133 gchar *structure_str;
134 gst_structure_filter_and_map_in_place (structure, structure_only_given_keys,
135 (gpointer) keys_to_print);
136 structure_str = gst_structure_to_string (structure);
137 g_array_append_val (structures_strv, structure_str);
140 caps_str = g_strjoinv (" ", (gchar **) structures_strv->data);
141 g_array_free (structures_strv, TRUE);
147 buffer_get_flags_string (GstBuffer * buffer)
149 GFlagsClass *flags_class =
150 G_FLAGS_CLASS (g_type_class_ref (gst_buffer_flags_get_type ()));
151 GstBufferFlags flags = GST_BUFFER_FLAGS (buffer);
152 GString *string = NULL;
155 GFlagsValue *value = g_flags_get_first_value (flags_class, flags);
160 string = g_string_new (NULL);
162 g_string_append (string, " ");
164 g_string_append (string, value->value_nick);
165 flags &= ~value->value;
168 return (string != NULL) ? g_string_free (string, FALSE) : NULL;
171 /* Returns a newly-allocated string describing the metas on this buffer, or NULL */
173 buffer_get_meta_string (GstBuffer * buffer)
175 gpointer state = NULL;
179 while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
180 const gchar *desc = g_type_name (meta->info->type);
183 s = g_string_new (NULL);
185 g_string_append (s, ", ");
187 g_string_append (s, desc);
190 return (s != NULL) ? g_string_free (s, FALSE) : NULL;
194 validate_flow_format_buffer (GstBuffer * buffer)
196 gchar *flags_str, *meta_str, *buffer_str;
197 gchar *buffer_parts[6];
198 int buffer_parts_index = 0;
200 if (GST_CLOCK_TIME_IS_VALID (buffer->dts)) {
202 format_time (time_str, buffer->dts);
203 buffer_parts[buffer_parts_index++] = g_strdup_printf ("dts=%s", time_str);
206 if (GST_CLOCK_TIME_IS_VALID (buffer->pts)) {
208 format_time (time_str, buffer->pts);
209 buffer_parts[buffer_parts_index++] = g_strdup_printf ("pts=%s", time_str);
212 if (GST_CLOCK_TIME_IS_VALID (buffer->duration)) {
214 format_time (time_str, buffer->duration);
215 buffer_parts[buffer_parts_index++] = g_strdup_printf ("dur=%s", time_str);
218 flags_str = buffer_get_flags_string (buffer);
220 buffer_parts[buffer_parts_index++] =
221 g_strdup_printf ("flags=%s", flags_str);
224 meta_str = buffer_get_meta_string (buffer);
226 buffer_parts[buffer_parts_index++] = g_strdup_printf ("meta=%s", meta_str);
228 buffer_parts[buffer_parts_index] = NULL;
230 buffer_parts_index > 0 ? g_strjoinv (", ",
231 buffer_parts) : g_strdup ("(empty)");
235 while (buffer_parts_index > 0)
236 g_free (buffer_parts[--buffer_parts_index]);
242 validate_flow_format_event (GstEvent * event, gboolean allow_stream_id,
243 const gchar * const *caps_properties)
245 const gchar *event_type;
246 gchar *structure_string;
249 event_type = gst_event_type_get_name (GST_EVENT_TYPE (event));
251 if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
252 const GstSegment *segment;
253 gst_event_parse_segment (event, &segment);
254 structure_string = validate_flow_format_segment (segment);
255 } else if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
257 gst_event_parse_caps (event, &caps);
258 structure_string = validate_flow_format_caps (caps, caps_properties);
259 } else if (!gst_event_get_structure (event)) {
260 structure_string = g_strdup ("(no structure)");
262 GstStructure *printable =
263 gst_structure_copy (gst_event_get_structure (event));
265 if (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START && !allow_stream_id)
266 gst_structure_remove_fields (printable, "stream-id", NULL);
268 structure_string = gst_structure_to_string (printable);
269 gst_structure_free (printable);
272 event_string = g_strdup_printf ("%s: %s", event_type, structure_string);
273 g_free (structure_string);