A question regarding the proper handling of pipelines and webrtcbin
Neil Young
foreverneilyoung at googlemail.com
Tue Aug 17 18:19:24 UTC 2021
OK, doing it manually works great. And fast.
Just the commented part doesn't work, since "trans" is None. That's why the OFFER goes out with "sendrecv"
The "get-transceivers" returns a GArray, but I wouldn't know how to subscribe this in Python...
def start_pipeline(self):
self.webrtcbin = Gst.ElementFactory.make("webrtcbin")
self.webrtcbin.set_property("bundle-policy", "max-bundle")
self.webrtcbin.set_property("stun-server", "stun://stun.l.google.com:19302")
# if Gst.version().major >= 1 and Gst.version().minor >= 17:
# trans = self.webrtcbin.emit('get-transceiver', 0)
# print(trans)
# if self.direction == 'sendonly':
# trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY)
# elif self.direction == 'recvonly':
# trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.RECVONLY)
# else:
# trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDRECV)
self.webrtcbin.connect('on-negotiation-needed', self.on_negotiation_needed)
self.webrtcbin.connect('on-ice-candidate', self.on_ice_candidate)
self.webrtcbin.connect('pad-added', self.on_pad_added)
self.webrtcbin.connect('notify::connection-state', self.on_connection_state)
self.webrtcbin.connect('notify::signaling-state', self.on_signaling_state)
self.webrtcbin.connect('notify::ice-connection-state', self.on_ice_connection_state)
self.webrtcbin.connect('notify::ice-gathering-state', self.on_ice_gathering_state)
self.pipeline = Gst.Pipeline.new()
self.pipeline.add(self.webrtcbin)
videotestsrc = Gst.ElementFactory.make("videotestsrc", "videotestsrc")
videotestsrc.set_property("is-live", True)
videotestsrc.set_property("pattern", "ball")
videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
vp8enc = Gst.ElementFactory.make("vp8enc", "vp8enc")
vp8enc.set_property("deadline", 1)
rtpvp8pay = Gst.ElementFactory.make("rtpvp8pay", "rtpvp8pay")
rtpvp8pay_caps = Gst.caps_from_string("application/x-rtp")
rtpvp8pay_caps.set_value("media", "video")
rtpvp8pay_caps.set_value("encoding-name", "VP8")
rtpvp8pay_caps_filter = Gst.ElementFactory.make("capsfilter")
rtpvp8pay_caps_filter.set_property("caps", rtpvp8pay_caps)
self.pipeline.add(videotestsrc)
self.pipeline.add(videoconvert)
self.pipeline.add(vp8enc)
self.pipeline.add(rtpvp8pay)
self.pipeline.add(rtpvp8pay_caps_filter)
if not Gst.Element.link(videotestsrc, videoconvert):
print("Failed to link videotestsrc -> videoconvert")
if not Gst.Element.link(videoconvert, vp8enc):
print("Failed to link videoconvert -> vp8enc")
if not Gst.Element.link(vp8enc, rtpvp8pay):
print("Failed to link vp8enc -> rtpvp8pay")
if not Gst.Element.link(rtpvp8pay, rtpvp8pay_caps_filter):
print("Failed to link rtpvp8pay -> rtpvp8pay_caps_filter")
if not Gst.Element.link(rtpvp8pay_caps_filter, self.webrtcbin):
print("Failed to link rtpvp8pay_caps_filter -> self.webrtcbin")
self.pipeline.add(self.webrtcbin)
self.pipeline.set_state(Gst.State.PLAYING)
> Am 17.08.2021 um 15:38 schrieb Neil Young <foreverneilyoung at googlemail.com>:
>
> I'm trying to refactor some working sample code which is using this pattern:
>
> - A webrtcbin pipeline is created from string
> - The "on_negotiation_needed" callback triggers the OFFER creation.
>
> Basically this is the Python code, which appears in many forms on the Internet and is originated from one of the GStreamer sample codes:
>
> PIPELINE_TEST_VP8 = '''
> webrtcbin name=webrtcbin bundle-policy=max-bundle stun-server=stun://stun.l.google.com:19302 <stun://stun.l.google.com:19302>
> videotestsrc is-live=true pattern=ball ! videoconvert ! queue ! vp8enc deadline=1 ! queue ! rtpvp8pay !
> queue ! application/x-rtp,media=video,encoding-name=VP8 ! webrtcbin.
> '''
>
>
> def start_pipeline(self):
> self.pipe = Gst.parse_launch(PIPELINE_TEST_VP8)
> self.webrtcbin = self.pipe.get_by_name('webrtcbin')
> if Gst.version().major >= 1 and Gst.version().minor >= 17:
> trans = self.webrtcbin.emit('get-transceiver', 0)
> if self.direction == 'sendonly':
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY)
> elif self.direction == 'recvonly':
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.RECVONLY)
> else:
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDRECV)
> self.webrtcbin.connect('on-negotiation-needed', self.on_negotiation_needed)
> self.webrtcbin.connect('on-ice-candidate', self.on_ice_candidate)
> self.webrtcbin.connect('pad-added', self.on_pad_added)
> self.webrtcbin.connect('notify::connection-state', self.on_connection_state)
> self.webrtcbin.connect('notify::signaling-state', self.on_signaling_state)
> self.webrtcbin.connect('notify::ice-connection-state', self.on_ice_connection_state)
> self.webrtcbin.connect('notify::ice-gathering-state', self.on_ice_gathering_state)
> self.pipe.set_state(Gst.State.PLAYING)
>
>
> The offer looks good and is answered correctly, video flows.
>
> v=0
> o=- 7638256982687930899 0 IN IP4 0.0.0.0
> s=-
> t=0 0
> a=ice-options:trickle
> a=group:BUNDLE video0
> m=video 9 UDP/TLS/RTP/SAVPF 96
> c=IN IP4 0.0.0.0
> a=setup:actpass
> a=ice-ufrag:bGQItiwLYlgcID/WCvvmBOvCOn7T5c/I
> a=ice-pwd:7XItJ6VJFOoh8jcwd4Rvq34OW1/KYRSD
> a=rtcp-mux
> a=rtcp-rsize
> a=sendrecv
> a=rtpmap:96 H264/90000
> a=rtcp-fb:96 nack pli
> a=framerate:30
> a=fmtp:96 packetization-mode=1;profile-level-id=42c01e;sprop-parameter-sets=Z0LAHtkAoD2wFqDAwNSgAAADACAAAAeR4sXJ,aMuMsg==
> a=ssrc:480748954 msid:user4125901687 at host-1eadd0cf webrtctransceiver0
> a=ssrc:480748954 cname:user4125901687 at host-1eadd0cf
> a=mid:video0
> a=fingerprint:sha-256 54:82:06:0C:5D:7C:47:63:C2:1A:8D:D0:CC:0E:9D:20:47:A8:6C:B0:CF:31:74:0D:E2:5F:D6:D9:F5:21:D5:94
>
>
>
> Because this approach of a pre-canned pipeline seems to have difficulties in a mode, in which I try to ANSWER an incoming OFFER I was trying to refactor it and split the webrtcbin object generation from the input pipeline.
>
> PIPELINE_TEST_VP8_2 = '''
> videotestsrc is-live=true pattern=ball !
> videoconvert !
> queue !
> vp8enc deadline=1 !
> queue !
> rtpvp8pay !
> queue !
> application/x-rtp,media=video,encoding-name=VP8 !
> webrtcbin
> '''
>
> def start_pipeline(self):
> self.pipe = Gst.parse_launch(PIPELINE_TEST_VP8_2)
> self.webrtcbin = Gst.ElementFactory.make("webrtcbin")
> self.webrtcbin.set_property("bundle-policy", "max-bundle")
> self.webrtcbin.set_property("name", "webrtcbin")
> self.webrtcbin.set_property("stun-server", "stun://stun.l.google.com:19302 <stun://stun.l.google.com:19302>")
> if Gst.version().major >= 1 and Gst.version().minor >= 17:
> trans = self.webrtcbin.emit('get-transceiver', 0)
> if self.direction == 'sendonly':
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY)
> elif self.direction == 'recvonly':
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.RECVONLY)
> else:
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDRECV)
> self.webrtcbin.connect('on-negotiation-needed', self.on_negotiation_needed)
> self.webrtcbin.connect('on-ice-candidate', self.on_ice_candidate)
> self.webrtcbin.connect('pad-added', self.on_pad_added)
> self.webrtcbin.connect('notify::connection-state', self.on_connection_state)
> self.webrtcbin.connect('notify::signaling-state', self.on_signaling_state)
> self.webrtcbin.connect('notify::ice-connection-state', self.on_ice_connection_state)
> self.webrtcbin.connect('notify::ice-gathering-state', self.on_ice_gathering_state)
> self.pipe.add(self.webrtcbin)
> self.pipe.set_state(Gst.State.PLAYING)
>
>
> The first problem with this is the missing "trans":
>
> 0:00:00.352922991 11197 0xb2847240 ERROR webrtcbin gstwebrtcbin.c:5032:gst_webrtc_bin_get_transceiver:<webrtcbin> No transceiver for idx 0
>
>
> trans.set_property('direction', GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY)
> AttributeError: 'NoneType' object has no attribute 'set_property'
>
> But even if I omit the entire part to determine the transceiver, the result is still not working, because this is my OFFER then:
>
> v=0
> o=- 4039551208253794554 0 IN IP4 0.0.0.0
> s=-
> t=0 0
> a=ice-options:trickle
> a=group:BUNDLE
>
>
> I suppose there is something wrong with the inputs definitions, but before I go and create them manually I wanted to at least have some success with this.
>
> Does anybody have a pointer, what's going wrong here?
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20210817/566eb206/attachment-0001.htm>
More information about the gstreamer-devel
mailing list