GStreamer Pipeline startet nicht

Der Wolf

Erfahrenes Mitglied
Hallo Leute,

ich versuche gerade eine GStreamer Kette zu bauen und auf ihren Bus zu hören. Allerdings startet die Kette nicht, beziehungsweise ich schaffe es nicht, ihre einzelnen Kettenglieder zu verlinken.

Code:
#include <iostream>
#include <gst/gst.h>


int
main(int argc, char* argv[]) {

	gst_init(&argc, &argv);

	GMainLoop *loop = g_main_loop_new(NULL, FALSE);
	GstElement *pipeline = gst_pipeline_new("analyse");
	GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));

//	g_object_set(G_OBJECT(pipeline), "gst-debug-level", "2", NULL);

	GstElement *source = gst_element_factory_make("filesrc", "src");
	g_object_set(G_OBJECT(source), "location", argv[1], NULL);

//	GstElement *source = gst_element_factory_make("alsasrc", "src");
//	g_object_set(G_OBJECT(source), "device", "plug:hw:1", NULL);

	GstElement *decoder = gst_element_factory_make("decodebin", "decoder");

	GstElement *spectrum = gst_element_factory_make("spectrum", "spectrum");

	GstElement *queue = gst_element_factory_make("queue", "queue1");

	GstElement *audioconvert = gst_element_factory_make("audioconvert", "convert");
		
	GstElement *sink = gst_element_factory_make("alsasink", "sink");	


	gst_bin_add_many(GST_BIN(pipeline), source, decoder, audioconvert, queue, spectrum, sink, NULL);

	if (!gst_element_link_many(source, decoder, sink, NULL)) {
		std::cout << "Could not link all elements together." << std::endl;
		GstMessage *msg = gst_bus_poll(bus, GST_MESSAGE_ERROR, 0);
		if (msg) {
      GError *err = NULL;

      gst_message_parse_error (msg, &err, NULL);
      g_print ("ERROR: %s\n", err->message);
      g_error_free (err);
      gst_message_unref (msg);
		} else {
			std::cout << "No error message available." << std::endl;
		}
		return -1;
	} else {
		std::cout << "All linked together." << std::endl;
	}

	GstStateChangeReturn ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
	if (ret == GST_STATE_CHANGE_FAILURE) {
		GstMessage *msg;

    g_print ("Failed to start up pipeline!\n");

    /* check if there is an error message with details on the bus */
    msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
    if (msg) {
      GError *err = NULL;

      gst_message_parse_error (msg, &err, NULL);
      g_print ("ERROR: %s\n", err->message);
      g_error_free (err);
      gst_message_unref (msg);
		}
	}
  g_main_loop_run (loop);

  /* clean up */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);

}

Das müsste in etwa in der Kette:

Code:
gst-launch-0.10 filesrc location=<filelocation> ! decodebin ! alsasink

enden. Führe ich die Kette so auf der Kommandozeile aus, bekomme ich keine Probleme. Stelle ich sich im oben genannten Code zusammen bekomme, meckert er beim linken der einzelnen Glieder. Allerdings habe ich keine Ahnung wo da das Problem liegt, weil ich keine Fehlerausgaben oder Debugausgaben bekomme. Ich weiss, dass ich auf der Kommandozeile mit --gst-debug-level=2 mir Debugausgaben anzeigen lassen kann, allerdings weiss ich nicht, wie das oben im Code angegeben werden soll. Ich bin für jede Hilfe dankbar.

Gruß
Der Wolf
 
Hi.
Stelle ich sich im oben genannten Code zusammen bekomme, meckert er beim linken der einzelnen Glieder.
Wer meckert? Was meckert er?
Allerdings habe ich keine Ahnung wo da das Problem liegt, weil ich keine Fehlerausgaben oder Debugausgaben bekomme. Ich weiss, dass ich auf der Kommandozeile mit --gst-debug-level=2 mir Debugausgaben anzeigen lassen kann, allerdings weiss ich nicht, wie das oben im Code angegeben werden soll.
Es sollte ausreichen die GST_DEBUG Umgebungsvariable zu setzen. Siehe http://www.gstreamer.net/data/doc/gstreamer/head/gstreamer/html/gst-running.html

Gruß
 
Wer meckert? Was meckert er?

Etwas missverständlich ausgedrückt. Mit meckern meinte ich

Code:
gst_element_link_many(...)

liefert false zurück.

Es sollte ausreichen die GST_DEBUG Umgebungsvariable zu setzen.

Danke, das hat schonnmal weitergeholfen. Ich hatte bisher nur versucht das im Code direkt per g_object_set zu setzen.

\edit:

Ah. Dank der debug Ausgaben habe ich schonmal folgende Meldung gefunden:

0:00:00.300884621 4816 0x804f008 INFO GST_ELEMENT_PADS gstelement.c:884:gst_element_get_static_pad: no such pad 'src%d' in element "decoder"
0:00:00.300911476 4816 0x804f008 INFO GST_ELEMENT_PADS gstutils.c:979:gst_element_get_compatible_pad:<decoder> Could not find a compatible pad to link to sink:sink

Gruß
Der Wolf
 
Zuletzt bearbeitet:
Ok, ich habe es mittlerweile herausgefunden.
Anscheinend kann man das decodebin nicht so einfach in die Kette einfügen. Hier mal der neue Code, mit dem es bei mir funktioniert.

C:
#include <iostream>
#include <gst/gst.h>

GstElement *audio;

static gboolean 
callback(GstBus *bus, GstMessage *msg, gpointer data) {

	if (msg->type == GST_MESSAGE_ELEMENT) {

		const GstStructure *s = gst_message_get_structure(msg);
		const gchar *name = gst_structure_get_name(s);		
		
		if (strcmp(name, "spectrum") == 0) {
			std::cout << "New spectrum received." << std::endl;
    }

	}

	return true;

}

static void
cb_newpad (GstElement *decodebin,
	   GstPad     *pad,
	   gboolean    last,
	   gpointer    data) {
  GstCaps *caps;
  GstStructure *str;
  GstPad *audiopad;

  /* only link once */
  audiopad = gst_element_get_static_pad (audio, "sink");
  if (GST_PAD_IS_LINKED (audiopad)) {
    g_object_unref (audiopad);
    return;
  }

  /* check media type */
  caps = gst_pad_get_caps (pad);
  str = gst_caps_get_structure (caps, 0);
  if (!g_strrstr (gst_structure_get_name (str), "audio")) {
    gst_caps_unref (caps);
    gst_object_unref (audiopad);
    return;
  }
  gst_caps_unref (caps);

  /* link'n'play */
  gst_pad_link (pad, audiopad);

  g_object_unref (audiopad);
}



int
main(int argc, char* argv[]) {

	gst_init(&argc, &argv);

	GMainLoop *loop = g_main_loop_new(NULL, FALSE);
	GstElement *pipeline = gst_pipeline_new("analyse");
	GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
	gst_bus_add_watch(bus, callback, loop);

	// Creating audio src bin.	
	GstElement *source = gst_element_factory_make("filesrc", "src");
	GstElement *decoder = gst_element_factory_make("decodebin", "decoder");
	g_signal_connect (decoder, "new-decoded-pad", G_CALLBACK (cb_newpad), NULL);

	g_object_set(G_OBJECT(source), "location", argv[1], NULL);

	gst_bin_add_many(GST_BIN(pipeline), source, decoder, NULL);
	gst_element_link(source, decoder);

	// Creating audio output.
	audio = gst_bin_new ("audiobin");
	GstElement *spectrum = gst_element_factory_make("spectrum", "spectrum");
  GstElement *conv = gst_element_factory_make ("audioconvert", "aconv");
  GstPad *audiopad = gst_element_get_static_pad (conv, "sink");
  GstElement *sink = gst_element_factory_make ("alsasink", "sink");
  gst_bin_add_many (GST_BIN(audio), spectrum, conv, sink, NULL);
  gst_element_link_many (conv, spectrum, sink);
  gst_element_add_pad(audio, gst_ghost_pad_new ("sink", audiopad));
  gst_object_unref (audiopad);
  gst_bin_add (GST_BIN (pipeline), audio);

	/* run */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  g_main_loop_run (loop);

  /* cleanup */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (GST_OBJECT (pipeline));

  return 0;

}

Ich bin im Developer-Part der GStreamer Dokumentation auf die Lösung gestoßen (bitte keinen Kommentar -.- ;) ). Die Kette enthält jetzt zusätzlich auch noch ein plugin das das Spektrum des Signals analysiert und das Ergebnis auf dem Bus published.

Gruß
Der Wolf
 

Neue Beiträge

Zurück