コード例 #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
ファイル: gstshmsink.c プロジェクト: 0p1pp1/gst-plugins-bad
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;
}
コード例 #3
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;
}