Files
AC707N/SDK/apps/common/device/usb/host/videobuf.c
T
2025-12-03 11:12:34 +08:00

296 lines
6.9 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".usb.data.bss")
#pragma data_seg(".usb.data")
#pragma code_seg(".usb.text")
#pragma const_seg(".usb.text.const")
#pragma str_literal_override(".usb.text.const")
#endif
#include "videobuf.h"
/* #include "video/video_ioctl.h" */
/* #include "system/malloc.h" */
#include "irq.h"
#include "asm/debug.h"
#include "debug.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
void videobuf_queue_init(struct videobuf_queue *q, int align, const char *name)
{
q->ref = 0;
q->buf = NULL;
q->lbuf = NULL;
q->align = align;
q->streaming = 0;
q->name = name;
os_sem_create(&q->sem, 0);
}
void videobuf_queue_release(struct videobuf_queue *q)
{
if (q->buf) {
/* free(q->buf); */
free_psram(q->buf);
q->buf = NULL;
}
}
int videobuf_reqbufs(struct videobuf_queue *q, struct video_reqbufs *req)
{
if (q->lbuf) {
return 0;
}
if (!req->buf) {
/* q->buf = (void *)malloc(req->size); */
q->buf = (void *)malloc_psram(req->size);
if (!q->buf) {
printf("-----------no-mem: size=%x\n", req->size);
return -ENOMEM;
}
req->buf = q->buf;
}
q->lbuf = lbuf_init(req->buf, req->size, q->align, sizeof(struct videobuf_buffer));
return 0;
}
int videobuf_snoop_buf(struct videobuf_queue *q, struct video_buffer *b)
{
printf("\n [ERROR] %s -[no defined] %d\n ", __FUNCTION__, __LINE__);
return 0;
#if 0
int err = 0;
struct videobuf_buffer *buf;
while (1) {
buf = lbuf_snoop(q->lbuf, BIT(b->index));
if (buf) {
if ((q->streaming & BIT(b->index))) {
break;
}
log_info("\n\n\n\n\n\nmmmmmm %x, %x\n\n\n\n\n\n\n\n\n", q->streaming, b->index);
ASSERT(buf && buf->magic == 0x56784321, ", %s, %x, %x, %s, \n", q->name,
(u32)buf, (u32)buf->magic, __func__);
} else {
if (b->noblock) {
b->len = 0;
return 0;
}
if (!(q->streaming & BIT(b->index))) {
b->len = 0;
return -EINVAL;
}
err = os_sem_pend(&q->sem, b->timeout / 10);
if (err != OS_ERR_NONE) {
return err;
}
}
}
ASSERT(buf && buf->magic == 0x56784321, ", %s, %x, %x, %s, \n", q->name,
(u32)buf, (u32)buf->magic, __func__);
b->baddr = (u32)buf->data;
b->len = buf->len;
b->priv = buf;
b->time_msec = buf->msec;
return 0;
#endif
}
int videobuf_dqbuf(struct videobuf_queue *q, struct video_buffer *b)
{
int err = 0;
struct videobuf_buffer *buf;
while (1) {
buf = lbuf_pop(q->lbuf, BIT(b->index));
if (buf) {
if ((q->streaming & BIT(b->index))) {
break;
}
log_info("\n\n\n\n\n\nmmmmmm %x, %x\n\n\n\n\n\n\n\n\n", q->streaming, b->index);
ASSERT(buf && buf->magic == 0x56784321, ", %s, %x, %x, %s, \n", q->name,
(u32)buf, (u32)buf->magic, __func__);
lbuf_free(buf);
} else {
if (b->noblock) {
b->len = 0;
return 0;
}
if (!(q->streaming & BIT(b->index))) {
b->len = 0;
return -EINVAL;
}
err = os_sem_pend(&q->sem, b->timeout / 10);
if (err != OS_ERR_NONE) {
return err;
}
}
}
ASSERT(buf && buf->magic == 0x56784321, ", %s, %x, %x, %s, \n", q->name,
(u32)buf, (u32)buf->magic, __func__);
b->baddr = (u32)buf->data;
b->len = buf->len;
b->priv = buf;
b->time_msec = buf->msec;
return 0;
}
int videobuf_qbuf(struct videobuf_queue *q, struct video_buffer *b)
{
struct videobuf_buffer *buf = (struct videobuf_buffer *)b->priv;
ASSERT(buf && buf->magic == 0x56784321, ", %s, %x, %x, %s, \n", q->name,
(u32)buf, (u32)buf->magic, __func__);
lbuf_free(b->priv);
return 0;
}
int videobuf_streamon(struct videobuf_queue *q, u8 *channel)
{
int i;
struct lbuff_state s;
if (q->streaming == 0) {
//判断之前是否有未释放的buf
ASSERT(lbuf_empty(q->lbuf) == 1, "videobuf not free completed, %s\n", q->name);
lbuf_state(q->lbuf, &s);
if (s.fragment != 1) {
lbuf_dump(q->lbuf);
ASSERT(s.fragment == 1, "videobuf not free completed, %s\n", q->name);
}
} else {
//ASSERT(lbuf_pop(q->lbuf, BIT(channel)) == NULL);
}
for (i = 0; i < 8; i++) {
if (!(q->streaming & BIT(i))) {
*channel = i;
q->streaming |= BIT(i);
return 0;
}
}
return -EFAULT;
}
int videobuf_clear_stream(struct videobuf_queue *q, u8 channel)
{
struct videobuf_buffer *b;
do {
b = lbuf_pop(q->lbuf, BIT(channel));
if (b) {
lbuf_free(b);
}
} while (b);
return 0;
}
int videobuf_streamoff(struct videobuf_queue *q, u8 channel)
{
struct videobuf_buffer *b;
q->streaming &= ~BIT(channel);
videobuf_clear_stream(q, channel);
os_sem_post(&q->sem);
return 0;
}
struct videobuf_buffer *videobuf_stream_alloc(struct videobuf_queue *q, u32 size)
{
struct videobuf_buffer *b;
ASSERT(q->lbuf, "%s\n", q->name);
b = lbuf_alloc(q->lbuf, size);
if (b) {
b->magic = 0x56784321;
}
return b;
}
u32 videobuf_stream_free_space(struct videobuf_queue *q)
{
ASSERT(q->lbuf, "%s\n", q->name);
return lbuf_free_space(q->lbuf);
}
struct videobuf_buffer *videobuf_stream_realloc(struct videobuf_queue *q,
struct videobuf_buffer *b, int size)
{
ASSERT(b && b->magic == 0x56784321, "%s, %x, %x, %s\n", q->name, (u32)b,
(u32)b->magic, __func__);
return lbuf_realloc(b, size);
}
void videobuf_stream_free(struct videobuf_queue *q, struct videobuf_buffer *b)
{
ASSERT(b && b->magic == 0x56784321, "%s, %x, %x, %s\n", q->name, (u32)b,
(u32)b->magic, __func__);
lbuf_free(b);
}
int videobuf_stream_finish(struct videobuf_queue *q, struct videobuf_buffer *b)
{
ASSERT(b && b->magic == 0x56784321, "%s, %x, %x, %s\n", q->name, (u32)b,
(u32)b->magic, __func__);
if (q->streaming == 0) {
/* log_i("\n\n\n\n\n\ntttt %x, %s\n\n\n\n\n\n\n\n\n", q->streaming, q->name); */
lbuf_free(b);
return -EINVAL;
}
lbuf_push(b, q->streaming);
os_sem_set(&q->sem, 0);
os_sem_post(&q->sem);
return 0;
}
int videobuf_query(struct videobuf_queue *q, struct videobuf_state *sta)
{
struct lbuff_state lbuf_sta;
if (sta) {
lbuf_state(q->lbuf, &lbuf_sta);
sta->available_len = lbuf_sta.avaliable;
sta->max_continue_len = lbuf_sta.max_continue_len;
}
return lbuf_traversal(q->lbuf);
}