186 lines
4.2 KiB
C
186 lines
4.2 KiB
C
#include <libavformat/avformat.h>
|
|
|
|
#include <rthreads/rthreads.h>
|
|
|
|
#include "swsbuffer.h"
|
|
|
|
enum kbStatus
|
|
{
|
|
KB_OPEN,
|
|
KB_IN_PROGRESS,
|
|
KB_FINISHED
|
|
};
|
|
|
|
struct swsbuffer
|
|
{
|
|
sws_context_t *buffer;
|
|
enum kbStatus *status;
|
|
size_t size;
|
|
slock_t *lock;
|
|
int64_t head;
|
|
int64_t tail;
|
|
};
|
|
|
|
swsbuffer_t *swsbuffer_create(size_t num, int frame_size, int width, int height)
|
|
{
|
|
swsbuffer_t *b = malloc(sizeof (swsbuffer_t));
|
|
if (b == NULL)
|
|
return NULL;
|
|
|
|
b->status = malloc(sizeof(enum kbStatus) * num);
|
|
if (b->status == NULL)
|
|
return NULL;
|
|
for (int i = 0; i < num; i++)
|
|
b->status[i] = KB_OPEN;
|
|
|
|
b->lock = slock_new();
|
|
if (b->lock == NULL)
|
|
return NULL;
|
|
|
|
b->buffer = malloc(sizeof(sws_context_t) * num);
|
|
if (b->buffer == NULL)
|
|
return NULL;
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
b->buffer[i].index = i;
|
|
b->buffer[i].sws = sws_alloc_context();
|
|
b->buffer[i].source = av_frame_alloc();
|
|
#if LIBAVUTIL_VERSION_MAJOR > 55
|
|
b->buffer[i].hw_source = av_frame_alloc();
|
|
#endif
|
|
b->buffer[i].target = av_frame_alloc();
|
|
b->buffer[i].frame_buf = av_malloc(frame_size);
|
|
|
|
avpicture_fill((AVPicture*)b->buffer[i].target, (const uint8_t*)b->buffer[i].frame_buf,
|
|
PIX_FMT_RGB32, width, height);
|
|
}
|
|
|
|
b->size = num;
|
|
b->head = 0;
|
|
b->tail = 0;
|
|
return b;
|
|
}
|
|
|
|
void swsbuffer_destroy(swsbuffer_t *swsbuffer)
|
|
{
|
|
if (swsbuffer != NULL) {
|
|
slock_free(swsbuffer->lock);
|
|
free(swsbuffer->status);
|
|
for (int i = 0; i < swsbuffer->size; i++)
|
|
{
|
|
#if LIBAVUTIL_VERSION_MAJOR > 55
|
|
av_frame_free(&swsbuffer->buffer[i].hw_source);
|
|
#endif
|
|
av_frame_free(&swsbuffer->buffer[i].source);
|
|
av_frame_free(&swsbuffer->buffer[i].target);
|
|
av_freep(&swsbuffer->buffer[i].frame_buf);
|
|
sws_freeContext(swsbuffer->buffer[i].sws);
|
|
}
|
|
free(swsbuffer->buffer);
|
|
free(swsbuffer);
|
|
}
|
|
}
|
|
|
|
void swsbuffer_clear(swsbuffer_t *swsbuffer)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
swsbuffer->head = 0;
|
|
swsbuffer->tail = 0;
|
|
for (int i = 0; i < swsbuffer->size; i++)
|
|
swsbuffer->status[i] = KB_OPEN;
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
void swsbuffer_get_open_slot(swsbuffer_t *swsbuffer, sws_context_t **context)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[swsbuffer->head] == KB_OPEN)
|
|
{
|
|
*context = &swsbuffer->buffer[swsbuffer->head];
|
|
swsbuffer->status[swsbuffer->head] = KB_IN_PROGRESS;
|
|
swsbuffer->head++;
|
|
swsbuffer->head %= swsbuffer->size;
|
|
}
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
void swsbuffer_return_open_slot(swsbuffer_t *swsbuffer, sws_context_t *context)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[context->index] == KB_IN_PROGRESS)
|
|
{
|
|
swsbuffer->status[context->index] = KB_OPEN;
|
|
swsbuffer->head--;
|
|
swsbuffer->head %= swsbuffer->size;
|
|
}
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
void swsbuffer_open_slot(swsbuffer_t *swsbuffer, sws_context_t *context)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[context->index] == KB_FINISHED)
|
|
{
|
|
swsbuffer->status[context->index] = KB_OPEN;
|
|
swsbuffer->tail++;
|
|
swsbuffer->tail %= (swsbuffer->size);
|
|
}
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
void swsbuffer_get_finished_slot(swsbuffer_t *swsbuffer, sws_context_t **context)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[swsbuffer->tail] == KB_FINISHED)
|
|
*context = &swsbuffer->buffer[swsbuffer->tail];
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
void swsbuffer_finish_slot(swsbuffer_t *swsbuffer, sws_context_t *context)
|
|
{
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[context->index] == KB_IN_PROGRESS)
|
|
swsbuffer->status[context->index] = KB_FINISHED;
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
}
|
|
|
|
bool swsbuffer_has_open_slot(swsbuffer_t *swsbuffer)
|
|
{
|
|
bool ret = false;
|
|
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[swsbuffer->head] == KB_OPEN)
|
|
ret = true;
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool swsbuffer_has_finished_slot(swsbuffer_t *swsbuffer)
|
|
{
|
|
bool ret = false;
|
|
|
|
slock_lock(swsbuffer->lock);
|
|
|
|
if (swsbuffer->status[swsbuffer->tail] == KB_FINISHED)
|
|
ret = true;
|
|
|
|
slock_unlock(swsbuffer->lock);
|
|
|
|
return ret;
|
|
}
|