Gstreamer+python: добавление и удаление источников звука во время работы пайплайна

Я работаю над образцом скрипта python, первоначально найденным здесь: Добавление и удаление источников звука в/из конвейера GStreamer на ходу. Цель состоит в том, чтобы создать сценарий, подобный приведенному выше, способный вставлять и удалять источники звука во время работы конвейера, но с элементом аудиопреобразования между источником и сумматором. . Это связано с тем, что в более общем случае Adder хочет, чтобы входящие потоки были одного формата.

Итак, вот код; создаем 2 генератора (зуммера). Первый издает тон 1000 Гц и ожидает возврата клавиши. Второй тон 500 Гц, который суммируется с первым после нажатия клавиши. Опять же, по нажатию клавиши возврата слышен только второй генератор.

#!/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.")

Если вы используете create_raw_audiotest_signal вместо create_audiotest_signal_with_converter в обоих вызовах, конечно, это работает. Если вы используете смесь из двух, это работает, но с нежелательной дополнительной задержкой между ними. Самый интересный случай, когда вы используете audioconvert в обоих вызовах, но gtk блокируется на первом ключе возврата.

У кого-нибудь есть предложения? Что я делаю неправильно? Заранее спасибо.


person user1048335    schedule 15.11.2011    source источник


Ответы (1)


Я нашел ответ сам, это было действительно просто... Я добавил другие компоненты, но они живут в конвейере и продолжают иметь статус независимой игры. Таким образом, решение настраивает весь конвейер на воспроизведение, что, в свою очередь, устанавливает статус для всех дочерних элементов.

pipe.set_state(gst.STATE_PLAYING)

вместо:

buzzer2.set_state(gst.STATE_PLAYING)

и он снова работает.

person user1048335    schedule 16.11.2011