/*
 * Chain list function for testing buffer lists
 */
static GstFlowReturn
rtp_pipeline_chain_list (GstPad * pad, GstBufferList * list)
{
  GstBufferListIterator *it;

  fail_if (!list);
  it = gst_buffer_list_iterate (list);

  /*
   * Count the size of the payload in the buffer list.
   */

  /* Loop through all groups */
  while (gst_buffer_list_iterator_next_group (it)) {
    GstBuffer *paybuf;

    /* Skip the first buffer in the group, its the RTP header */
    fail_if (!gst_buffer_list_iterator_next (it));

    /* Loop through all payload buffers in the current group */
    while ((paybuf = gst_buffer_list_iterator_next (it))) {
      chain_list_bytes_received += GST_BUFFER_SIZE (paybuf);
    }
  }

  gst_buffer_list_iterator_free (it);
  gst_buffer_list_unref (list);

  return GST_FLOW_OK;
}
Example #2
0
/**
 * gst_rtp_buffer_list_get_payload_len:
 * @list: the buffer list
 *
 * Get the length of the payload of the RTP packet in @list.
 *
 * Returns: The length of the payload in @list.
 *
 * Since: 0.10.24
 */
guint
gst_rtp_buffer_list_get_payload_len (GstBufferList * list)
{
  guint len;
  GstBufferListIterator *it;

  it = gst_buffer_list_iterate (list);
  len = 0;

  while (gst_buffer_list_iterator_next_group (it)) {
    guint i;
    GstBuffer *buf;

    i = 0;
    while ((buf = gst_buffer_list_iterator_next (it))) {
      /* skip the RTP header */
      if (!i++)
        continue;
      /* take the size of the current buffer */
      len += GST_BUFFER_SIZE (buf);
    }
  }

  gst_buffer_list_iterator_free (it);

  return len;
}
Example #3
0
/*
 * Render function for testing udpsink with buffer lists
 */
static GstFlowReturn
udpsink_render (GstBaseSink * sink, GstBufferList * list)
{
  GstBufferListIterator *it;

  fail_if (!list);

  /*
   * Count the size of the rtp header and the payload in the buffer list.
   */

  it = gst_buffer_list_iterate (list);

  /* Loop through all groups */
  while (gst_buffer_list_iterator_next_group (it)) {
    GstBuffer *buf;
    /* Loop through all buffers in the current group */
    while ((buf = gst_buffer_list_iterator_next (it))) {
      guint size;

      size = GST_BUFFER_SIZE (buf);
      GST_DEBUG ("rendered %u bytes", size);

      render_list_bytes_received += size;
    }
  }

  gst_buffer_list_iterator_free (it);

  return GST_FLOW_OK;
}
Example #4
0
/**
 * gst_rtp_buffer_list_validate:
 * @list: the buffer list to validate
 *
 * Check if all RTP packets in the @list are valid using validate_data().
 * Use this function to validate an list before using the other functions in
 * this module.
 *
 * Returns: TRUE if @list consists only of valid RTP packets.
 *
 * Since: 0.10.24
 */
gboolean
gst_rtp_buffer_list_validate (GstBufferList * list)
{
  guint16 prev_seqnum = 0;
  GstBufferListIterator *it;
  guint i = 0;

  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE);

  it = gst_buffer_list_iterate (list);
  g_return_val_if_fail (it != NULL, FALSE);

  /* iterate through all the RTP packets in the list */
  while (gst_buffer_list_iterator_next_group (it)) {
    GstBuffer *rtpbuf;
    GstBuffer *paybuf;
    guint8 *packet_header;
    guint8 *packet_payload;
    guint payload_size;
    guint packet_size;

    /* each group should consists of 2 buffers: one containing the RTP header
     * and the other one the payload, FIXME, relax the requirement of only one
     * payload buffer. */
    if (gst_buffer_list_iterator_n_buffers (it) != 2)
      goto invalid_list;

    /* get the RTP header */
    rtpbuf = gst_buffer_list_iterator_next (it);
    packet_header = GST_BUFFER_DATA (rtpbuf);
    if (packet_header == NULL)
      goto invalid_list;

    /* get the payload */
    paybuf = gst_buffer_list_iterator_next (it);
    packet_payload = GST_BUFFER_DATA (paybuf);
    if (packet_payload == NULL) {
      goto invalid_list;
    }
    payload_size = GST_BUFFER_SIZE (paybuf);
    if (payload_size == 0) {
      goto invalid_list;
    }

    /* the size of the RTP packet within the current group */
    packet_size = GST_BUFFER_SIZE (rtpbuf) + payload_size;

    /* check the sequence number */
    if (G_UNLIKELY (i == 0)) {
      prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header));
      i++;
    } else {
      if (++prev_seqnum != g_ntohs (GST_RTP_HEADER_SEQ (packet_header)))
        goto invalid_list;
    }

    /* validate packet */
    if (!validate_data (packet_header, packet_size, packet_payload,
            payload_size)) {
      goto invalid_list;
    }
  }

  gst_buffer_list_iterator_free (it);

  return TRUE;

  /* ERRORS */
invalid_list:
  {
    gst_buffer_list_iterator_free (it);
    return FALSE;
  }
}
Example #5
0
BufferPtr BufferListIterator::next()
{
    return BufferPtr::wrap(gst_buffer_list_iterator_next(m_it));
}
Example #6
0
static GstFlowReturn
gst_multiudpsink_render_list (GstBaseSink * bsink, GstBufferList * list)
{
  GstMultiUDPSink *sink;
  GList *clients;
  gint ret, size = 0, num = 0, no_clients = 0;
  struct iovec *iov;
  struct msghdr msg = { 0 };

  GstBufferListIterator *it;
  guint gsize;
  GstBuffer *buf;

  sink = GST_MULTIUDPSINK (bsink);

  g_return_val_if_fail (list != NULL, GST_FLOW_ERROR);

  it = gst_buffer_list_iterate (list);
  g_return_val_if_fail (it != NULL, GST_FLOW_ERROR);

  while (gst_buffer_list_iterator_next_group (it)) {
    msg.msg_iovlen = 0;
    size = 0;

    if ((gsize = gst_buffer_list_iterator_n_buffers (it)) == 0) {
      goto invalid_list;
    }

    iov = (struct iovec *) g_malloc (gsize * sizeof (struct iovec));
    msg.msg_iov = iov;

    while ((buf = gst_buffer_list_iterator_next (it))) {
      if (GST_BUFFER_SIZE (buf) > UDP_MAX_SIZE) {
        GST_WARNING ("Attempting to send a UDP packet larger than maximum "
            "size (%d > %d)", GST_BUFFER_SIZE (buf), UDP_MAX_SIZE);
      }

      msg.msg_iov[msg.msg_iovlen].iov_len = GST_BUFFER_SIZE (buf);
      msg.msg_iov[msg.msg_iovlen].iov_base = GST_BUFFER_DATA (buf);
      msg.msg_iovlen++;
      size += GST_BUFFER_SIZE (buf);
    }

    sink->bytes_to_serve += size;

    /* grab lock while iterating and sending to clients, this should be
     * fast as UDP never blocks */
    g_mutex_lock (sink->client_lock);
    GST_LOG_OBJECT (bsink, "about to send %d bytes", size);

    for (clients = sink->clients; clients; clients = g_list_next (clients)) {
      GstUDPClient *client;
      gint count;

      client = (GstUDPClient *) clients->data;
      no_clients++;
      GST_LOG_OBJECT (sink, "sending %d bytes to client %p", size, client);

      count = sink->send_duplicates ? client->refcount : 1;

      while (count--) {
        while (TRUE) {
          msg.msg_name = (void *) &client->theiraddr;
          msg.msg_namelen = sizeof (client->theiraddr);
          ret = sendmsg (*client->sock, &msg, 0);

          if (ret < 0) {
            if (!socket_error_is_ignorable ()) {
              break;
            }
          } else {
            num++;
            client->bytes_sent += ret;
            client->packets_sent++;
            sink->bytes_served += ret;
            break;
          }
        }
      }
    }
    g_mutex_unlock (sink->client_lock);

    g_free (iov);
    msg.msg_iov = NULL;

    GST_LOG_OBJECT (sink, "sent %d bytes to %d (of %d) clients", size, num,
        no_clients);
  }

  gst_buffer_list_iterator_free (it);

  return GST_FLOW_OK;

invalid_list:
  gst_buffer_list_iterator_free (it);
  return GST_FLOW_ERROR;
}