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 void
create_destroy_element_harness (gpointer data, gpointer user_data)
{
  GstElement *element = user_data;
  GstHarness *h = gst_harness_new_with_element (element, NULL, NULL);
  gst_harness_teardown (h);
}
static void
session_harness_free (SessionHarness * h)
{
  gst_system_clock_set_default (NULL);

  gst_caps_unref (h->caps);
  gst_object_unref (h->testclock);

  gst_harness_teardown (h->rtcp_h);
  gst_harness_teardown (h->recv_rtp_h);
  gst_harness_teardown (h->send_rtp_h);

  g_object_unref (h->internal_session);
  gst_object_unref (h->session);
  g_free (h);
}
static void
rtp_jpeg_do_packet_loss (gdouble prob, gint num_expected)
{
  GstHarness *h;
  gboolean eos = FALSE;
  gchar *s;
  guint i, buffer_count;

  s = g_strdup_printf ("videotestsrc pattern=ball num-buffers=100 ! "
      "jpegenc quality=50 ! rtpjpegpay ! identity drop-probability=%g ! "
      "rtpjpegdepay", prob);
  GST_INFO ("running pipeline %s", s);
  h = gst_harness_new_parse (s);
  g_free (s);

  gst_harness_play (h);

  do {
    GstEvent *event;

    event = gst_harness_pull_event (h);
    eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
    gst_event_unref (event);
  } while (!eos);

  buffer_count = gst_harness_buffers_received (h);
  GST_INFO ("Got %u buffers", buffer_count);

  if (num_expected >= 0) {
    fail_unless_equals_int (num_expected, buffer_count);
  }

  for (i = 0; i < buffer_count; ++i) {
    GstBuffer *buf;
    GstMapInfo map;
    guint16 soi, eoi;

    buf = gst_harness_pull (h);
    fail_unless (buf != NULL);

    fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
    GST_MEMDUMP ("jpeg frame", map.data, map.size);
    fail_unless (map.size > 4);
    soi = GST_READ_UINT16_BE (map.data);
    fail_unless (soi == 0xffd8, "expected JPEG frame start FFD8 not %02X", soi);
    eoi = GST_READ_UINT16_BE (map.data + map.size - 2);
    fail_unless (eoi == 0xffd9, "expected JPEG frame end FFD9 not %02X", eoi);
    gst_buffer_unmap (buf, &map);
    gst_buffer_unref (buf);
  }

  gst_harness_teardown (h);
}
static guint
check_rtxsenders_stats_and_teardown (RtxSender * senders, guint senders_num)
{
  guint total_pakets_num = 0;
  for (gint i = 0; i < senders_num; ++i) {
    guint rtx_requests;
    guint rtx_packets;
    g_object_get (G_OBJECT (senders[i].h->element),
        "num-rtx-requests", &rtx_requests,
        "num-rtx-packets", &rtx_packets, NULL);
    fail_unless_equals_int (rtx_packets, senders[i].expected_rtx_packets);
    fail_unless_equals_int (rtx_requests, senders[i].expected_rtx_packets);
    total_pakets_num += rtx_packets;

    gst_harness_teardown (senders[i].h);
  }
  return total_pakets_num;
}
Beispiel #6
0
static void
_recovered_from_fec_base (guint32 ssrc, guint8 fec_pt,
    guint8 lost_pt, guint16 lost_seq,
    gconstpointer fec_packet, gsize fec_packet_size,
    gconstpointer lost_packet, gsize lost_packet_size)
{
  GstHarness *h = harness_rtpulpfecdec (ssrc, lost_pt, 123);
  RecoveredPacketInfo info = {.pt = lost_pt,.ssrc = ssrc,.seq = lost_seq };
  GList *expected = expect_recovered_packets (h, &info, 1);

  push_data (h, fec_packet, fec_packet_size);
  lose_and_recover_test (h, lost_seq, lost_packet, lost_packet_size);

  check_rtpulpfecdec_stats (h, 1, 0);

  g_list_free (expected);
  gst_harness_teardown (h);
}