GNOME Bugzilla – Bug 642274
[playbin2] arbitrary audio-sink is chosen even though explicitely having set a custom audio-sink bin
Last modified: 2011-05-09 10:00:02 UTC
Created attachment 180805 [details] debug log this issue showed up when trying to circumvent the issue https://bugzilla.gnome.org/show_bug.cgi?id=632788 (movies that contain multiple audio streams out of which some can be decoded by dvbaudiosink (mpeg hardware decoder sink) and some cannot - for example one AC3 and one vorbis stream) by doing something like this in the code: if ( m_gst_audiobin ) { GstElement *dvbaudiosink = gst_element_factory_make("dvbaudiosink", "dvbaudiosink"); int ret = gst_bin_add(GST_BIN(m_gst_audiobin), dvbaudiosink); GstPad *dvbaudiosinkpad = gst_element_get_static_pad(dvbaudiosink, "sink"); GstCaps *dvbaudiosinkcaps = gst_caps_copy(gst_pad_get_pad_template_caps (dvbaudiosinkpad)); GstCaps* decodebincaps = gst_caps_from_string("audio/x-vorbis; audio/x-flac; audio/x-wav; audio/x-raw-int"); gst_caps_merge(decodebincaps, dvbaudiosinkcaps); eDebug("after merge: decodebincaps = %s", gst_caps_to_string(decodebincaps)); GstPad *universal_audiosinkpad = gst_ghost_pad_new_no_target_from_template("sink", gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, decodebincaps)); gst_element_add_pad (m_gst_audiobin, universal_audiosinkpad); // GstElement *decodebin = gst_element_factory_make("decodebin", "decodebin"); // GstElement *audioconvert = gst_element_factory_make("audioconvert", "audioconvert"); // GstElement *alsasink = gst_element_factory_make("alsasink", "alsasink"); GstElement *fakesink = gst_element_factory_make("fakesink", "audio_fakesink"); // gst_bin_add_many(GST_BIN(m_gst_audiobin), dvbaudiosink, decodebin, audioconvert, alsasink, NULL); gst_bin_add(GST_BIN(m_gst_audiobin), fakesink); // int ret = gst_element_link_many(decodebin, audioconvert, alsasink, NULL); // gst_ghost_pad_set_target (GST_GHOST_PAD(universal_audiosinkpad), gst_element_get_static_pad(fakesink, "sink")); g_object_set (G_OBJECT (m_gst_playbin), "audio-sink", m_gst_audiobin, NULL); g_signal_connect (G_OBJECT (universal_audiosinkpad), "notify::caps", G_CALLBACK (gstGhostpadHasCAPS), this); } and then down below in the hascaps function doing this: eDebug("gstGhostpadHasCAPS:: AUDIO signal::caps = %s", gst_caps_to_string(caps)); GstPad *dvbaudiosinkpad = gst_element_get_static_pad(gst_bin_get_by_name(GST_BIN(this->m_gst_audiobin), "dvbaudiosink"), "sink"); GstCaps *dvbaudiosinkcaps; dvbaudiosinkcaps = gst_caps_copy(gst_pad_get_pad_template_caps (dvbaudiosinkpad)); eDebug("dvbaudiosink's caps = %s", gst_caps_to_string(dvbaudiosinkcaps)); int ret = gst_caps_is_subset(caps, dvbaudiosinkcaps); eDebug("gst_caps_is_subset = %i", ret); if ( ret == 1 ) { int r = gst_ghost_pad_set_target (GST_GHOST_PAD(pad), dvbaudiosinkpad); eDebug("setting ghostpad target to dvbaudiosinkpad@%p returns %i", dvbaudiosinkpad, r); } else { // GstPad *decodebinpad = gst_element_get_static_pad(gst_bin_get_by_name(GST_BIN(this->m_gst_audiobin), "decodebin"), "sink"); GstPad *decodebinpad = gst_element_get_static_pad(gst_bin_get_by_name(GST_BIN(this->m_gst_audiobin), "audio_fakesink"), "sink"); int r = gst_ghost_pad_set_target (GST_GHOST_PAD(pad), decodebinpad); eDebug("setting ghostpad target to decodebinpad@%p returns %i", decodebinpad, r); } the idea behind this is that any type of stream can be directed from playbin2 into one single sink pad and the audio bin will automatically determine whether the stream can be decoded by hardware or requires a software decoder and will set the target of the ghostbin accordingly. now to cut to the chase: as per debug log, the custom audiobin with its seperate elements and the ghost are created correctly, and playbin2 also accepts the custom audio-sink property change. afterwards though, it ignores that and creates another dvbaudiosink element which it tries to use as a sink element. this leads to the problems described in 632788 because the sink can't handle the vorbis stream. line 5297 shows that another dvbaudiosink is created then starting at 9326 it goes into a loop with a message: playbin2 gstplaybin2.c:1851:gst_play_bin_get_current_sink:<playbin> play_sink_get_sink() returned audio sink <dvbaudiosink0>, the originally set audio sink is <universal_audiobin>
Created attachment 180807 [details] debug log of a file with a vorbis stream
Created attachment 180813 [details] debug log when setting the universal_audiobin explicitely to playing
Created attachment 180963 [details] testcase app run with movie uri as command line parameter e.g. bug642274_universal_audiobin file:///media/hdd/movie/mkv/Monster.Inc.mkv in the code, a universal audiobin is created with a capsfilter supposedly accepting any caps and a fakesink linked to it. a ghostpad targeting to the capsfilter is configured to be playbin2's audio-sink playbin2 creates another audiosink (in my case dvbaudiosink0) and ignores the universal_audiobin
on the pc this app plugs a dtsdec element instead of using the universal_audiobin
Created attachment 181014 [details] testcase app Small cleanups. The test works for me though.
Created attachment 181015 [details] debug log it will try plugging the dvbaudiosink no matter what... on the pc this plays (without sound as expected) because dtsdec and vorbisdec are both present and all ends up in one sink which can handle everything but on the embedded arch, with missing dtsdec it fails to preroll
To make that more obvious, you could set specific caps on the capsfilter. The problem here is that playbin2 does not manage the autoplug-continue on decodebin2. This could be what the patch in bug #642433 is doing.
Created attachment 181021 [details] this testcase sets the correct caps and leads to problems on both pc and mips caps for universal audiobin:= audio/x-dts; audio/x-vorbis ERROR: from element /GstPlayBin2:playbin20/GstPlaySink:playsink0: Internal GStreamer error: pad problem. Please file a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer. Additional debug info: gstplaysink.c(1801): gen_audio_chain (): /GstPlayBin2:playbin20/GstPlaySink:playsink0: Failed to configure the audio sink.
Created attachment 181110 [details] sets correct caps and supposedly switches sink elements depending on the stream caps
I think that playsink classifies the pipeline's output into raw and non-raw, and find/connect separate sink bins. I wonder if your universal_audio_bin was filtered out by playsink for the caps problem or state changing or something else, if so, playsink would create by itself a new compatible sink (which is a dvbaudiosink in this case) for non-raw outputs. In addition, if universal-audio-bin was tried to be used for raw-output sinks but failed, then the vorbis output chain would also fail. I couldn't find in you debug log the message "Setting sinks <universal_audio_bin0> for raw audio-output, just found dvbaudiosink0 for non-raw audio, dvbvideosink0 for non-raw video, subtitle_bin for subtitle. thus, if playsink (and universal-audiobin) has something to do with the problem, then the bug #642433 may be unrelated.
Created attachment 181233 [details] debug log GST_DEBUG_NO_COLOR=1 GST_DEBUG=*:5 gst-launch ./bug642274_universal_audiobin_ver2 file:///hdd/movie/mkv/Monster.Inc.mkv > bug642274_2 0110218.log 2>&1 with git checkout from today
Created attachment 181235 [details] debug log GST_DEBUG_NO_COLOR=1 GST_DEBUG=*:5 ./bug642274_universal_audiobin_ver2 file:///hdd/movie/mkv/Monster.Inc.mkv >bug642274_20110218.log 2>&1 with git checkout from today
with latest git head, the issue seems fixed! thanks ensonic & slomo!!