Files
TAIXIN/sdk/lib/multimedia/msi/fbqueue.c

269 lines
5.7 KiB
C
Raw Normal View History

#include "basic_include.h"
#include "lib/multimedia/msi.h"
#ifdef MORE_SRAM
#define FBQ_MALLOC os_malloc_psram
#define FBQ_FREE os_free_psram
#define FBQ_ZALLOC os_zalloc_psram
#else
#define FBQ_MALLOC os_malloc
#define FBQ_FREE os_free
#define FBQ_ZALLOC os_zalloc
#endif
int32 fbq_init(struct fbqueue *q, uint8 *qbuff, int32 qsize)
{
if (qbuff == NULL && qsize) {
qbuff = (uint8 *)FBQ_MALLOC(sizeof(struct framebuff *) * (qsize + 1));
q->alloc = 1;
}
ASSERT(qbuff);
if (qbuff && qsize) {
RB_INIT_R(&q->rbQ, (qsize + 1), (struct framebuff **)qbuff);
os_sema_init(&q->sema, 0);
q->reader_max = 1;
q->readers = NULL;
q->init = 1;
return RET_OK;
}
return RET_ERR;
}
int32 fbq_destory(struct fbqueue *q)
{
if (q && q->init) {
while (RB_COUNT(&q->rbQ)) {
fb_put(fbq_dequeue(q, 0));
}
if (q->alloc) {
FBQ_FREE(q->rbQ.rbq);
}
if (q->readers) {
FBQ_FREE(q->readers);
}
os_sema_del(&q->sema);
q->init = 0;
}
return RET_OK;
}
int32 fbq_enqueue(struct fbqueue *q, struct framebuff *fb)
{
int32 ret;
uint32 i;
uint32 rpos;
uint32 flags;
struct framebuff *last = NULL;
if (!q || !q->init || !fb) {
return 0;
}
fb_get(fb);
if (q->reader_max > 1) {
flags = disable_irq();
if (RB_FULL(&q->rbQ)) { // FULL ! move rpos.
last = q->rbQ.rbq[q->rbQ.rpos];
rpos = RB_NPOS(&q->rbQ, rpos, 1);
for (i = 0; i < q->reader_max; i++) {
if (q->readers[i] == q->rbQ.rpos) {
q->readers[i] = rpos;
}
}
q->rbQ.rpos = rpos;
}
q->rbQ.rbq[q->rbQ.wpos] = fb;
q->rbQ.wpos = RB_NPOS(&q->rbQ, wpos, 1);
enable_irq(flags);
fb_put(last);
return 1;
} else {
ret = RB_INT_SET(&q->rbQ, fb);
if (ret) {
os_sema_up(&q->sema);
return 1;
} else {
fb_put(fb);
return 0;
}
}
}
static int32 fbq_trace_pos(struct fbqueue *q, struct framebuff *fb, uint32 start, uint32 end, int8 discard)
{
uint32 pos;
for (pos = start; pos < end; pos++) {
if (q->rbQ.rbq[pos] == fb) {
if (discard) {
q->rbQ.rbq[pos] = NULL;
}
return 1;
}
}
return 0;
}
int32 fbq_trace(struct fbqueue *q, struct framebuff *fb, int8 discard)
{
uint32 ret = 0;
uint32 flag;
if (!q || !q->init || !fb) {
return 0;
}
flag = disable_irq();
if (q->rbQ.rpos <= q->rbQ.wpos) {
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.wpos, discard);
} else {
ret = fbq_trace_pos(q, fb, 0, q->rbQ.wpos, discard);
if (!ret) {
ret = fbq_trace_pos(q, fb, q->rbQ.rpos, q->rbQ.qsize, discard);
}
}
enable_irq(flag);
if (ret && discard) {
fb_put(fb);
}
return 0;
}
struct framebuff *fbq_dequeue(struct fbqueue *q, uint32 tmo_ms)
{
uint64 jiff;
struct framebuff *fb;
if (!q || !q->init) {
return NULL;
}
do {
if (!RB_EMPTY(&q->rbQ)) {
RB_GET(&q->rbQ, fb);
return fb;
}
if(tmo_ms == 0){
return NULL;
}
jiff = os_jiffies();
os_sema_down(&q->sema, tmo_ms);
jiff = DIFF_JIFFIES(jiff, os_jiffies());
jiff = os_jiffies_to_msecs(jiff);
if (jiff >= tmo_ms) {
break;
}
tmo_ms -= jiff;
} while (tmo_ms);
return NULL;
}
struct framebuff *fbq_dequeue_r(struct fbqueue *q, uint8 reader)
{
uint32 i = 0;
uint32 pos;
uint32 flags;
struct framebuff *fb = NULL;
struct framebuff *last = NULL;
if (!q || !q->init) {
return NULL;
}
ASSERT(reader > 0 && reader <= q->reader_max);
ASSERT(q->readers[reader - 1] != 0xffffffff);
reader -= 1;
flags = disable_irq();
pos = q->readers[reader];
if (pos == q->rbQ.wpos) { //no fb for this reader
enable_irq(flags);
return fb;
}
fb = q->rbQ.rbq[pos];
q->readers[reader] = NEXT_RPOS(pos, q->rbQ.qsize, 1);
//move rpos: find min pos.
pos = 0xffffffff;
for (i = 0; i < q->reader_max; i++) {
if (q->readers[i] < pos) {
pos = q->readers[i];
}
}
if (pos != 0xffffffff && q->rbQ.rpos != pos) {
last = q->rbQ.rbq[q->rbQ.rpos];
q->rbQ.rpos = pos;
}
fb_get(fb);
enable_irq(flags);
fb_put(last);
return fb;
}
int32 fbq_conf_readers(struct fbqueue *q, uint16 reader_max)
{
uint32 i;
uint32 *ptr;
if (!q || !q->init || reader_max <= 1 || q->readers) {
return -EINVAL;
}
ptr = (uint32 *)FBQ_MALLOC(reader_max * sizeof(uint32));
if (ptr) {
for (i = 0; i < q->reader_max; i++) {
q->readers[i] = 0xffffffff;
}
q->readers = ptr;
q->reader_max = reader_max;
return RET_OK;
}
return -ENOMEM;
}
int32 fbq_open_reader(struct fbqueue *q)
{
uint32 i;
uint32 flags;
if (!q || !q->init || !q->readers) {
return 0;
}
flags = disable_irq();
for (i = 0; i < q->reader_max; i++) {
if (q->readers[i] == 0xffffffff) {
q->readers[i] = q->rbQ.rpos;
break;
}
}
enable_irq(flags);
return i < q->reader_max ? (i + 1) : 0;
}
int32 fbq_close_reader(struct fbqueue *q, uint8 reader)
{
uint32 flags;
if (!q || !q->init || !q->readers) {
return -EINVAL;
}
ASSERT(reader > 0 && reader <= q->reader_max);
flags = disable_irq();
q->readers[reader - 1] = 0xffffffff;
enable_irq(flags);
return RET_OK;
}