I'm trying to get 28 channels out of a jackaudiosrc
but as soon
as I connect, say, a deinterleave
element, the source will fall back to
the 2-channel setup that works without any channel mask. My attempts at
setting a channel mask have been futile.
Here's what happens:
potential caps: audio/x-raw-float, endianness=(int)1234, width=(int)32, rate=(int)48000, channels=(int)[ 1, 28 ]
filter caps: audio/x-raw-float, channels=(int)28, channel-positions=(GstAudioChannelPosition)< GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE >
actual caps: audio/x-raw-float, endianness=(int)1234, width=(int)32, rate=(int)48000, channels=(int)2, channel-positions=(GstAudioChannelPosition)< GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT >
And here's the Python code that produces that output:
import pygst
pygst.require("0.10")
import gst
import gobject
import gst.audio
gobject.threads_init()
pipeline = gst.Pipeline("mypipeline")
src = gst.element_factory_make("jackaudiosrc", "jacksrc")
pipeline.add(src)
srcpad = src.get_pad("src")
pipeline.set_state(gst.STATE_PLAYING)
print 'potential caps:',srcpad.get_caps()
sink = gst.element_factory_make("fakesink", "sink")
pipeline.add(sink)
filtercaps = gst.caps_from_string("audio/x-raw-float,channels=28")
filtercaps[0].set_value("channel-positions", tuple([gst.audio.AUDIO_CHANNEL_POSITION_NONE]*28))
print "filter caps:",filtercaps
src.link_filtered(sink, filtercaps)
pipeline.set_state(gst.STATE_PLAYING)
print 'actual caps:',srcpad.get_negotiated_caps()
#gst.DEBUG_BIN_TO_DOT_FILE_WITH_TS(pipeline, gst.DEBUG_GRAPH_SHOW_ALL, 'caps')
I also tried to set the caps of the output directly instead of using a filter but that didn't do anything either.
Here's the output of that last bin-to-dot-file line (click to enlarge).
Here's a gst-launch
line that works without an actual multichannel audio setup but does not actually reproduce the error, I believe because the interleave
element sets the NONE caps correctly by default while the jackaudiosrc
doesn't. Maybe it still helps people to play around with this issue who can't reproduce it themselves because of technical restrictions. Credit to http://tristanswork.blogspot.de/2008/08/multichannel-audio-with-gstreamer.html for the original launch line that I adapted.
gst-launch-0.10 interleave name=i ! audioconvert ! audioresample ! queue ! deinterleave name=o audiotestsrc ! audioconvert ! queue ! i. audiotestsrc ! audioconvert ! queue ! i. audiotestsrc ! audioconvert ! queue ! i. o. ! queue ! fakesink dump=true o. ! queue ! fakesink dump=true o. ! queue ! fakesink dump=true
Edit: I now tried to do the same thing in GStreamer 1.x. The tuple
data type is no longer accepted so here's what I came up with after having a look at others wrote channel positions directly to the get_caps_from_string
function.
from gi.repository import GObject, Gst, GstAudio
GObject.threads_init()
Gst.init(None)
pipeline = Gst.Pipeline("mypipeline")
src = Gst.ElementFactory.make("jackaudiosrc", "jacksrc")
pipeline.add(src)
srcpad = src.get_static_pad("src")
pipeline.set_state(Gst.State.PLAYING)
print 'potential caps:', srcpad.query_caps()
sink = Gst.ElementFactory.make("fakesink", "sink")
pipeline.add(sink)
filtercaps = Gst.caps_from_string("audio/x-raw, channels=(int)28, channel-positions=(int)< 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 >")
print "filter caps:", filtercaps
src.link_filtered(sink, filtercaps)
pipeline.set_state(Gst.State.PLAYING)
print 'actual caps:', srcpad.get_current_caps()
Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, 'caps')
The output both in text form and the graph are shockingly similar:
potential caps: audio/x-raw, format=(string)F32LE, layout=(string)interleaved, rate=(int)48000, channels=(int)[ 1, 28 ]
filter caps: audio/x-raw, channels=(int)28, channel-positions=(int)< 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 >
actual caps: audio/x-raw, format=(string)F32LE, layout=(string)interleaved, rate=(int)48000, channels=(int)2