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); }
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; }