tee branches with different sample rates

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

tee branches with different sample rates

t.loeffler3
Hi everyone, I'm writing a little gstreamer-based application in Python and
I'm currently stuck at properly constructing my pipeline. I'm using playbin2
with a custom audio-sink to be able to insert an equalizer into my pipeline.
Now I'd like to do some analysis of the data that passes through my pipeline
and for that I'm using a tee element in combination with an appsink. The basic
setup for this works fine. However, I'm having trouble negotiating the format
for my appsink.

Basically I'd like the data that arrives at my autoaudiosink to be unchanged
(i.e. just forward the output of the equalizer element which gets its data from
the playbin2) and perform resampling in my analysis branch to ensure a
sampling rate of 8 kHz. I thought that since since the caps property was only
set for an element in the analysis branch the branch with the autoaudiosink
would be unaffected which turns out to be wrong. The format is correct in the
analysis branch, i.e. the output of the new_buffer callback is

audio/x-raw-float, endianness=(int)1234, channels=(int)2, width=(int)32, depth=(int)32, signed=(boolean)true, rate=(int)8000

However, it's clearly audible that the sampling rate is in fact 8 kHz as well
in the autoaudiosink branch. Here's the stripped down code I use to construct
the pipeline.

def __init_pipeline(self):
    bin = gst.Bin()

    equalizer = gst.element_factory_make("equalizer-10bands")

    tee = gst.element_factory_make("tee")
    queue_vis = gst.element_factory_make("queue")
    queue_vis.set_property("max_size_time", 1500 * gst.MSECOND)

    caps = gst.Caps(
        """
        audio/x-raw-float,
        endianness=(int)1234,
        channels=(int)2,
        width=(int)32,
        depth=(int)32,
        signed=(boolean)true,
        rate=(int)8000
        """
    )
    appsink = gst.element_factory_make("appsink")
    appsink.set_property("drop", True)
    appsink.set_property("sync", False)
    appsink.set_property("emit_signals", True)
    def pull(sink): print sink.emit("pull_buffer").get_caps()
    appsink.connect("new_buffer", pull)
    appsink.set_property("caps", caps)

    queue_player = gst.element_factory_make("queue")
    queue_player.set_property("max_size_time", 500 * gst.MSECOND)
    sink = gst.element_factory_make("autoaudiosink")

    elements = [equalizer, tee, queue_vis, appsink, queue_player, sink]
    map(bin.add, elements)

    pad = elements[0].get_static_pad("sink")
    bin.add_pad(gst.GhostPad("sink", pad))

    gst.element_link_many(self.__equalizer, tee)
    gst.element_link_many(tee, queue_player, sink)
    gst.element_link_many(tee, queue_vis, appsink)

    playbin = gst.element_factory_make("playbin2")
    playbin.set_property("audio_sink", bin)
    playbin.set_property("video_sink", None)
   
How can I ensure that the data is only converted in my analysis branch? I tried
adding an audioconvert element before the appsink as well to no avail. It seems
like specifying the caps property of the appsink causes an upstream conversion
of the data if that makes sense.

I'd really appreciate the help.
Kind regards, Klaus