近日游玩看了videobuf2相关的videobuf2-v4l2.c,vidoebuf-core.c,
video-vmalloc.c,videobuf2-memops.c,videobuf2-internal.h,
有些感悟,写如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#define dprintk(level, fmt, arg...) \
do { \
printf("vb2: %s: " fmt, __func__, ## arg); \
} while (0)
#define log_memop(vb, op) \
dprintk(2, "call_memop(%p, %d, %s)%s\n", \
(vb)->vb2_queue, (vb)->index, #op, \
(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
#define call_memop(vb, op, args...) \
({ \
struct vb2_queue *_q = (vb)->vb2_queue; \
\
log_memop(vb, op); \
_q->mem_ops->op ? _q->mem_ops->op(args) : 0; \
})
#define log_qop(q, op) \
dprintk(2, "call_qop(%p, %s)%s\n", q, #op, \
(q)->ops->op ? "" : " (nop)")
#define call_qop(q, op, args...) \
({ \
int err; \
\
log_qop(q, op); \
err = (q)->ops->op ? (q)->ops->op(args) : 0; \
if (!err) \
(q)->cnt_ ## op++; \
err; \
})
#define log_vb_qop(vb, op, args...) \
dprintk(2, "call_vb_qop(%p, %d, %s)%s\n", \
(vb)->vb2_queue, (vb)->index, #op, \
(vb)->vb2_queue->ops->op ? "" : " (nop)")
#define call_vb_qop(vb, op, args...) \
({ \
\
log_vb_qop(vb, op); \
(vb)->vb2_queue->ops->op ? \
(vb)->vb2_queue->ops->op(args) : 0; \
})
struct vb2_queue;
#define VB2_MAX_PLANES (8)
struct vb2_buffer
{
struct vb2_queue*vb2_queue;
unsigned int index;
unsigned int cnt_buf_queue;
};
struct vb2_mem_ops
{
void*(*alloc)(void*alloc_ctx,unsigned long size);
void (*put)(void*buf_priv);
void (*prepare)(void*buf_priv);
void (*finish)(void*buf_priv);
int (*mmap)(void*buf_priv,int vma);
};
struct vb2_ops
{
int (*queue_setup)(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[]);
int(*buf_init)(struct vb2_buffer*vb);
int(*buf_prepare)(struct vb2_buffer*vb);
void(*buf_queue)(struct vb2_buffer*vb);
};
struct vb2_buf_ops
{
int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
int(*set_timestamp)(struct vb2_buffer*vb,const void*pb);
};
struct vb2_queue
{
const struct vb2_ops*ops;
const struct vb2_mem_ops*mem_ops;
const struct vb2_buf_ops*buf_ops;
unsigned int plane_sizes[VB2_MAX_PLANES];
void *alloc_ctx[VB2_MAX_PLANES];
unsigned int cnt_queue_setup;
unsigned int cnt_wait_prepare;
unsigned int cnt_wait_finish;
unsigned int cnt_start_streaming;
unsigned int cnt_stop_streaming;
};
static int vb2_queue_setup(struct vb2_queue*vq,const void*
parg,unsigned int*num_buffers,unsigned int*nplanes,unsigned int sizes[],
void*alloc_ctxs[])
{
if(*num_buffers > 32)
*num_buffers = 32;
*nplanes = 1;
sizes[0] = 1920*1080*2;
printf("vb2_queue_setup \n");
}
static void vb2_buf_queue(struct vb2_buffer*vb)
{
printf("vb2_buf_queue \n");
}
static void*vb2_vmalloc_alloc(void*alloc_ctx,unsigned long size)
{
printf("vb2_vmalloc_alloc\n");
}
static int vb2_vmalloc_mmap(void*buf_priv,int vma)
{
printf("vb2_vmalloc_mmap\n");
}
static int vb2_set_timestamp(struct vb2_buffer*vb,const void*pb)
{
printf("vb2_set_timestamp\n");
}
static struct vb2_ops vb2_queue_qops =
{
.queue_setup = vb2_queue_setup,
.buf_queue = vb2_buf_queue,
};
static struct vb2_mem_ops vb2_vmalloc_memops =
{
.alloc = vb2_vmalloc_alloc,
.mmap = vb2_vmalloc_mmap,
};
static const struct vb2_buf_ops v4l2_buf_ops =
{
.set_timestamp = vb2_set_timestamp,
};
struct vb2_queue vb2 =
{
.ops = &vb2_queue_qops,
.mem_ops = &vb2_vmalloc_memops,
.buf_ops = &v4l2_buf_ops,
};
struct vb2_buffer vb_buffer =
{
.vb2_queue = &vb2,
};
int main()
{
unsigned int num_buffers, allocated_buffers, num_planes = 0;
int ret = 0;
call_memop(&vb_buffer,alloc,&vb2.alloc_ctx,num_buffers);
ret = call_qop(&vb2, queue_setup, &vb2, NULL, &num_buffers, &num_planes,
vb2.plane_sizes, vb2.alloc_ctx);
call_vb_qop(&vb_buffer, buf_queue, &vb_buffer);
return 0;
}
root@ubuntu:/nfsroot/callback# ./a.out
vb2: main: call_memop(0x804a080, 0, alloc)
vb2_vmalloc_alloc
vb2: main: call_qop(0x804a080, queue_setup)
vb2_queue_setup
vb2: main: call_vb_qop(0x804a080, 0, buf_queue)
vb2_buf_queue