static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv;
  GstMapInfo map;

  GST_OBJECT_LOCK (self);
  while (self->wait_for_connection && !self->clients) {
    g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock) {
      GST_OBJECT_UNLOCK (self);
      return GST_FLOW_FLUSHING;
    }
  }

  while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) {
    g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock) {
      GST_OBJECT_UNLOCK (self);
      return GST_FLOW_FLUSHING;
    }
  }

  gst_buffer_map (buf, &map, GST_MAP_READ);
  rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size,
      GST_BUFFER_TIMESTAMP (buf));
  gst_buffer_unmap (buf, &map);

  if (rv == -1) {
    ShmBlock *block = NULL;
    gchar *shmbuf = NULL;
    while ((block = sp_writer_alloc_block (self->pipe,
                gst_buffer_get_size (buf))) == NULL) {
      g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        return GST_FLOW_FLUSHING;
      }
    }
    while (self->wait_for_connection && !self->clients) {
      g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        sp_writer_free_block (block);
        GST_OBJECT_UNLOCK (self);
        return GST_FLOW_FLUSHING;
      }
    }

    shmbuf = sp_writer_block_get_buf (block);
    gst_buffer_extract (buf, 0, shmbuf, gst_buffer_get_size (buf));
    sp_writer_send_buf (self->pipe, shmbuf, gst_buffer_get_size (buf),
        GST_BUFFER_TIMESTAMP (buf));
    sp_writer_free_block (block);
  }

  GST_OBJECT_UNLOCK (self);

  return GST_FLOW_OK;
}
Exemple #2
0
static GstMemory *
gst_shm_sink_allocator_alloc_locked (GstShmSinkAllocator * self, gsize size,
    GstAllocationParams * params)
{
  GstMemory *memory = NULL;
  ShmBlock *block = NULL;
  gsize maxsize = size + params->prefix + params->padding;
  gsize align = params->align;

  /* ensure configured alignment */
  align |= gst_memory_alignment;
  /* allocate more to compensate for alignment */
  maxsize += align;

  block = sp_writer_alloc_block (self->sink->pipe, maxsize);
  if (block) {
    GstShmSinkMemory *mymem;
    gsize aoffset, padding;

    GST_LOG_OBJECT (self,
        "Allocated block %p with %" G_GSIZE_FORMAT " bytes at %p", block, size,
        sp_writer_block_get_buf (block));

    mymem = g_slice_new0 (GstShmSinkMemory);
    memory = GST_MEMORY_CAST (mymem);
    mymem->data = sp_writer_block_get_buf (block);
    mymem->sink = gst_object_ref (self->sink);
    mymem->block = block;

    /* do alignment */
    if ((aoffset = ((guintptr) mymem->data & align))) {
      aoffset = (align + 1) - aoffset;
      mymem->data += aoffset;
      maxsize -= aoffset;
    }

    if (params->prefix && (params->flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
      memset (mymem->data, 0, params->prefix);

    padding = maxsize - (params->prefix + size);
    if (padding && (params->flags & GST_MEMORY_FLAG_ZERO_PADDED))
      memset (mymem->data + params->prefix + size, 0, padding);

    gst_memory_init (memory, params->flags,
        GST_ALLOCATOR_CAST (g_object_ref (self)), NULL, maxsize, align,
        params->prefix, size);
  }

  return memory;
}
Exemple #3
0
static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv;

  GST_OBJECT_LOCK (self);
  while (self->wait_for_connection && !self->clients) {
    g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock) {
      GST_OBJECT_UNLOCK (self);
      return GST_FLOW_WRONG_STATE;
    }
  }

  rv = sp_writer_send_buf (self->pipe, (char *) GST_BUFFER_DATA (buf),
      GST_BUFFER_SIZE (buf));

  if (rv == -1) {
    ShmBlock *block = NULL;
    gchar *shmbuf = NULL;
    while ((block = sp_writer_alloc_block (self->pipe,
                GST_BUFFER_SIZE (buf))) == NULL) {
      g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        return GST_FLOW_WRONG_STATE;
      }
    }
    while (self->wait_for_connection && !self->clients) {
      g_cond_wait (self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        sp_writer_free_block (block);
        GST_OBJECT_UNLOCK (self);
        return GST_FLOW_WRONG_STATE;
      }
    }


    shmbuf = sp_writer_block_get_buf (block);
    memcpy (shmbuf, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
    sp_writer_send_buf (self->pipe, shmbuf, GST_BUFFER_SIZE (buf));
    sp_writer_free_block (block);
  }

  GST_OBJECT_UNLOCK (self);

  return GST_FLOW_OK;
}
static GstFlowReturn
gst_shm_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
    GstCaps * caps, GstBuffer ** out_buf)
{
  GstShmSink *self = GST_SHM_SINK (sink);
  GstBuffer *buffer;
  ShmBlock *block = NULL;
  gpointer buf = NULL;

  GST_OBJECT_LOCK (self);
  block = sp_writer_alloc_block (self->pipe, size);
  if (block) {
    buf = sp_writer_block_get_buf (block);
    g_object_ref (self);
  }
  GST_OBJECT_UNLOCK (self);

  if (block) {
    buffer = gst_buffer_new ();
    GST_BUFFER_DATA (buffer) = buf;
    GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) block;
    GST_BUFFER_FREE_FUNC (buffer) =
        GST_DEBUG_FUNCPTR (gst_shm_sink_free_buffer);
    GST_BUFFER_SIZE (buffer) = size;
    GST_LOG_OBJECT (self,
        "Allocated buffer of %u bytes from shared memory at %p", size, buf);
  } else {
    buffer = gst_buffer_new_and_alloc (size);
    GST_LOG_OBJECT (self, "Not enough shared memory for buffer of %u bytes, "
        "allocating using standard allocator", size);
  }

  GST_BUFFER_OFFSET (buffer) = offset;
  gst_buffer_set_caps (buffer, caps);

  *out_buf = buffer;

  return GST_FLOW_OK;
}
Exemple #5
0
/**
 * shm_writer_send_buffer
 * @self: the #ShmWriter with which to send the data buffer
 * @buffer: the data buffer to send to all connected clients
 * @len: the length of the data @buffer
 *
 * Sends a buffer of data to all connected clients. The data is internally
 * copied into the appropriate shm area so the passed buffer doesn't need
 * to be saved.
 *
 * Returns: the number of clients the buffer was successfully sent to or %-1
 *          on error. This number only signifies that it was sent successfully,
 *          not that the clients processed it successfully.
 */
int
shm_writer_send_buffer (ShmWriter *self, const gchar *buffer, gsize len)
{
  ShmWriterPrivate *priv = self->priv;
  ShmBlock *block;
  gchar *buf;
  int ret;

  if (!priv->open)
    {
      g_debug ("ShmWriter not open");
      return SHM_WRITER_FAILURE;
    }

  /* Allocating, copying, and freeing all this may seem silly,
   * but the data needs to be in the correct range in memory
   * in order to share it with other processes */
  g_mutex_lock (priv->lock);
  block = sp_writer_alloc_block (priv->writer, len);

  if (block == NULL)
    {
      g_debug ("ShmWriter: unable to allocate block");
      g_mutex_unlock (priv->lock);
      return SHM_WRITER_FAILURE;
    }

  buf = sp_writer_block_get_buf (block);
  memcpy (buf, buffer, len);

  ret = sp_writer_send_buf (priv->writer, buf, len);

  sp_writer_free_block (block);
  g_mutex_unlock (priv->lock);
  return ret;
}