<div dir="auto">I just follow the code in the article.</div><div dir="auto">Anyway it turns out the server did not send and rtcp message, I wireshark the communication between client and server.</div><div dir="auto">So the code works. </div><div dir="auto">Thanks😁</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 23 May 2023 at 6:26 PM, Mathieu Duponchelle <<a href="mailto:mathieu@centricular.com">mathieu@centricular.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Why are you requesting the pad in the first place?<br>
<br>
On Sun, 2023-05-21 at 15:27 +0800, Max Weng via gstreamer-devel wrote:<br>
> Hi, <br>
> <br>
>     I am currently exploring the possibilities of using GStreamer for<br>
> a project, a territory that is relatively new to me. I am convinced,<br>
> however, that GStreamer is an ideal fit for my objectives.<br>
> <br>
> The task at hand is to extract server timestamps from RTCP packets.<br>
> For this, I referred to the article, Absolute Timestamp of Arbitrary<br>
> Frame in RTSP Stream with GStreamer<br>
> <br>
>   I have been running into some difficulties during the<br>
> implementation phase.<br>
> <br>
> I am experiencing an inconsistent triggering of the "on-receiving-<br>
> rtcp" event. It appears to get activated only sporadically,<br>
> approximately once in every 20 attempts. This inconsistency makes it<br>
> challenging for me to proceed effectively with the project.<br>
> <br>
> In addition, an error message always presents itself: "Element<br>
> manager already has a pad named recv_rtcp_sink_0, the behaviour of<br>
> gst_element_get_request_pad() for existing pads is undefined!". This<br>
> error is making the situation even more complex to understand and<br>
> resolve.<br>
> <br>
> I would truly appreciate it if you could provide some insights or<br>
> suggestions regarding these issues. I am eager to understand what<br>
> might be causing these problems, and how best to address them.<br>
> <br>
>   here is my code test_gstreamer.py:<br>
> <br>
> import datetime<br>
> import pickle<br>
> from multiprocessing.connection import Connection<br>
> import threading<br>
> <br>
> from time import sleep<br>
> import gi<br>
> from log import setup_custom_logger<br>
> <br>
> gi.require_version("Gst", "1.0")<br>
> gi.require_version("GstRtp", "1.0")<br>
> gi.require_version("GstVideo", "1.0")<br>
> <br>
> from gi.repository import GLib, GObject, Gst, GstRtp, GstVideo #<br>
> noqa:F401,E402<br>
> <br>
> logger = setup_custom_logger(__name__)<br>
> <br>
> GObject.threads_init()<br>
> Gst.init()<br>
> <br>
> url = 'rtsp://localhost:8554/mystream'<br>
> pipeline = ''<br>
> <br>
> <br>
> def fly():<br>
>  main_loop = GLib.MainLoop()<br>
>  main_loop_thread = threading.Thread(target=main_loop.run)<br>
>  main_loop_thread.start()<br>
>  command = f"rtspsrc name=rtspsrc location={url} protocols=tcp<br>
> latency=10 max-rtcp-rtp-time-diff=10 ! errorignore ! rtph265depay<br>
> name=depay ! appsink name=sink"<br>
>  pipeline = Gst.parse_launch(command)<br>
>  bus = pipeline.get_bus()<br>
>  bus.add_signal_watch()<br>
>  bus.connect("message", on_message)<br>
>  bus.enable_sync_message_emission()<br>
> <br>
>  rtspsrc = pipeline.get_by_name("rtspsrc")<br>
>  rtspsrc.connect("new-manager", on_new_manager)<br>
>  depay = pipeline.get_by_name("depay")<br>
>  sinkpad = depay.get_static_pad("sink")<br>
>  probeID = sinkpad.add_probe(<br>
>  Gst.PadProbeType.BUFFER, calculate_timestamp)<br>
> <br>
>  pipeline.set_state(Gst.State.PLAYING)<br>
> <br>
>  try:<br>
>  while True:<br>
>  sleep(0.1)<br>
>  except KeyboardInterrupt:<br>
>  pass<br>
> <br>
>  pipeline.set_state(Gst.State.NULL)<br>
>  main_loop.quit()<br>
>  main_loop_thread.join()<br>
> <br>
> <br>
> def calculate_timestamp(pad, info):<br>
>  return Gst.PadProbeReturn.OK<br>
> <br>
> <br>
> def on_new_manager(rtspsrc, manager):<br>
>  <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(f"on_new_manager")<br>
>  sinkpad = manager.get_request_pad("recv_rtcp_sink_0")<br>
>  session = manager.emit("get-internal-session", 0)<br>
>  session.connect("on-receiving-rtcp", on_receive_rtcp)<br>
> <br>
> <br>
> def on_receive_rtcp(session, buffer: Gst.Buffer):<br>
>  <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>("on_receive_rtcp")<br>
>  <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(buffer)<br>
>  rtcp_buffer = GstRtp.RTCPBuffer()<br>
>  res = GstRtp.RTCPBuffer.map(buffer, Gst.MapFlags.READ, rtcp_buffer)<br>
>  rtcp_packet = GstRtp.RTCPPacket()<br>
>  rtcp_buffer.get_first_packet(rtcp_packet)<br>
> <br>
>  while True:<br>
>  if rtcp_packet.get_type() == <a href="http://GstRtp.RTCPType.SR" rel="noreferrer" target="_blank">GstRtp.RTCPType.SR</a>:<br>
>  <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(rtcp_packet)<br>
>  si = rtcp_packet.sr_get_sender_info()<br>
>  ntp_time = si[1]<br>
>  rtp_time = si[2]<br>
>  <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>("ntp_time: %d, rtp_time: %d", ntp_time, rtp_time)<br>
>  if rtcp_packet.move_to_next() == False:<br>
>  break<br>
> <br>
> <br>
> def on_message(bus: Gst.Bus, message: Gst.Message):<br>
>  mtype = message.type<br>
>  # TODO handle message<br>
> <br>
> <br>
> if __name__ == "__main__":<br>
>  fly()<br>
> <br>
> <br>
> here is how I run a local RSTP server:<br>
> $ docker run --rm -it --network=host aler9/rtsp-simple-server<br>
> $ while true; do gst-launch-1.0 rtspclientsink name=s<br>
> location=rtsp://localhost:8554/mystream<br>
>  filesrc location=//path/to/video.mp4<br>
>  ! qtdemux name=d d.video_0 ! queue ! s.sink_0 d.audio_0 ! queue ! <br>
> s.sink_1 ; done<br>
> <br>
> here is the output from my code, no "on-receiving-rtcp" triggered:<br>
> $ python test_gstreamer.py <br>
> test_gstreamer.py:19: PyGIDeprecationWarning: Since version 3.11,<br>
> calling threads_init is no longer needed. See:<br>
> <a href="https://wiki.gnome.org/PyGObject/Threading" rel="noreferrer" target="_blank">https://wiki.gnome.org/PyGObject/Threading</a><br>
>   GObject.threads_init()<br>
> 2023-05-21 15:05:06,467 - __main__ - INFO - on_new_manager<br>
> <br>
> (python:96503): GStreamer-CRITICAL **: 15:05:06.469: Element manager<br>
> already has a pad named recv_rtcp_sink_0, the behaviour of<br>
>  gst_element_get_request_pad() for existing pads is undefined!<br>
> <br>
> here is output with "on-receiving-rtcp" triggered:<br>
> $ python test_gstreamer.py <br>
> test_gstreamer.py:19: PyGIDeprecationWarning: Since version 3.11,<br>
> calling threads_init is no longer needed. See:<br>
> <a href="https://wiki.gnome.org/PyGObject/Threading" rel="noreferrer" target="_blank">https://wiki.gnome.org/PyGObject/Threading</a><br>
>   GObject.threads_init()<br>
> 2023-05-21 15:05:10,382 - __main__ - INFO - on_new_manager<br>
> <br>
> (python:96548): GStreamer-CRITICAL **: 15:05:10.384: Element manager<br>
> already has a pad named recv_rtcp_sink_0, the behaviour of <br>
> gst_element_get_request_pad() for existing pads is undefined!<br>
> 2023-05-21 15:05:11,730 - __main__ - INFO - on_receive_rtcp<br>
> 2023-05-21 15:05:11,730 - __main__ - INFO - <Gst.Buffer object at<br>
> 0x7fbf3a6918e0 (GstBuffer at 0x166cc60)><br>
> 2023-05-21 15:05:11,732 - __main__ - INFO - <GstRtp.RTCPPacket object<br>
> at 0x7fbf39c49860 (void at 0x7fbf2c08b390)><br>
> 2023-05-21 15:05:11,732 - __main__ - INFO - ntp_time:<br>
> 16723062952823484284, rtp_time: 4125066893<br>
> <br>
</blockquote></div></div>