/* ------------------------------------------------------------------------ * Video buffers queue management. * * Video queues is initialized by uvc_queue_init(). The function performs * basic initialization of the uvc_video_queue struct and never fails. * * Video buffers are managed by videobuf2. The driver uses a mutex to protect * the videobuf2 queue operations by serializing calls to videobuf2 and a * spinlock to protect the IRQ queue that holds the buffers to be processed by * the driver.
*/
/* * Return all queued buffers to videobuf2 in the requested state. * * This function must be called with the queue spinlock held.
*/ staticvoid __uvc_queue_return_buffers(struct uvc_video_queue *queue, enum uvc_buffer_state state)
{ enum vb2_buffer_state vb2_state = state == UVC_BUF_STATE_ERROR
? VB2_BUF_STATE_ERROR
: VB2_BUF_STATE_QUEUED;
/* * When called with plane sizes, validate them. The driver supports * single planar formats only, and requires buffers to be large enough * to store a complete frame.
*/ if (*nplanes) return *nplanes != 1 || sizes[0] < size ? -EINVAL : 0;
spin_lock_irqsave(&queue->irqlock, flags); if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
kref_init(&buf->ref);
list_add_tail(&buf->queue, &queue->irqqueue);
} else { /* * If the device is disconnected return the buffer to userspace * directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
staticconststruct vb2_ops uvc_meta_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue, /* * .start_streaming is not provided here. Metadata relies on video * streaming being active. If video isn't streaming, then no metadata * will arrive either.
*/
.stop_streaming = uvc_stop_streaming_meta,
};
int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{ int ret;
/* * Cancel the video buffers queue. * * Cancelling the queue marks all buffers on the irq queue as erroneous, * wakes them up and removes them from the queue. * * If the disconnect parameter is set, further calls to uvc_queue_buffer will * fail with -ENODEV. * * This function acquires the irq spinlock and can be called from interrupt * context.
*/ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{ unsignedlong flags;
spin_lock_irqsave(&queue->irqlock, flags);
__uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); /* * This must be protected by the irqlock spinlock to avoid race * conditions between uvc_buffer_queue and the disconnection event that * could result in an interruptible wait in uvc_dequeue_buffer. Do not * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED * state outside the queue code.
*/ if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
/* * uvc_queue_get_current_buffer: Obtain the current working output buffer * * Buffers may span multiple packets, and even URBs, therefore the active buffer * remains on the queue until the EOF marker.
*/ staticstruct uvc_buffer *
__uvc_queue_get_current_buffer(struct uvc_video_queue *queue)
{ if (list_empty(&queue->irqqueue)) return NULL;
/* * uvc_queue_buffer_requeue: Requeue a buffer on our internal irqqueue * * Reuse a buffer through our internal queue without the need to 'prepare'. * The buffer will be returned to userspace through the uvc_buffer_queue call if * the device has been disconnected.
*/ staticvoid uvc_queue_buffer_requeue(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
buf->error = 0;
buf->state = UVC_BUF_STATE_QUEUED;
buf->bytesused = 0;
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
/* * Release a reference on the buffer. Complete the buffer when the last * reference is released.
*/ void uvc_queue_buffer_release(struct uvc_buffer *buf)
{
kref_put(&buf->ref, uvc_queue_buffer_complete);
}
/* * Remove this buffer from the queue. Lifetime will persist while async actions * are still running (if any), and uvc_queue_buffer_release will give the buffer * back to VB2 when all users have completed.
*/ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{ struct uvc_buffer *nextbuf; unsignedlong flags;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.