static void
gst_v4l2_allocator_dispose (GObject * obj)
{
  GstV4l2Allocator *allocator = (GstV4l2Allocator *) obj;
  gint i;

  GST_LOG_OBJECT (obj, "called");

  for (i = 0; i < allocator->count; i++) {
    GstV4l2MemoryGroup *group = allocator->groups[i];
    allocator->groups[i] = NULL;
    if (group)
      gst_v4l2_memory_group_free (group);
  }

  G_OBJECT_CLASS (parent_class)->dispose (obj);
}
Exemplo n.º 2
0
GstV4l2Return
gst_v4l2_allocator_stop (GstV4l2Allocator * allocator)
{
  GstV4l2Object *obj = allocator->obj;
  struct v4l2_requestbuffers breq = { 0, obj->type, allocator->memory };
  gint i = 0;
  GstV4l2Return ret = GST_V4L2_OK;

  GST_DEBUG_OBJECT (allocator, "stop allocator");

  GST_OBJECT_LOCK (allocator);

  if (!g_atomic_int_get (&allocator->active))
    goto done;

  if (gst_atomic_queue_length (allocator->free_queue) != allocator->count) {
    GST_DEBUG_OBJECT (allocator, "allocator is still in use");
    ret = GST_V4L2_BUSY;
    goto done;
  }

  while (gst_atomic_queue_pop (allocator->free_queue)) {
    /* nothing */
  };

  for (i = 0; i < allocator->count; i++) {
    GstV4l2MemoryGroup *group = allocator->groups[i];
    allocator->groups[i] = NULL;
    if (group)
      gst_v4l2_memory_group_free (group);
  }

  /* Not all drivers support rebufs(0), so warn only */
  if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0)
    GST_WARNING_OBJECT (allocator,
        "error releasing buffers buffers: %s", g_strerror (errno));

  allocator->count = 0;

  g_atomic_int_set (&allocator->active, FALSE);

done:
  GST_OBJECT_UNLOCK (allocator);
  return ret;
}
static GstV4l2MemoryGroup *
gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index)
{
  gint video_fd = allocator->video_fd;
  guint32 memory = allocator->memory;
  struct v4l2_format *format = &allocator->format;
  GstV4l2MemoryGroup *group;
  gsize img_size, buf_size;

  group = g_slice_new0 (GstV4l2MemoryGroup);

  group->buffer.type = format->type;
  group->buffer.index = index;
  group->buffer.memory = memory;

  if (V4L2_TYPE_IS_MULTIPLANAR (format->type)) {
    group->n_mem = group->buffer.length = format->fmt.pix_mp.num_planes;
    group->buffer.m.planes = group->planes;
  } else {
    group->n_mem = 1;
  }

  if (v4l2_ioctl (video_fd, VIDIOC_QUERYBUF, &group->buffer) < 0)
    goto querybuf_failed;

  if (group->buffer.index != index) {
    GST_ERROR_OBJECT (allocator, "Buffer index returned by VIDIOC_QUERYBUF "
        "didn't match, this indicate the presence of a bug in your driver or "
        "libv4l2");
    g_slice_free (GstV4l2MemoryGroup, group);
    return NULL;
  }

  /* Check that provided size matches the format we have negotiation. Failing
   * there usually means a driver of libv4l bug. */
  if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
    gint i;

    for (i = 0; i < group->n_mem; i++) {
      img_size = allocator->format.fmt.pix_mp.plane_fmt[i].sizeimage;
      buf_size = group->planes[i].length;
      if (buf_size < img_size)
        goto buffer_too_short;
    }
  } else {
    img_size = allocator->format.fmt.pix.sizeimage;
    buf_size = group->buffer.length;
    if (buf_size < img_size)
      goto buffer_too_short;
  }

  /* We save non planar buffer information into the multi-planar plane array
   * to avoid duplicating the code later */
  if (!V4L2_TYPE_IS_MULTIPLANAR (format->type)) {
    group->planes[0].bytesused = group->buffer.bytesused;
    group->planes[0].length = group->buffer.length;
    g_assert (sizeof (group->planes[0].m) == sizeof (group->buffer.m));
    memcpy (&group->planes[0].m, &group->buffer.m, sizeof (group->buffer.m));
  }

  GST_LOG_OBJECT (allocator, "Got %s buffer", memory_type_to_str (memory));
  GST_LOG_OBJECT (allocator, "  index:     %u", group->buffer.index);
  GST_LOG_OBJECT (allocator, "  type:      %d", group->buffer.type);
  GST_LOG_OBJECT (allocator, "  flags:     %08x", group->buffer.flags);
  GST_LOG_OBJECT (allocator, "  field:     %d", group->buffer.field);
  GST_LOG_OBJECT (allocator, "  memory:    %d", group->buffer.memory);
  GST_LOG_OBJECT (allocator, "  planes:    %d", group->n_mem);

#ifndef GST_DISABLE_GST_DEBUG
  if (memory == V4L2_MEMORY_MMAP) {
    gint i;
    for (i = 0; i < group->n_mem; i++) {
      GST_LOG_OBJECT (allocator, "  [%u] bytesused: %u, length: %u", i,
          group->planes[i].bytesused, group->planes[i].length);
      GST_LOG_OBJECT (allocator, "  [%u] MMAP offset:  %u", i,
          group->planes[i].m.mem_offset);
    }
  }
#endif

  return group;

querybuf_failed:
  {
    GST_ERROR ("error querying buffer %d: %s", index, g_strerror (errno));
    goto failed;
  }
buffer_too_short:
  {
    GST_ERROR ("buffer size %" G_GSIZE_FORMAT
        " is smaller then negotiated size %" G_GSIZE_FORMAT
        ", this is usually the result of a bug in the v4l2 driver or libv4l.",
        buf_size, img_size);
    goto failed;
  }
failed:
  gst_v4l2_memory_group_free (group);
  return NULL;
}