LINUX.ORG.RU

gstreamer rtp через appsrc

 , , ,


0

1

Есть один пайплайн:

Gst.parse_launch('udpsrc address=127.0.0.1 port=5000 caps="application/x-rtp" ! queue ! rtppcmudepay ! queue ! autoaudiosink')

шлю ему пакеты rtp по udp и норм. Но нужно убрать лишний шаг udp, и пихать ему пакеты вызовом функции как-то. догуглился до такого:

source = Gst.ElementFactory.make("appsrc", "mysrc")
bin = Gst.parse_launch(f'appsrc caps=application/x-rtp name=mysrc  ! queue  ! rtppcmudepay ! queue ! autoaudiosink')

и пихаю пакеты через

source.emit('push-buffer', Gst.Buffer.new_wrapped(buf)).

но звука уже не слышу. Ошибок тоже не выдаёт. Вижу что график пайплайна отличается:

рабочий: https://i.stack.imgur.com/NIsD1.png

нерабочий: https://i.stack.imgur.com/sSk1d.png

Но причину отличия понять не могу…

Теперь пытаюсь вообще хоть как-то приручить appsink/appsrc.

Вот например успешно шлю туда-сюда звук от audiotestsrc через udpsink-udpsrc:

import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
Gst.init()
pipe1=Gst.parse_launch('audiotestsrc ! audioconvert ! audioresample ! mulawenc ! rtppcmupay ! udpsink host=127.0.0.1 port=5001')
pipe2=Gst.parse_launch('udpsrc port=5001 caps="application/x-rtp,media=audio,payload=0,clock-rate=8000,encoding-name=PCMU" ! rtppcmudepay ! mulawdec ! audioconvert ! autoaudiosink sync=false')
pipe1.set_state(Gst.State.PLAYING)
pipe2.set_state(Gst.State.PLAYING)
input()

Пытаюсь сделать ровно то же через appsink-appsrc - начинается сущий ад. Скрипт:

import os
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
Gst.debug_set_active(True)
Gst.debug_set_default_threshold(2)
Gst.init()

def _on_sender_sink_new_sample(sink):
    buf = sink.emit('pull-sample').get_buffer()
    # feed to receiver_src
    receiver_src.emit('push-buffer', buf)
    return Gst.FlowReturn.OK

def _on_gst_message(_bus: Gst.Bus, message: Gst.Message) -> None:
    if message.get_structure() is not None:
        print(message.get_structure().to_string())

caps=Gst.Caps.from_string('application/x-rtp,media=audio,payload=0,clock-rate=8000,encoding-name=PCMU')
# sender
sender_pipeline=Gst.Pipeline()
sender_sink = Gst.ElementFactory.make("appsink", "myappsink")
sender_sink.props.emit_signals = True
sender_sink.connect('new-sample', _on_sender_sink_new_sample)
sender_sink.props.sync = True
sender_sink.props.drop = True
sender_sink.props.wait_on_eos = False

sender_source=Gst.parse_bin_from_description('audiotestsrc ! audioconvert ! audioresample ! mulawenc ! rtppcmupay', True)
sender_source.caps=caps
sender_pipeline.add(sender_source)
sender_pipeline.add(sender_sink)
sender_source.link(sender_sink)

# receiver
receiver_pipeline=Gst.Pipeline()
receiver_src= Gst.ElementFactory.make("appsrc", "myappsrc")
receiver_src.caps=Gst.caps
receiver_src.do_timestamp = True
receiver_src.format = Gst.Format.TIME
receiver_src.props.is_live = True
receiver_src.sync=True

receiver_sink=Gst.parse_bin_from_description('rtppcmudepay ! mulawdec ! audioconvert ! alsasink', True)

receiver_pipeline.add(receiver_src)
receiver_pipeline.add(receiver_sink)
receiver_src.link(receiver_sink)

Gst.debug_bin_to_dot_file(sender_pipeline, Gst.DebugGraphDetails.ALL, f"sender.dot")
Gst.debug_bin_to_dot_file(receiver_pipeline, Gst.DebugGraphDetails.ALL, f"receiver.dot")

bus=sender_pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', _on_gst_message)
bus=receiver_pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', _on_gst_message)

sender_pipeline.set_state(Gst.State.PLAYING)
receiver_pipeline.set_state(Gst.State.PLAYING)

input()

Лог:

0:00:00.030790366 [32m134767[00m 0x7fc910001890 [33;01mWARN   [00m [00m     audio-resampler audio-resampler.c:274:convert_taps_gint16_c:[00m can't find exact taps
0:00:00.031691804 [32m134767[00m 0x7fc91000bdf0 [31;01mERROR  [00m [00m    rtpbasedepayload gstrtpbasedepayload.c:970:gst_rtp_base_depayload_handle_event:<rtppcmudepay0>[00m Segment with non-TIME format not supported
0:00:00.031716125 [32m134767[00m 0x7fc91000bdf0 [31;01mERROR  [00m [00m    rtpbasedepayload gstrtpbasedepayload.c:970:gst_rtp_base_depayload_handle_event:<rtppcmudepay0>[00m Segment with non-TIME format not supported
0:00:00.031742994 [32m134767[00m 0x7fc91000bdf0 [33;01mWARN   [00m [00m             basesrc gstbasesrc.c:3132:gst_base_src_loop:<myappsrc>[00m error: Internal data stream error.
0:00:00.031752100 [32m134767[00m 0x7fc91000bdf0 [33;01mWARN   [00m [00m             basesrc gstbasesrc.c:3132:gst_base_src_loop:<myappsrc>[00m error: streaming stopped, reason error (-5)
0:00:00.031780509 [32m134767[00m 0x7fc91000bdf0 [31;01mERROR  [00m [00m    rtpbasedepayload gstrtpbasedepayload.c:970:gst_rtp_base_depayload_handle_event:<rtppcmudepay0>[00m Segment with non-TIME format not supported
0:00:00.031793751 [32m134767[00m 0x7fc91000bdf0 [31;01mERROR  [00m [00m    rtpbasedepayload gstrtpbasedepayload.c:970:gst_rtp_base_depayload_handle_event:<rtppcmudepay0>[00m Segment with non-TIME format not supported
0:00:00.031806565 [32m134767[00m 0x7fc91000bdf0 [31;01mERROR  [00m [00m    rtpbasedepayload gstrtpbasedepayload.c:970:gst_rtp_base_depayload_handle_event:<rtppcmudepay0>[00m Segment with non-TIME format not supported
0:00:00.031824151 [32m134767[00m 0x7fc91000bdf0 [33;01mWARN   [00m [00m       audiobasesink gstaudiobasesink.c:1117:gst_audio_base_sink_wait_event:<alsasink0>[00m error: Sink not negotiated before eos event.
h

Видно что timestamp’ы ему не нравятся. Где, как они должны проставляться?..

wusspuss
() автор топика
Ответ на: комментарий от blex

Тем, что udpsrc почему-то иногда подлагивает при запуске (может, конечно, дело и не в нём), да и в принципе как-то костыльно гонять через локалхост, на компьютере конечного пользователя порт может оказаться и использованным.

wusspuss
() автор топика