I wrote a little Python script which uses an Adder
plugin to mix two source streams together.
After starting the program, you hear a 1kHz tone generated by the audiotestsrc
plugin. When you press Enter, an another 500Hz test tone is connected to the Adder
so you hear them together. (By the way, i don't really get why should i set the pipeline again to playing state here to hear the mix. Is there any way i can plug in new sources without having to restart the pipeline?)
When you press Enter once again, the 1kHz tone should be removed from the mix and the 500Hz tone should keep playing, but instead i hear nothing anymore. I get a pulse pulsesink.c:528:gst_pulsering_stream_underflow_cb:<pulseaudio_output> Got underflow
in the debug output as the last line. I don't really know what to try next.
Here is the full source code:
#!/usr/bin/python
# On-the-go source removal doesn't work this way with GStreamer. Why?
import gobject;
gobject.threads_init()
import gst;
if __name__ == "__main__":
pipe = gst.Pipeline("mypipe")
adder = gst.element_factory_make("adder","audiomixer")
pipe.add(adder)
buzzer = gst.element_factory_make("audiotestsrc","buzzer")
buzzer.set_property("freq",1000)
pipe.add(buzzer)
pulse = gst.element_factory_make("pulsesink", "pulseaudio_output")
pipe.add(pulse)
buzzer.link(adder)
adder.link(pulse)
pipe.set_state(gst.STATE_PLAYING)
raw_input("1kHz test sound. Press <ENTER> to continue.")
buzzer2=gst.element_factory_make("audiotestsrc","buzzer2")
buzzer2.set_property("freq",500)
pipe.add(buzzer2)
buzzer2.link(adder)
pipe.set_state(gst.STATE_PLAYING)
raw_input("1kHz + 500Hz test sound playing simoultenously. Press <ENTER> to continue.")
buzzer.unlink(adder)
pipe.set_state(gst.STATE_PLAYING)
raw_input("Only 500Hz test sound. Press <ENTER> to stop.")
I've found the solution on my own. I had to use request pads with Adder
and use the pad blocking capability of GStreamer.
Here's the working source code with some descriptions:
#!/usr/bin/python
import gobject;
gobject.threads_init()
import gst;
if __name__ == "__main__":
# First create our pipeline
pipe = gst.Pipeline("mypipe")
# Create a software mixer with "Adder"
adder = gst.element_factory_make("adder","audiomixer")
pipe.add(adder)
# Gather a request sink pad on the mixer
sinkpad1=adder.get_request_pad("sink%d")
# Create the first buzzer..
buzzer1 = gst.element_factory_make("audiotestsrc","buzzer1")
buzzer1.set_property("freq",1000)
pipe.add(buzzer1)
# .. and connect it's source pad to the previously gathered request pad
buzzersrc1=buzzer1.get_pad("src")
buzzersrc1.link(sinkpad1)
# Add some output
output = gst.element_factory_make("autoaudiosink", "audio_out")
pipe.add(output)
adder.link(output)
# Start the playback
pipe.set_state(gst.STATE_PLAYING)
raw_input("1kHz test sound. Press <ENTER> to continue.")
# Get an another request sink pad on the mixer
sinkpad2=adder.get_request_pad("sink%d")
# Create an another buzzer and connect it the same way
buzzer2 = gst.element_factory_make("audiotestsrc","buzzer2")
buzzer2.set_property("freq",500)
pipe.add(buzzer2)
buzzersrc2=buzzer2.get_pad("src")
buzzersrc2.link(sinkpad2)
# Start the second buzzer (other ways streaming stops because of starvation)
buzzer2.set_state(gst.STATE_PLAYING)
raw_input("1kHz + 500Hz test sound playing simoultenously. Press <ENTER> to continue.")
# Before removing a source, we must use pad blocking to prevent state changes
buzzersrc1.set_blocked(True)
# Stop the first buzzer
buzzer1.set_state(gst.STATE_NULL)
# Unlink from the mixer
buzzersrc1.unlink(sinkpad1)
# Release the mixers first sink pad
adder.release_request_pad(sinkpad1)
# Because here none of the Adder's sink pads block, streaming continues
raw_input("Only 500Hz test sound. Press <ENTER> to stop.")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With