static GstV4l2MemoryGroup * gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator) { GstV4l2Object *obj = allocator->obj; struct v4l2_create_buffers bcreate = { 0 }; GstV4l2MemoryGroup *group = NULL; GST_OBJECT_LOCK (allocator); if (!g_atomic_int_get (&allocator->active)) goto done; bcreate.memory = allocator->memory; bcreate.format = obj->format; bcreate.count = 1; if (!allocator->can_allocate) goto done; if (obj->ioctl (obj->video_fd, VIDIOC_CREATE_BUFS, &bcreate) < 0) goto create_bufs_failed; if (allocator->groups[bcreate.index] != NULL) goto create_bufs_bug; group = gst_v4l2_memory_group_new (allocator, bcreate.index); if (group) { allocator->groups[bcreate.index] = group; allocator->count++; } done: GST_OBJECT_UNLOCK (allocator); return group; create_bufs_failed: { GST_WARNING_OBJECT (allocator, "error creating a new buffer: %s", g_strerror (errno)); goto done; } create_bufs_bug: { GST_ERROR_OBJECT (allocator, "created buffer has already used buffer " "index %i, this means there is an bug in your driver or libv4l2", bcreate.index); goto done; } }
guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, guint32 memory) { struct v4l2_requestbuffers breq = { count, allocator->type, memory }; gboolean can_allocate; gint i; g_return_val_if_fail (count != 0, 0); GST_OBJECT_LOCK (allocator); if (g_atomic_int_get (&allocator->active)) goto already_active; if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) < 0) goto reqbufs_failed; if (breq.count < 1) goto out_of_memory; switch (memory) { case V4L2_MEMORY_MMAP: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (allocator, MMAP); break; case V4L2_MEMORY_USERPTR: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (allocator, USERPTR); break; case V4L2_MEMORY_DMABUF: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (allocator, DMABUF); break; default: can_allocate = FALSE; break; } GST_DEBUG_OBJECT (allocator, "allocated %u %s buffers out of %u requested", breq.count, memory_type_to_str (memory), count); allocator->can_allocate = can_allocate; allocator->count = breq.count; allocator->memory = memory; /* Create memory groups */ for (i = 0; i < allocator->count; i++) { allocator->groups[i] = gst_v4l2_memory_group_new (allocator, i); if (allocator->groups[i] == NULL) goto error; gst_atomic_queue_push (allocator->free_queue, allocator->groups[i]); } g_atomic_int_set (&allocator->active, TRUE); done: GST_OBJECT_UNLOCK (allocator); return breq.count; already_active: { GST_ERROR_OBJECT (allocator, "allocator already active"); goto error; } reqbufs_failed: { GST_ERROR_OBJECT (allocator, "error requesting %d buffers: %s", count, g_strerror (errno)); goto error; } out_of_memory: { GST_ERROR_OBJECT (allocator, "Not enough memory to allocate buffers"); goto error; } error: { breq.count = 0; goto done; } }