133 g_free (properties); |
117 g_free (properties); |
134 } |
118 } |
135 return param_name; |
119 return param_name; |
136 } |
120 } |
137 |
121 |
138 static void |
|
139 debug_dump_pad (GstPad * pad, gchar * color_name, gchar * element_name, |
|
140 FILE * out, const gint indent) |
|
141 { |
|
142 GstPadTemplate *pad_templ; |
|
143 GstPadPresence presence; |
|
144 gchar *pad_name, *style_name; |
|
145 gchar pad_flags[6]; |
|
146 const gchar *activation_mode = "-><"; |
|
147 const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)]; |
|
148 |
|
149 pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); |
|
150 |
|
151 /* pad availability */ |
|
152 style_name = "filled,solid"; |
|
153 if ((pad_templ = gst_pad_get_pad_template (pad))) { |
|
154 presence = GST_PAD_TEMPLATE_PRESENCE (pad_templ); |
|
155 if (presence == GST_PAD_SOMETIMES) { |
|
156 style_name = "filled,dotted"; |
|
157 } else if (presence == GST_PAD_REQUEST) { |
|
158 style_name = "filled,dashed"; |
|
159 } |
|
160 } |
|
161 /* check if pad flags */ |
|
162 pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b'; |
|
163 pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f'; |
|
164 pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g'; |
|
165 pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS) ? 's' : 's'; |
|
166 pad_flags[4] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b'; |
|
167 pad_flags[5] = '\0'; |
|
168 |
|
169 fprintf (out, "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n", spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), activation_mode[pad->mode], /* NONE/PUSH/PULL */ |
|
170 pad_flags, style_name); |
|
171 |
|
172 g_free (pad_name); |
|
173 } |
|
174 |
|
175 static void |
|
176 debug_dump_element_pad (GstPad * pad, GstElement * element, |
|
177 GstDebugGraphDetails details, FILE * out, const gint indent) |
|
178 { |
|
179 GstElement *target_element; |
|
180 GstPad *target_pad, *tmp_pad; |
|
181 GstPadDirection dir; |
|
182 gchar *pad_name, *element_name; |
|
183 gchar *target_element_name; |
|
184 gchar *color_name; |
|
185 |
|
186 dir = gst_pad_get_direction (pad); |
|
187 pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); |
|
188 element_name = debug_dump_make_object_name (GST_OBJECT (element)); |
|
189 if (GST_IS_GHOST_PAD (pad)) { |
|
190 color_name = |
|
191 (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir == |
|
192 GST_PAD_SINK) ? "#ddddff" : "#ffffff"); |
|
193 /* output target-pad so that it belongs to this element */ |
|
194 if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { |
|
195 if ((target_pad = gst_pad_get_peer (tmp_pad))) { |
|
196 if ((target_element = gst_pad_get_parent_element (target_pad))) { |
|
197 target_element_name = |
|
198 debug_dump_make_object_name (GST_OBJECT (target_element)); |
|
199 } else { |
|
200 target_element_name = ""; |
|
201 } |
|
202 debug_dump_pad (target_pad, color_name, target_element_name, out, |
|
203 indent); |
|
204 if (target_element) { |
|
205 g_free (target_element_name); |
|
206 gst_object_unref (target_element); |
|
207 } |
|
208 gst_object_unref (target_pad); |
|
209 } |
|
210 gst_object_unref (tmp_pad); |
|
211 } |
|
212 } else { |
|
213 color_name = |
|
214 (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir == |
|
215 GST_PAD_SINK) ? "#aaaaff" : "#cccccc"); |
|
216 } |
|
217 /* pads */ |
|
218 debug_dump_pad (pad, color_name, element_name, out, indent); |
|
219 g_free (element_name); |
|
220 } |
|
221 |
|
222 static gboolean |
|
223 string_append_field (GQuark field, const GValue * value, gpointer ptr) |
|
224 { |
|
225 GString *str = (GString *) ptr; |
|
226 gchar *value_str = gst_value_serialize (value); |
|
227 |
|
228 /* some enums can become really long */ |
|
229 if (strlen (value_str) > 25) { |
|
230 gint pos = 24; |
|
231 |
|
232 /* truncate */ |
|
233 value_str[25] = '\0'; |
|
234 |
|
235 /* mirror any brackets */ |
|
236 if (value_str[0] == '<') |
|
237 value_str[pos--] = '>'; |
|
238 if (value_str[0] == '[') |
|
239 value_str[pos--] = ']'; |
|
240 if (value_str[0] == '(') |
|
241 value_str[pos--] = ')'; |
|
242 if (value_str[0] == '{') |
|
243 value_str[pos--] = '}'; |
|
244 if (pos != 24) |
|
245 value_str[pos--] = ' '; |
|
246 /* elippsize */ |
|
247 value_str[pos--] = '.'; |
|
248 value_str[pos--] = '.'; |
|
249 value_str[pos--] = '.'; |
|
250 } |
|
251 g_string_append_printf (str, " %18s: %s\\l", g_quark_to_string (field), |
|
252 value_str); |
|
253 |
|
254 g_free (value_str); |
|
255 return TRUE; |
|
256 } |
|
257 |
|
258 static gchar * |
|
259 debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details, |
|
260 gboolean * need_free) |
|
261 { |
|
262 gchar *media = NULL; |
|
263 |
|
264 if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) { |
|
265 |
|
266 if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) { |
|
267 media = gst_caps_to_string (caps); |
|
268 *need_free = TRUE; |
|
269 |
|
270 } else { |
|
271 GString *str = NULL; |
|
272 guint i; |
|
273 guint slen = 0; |
|
274 |
|
275 for (i = 0; i < gst_caps_get_size (caps); i++) { |
|
276 slen += 25 + |
|
277 STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i)); |
|
278 } |
|
279 |
|
280 str = g_string_sized_new (slen); |
|
281 for (i = 0; i < gst_caps_get_size (caps); i++) { |
|
282 GstStructure *structure = gst_caps_get_structure (caps, i); |
|
283 |
|
284 g_string_append (str, gst_structure_get_name (structure)); |
|
285 g_string_append (str, "\\l"); |
|
286 |
|
287 gst_structure_foreach (structure, string_append_field, (gpointer) str); |
|
288 } |
|
289 |
|
290 media = g_string_free (str, FALSE); |
|
291 *need_free = TRUE; |
|
292 } |
|
293 |
|
294 } else { |
|
295 if (GST_CAPS_IS_SIMPLE (caps)) |
|
296 media = |
|
297 (gchar *) gst_structure_get_name (gst_caps_get_structure (caps, 0)); |
|
298 else |
|
299 media = "*"; |
|
300 *need_free = FALSE; |
|
301 } |
|
302 return media; |
|
303 } |
|
304 |
|
305 static void |
|
306 debug_dump_element_pad_link (GstPad * pad, GstElement * element, |
|
307 GstDebugGraphDetails details, FILE * out, const gint indent) |
|
308 { |
|
309 GstElement *peer_element, *target_element; |
|
310 GstPad *peer_pad, *target_pad, *tmp_pad; |
|
311 GstCaps *caps, *peer_caps; |
|
312 gboolean free_caps, free_peer_caps; |
|
313 gboolean free_media, free_media_src, free_media_sink; |
|
314 gchar *media = NULL; |
|
315 gchar *media_src = NULL, *media_sink = NULL; |
|
316 gchar *pad_name, *element_name; |
|
317 gchar *peer_pad_name, *peer_element_name; |
|
318 gchar *target_pad_name, *target_element_name; |
|
319 const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)]; |
|
320 |
|
321 if ((peer_pad = gst_pad_get_peer (pad))) { |
|
322 free_media = free_media_src = free_media_sink = FALSE; |
|
323 if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) || |
|
324 (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) |
|
325 ) { |
|
326 if ((caps = gst_pad_get_negotiated_caps (pad))) { |
|
327 free_caps = TRUE; |
|
328 } else { |
|
329 free_caps = FALSE; |
|
330 if (!(caps = (GstCaps *) |
|
331 gst_pad_get_pad_template_caps (pad))) { |
|
332 /* this should not happen */ |
|
333 media = "?"; |
|
334 } |
|
335 } |
|
336 if ((peer_caps = gst_pad_get_negotiated_caps (peer_pad))) { |
|
337 free_peer_caps = TRUE; |
|
338 } else { |
|
339 free_peer_caps = FALSE; |
|
340 peer_caps = (GstCaps *) gst_pad_get_pad_template_caps (peer_pad); |
|
341 } |
|
342 if (caps) { |
|
343 media = debug_dump_describe_caps (caps, details, &free_media); |
|
344 /* check if peer caps are different */ |
|
345 if (peer_caps && !gst_caps_is_equal (caps, peer_caps)) { |
|
346 gchar *tmp; |
|
347 gboolean free_tmp; |
|
348 |
|
349 tmp = debug_dump_describe_caps (peer_caps, details, &free_tmp); |
|
350 if (gst_pad_get_direction (pad) == GST_PAD_SRC) { |
|
351 media_src = media; |
|
352 free_media_src = free_media; |
|
353 media_sink = tmp; |
|
354 free_media_sink = free_tmp; |
|
355 } else { |
|
356 media_src = tmp; |
|
357 free_media_src = free_tmp; |
|
358 media_sink = media; |
|
359 free_media_sink = free_media; |
|
360 } |
|
361 media = NULL; |
|
362 free_media = FALSE; |
|
363 } |
|
364 if (free_caps) { |
|
365 gst_caps_unref (caps); |
|
366 } |
|
367 } |
|
368 if (free_peer_caps && peer_caps) { |
|
369 gst_caps_unref (peer_caps); |
|
370 } |
|
371 } |
|
372 |
|
373 pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); |
|
374 if (element) { |
|
375 element_name = debug_dump_make_object_name (GST_OBJECT (element)); |
|
376 } else { |
|
377 element_name = ""; |
|
378 } |
|
379 peer_pad_name = debug_dump_make_object_name (GST_OBJECT (peer_pad)); |
|
380 if ((peer_element = gst_pad_get_parent_element (peer_pad))) { |
|
381 peer_element_name = |
|
382 debug_dump_make_object_name (GST_OBJECT (peer_element)); |
|
383 } else { |
|
384 peer_element_name = ""; |
|
385 } |
|
386 |
|
387 if (GST_IS_GHOST_PAD (pad)) { |
|
388 if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { |
|
389 if ((target_pad = gst_pad_get_peer (tmp_pad))) { |
|
390 target_pad_name = |
|
391 debug_dump_make_object_name (GST_OBJECT (target_pad)); |
|
392 if ((target_element = gst_pad_get_parent_element (target_pad))) { |
|
393 target_element_name = |
|
394 debug_dump_make_object_name (GST_OBJECT (target_element)); |
|
395 } else { |
|
396 target_element_name = ""; |
|
397 } |
|
398 /* src ghostpad relationship */ |
|
399 fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, |
|
400 target_element_name, target_pad_name, element_name, pad_name); |
|
401 |
|
402 g_free (target_pad_name); |
|
403 if (target_element) { |
|
404 g_free (target_element_name); |
|
405 gst_object_unref (target_element); |
|
406 } |
|
407 gst_object_unref (target_pad); |
|
408 } |
|
409 gst_object_unref (tmp_pad); |
|
410 } |
|
411 } |
|
412 if (GST_IS_GHOST_PAD (peer_pad)) { |
|
413 if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) { |
|
414 if ((target_pad = gst_pad_get_peer (tmp_pad))) { |
|
415 target_pad_name = |
|
416 debug_dump_make_object_name (GST_OBJECT (target_pad)); |
|
417 if ((target_element = gst_pad_get_parent_element (target_pad))) { |
|
418 target_element_name = |
|
419 debug_dump_make_object_name (GST_OBJECT (target_element)); |
|
420 } else { |
|
421 target_element_name = ""; |
|
422 } |
|
423 /* sink ghostpad relationship */ |
|
424 fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, |
|
425 peer_element_name, peer_pad_name, |
|
426 target_element_name, target_pad_name); |
|
427 /* FIXME: we are missing links from the proxy pad |
|
428 * theoretically we need to: |
|
429 * pad=gst_object_ref(target_pad); |
|
430 * goto line 280: if ((peer_pad = gst_pad_get_peer (pad))) |
|
431 * as this would be ugly we need to refactor ... |
|
432 */ |
|
433 debug_dump_element_pad_link (target_pad, target_element, details, out, |
|
434 indent); |
|
435 g_free (target_pad_name); |
|
436 if (target_element) { |
|
437 g_free (target_element_name); |
|
438 gst_object_unref (target_element); |
|
439 } |
|
440 gst_object_unref (target_pad); |
|
441 } |
|
442 gst_object_unref (tmp_pad); |
|
443 } |
|
444 } |
|
445 |
|
446 /* pad link */ |
|
447 if (media) { |
|
448 fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc, |
|
449 element_name, pad_name, peer_element_name, peer_pad_name, media); |
|
450 if (free_media) { |
|
451 g_free (media); |
|
452 } |
|
453 } else if (media_src && media_sink) { |
|
454 /* dot has some issues with placement of head and taillabels, |
|
455 * we need an empty label to make space */ |
|
456 fprintf (out, "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", " |
|
457 "label=\" \", " |
|
458 "headlabel=\"%s\", taillabel=\"%s\"]\n", |
|
459 spc, element_name, pad_name, peer_element_name, peer_pad_name, |
|
460 media_src, media_sink); |
|
461 if (free_media_src) |
|
462 g_free (media_src); |
|
463 if (free_media_sink) |
|
464 g_free (media_sink); |
|
465 } else { |
|
466 fprintf (out, "%s%s_%s -> %s_%s\n", spc, |
|
467 element_name, pad_name, peer_element_name, peer_pad_name); |
|
468 } |
|
469 |
|
470 g_free (pad_name); |
|
471 if (element) { |
|
472 g_free (element_name); |
|
473 } |
|
474 g_free (peer_pad_name); |
|
475 if (peer_element) { |
|
476 g_free (peer_element_name); |
|
477 gst_object_unref (peer_element); |
|
478 } |
|
479 gst_object_unref (peer_pad); |
|
480 } |
|
481 } |
|
482 |
|
483 /* |
122 /* |
484 * debug_dump_element: |
123 * debug_dump_element: |
485 * @bin: the bin that should be analyzed |
124 * @bin: the bin that should be analyzed |
486 * @out: file to write to |
125 * @out: file to write to |
487 * @indent: level of graph indentation |
126 * @indent: level of graph indentation |
581 while (!pads_done) { |
250 while (!pads_done) { |
582 switch (gst_iterator_next (pad_iter, (gpointer) & pad)) { |
251 switch (gst_iterator_next (pad_iter, (gpointer) & pad)) { |
583 case GST_ITERATOR_OK: |
252 case GST_ITERATOR_OK: |
584 if (gst_pad_is_linked (pad) |
253 if (gst_pad_is_linked (pad) |
585 && gst_pad_get_direction (pad) == GST_PAD_SRC) { |
254 && gst_pad_get_direction (pad) == GST_PAD_SRC) { |
586 debug_dump_element_pad_link (pad, element, details, out, |
255 if ((peer_pad = gst_pad_get_peer (pad))) { |
587 indent); |
256 free_media = FALSE; |
|
257 if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) || |
|
258 (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) |
|
259 ) { |
|
260 if ((caps = gst_pad_get_negotiated_caps (pad))) { |
|
261 free_caps = TRUE; |
|
262 } else { |
|
263 free_caps = FALSE; |
|
264 if (!(caps = (GstCaps *) |
|
265 gst_pad_get_pad_template_caps (pad))) { |
|
266 /* this should not happen */ |
|
267 media = "?"; |
|
268 } |
|
269 } |
|
270 if (caps) { |
|
271 if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) { |
|
272 gchar *tmp = |
|
273 g_strdelimit (gst_caps_to_string (caps), ",", |
|
274 '\n'); |
|
275 |
|
276 media = g_strescape (tmp, NULL); |
|
277 free_media = TRUE; |
|
278 g_free (tmp); |
|
279 } else { |
|
280 if (GST_CAPS_IS_SIMPLE (caps)) { |
|
281 structure = gst_caps_get_structure (caps, 0); |
|
282 media = |
|
283 (gchar *) gst_structure_get_name (structure); |
|
284 } else |
|
285 media = "*"; |
|
286 } |
|
287 if (free_caps) { |
|
288 gst_caps_unref (caps); |
|
289 } |
|
290 } |
|
291 } |
|
292 |
|
293 pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); |
|
294 element_name = |
|
295 debug_dump_make_object_name (GST_OBJECT (element)); |
|
296 peer_pad_name = |
|
297 debug_dump_make_object_name (GST_OBJECT (peer_pad)); |
|
298 if ((peer_element = gst_pad_get_parent_element (peer_pad))) { |
|
299 peer_element_name = |
|
300 debug_dump_make_object_name (GST_OBJECT |
|
301 (peer_element)); |
|
302 } else { |
|
303 peer_element_name = ""; |
|
304 } |
|
305 /* pad link */ |
|
306 if (media) { |
|
307 fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc, |
|
308 element_name, pad_name, peer_element_name, |
|
309 peer_pad_name, media); |
|
310 if (free_media) { |
|
311 g_free (media); |
|
312 } |
|
313 } else { |
|
314 fprintf (out, "%s%s_%s -> %s_%s\n", spc, |
|
315 element_name, pad_name, peer_element_name, |
|
316 peer_pad_name); |
|
317 } |
|
318 |
|
319 if (GST_IS_GHOST_PAD (pad)) { |
|
320 if ((target_pad = |
|
321 gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { |
|
322 target_pad_name = |
|
323 debug_dump_make_object_name (GST_OBJECT |
|
324 (target_pad)); |
|
325 if ((target_element = |
|
326 gst_pad_get_parent_element (target_pad))) { |
|
327 target_element_name = |
|
328 debug_dump_make_object_name (GST_OBJECT |
|
329 (target_element)); |
|
330 } else { |
|
331 target_element_name = ""; |
|
332 } |
|
333 /* src ghostpad relationship */ |
|
334 fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc, |
|
335 target_element_name, target_pad_name, element_name, |
|
336 pad_name); |
|
337 |
|
338 g_free (target_pad_name); |
|
339 if (target_element) { |
|
340 g_free (target_element_name); |
|
341 gst_object_unref (target_element); |
|
342 } |
|
343 gst_object_unref (target_pad); |
|
344 } |
|
345 } |
|
346 if (GST_IS_GHOST_PAD (peer_pad)) { |
|
347 if ((target_pad = |
|
348 gst_ghost_pad_get_target (GST_GHOST_PAD |
|
349 (peer_pad)))) { |
|
350 target_pad_name = |
|
351 debug_dump_make_object_name (GST_OBJECT |
|
352 (target_pad)); |
|
353 if ((target_element = |
|
354 gst_pad_get_parent_element (target_pad))) { |
|
355 target_element_name = |
|
356 debug_dump_make_object_name (GST_OBJECT |
|
357 (target_element)); |
|
358 } else { |
|
359 target_element_name = ""; |
|
360 } |
|
361 /* sink ghostpad relationship */ |
|
362 fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc, |
|
363 peer_element_name, peer_pad_name, |
|
364 target_element_name, target_pad_name); |
|
365 |
|
366 g_free (target_pad_name); |
|
367 if (target_element) { |
|
368 g_free (target_element_name); |
|
369 gst_object_unref (target_element); |
|
370 } |
|
371 gst_object_unref (target_pad); |
|
372 } |
|
373 } |
|
374 |
|
375 g_free (pad_name); |
|
376 g_free (element_name); |
|
377 g_free (peer_pad_name); |
|
378 if (peer_element) { |
|
379 g_free (peer_element_name); |
|
380 gst_object_unref (peer_element); |
|
381 } |
|
382 gst_object_unref (peer_pad); |
|
383 } |
588 } |
384 } |
589 gst_object_unref (pad); |
385 gst_object_unref (pad); |
590 break; |
386 break; |
591 case GST_ITERATOR_RESYNC: |
387 case GST_ITERATOR_RESYNC: |
592 gst_iterator_resync (pad_iter); |
388 gst_iterator_resync (pad_iter); |