RTCP Sender Reports Fail Sanity Checks (DAHUA-type camera)

Hi,

in our production environment we deploy cameras of the type DAHUA HDBW3841R-ZS-S2.
These cameras periodically send RTCP Sender reports containing an NTP timestamp, e.g.:

Frame 641: 86 bytes on wire (688 bits), 86 bytes captured (688 bits) on interface enp1s0, id 0
Ethernet II, Src: Zhejiang_7c:e7:f0 (f4:b1:c2:7c:e7:f0), Dst: 10:98:19:2f:cc:69 (10:98:19:2f:cc:69)
Internet Protocol Version 4, Src: 172.22.71.30, Dst: 172.22.80.12
User Datagram Protocol, Src Port: 24455, Dst Port: 55597
Real-time Transport Control Protocol (Sender Report)
    [Stream setup by RTSP (frame 630)]
    10.. .... = Version: RFC 1889 Version (2)
    ..0. .... = Padding: False
    ...0 0000 = Reception report count: 0
    Packet type: Sender Report (200)
    Length: 6 (28 bytes)
    Sender SSRC: 0x3a303120 (976236832)
    Timestamp, MSW: 3956036143 (0xebcc522f)
    Timestamp, LSW: 579820584 (0x228f5c28)
    [MSW and LSW as NTP timestamp: May 12, 2025 10:55:43.134999999 UTC]
    RTP timestamp: 398644454
    Sender's packet count: 0
    Sender's octet count: 0
Real-time Transport Control Protocol (Source description)
    [Stream setup by RTSP (frame 630)]
    10.. .... = Version: RFC 1889 Version (2)
    ..0. .... = Padding: False
    ...0 0001 = Source count: 1
    Packet type: Source description (202)
    Length: 3 (16 bytes)
    Chunk 1, SSRC/CSRC 0x3A303120
    [RTCP frame length check: OK - 44 bytes]

When running a simple pipeline via

GST_DEBUG=3,rtpjitterbuffer:6 GST_DEBUG_FILE=dahua.log timeout 60s gst-launch-1.0 rtspsrc location=‘rtsp://USER:PASSWORD@172.22.71.30:554/cam/realmonitor?channel=1&subtype=0’ latency=200 ! rtph264depay ! avdec_h264 ! autovideosink

the resulting log shows entries like

0:00:00.238372877 e[31m3105222e[00m 0x76f2ac017240 e[37mDEBUG  e[00m e[00m     rtpjitterbuffer gstrtpjitterbuffer.c:4284:do_handle_sync:<rtpjitterbuffer0>e[00m ext SR 398644454, base 18446744073709551615, clock-rate 0, clock-base 18446744073709551615, last-rtptime 18446744073709551615
0:00:00.238386492 e[31m3105222e[00m 0x76f2ac017240 e[37mDEBUG  e[00m e[00m     rtpjitterbuffer gstrtpjitterbuffer.c:4292:do_handle_sync:<rtpjitterbuffer0>e[00m keeping for later, no RTP values
0:00:00.238396583 e[31m3105222e[00m 0x76f2ac017240 e[37mDEBUG  e[00m e[00m     rtpjitterbuffer gstrtpjitterbuffer.c:4324:do_handle_sync:<rtpjitterbuffer0>e[00m keeping RTCP packet for later

which as far as we understand means the following sanity check in this GStreamer code fails.

...
/* collect the info from the lastest RTCP packet and the jitterbuffer sync, do
 * some sanity checks and then emit the handle-sync signal with the parameters.
 * This function must be called with the LOCK */
static void
do_handle_sync (GstRtpJitterBuffer * jitterbuffer)
{
  GstRtpJitterBufferPrivate *priv;
  guint64 base_rtptime, base_time;
  guint32 clock_rate;
  guint64 last_rtptime;
  guint64 clock_base;
  guint64 ext_rtptime, diff;
  gboolean valid = TRUE, keep = FALSE;

  priv = jitterbuffer->priv;

  /* get the last values from the jitterbuffer */
  rtp_jitter_buffer_get_sync (priv->jbuf, &base_rtptime, &base_time,
      &clock_rate, &last_rtptime);

  clock_base = priv->clock_base;
  ext_rtptime = priv->ext_rtptime;

  GST_DEBUG_OBJECT (jitterbuffer, "ext SR %" G_GUINT64_FORMAT ", base %"
      G_GUINT64_FORMAT ", clock-rate %" G_GUINT32_FORMAT
      ", clock-base %" G_GUINT64_FORMAT ", last-rtptime %" G_GUINT64_FORMAT,
      ext_rtptime, base_rtptime, clock_rate, clock_base, last_rtptime);

  if (base_rtptime == -1 || clock_rate == -1 || base_time == -1) {
    /* we keep this SR packet for later. When we get a valid RTP packet the
     * above values will be set and we can try to use the SR packet */
    GST_DEBUG_OBJECT (jitterbuffer, "keeping for later, no RTP values");
    keep = TRUE;
  } else {
...

The log shows that base_rtptime and clock_rate are not equal to -1 which means the check fails due to base_time being equal to -1. We need the NTP-timestamp properly processed since we extract it downstream in a DeepStream pipeline, which due to this issue for DAHUA-type cameras always resolves to 0. For AXIS-type cameras, where the above sanity check does not fail, the NTP-timestamp extracted in the DeepStream pipeline is correct and differs from 0.

Therefore we’d like to kindly ask why base_time = -1 for the DAHUA camera in question and how to address that issue.

Thank you very much for your time!

Attachments

Here you can find the GStreamer log and the corresponding Wireshark capture of the pipeline from above (60 seconds of playtime, including the RTSP handshake in the beginning).