Linux/drivers/media/v4l2-core/videobuf2-core.c
时间紧迫,粗略读了一下,这个函数的实现,得到以下结论:
(1)用户空间请求驱动分配内存,建立缓冲,要传递这个宏给驱动,实际执行的函数就是下面这个。
用户空间会传递 struct v4l2_requestbuffers *req 结构体,带有请求信息,给驱动的vidioc_reqbufs 处理者来处理。
(2)驱动会有一个回调函数,叫做queue_setup() 来执行设置缓冲区的操作。
(3)当vb2_reqbufs 已经被调用过了,但是,缓冲不处于in use的状态,那么可以free掉,重新按照这次的要求,分配内存。
(4)如果请求为缓冲队列分配的空间req->count是0,那么会释放掉所有内存,返回。
(5)请求分配的内存空间,不能超过VIDEO_MAX_FRAME大小。
(6)会检查驱动是否可以按照请求来分配内存,这部分操作的接口,我不太懂。
(7)如果驱动ok,那么req->count 会被设置为实际分配的缓冲大小。
(8) for MMAP memory type, allocates actual video memory, using the memory handling/allocation routines provided during queue initialization
对于MMAP的内存操作的函数,是在队列初始化的时候给出的。
597 /**
598 * __reqbufs() - Initiate streaming
599 * @q: videobuf2 queue
600 * @req: struct passed from userspace to vidioc_reqbufs handler in driver 从用户空间传递到驱动中的vidioc_reqbufs handler ,这不是要求分配缓冲空间么???
601 *
602 * Should be called from vidioc_reqbufs ioctl handler of a driver.
603 * This function:
604 * 1) verifies streaming parameters passed from the userspace,
605 * 2) sets up the queue,
606 * 3) negotiates商议 number of buffers and planes per buffer with the driver to be used during streaming,
608 * 4) allocates internal buffer structures (struct vb2_buffer), according to the agreed parameters, 分配内部缓冲
610 * 5) for MMAP memory type, allocates actual video memory, using the
611 * memory handling/allocation routines provided during queue initialization
612 *
613 * If req->count is 0, all the memory will be freed instead.
614 * If the queue has been allocated previously (by a previous vb2_reqbufs) call
615 * and the queue is not busy, memory will be reallocated. 还有重新被分配的情况。
616 *
617 * The return values from this function are intended to be directly returned
618 * from vidioc_reqbufs handler in driver.
619 */
//给 vb2_queue 分配内存空间。
620 static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
621 {
622 unsigned int num_buffers, allocated_buffers, num_planes = 0;
623 int ret;
624
625 if (q->streaming) {
626 dprintk(1, "reqbufs: streaming active\n");
627 return -EBUSY;
628 }
629
//q->num_buffers != 0 代表缓冲已经被分配了???
630 if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
631 /*
632 * We already have buffers allocated, so first check if they
633 * are not in use and can be freed.
634 */
635 if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) { //检查缓冲是否被使用中。
636 dprintk(1, "reqbufs: memory in use, cannot free\n");
637 return -EBUSY;
638 }
639
//不在使用中,可以被free掉,然后重新分配。。
640 __vb2_queue_free(q, q->num_buffers);
641
642 /*
643 * In case of REQBUFS(0) return immediately without calling
644 * driver's queue_setup() callback and allocating resources.
645 */
646 if (req->count == 0)
647 return 0;
648 }
649
650 /*
651 * Make sure the requested values and current defaults are sane健全的.
652 */
//要求分配的空间大小
653 num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
654 memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
655 memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
656 q->memory = req->memory;
657
658 /*
659 * Ask the driver how many buffers and planes per buffer it requires.
660 * Driver also sets the size and allocator context for each plane.
661 */
662 ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
663 q->plane_sizes, q->alloc_ctx);
664 if (ret)
665 return ret;
666
667 /* Finally, allocate buffers and video memory 分配缓冲空间*/
668 ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
669 if (ret == 0) {
670 dprintk(1, "Memory allocation failed\n");
671 return -ENOMEM;
672 }
673
674 allocated_buffers = ret;
675
676 /*
677 * Check if driver can handle the allocated number of buffers.
678 */
679 if (allocated_buffers < num_buffers) {
680 num_buffers = allocated_buffers;
681
682 ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
683 &num_planes, q->plane_sizes, q->alloc_ctx);
684
685 if (!ret && allocated_buffers < num_buffers)
686 ret = -ENOMEM;
687
688 /*
689 * Either the driver has accepted a smaller number of buffers,
690 * or .queue_setup() returned an error
691 */
692 }
693
694 q->num_buffers = allocated_buffers; //缓冲大小
695
696 if (ret < 0) {
697 __vb2_queue_free(q, allocated_buffers);
698 return ret;
699 }
700
701 /*
702 * Return the number of successfully allocated buffers to the userspace.
704 */
705 req->count = allocated_buffers; //分配的实际缓冲大小
706
707 return 0;
708 }
709 封装。。。,暴露给应用程序用。
710 /**
711 * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
712 * type values.
713 * @q: videobuf2 queue
714 * @req: struct passed from userspace to vidioc_reqbufs handler in driver
715 */
716 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
717 {
718 int ret = __verify_memory_type(q, req->memory, req->type);
719
720 return ret ? ret : __reqbufs(q, req);
721 }
722 EXPORT_SYMBOL_GPL(vb2_reqbufs);