static void
test_rtxsender_packet_retention (gboolean test_with_time)
{
  guint master_ssrc = 1234567;
  guint master_pt = 96;
  guint rtx_ssrc = 7654321;
  guint rtx_pt = 99;
  gint num_buffers = test_with_time ? 30 : 10;
  gint half_buffers = num_buffers / 2;
  guint timestamp_delta = 90000 / 30;
  guint timestamp = G_MAXUINT32 - half_buffers * timestamp_delta;
  GstHarness *h;
  GstStructure *pt_map = gst_structure_new ("application/x-rtp-pt-map",
      "96", G_TYPE_UINT, rtx_pt, NULL);
  GstStructure *ssrc_map = gst_structure_new ("application/x-rtp-ssrc-map",
      "1234567", G_TYPE_UINT, rtx_ssrc, NULL);

  h = gst_harness_new ("rtprtxsend");

  /* In both cases we want the rtxsend queue to store 'half_buffers'
     amount of buffers at most. In max-size-packets mode, it's trivial.
     In max-size-time mode, we specify almost half a second, which is
     the equivalent of 15 frames in a 30fps video stream.
   */
  g_object_set (h->element,
      "max-size-packets", test_with_time ? 0 : half_buffers,
      "max-size-time", test_with_time ? 499 : 0,
      "payload-type-map", pt_map, "ssrc-map", ssrc_map, NULL);

  gst_harness_set_src_caps_str (h, "application/x-rtp, "
      "media = (string)video, payload = (int)96, "
      "ssrc = (uint)1234567, clock-rate = (int)90000, "
      "encoding-name = (string)RAW");

  /* Now push all buffers and request retransmission every time for all of them */
  for (gint i = 0; i < num_buffers; ++i, timestamp += timestamp_delta) {
    /* Request to retransmit all the previous ones */
    for (gint j = 0; j < i; ++j) {
      guint rtx_seqnum = 0x100 + j;
      gst_harness_push_upstream_event (h,
          create_rtx_event (master_ssrc, master_pt, rtx_seqnum));

      /* Pull only the ones supposed to be retransmited */
      if (j >= i - half_buffers)
        pull_and_verify (h, TRUE, rtx_ssrc, rtx_pt, rtx_seqnum);
    }
    /* Check there no extra buffers in the harness queue */
    fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);

    /* We create RTP buffers with timestamps that will eventualy wrap around 0
       to be sure, rtprtxsend can handle it properly */
    push_pull_and_verify (h,
        create_rtp_buffer_with_timestamp (master_ssrc, master_pt, 0x100 + i,
            timestamp), FALSE, master_ssrc, master_pt, 0x100 + i);
  }

  gst_structure_free (pt_map);
  gst_structure_free (ssrc_map);
  gst_harness_teardown (h);
}
static SessionHarness *
session_harness_new (void)
{
  SessionHarness *h = g_new0 (SessionHarness, 1);
  h->caps = generate_caps ();

  h->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
  gst_system_clock_set_default (GST_CLOCK_CAST (h->testclock));

  h->session = gst_element_factory_make ("rtpsession", NULL);
  gst_element_set_clock (h->session, GST_CLOCK_CAST (h->testclock));

  h->send_rtp_h = gst_harness_new_with_element (h->session,
      "send_rtp_sink", "send_rtp_src");
  gst_harness_set_src_caps (h->send_rtp_h, gst_caps_copy (h->caps));

  h->recv_rtp_h = gst_harness_new_with_element (h->session,
      "recv_rtp_sink", "recv_rtp_src");
  gst_harness_set_src_caps (h->recv_rtp_h, gst_caps_copy (h->caps));

  h->rtcp_h = gst_harness_new_with_element (h->session,
      "recv_rtcp_sink", "send_rtcp_src");
  gst_harness_set_src_caps_str (h->rtcp_h, "application/x-rtcp");

  g_signal_connect (h->session, "request-pt-map",
      (GCallback) _pt_map_requested, h);

  g_object_get (h->session, "internal-session", &h->internal_session, NULL);

  return h;
}
static GstStructure *
create_rtxsenders (RtxSender * senders, guint senders_num)
{
  GstStructure *recv_pt_map =
      gst_structure_new_empty ("application/x-rtp-pt-map");

  for (gint i = 0; i < senders_num; ++i) {
    gchar *master_pt_str;
    gchar *master_caps_str;
    GstStructure *send_pt_map;

    senders[i].h = gst_harness_new ("rtprtxsend");
    senders[i].master_ssrc = 1234567 + i;
    senders[i].rtx_ssrc = 7654321 + i;
    senders[i].master_pt = 80 + i;
    senders[i].rtx_pt = 20 + i;
    senders[i].seqnum = i * 1000;
    senders[i].expected_rtx_packets = 0;

    master_pt_str = g_strdup_printf ("%u", senders[i].master_pt);
    master_caps_str = g_strdup_printf ("application/x-rtp, "
        "media = (string)video, payload = (int)%u, "
        "ssrc = (uint)%u, clock-rate = (int)90000, "
        "encoding-name = (string)RAW",
        senders[i].master_pt, senders[i].master_ssrc);

    send_pt_map = gst_structure_new ("application/x-rtp-pt-map",
        master_pt_str, G_TYPE_UINT, senders[i].rtx_pt, NULL);
    gst_structure_set (recv_pt_map,
        master_pt_str, G_TYPE_UINT, senders[i].rtx_pt, NULL);

    g_object_set (senders[i].h->element, "payload-type-map", send_pt_map, NULL);
    gst_harness_set_src_caps_str (senders[i].h, master_caps_str);

    gst_structure_free (send_pt_map);
    g_free (master_pt_str);
    g_free (master_caps_str);
  }
  return recv_pt_map;
}
Beispiel #4
0
static GstHarness *
harness_rtpulpfecdec (guint32 ssrc, guint8 lost_pt, guint8 fec_pt)
{
  GstHarness *h =
      gst_harness_new_parse ("rtpstorage ! rtpulpfecdec ! identity");
  GObject *internal_storage;
  gchar *caps_str =
      g_strdup_printf ("application/x-rtp,ssrc=(uint)%u,payload=(int)%u",
      ssrc, lost_pt);

  gst_harness_set (h, "rtpstorage", "size-time", 200 * RTP_PACKET_DUR, NULL);
  gst_harness_get (h, "rtpstorage", "internal-storage", &internal_storage,
      NULL);
  gst_harness_set (h, "rtpulpfecdec", "storage", internal_storage, "pt", fec_pt,
      NULL);
  g_object_unref (internal_storage);

  gst_harness_set_src_caps_str (h, caps_str);
  g_free (caps_str);

  return h;
}