예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
0
static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv = 0;
  GstMapInfo map;
  gboolean need_new_memory = FALSE;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMemory *memory = NULL;
  GstBuffer *sendbuf = NULL;
  gsize written_bytes;

  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);
      ret = gst_base_sink_wait_preroll (bsink);
      if (ret == GST_FLOW_OK)
        GST_OBJECT_LOCK (self);
      else
        return ret;
    }
  }

  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);
      ret = gst_base_sink_wait_preroll (bsink);
      if (ret == GST_FLOW_OK)
        GST_OBJECT_LOCK (self);
      else
        return ret;
    }
  }


  if (gst_buffer_n_memory (buf) > 1) {
    GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single"
        " one, need to do a memcpy", buf, gst_buffer_n_memory (buf));
    need_new_memory = TRUE;
  } else {
    memory = gst_buffer_peek_memory (buf, 0);

    if (memory->allocator != GST_ALLOCATOR (self->allocator)) {
      need_new_memory = TRUE;
      GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by "
          "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
    }
  }

  if (need_new_memory) {
    if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) {
      gsize area_size = sp_writer_get_max_buf_size (self->pipe);
      GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, (NULL),
          ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than"
              "buffer of size %" G_GSIZE_FORMAT, area_size,
              gst_buffer_get_size (buf)));
      goto error;
    }

    while ((memory =
            gst_shm_sink_allocator_alloc_locked (self->allocator,
                gst_buffer_get_size (buf), &self->params)) == NULL) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        ret = gst_base_sink_wait_preroll (bsink);
        if (ret == GST_FLOW_OK)
          GST_OBJECT_LOCK (self);
        else
          return ret;
      }
    }

    while (self->wait_for_connection && !self->clients) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        ret = gst_base_sink_wait_preroll (bsink);
        if (ret == GST_FLOW_OK) {
          GST_OBJECT_LOCK (self);
        } else {
          gst_memory_unref (memory);
          return ret;
        }
      }
    }

    if (!gst_memory_map (memory, &map, GST_MAP_WRITE)) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to map memory"));
      goto error;
    }

    GST_DEBUG_OBJECT (self,
        "Copying %" G_GSIZE_FORMAT " bytes into map of size %" G_GSIZE_FORMAT
        " bytes.", gst_buffer_get_size (buf), map.size);
    written_bytes = gst_buffer_extract (buf, 0, map.data, map.size);
    GST_DEBUG_OBJECT (self, "Copied %" G_GSIZE_FORMAT " bytes.", written_bytes);
    gst_memory_unmap (memory, &map);

    sendbuf = gst_buffer_new ();
    if (!gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1)) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to copy data into send buffer"));
      gst_buffer_unref (sendbuf);
      goto error;
    }
    gst_buffer_append_memory (sendbuf, memory);
  } else {
    sendbuf = gst_buffer_ref (buf);
  }

  if (!gst_buffer_map (sendbuf, &map, GST_MAP_READ)) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED,
        (NULL), ("Failed to map data into send buffer"));
    goto error;
  }

  /* Make the memory readonly as of now as we've sent it to the other side
   * We know it's not mapped for writing anywhere as we just mapped it for
   * reading
   */
  rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf);
  if (rv == -1) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED,
        (NULL), ("Failed to send data over SHM"));
    gst_buffer_unmap (sendbuf, &map);
    goto error;
  }

  gst_buffer_unmap (sendbuf, &map);

  GST_OBJECT_UNLOCK (self);

  if (rv == 0) {
    GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer");
    gst_buffer_unref (sendbuf);
  }

  return ret;

error:
  GST_OBJECT_UNLOCK (self);
  return GST_FLOW_ERROR;
}
예제 #5
0
static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv = 0;
  GstMapInfo map;
  gboolean need_new_memory = FALSE;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMemory *memory = NULL;
  GstBuffer *sendbuf = NULL;

  GST_OBJECT_LOCK (self);
  while (self->wait_for_connection && !self->clients) {
    g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock)
      goto 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)
      goto flushing;
  }


  if (gst_buffer_n_memory (buf) > 1) {
    GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single"
        " one, need to do a memcpy", buf, gst_buffer_n_memory (buf));
    need_new_memory = TRUE;
  } else {
    memory = gst_buffer_peek_memory (buf, 0);

    if (memory->allocator != GST_ALLOCATOR (self->allocator)) {
      need_new_memory = TRUE;
      GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by "
          "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
    }
  }

  if (need_new_memory) {
    if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) {
      gsize area_size = sp_writer_get_max_buf_size (self->pipe);
      GST_OBJECT_UNLOCK (self);
      GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
          ("Shared memory area is too small"),
          ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than"
              "buffer of size %" G_GSIZE_FORMAT, area_size,
              gst_buffer_get_size (buf)));
      return GST_FLOW_ERROR;
    }

    while ((memory =
            gst_shm_sink_allocator_alloc_locked (self->allocator,
                gst_buffer_get_size (buf), &self->params)) == NULL) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock)
        goto flushing;
    }

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

    gst_memory_map (memory, &map, GST_MAP_WRITE);
    gst_buffer_extract (buf, 0, map.data, map.size);
    gst_memory_unmap (memory, &map);

    sendbuf = gst_buffer_new ();
    gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
    gst_buffer_append_memory (sendbuf, memory);
  } else {
    sendbuf = gst_buffer_ref (buf);
  }

  gst_buffer_map (sendbuf, &map, GST_MAP_READ);
  /* Make the memory readonly as of now as we've sent it to the other side
   * We know it's not mapped for writing anywhere as we just mapped it for
   * reading
   */

  rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf);

  gst_buffer_unmap (sendbuf, &map);

  GST_OBJECT_UNLOCK (self);

  if (rv == 0) {
    GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer");
    gst_buffer_unref (sendbuf);
  } else if (rv == -1) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Invalid allocated buffer"),
        ("The shmpipe library rejects our buffer, this is a bug"));
    ret = GST_FLOW_ERROR;
  }

  /* If we allocated our own memory, then unmap it */

  return ret;

flushing:
  GST_OBJECT_UNLOCK (self);
  return GST_FLOW_FLUSHING;
}