Exemple #1
0
static GstBufferList *
_create_buffer_list (guint * data_size)
{
  GstBufferList *list;
  GstBufferListIterator *it;
  GstBuffer *rtp_buffer;
  GstBuffer *data_buffer;

  list = gst_buffer_list_new ();
  it = gst_buffer_list_iterate (list);

  /*** First group, i.e. first packet. **/

  /* Create the RTP header buffer */
  rtp_buffer = gst_buffer_new ();
  GST_BUFFER_MALLOCDATA (rtp_buffer) = g_malloc (RTP_HEADER_SIZE);
  GST_BUFFER_DATA (rtp_buffer) = GST_BUFFER_MALLOCDATA (rtp_buffer);
  GST_BUFFER_SIZE (rtp_buffer) = RTP_HEADER_SIZE;
  memset (GST_BUFFER_DATA (rtp_buffer), 0, RTP_HEADER_SIZE);

  /* Create the buffer that holds the payload */
  data_buffer = gst_buffer_new ();
  GST_BUFFER_MALLOCDATA (data_buffer) = g_malloc (RTP_PAYLOAD_SIZE);
  GST_BUFFER_DATA (data_buffer) = GST_BUFFER_MALLOCDATA (data_buffer);
  GST_BUFFER_SIZE (data_buffer) = RTP_PAYLOAD_SIZE;
  memset (GST_BUFFER_DATA (data_buffer), 0, RTP_PAYLOAD_SIZE);

  /* Create a new group to hold the rtp header and the payload */
  gst_buffer_list_iterator_add_group (it);
  gst_buffer_list_iterator_add (it, rtp_buffer);
  gst_buffer_list_iterator_add (it, data_buffer);

  /***  Second group, i.e. second packet. ***/

  /* Create the RTP header buffer */
  rtp_buffer = gst_buffer_new ();
  GST_BUFFER_MALLOCDATA (rtp_buffer) = g_malloc (RTP_HEADER_SIZE);
  GST_BUFFER_DATA (rtp_buffer) = GST_BUFFER_MALLOCDATA (rtp_buffer);
  GST_BUFFER_SIZE (rtp_buffer) = RTP_HEADER_SIZE;
  memset (GST_BUFFER_DATA (rtp_buffer), 0, RTP_HEADER_SIZE);

  /* Create the buffer that holds the payload */
  data_buffer = gst_buffer_new ();
  GST_BUFFER_MALLOCDATA (data_buffer) = g_malloc (RTP_PAYLOAD_SIZE);
  GST_BUFFER_DATA (data_buffer) = GST_BUFFER_MALLOCDATA (data_buffer);
  GST_BUFFER_SIZE (data_buffer) = RTP_PAYLOAD_SIZE;
  memset (GST_BUFFER_DATA (data_buffer), 0, RTP_PAYLOAD_SIZE);

  /* Create a new group to hold the rtp header and the payload */
  gst_buffer_list_iterator_add_group (it);
  gst_buffer_list_iterator_add (it, rtp_buffer);
  gst_buffer_list_iterator_add (it, data_buffer);

  /* Calculate the size of the data */
  *data_size = 2 * RTP_HEADER_SIZE + 2 * RTP_PAYLOAD_SIZE;

  gst_buffer_list_iterator_free (it);

  return list;
}
Exemple #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;
}
static void copyGstreamerBuffersToAudioChannel(GstBufferList* buffers, AudioChannel* audioChannel)
{
#ifdef GST_API_VERSION_1
    gsize offset = 0;
    for (unsigned i = 0; i < gst_buffer_list_length(buffers); i++) {
        GstBuffer* buffer = gst_buffer_list_get(buffers, i);
        if (!buffer)
            continue;
        GstMapInfo info;
        gst_buffer_map(buffer, &info, GST_MAP_READ);
        memcpy(audioChannel->mutableData() + offset, reinterpret_cast<float*>(info.data), info.size);
        offset += info.size / sizeof(float);
        gst_buffer_unmap(buffer, &info);
    }
#else
    GstBufferListIterator* iter = gst_buffer_list_iterate(buffers);
    gst_buffer_list_iterator_next_group(iter);
    GstBuffer* buffer = gst_buffer_list_iterator_merge_group(iter);
    if (buffer) {
        memcpy(audioChannel->mutableData(), reinterpret_cast<float*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
        gst_buffer_unref(buffer);
    }

    gst_buffer_list_iterator_free(iter);
#endif
}
Exemple #4
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;
}
/*
 * 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;
}
PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono)
{
    m_sampleRate = sampleRate;

    m_frontLeftBuffers = gst_buffer_list_new();
    m_frontRightBuffers = gst_buffer_list_new();

#ifndef GST_API_VERSION_1
    m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers);
    gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator);

    m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers);
    gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator);
#endif

    GRefPtr<GMainContext> context = adoptGRef(g_main_context_new());
    g_main_context_push_thread_default(context.get());
    m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE));

    // Start the pipeline processing just after the loop is started.
    GRefPtr<GSource> timeoutSource = adoptGRef(g_timeout_source_new(0));
    g_source_attach(timeoutSource.get(), context.get());
    g_source_set_callback(timeoutSource.get(), reinterpret_cast<GSourceFunc>(enteredMainLoopCallback), this, 0);

    g_main_loop_run(m_loop.get());
    g_main_context_pop_thread_default(context.get());

    if (m_errorOccurred)
        return nullptr;

    unsigned channels = mixToMono ? 1 : 2;
    OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(channels, m_channelSize, true));
    audioBus->setSampleRate(m_sampleRate);

    copyGstreamerBuffersToAudioChannel(m_frontLeftBuffers, audioBus->channel(0));
    if (!mixToMono)
        copyGstreamerBuffersToAudioChannel(m_frontRightBuffers, audioBus->channel(1));

    return audioBus.release();
}
Exemple #7
0
static void
add_buffer_to_goplist (MpegPsMux * mux, GstBuffer * buf)
{
  GstBufferListIterator *it;

  if (mux->gop_list == NULL)
    mux->gop_list = gst_buffer_list_new ();

  it = gst_buffer_list_iterate (mux->gop_list);

  /* move iterator to end */
  while (gst_buffer_list_iterator_next_group (it)) {
    /* .. */
  }

  gst_buffer_list_iterator_add_group (it);
  gst_buffer_list_iterator_add (it, buf);
  gst_buffer_list_iterator_free (it);
}
Exemple #8
0
static void
gst_fragment_init (GstFragment * fragment)
{
  GstFragmentPrivate *priv;

  fragment->priv = priv = GST_FRAGMENT_GET_PRIVATE (fragment);

  g_mutex_init (&fragment->priv->lock);
  priv->buffer_list = gst_buffer_list_new ();
  priv->size = 0;
  priv->buffer_iterator = gst_buffer_list_iterate (priv->buffer_list);
  gst_buffer_list_iterator_add_group (priv->buffer_iterator);
  fragment->download_start_time = g_get_real_time ();
  fragment->start_time = 0;
  fragment->stop_time = 0;
  fragment->index = 0;
  fragment->name = g_strdup ("");
  fragment->completed = FALSE;
  fragment->discontinuous = FALSE;
}
static GstFlowReturn
gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload)
{
  GstRtpJ2KDepay *rtpj2kdepay;
  guint8 end[2];
  guint8 *data;
  guint avail;

  GstFlowReturn ret = GST_FLOW_OK;

  rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);

  /* flush pending tile */
  gst_rtp_j2k_depay_flush_tile (depayload);

  /* last buffer take all data out of the adapter */
  avail = gst_adapter_available (rtpj2kdepay->f_adapter);
  if (avail == 0)
    goto done;

  if (avail > 2) {
    GstBuffer *outbuf;

    /* take the last bytes of the JPEG 2000 data to see if there is an EOC
     * marker */
    gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2);

    if (end[0] != 0xff && end[1] != 0xd9) {
      GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one");

      /* no EOI marker, add one */
      outbuf = gst_buffer_new_and_alloc (2);
      data = GST_BUFFER_DATA (outbuf);
      data[0] = 0xff;
      data[1] = 0xd9;

      gst_adapter_push (rtpj2kdepay->f_adapter, outbuf);
      avail += 2;
    }

    if (rtpj2kdepay->buffer_list) {
      GList *list;
      GstBufferList *buflist;
      GstBufferListIterator *it;

      GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail);
      list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail);

      buflist = gst_buffer_list_new ();
      it = gst_buffer_list_iterate (buflist);
      gst_buffer_list_iterator_add_group (it);
      gst_buffer_list_iterator_add_list (it, list);
      gst_buffer_list_iterator_free (it);

      ret = gst_base_rtp_depayload_push_list (depayload, buflist);
    } else {
      GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail);
      outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail);
      ret = gst_base_rtp_depayload_push (depayload, outbuf);
    }
  } else {
    GST_WARNING_OBJECT (rtpj2kdepay, "empty packet");
    gst_adapter_clear (rtpj2kdepay->f_adapter);
  }

  /* we accept any mh_id now */
  rtpj2kdepay->last_mh_id = -1;

  /* reset state */
  rtpj2kdepay->next_frag = 0;
  rtpj2kdepay->have_sync = FALSE;

done:
  /* we can't keep headers with mh_id of 0 */
  store_mheader (rtpj2kdepay, 0, NULL);

  return ret;
}
Exemple #10
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;
  }
}
static GstFlowReturn
gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload *
    baseaudiopayload, GstBuffer * buffer)
{
  GstBaseRTPPayload *basepayload;
  GstBaseRTPAudioPayloadPrivate *priv;
  GstBuffer *outbuf;
  GstClockTime timestamp;
  guint8 *payload;
  guint payload_len;
  GstFlowReturn ret;

  priv = baseaudiopayload->priv;
  basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);

  payload_len = GST_BUFFER_SIZE (buffer);
  timestamp = GST_BUFFER_TIMESTAMP (buffer);

  GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
      payload_len, GST_TIME_ARGS (timestamp));

  if (priv->buffer_list) {
    /* create just the RTP header buffer */
    outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
  } else {
    /* create buffer to hold the payload */
    outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
  }

  /* set metadata */
  gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
      timestamp);

  if (priv->buffer_list) {
    GstBufferList *list;
    GstBufferListIterator *it;

    list = gst_buffer_list_new ();
    it = gst_buffer_list_iterate (list);

    /* add both buffers to the buffer list */
    gst_buffer_list_iterator_add_group (it);
    gst_buffer_list_iterator_add (it, outbuf);
    gst_buffer_list_iterator_add (it, buffer);

    gst_buffer_list_iterator_free (it);

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list);
    ret = gst_basertppayload_push_list (basepayload, list);
  } else {
    /* copy payload */
    payload = gst_rtp_buffer_get_payload (outbuf);
    memcpy (payload, GST_BUFFER_DATA (buffer), payload_len);
    gst_buffer_unref (buffer);

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf);
    ret = gst_basertppayload_push (basepayload, outbuf);
  }

  return ret;
}
Exemple #12
0
BufferListIterator::BufferListIterator(const BufferListPtr & list)
{
    m_it = gst_buffer_list_iterate(list);
}
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;
}