GstV4l2MemoryGroup *
gst_v4l2_allocator_alloc_dmabufin (GstV4l2Allocator * allocator)
{
  GstV4l2MemoryGroup *group;
  gint i;

  g_return_val_if_fail (allocator->memory == V4L2_MEMORY_DMABUF, NULL);

  group = gst_v4l2_allocator_alloc (allocator);

  if (group == NULL)
    return NULL;

  GST_LOG_OBJECT (allocator, "allocating empty DMABUF import group");

  for (i = 0; i < group->n_mem; i++) {
    if (group->mem[i] == NULL) {
      group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
          NULL, 0, 0, 0, 0, i, NULL, -1, group);
    } else {
      /* Take back the allocator reference */
      gst_object_ref (allocator);
    }

    group->mems_allocated++;
  }

  gst_v4l2_allocator_clear_dmabufin (allocator, group);

  return group;
}
Пример #2
0
GstV4l2MemoryGroup *
gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator)
{
  GstV4l2Object *obj = allocator->obj;
  GstV4l2MemoryGroup *group;
  gint i;

  g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL);

  group = gst_v4l2_allocator_alloc (allocator);

  if (group == NULL)
    return NULL;

  for (i = 0; i < group->n_mem; i++) {
    if (group->mem[i] == NULL) {
      gpointer data;
      data = obj->mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE,
          MAP_SHARED, obj->video_fd, group->planes[i].m.mem_offset);

      if (data == MAP_FAILED)
        goto mmap_failed;

      GST_LOG_OBJECT (allocator,
          "mmap buffer length %d, data offset %d, plane %d",
          group->planes[i].length, group->planes[i].data_offset, i);

      group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
          NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, data,
          -1, group);
    } else {
      /* Take back the allocator reference */
      gst_object_ref (allocator);
    }

    group->mems_allocated++;
  }

  /* Ensure group size. Unlike GST, v4l2 have size (bytesused) initially set
   * to 0. As length might be bigger then the expected size exposed in the
   * format, we simply set bytesused initially and reset it here for
   * simplicity */
  gst_v4l2_allocator_reset_size (allocator, group);

  return group;

mmap_failed:
  {
    GST_ERROR_OBJECT (allocator, "Failed to mmap buffer: %s",
        g_strerror (errno));
    _cleanup_failed_alloc (allocator, group);
    return NULL;
  }
}
static GstV4l2Memory *
_v4l2mem_share (GstV4l2Memory * mem, gssize offset, gsize size)
{
  GstV4l2Memory *sub;
  GstMemory *parent;

  /* find the real parent */
  if ((parent = mem->mem.parent) == NULL)
    parent = (GstMemory *) mem;

  if (size == -1)
    size = mem->mem.size - offset;

  /* the shared memory is always readonly */
  sub = _v4l2mem_new (GST_MINI_OBJECT_FLAGS (parent) |
      GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent,
      mem->mem.maxsize, mem->mem.align, offset, size, mem->plane, mem->data,
      -1, mem->group);

  return sub;
}
GstV4l2MemoryGroup *
gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
    GstAllocator * dmabuf_allocator)
{
  GstV4l2MemoryGroup *group;
  gint i;

  g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL);

  group = gst_v4l2_allocator_alloc (allocator);

  if (group == NULL)
    return NULL;

  for (i = 0; i < group->n_mem; i++) {
    GstV4l2Memory *mem;
    GstMemory *dma_mem;
    gint dmafd;

    if (group->mem[i] == NULL) {
      struct v4l2_exportbuffer expbuf = { 0 };

      expbuf.type = allocator->type;
      expbuf.index = group->buffer.index;
      expbuf.plane = i;
      expbuf.flags = O_CLOEXEC | O_RDWR;

      if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0)
        goto expbuf_failed;

      GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d",
          expbuf.fd, i);

      group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator),
          NULL, group->planes[i].length, 0, 0, group->planes[i].length, i,
          NULL, expbuf.fd, group);
    } else {
      /* Take back the allocator reference */
      gst_object_ref (allocator);
    }

    g_assert (gst_is_v4l2_memory (group->mem[i]));
    mem = (GstV4l2Memory *) group->mem[i];

    if ((dmafd = dup (mem->dmafd)) < 0)
      goto dup_failed;

    dma_mem = gst_dmabuf_allocator_alloc (dmabuf_allocator, dmafd,
        mem->mem.maxsize);

    gst_mini_object_set_qdata (GST_MINI_OBJECT (dma_mem),
        GST_V4L2_MEMORY_QUARK, mem, (GDestroyNotify) gst_memory_unref);

    group->mem[i] = dma_mem;
    group->mems_allocated++;
  }

  gst_v4l2_allocator_reset_size (allocator, group);

  return group;

expbuf_failed:
  {
    GST_ERROR_OBJECT (allocator, "Failed to export DMABUF: %s",
        g_strerror (errno));
    goto cleanup;
  }
dup_failed:
  {
    GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s",
        g_strerror (errno));
    goto cleanup;
  }
cleanup:
  {
    _cleanup_failed_alloc (allocator, group);
    return NULL;
  }
}