Reputation: 61
I'm working on a sample python script, originally found here: Adding and removing audio sources to/from GStreamer pipeline on-the-go. The aim is to make a script such as the one above, able to insert and remove audio sources while the pipeline is running but with an audioconvert element between the source and the adder. This is because in a more general case Adder wants the incoming streams to be of the same format.
So here's the code; we create 2 generators (buzzers). The first emits a 1000Hz tone and waits for a return key. The second is a 500Hz tone, which is summed to the first one after the key press. Again, by pressing the return key, only the second generator is heard.
#!/usr/bin/python
import gobject;
gobject.threads_init()
import gst
# THE FOLLOWING FUNCTION IS A REWORK OF THE ORIGINAL, STILL DOING THE JOB
def create_raw_audiotest_signal(pipe, freq, adder):
# create buzzer of a given freq
buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
buzzer.set_property("freq",freq)
pipe.add(buzzer)
buzzersrc=buzzer.get_pad("src")
# Gather a request sink pad on the mixer
sinkpad=adder.get_request_pad("sink%d")
# .. and connect it to the buzzer
buzzersrc.link(sinkpad)
return buzzer, buzzersrc, sinkpad
# THIS IS A MODIFIED VERSION, NOT WORKING, THAT JUST PUTS AN AUDIOCONVERT
# ELEMENT BETWEEN THE GENERATOR AND THE ADDER.
def create_audiotest_signal_with_converter(pipe, freq, adder):
# create buzzer of a given freq
buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
buzzer.set_property("freq",freq)
# add a converter because adder wants inputs with the same format.
ac = gst.element_factory_make("audioconvert", "ac%d" % freq)
pipe.add(buzzer, ac)
# link the buzzer with the converter ...
buzzer.link(ac)
buzzersrc=buzzer.get_pad("src")
# Gather a request sink pad on the mixer
sinkpad=adder.get_request_pad("sink%d")
# and then the converter to the adder
ac.get_pad('src').link(sinkpad)
return buzzer, buzzersrc, sinkpad
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)
# Create the first buzzer..
#buzzer1, buzzersrc1, sinkpad1 = create_raw_audiotest_signal(pipe, 1000, adder)
buzzer1, buzzersrc1, sinkpad1 = create_audiotest_signal_with_converter(pipe, 1000, adder)
# 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 another generator
#buzzer2, buzzersrc2, sinkpad2 = create_raw_audiotest_signal(pipe, 500, adder)
buzzer2, buzzersrc2, sinkpad2 = create_audiotest_signal_with_converter(pipe, 500, adder)
# 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(sinkpad2)
# 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 use create_raw_audiotest_signal in place of create_audiotest_signal_with_converter in both the calls of course it works. If you use a mixture of the two, it works, but with an unwanted extra delay inbetween. The most interesting case is when you use the audioconvert in both the calls, but gtk blocks at the first return key.
Does anybody have any suggestion? What am I doing wrong? Thank you in advance.
Upvotes: 4
Views: 3057
Reputation: 61
I found the answer myself, it was simple indeed... I added other components, but they live in the pipeline and keep having an independent play status. So the solution is set all the pipeline to playing, which in turn sets the status to all the children.
pipe.set_state(gst.STATE_PLAYING)
instead of:
buzzer2.set_state(gst.STATE_PLAYING)
and it works again.
Upvotes: 2