summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cameron <Brian.Cameron@Sun.COM>2008-08-29 00:00:35 -0500
committerLennart Poettering <lennart@poettering.net>2008-08-29 21:11:38 +0200
commit132428efdd117a182dec90f457a286abf1201d9f (patch)
treea5c0b1866e55a2d9607081cf9b29c4e33a0f1867
parenteae317c6cd39f46508bd0e4855c822660a329246 (diff)
include audioconvert, audioconfig in GStreamer pipeline
> Brian, I will release libcanberra 0.8 shortly. If you want to make > sure that the Gst driver works fine on solaris before I do the > release, please test quickly! Sorry I was not able ot test before the release. I just tested, and I found it doesn't work for two reasons. One reason I fixed in the attached patch. On Solaris, it is necessary to include "audioconvert ! audioconfig" in the GStreamer pipeline. This is needed to ensure that GStreaner "just works" with sink plugins that may not implement the full range of possible output that can come out of decodebin. The attached patch fixes this. Totem, rhythmbox, and other GStreamer based programs use similar logic. Before the above fix, GStreamer would just hang, which would also happen with the gst-launch command if you ran it with a similar pipeline without "audioconvert". Brian Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com> Signed-off-by: Lennart Poettering <lennart@poettering.net>
-rw-r--r--src/gstreamer.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/gstreamer.c b/src/gstreamer.c
index a294378..2e0dba5 100644
--- a/src/gstreamer.c
+++ b/src/gstreamer.c
@@ -213,7 +213,7 @@ static GstBusSyncReply bus_cb(GstBus *bus, GstMessage *message, gpointer data) {
case GST_MESSAGE_ERROR:
err = CA_ERROR_SYSTEM;
break;
- /* only from bin */
+ /* only from bin */
case GST_MESSAGE_EOS:
if (GST_OBJECT(out->pipeline) != GST_MESSAGE_SRC(message))
return GST_BUS_DROP;
@@ -286,22 +286,38 @@ static int ca_gst_sound_file_open(ca_sound_file **_f, const char *fn) {
static void on_pad_added(GstElement *element, GstPad *pad, gboolean arg1, gpointer data)
{
- GstPad *sinkpad;
- GstElement *sink = GST_ELEMENT (data);
-
- sinkpad = gst_element_get_static_pad (sink, "sink");
-
- gst_pad_link (pad, sinkpad);
+ GstStructure *structure;
+ GstElement *sinkelement;
+ GstCaps *caps;
+ GstPad *vpad;
+ const char *type;
+
+ sinkelement = (GstElement *)data;
+
+ caps = gst_pad_get_caps (pad);
+ if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
+ gst_caps_unref (caps);
+ return;
+ }
- gst_object_unref (sinkpad);
+ structure = gst_caps_get_structure (caps, 0);
+ type = gst_structure_get_name (structure);
+ if (g_str_has_prefix (type, "audio/x-raw") == TRUE) {
+ vpad = gst_element_get_pad (sinkelement, "sink");
+ gst_pad_link (pad, vpad);
+ gst_object_unref (vpad);
+ }
+ gst_caps_unref (caps);
}
int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_callback_t cb, void *userdata) {
struct private *p;
struct outstanding *out = NULL;
ca_sound_file *f;
- GstElement *decodebin, *sink;
+ GstElement *decodebin, *sink, *audioconvert, *audioresample, *bin;
GstBus *bus;
+ GstPad *audiopad;
+ GstPad *pad;
int ret;
ca_return_val_if_fail(c, CA_ERROR_INVALID);
@@ -327,26 +343,42 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
if (!(out->pipeline = gst_pipeline_new(NULL))
|| !(decodebin = gst_element_factory_make("decodebin2", NULL))
+ || !(audioconvert = gst_element_factory_make("audioconvert", NULL))
+ || !(audioresample = gst_element_factory_make("audioresample", NULL))
|| !(sink = gst_element_factory_make("autoaudiosink", NULL))) {
ret = CA_ERROR_OOM;
goto fail;
}
+ bin = gst_bin_new ("audiobin");
+
+ g_signal_connect (decodebin, "new-decoded-pad", G_CALLBACK (on_pad_added), bin);
+
bus = gst_pipeline_get_bus(GST_PIPELINE (out->pipeline));
gst_bus_set_sync_handler(bus, bus_cb, out);
gst_object_unref(bus);
gst_bin_add_many(GST_BIN (out->pipeline),
- f->fdsrc, decodebin, sink, NULL);
+ f->fdsrc, decodebin, NULL);
if (!gst_element_link(f->fdsrc, decodebin)) {
f->fdsrc = NULL;
decodebin = NULL;
+ audioconvert = NULL;
+ audioresample = NULL;
sink = NULL;
goto fail;
}
- g_signal_connect (decodebin, "new-decoded-pad", G_CALLBACK (on_pad_added), sink);
+ gst_bin_add_many (GST_BIN (bin), audioconvert, audioresample, sink, NULL);
+ gst_element_link_many (audioconvert, audioresample, sink, NULL);
+
+ audiopad = gst_element_get_pad (audioconvert, "sink");
+ gst_element_add_pad (bin, gst_ghost_pad_new ("sink", audiopad));
+
+ gst_object_unref (audiopad);
+
+ gst_bin_add (GST_BIN (out->pipeline), bin);
decodebin = NULL;
sink = NULL;
@@ -368,7 +400,7 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
return CA_SUCCESS;
- fail:
+fail:
if (f && f->fdsrc)
gst_object_unref(f->fdsrc);
@@ -381,7 +413,7 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
if (decodebin)
gst_object_unref(decodebin);
- if (out->pipeline)
+ if (out && out->pipeline)
gst_object_unref(out->pipeline);
ca_free(out);