Gstreamer + python: adding and removing sound sources while the pipeline is running

I am working on a sample python script originally found here: Adding and removing sound sources to / from the GStreamer on-go pipeline . The goal is to make a script, for example, higher, capable of inserting and deleting audio sources while the pipeline is running , but with audio encoding 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 is the code; we create 2 generators (buzzers). The first emits a 1000 Hz tone and waits for a return. The second is a 500 Hz tone, which is added to the first after pressing a key. Again, by pressing the return key, only the second generator will be 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 sink pads block, streaming continues raw_input("Only 500Hz test sound. Press <ENTER> to stop.") 

If you use create_raw_audiotest_signal instead of create_audiotest_signal_with_converter in both calls, of course, this works. If you use a mixture of the two, this works, but with an undesirable additional delay between them. The most interesting case is when you use the audio converter in both calls, but gtk blocks with the first return key.

Does anyone have any suggestions? What am I doing wrong? Thank you in advance.

+4
source share
1 answer

I myself found the answer, it was just ... I added other components, but they live in the pipeline and continue to have independent game status. Thus, the solution sets the entire conveyor for playback, which, in turn, sets the status for all children.

pipe.set_state (gst.STATE_PLAYING)

instead:

buzzer2.set_state (gst.STATE_PLAYING)

and it works again.

+2
source

Source: https://habr.com/ru/post/1381370/


All Articles