You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
12 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2009-2019. All rights reserved.
* Description: queue of subtitle
* Author: dtv
* Create: 2009-03-02
*/
#include "so_queue.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include "linux_list.h"
typedef struct {
td_s32 num; /* number of item in msg queue */
td_u32 maxNodeNum;
td_s32 bufferSize; /* size of buffer in msg queue */
td_u32 maxBufferSize;
struct list_head list;
pthread_mutex_t lock;
td_handle bufHandle;
} SoQueue;
typedef struct {
struct list_head list;
SO_INFO_S soInfo;
td_u8 addr[0];
} SoNode;
#define SO_ADD_EXT_BYTE_NUM 4
#define SO_NODE_SIZE sizeof(SoNode)
#define SO_QUEUE_LOCK() \
do { \
td_s32 ret = pthread_mutex_lock(&soQueue->lock); \
if (ret != 0) { \
EXT_PRINT("SO call pthread_mutex_lock(QUEUE) failure,ret = 0x%x\n", ret); \
} \
} while (0)
#define SO_QUEUE_UNLOCK() \
do { \
td_s32 ret = pthread_mutex_unlock(&soQueue->lock); \
if (ret != 0) { \
EXT_PRINT("SO call pthread_mutex_unlock(QUEUE) failure,ret = 0x%x\n", ret); \
} \
} while (0)
static td_s32 GetBufLen(const SO_INFO_S *info)
{
td_s32 len = 0;
if (info->subt_type == UAPI_SUBTITLE_BITMAP) {
len = (td_s32)info->subtitle_param.gfx.len;
} else if (info->subt_type == UAPI_SUBTITLE_TEXT) {
len = (td_s32)info->subtitle_param.text.len;
} else if (info->subt_type == UAPI_SUBTITLE_ASS) {
len = (td_s32)info->subtitle_param.ass.frame_len;
} else {
len = 0;
}
return len;
}
static td_void InitNode(const SO_INFO_S *info, SoNode *node)
{
if (info->subt_type == UAPI_SUBTITLE_BITMAP) {
node->soInfo.subt_type = UAPI_SUBTITLE_BITMAP;
SO_CHK_FUN_RET_VOID(memcpy_s(node->addr, GetBufLen(info), info->subtitle_param.gfx.pix_data,
info->subtitle_param.gfx.len));
node->addr[info->subtitle_param.gfx.len] = '\0';
SO_CHK_FUN_RET_VOID(memcpy_s(&node->soInfo.subtitle_param.gfx, sizeof(uapi_so_gfx),
&info->subtitle_param.gfx, sizeof(uapi_so_gfx)));
} else if (info->subt_type == UAPI_SUBTITLE_TEXT) {
node->soInfo.subt_type = UAPI_SUBTITLE_TEXT;
SO_CHK_FUN_RET_VOID(memcpy_s(node->addr, GetBufLen(info), info->subtitle_param.text.data,
info->subtitle_param.text.len));
node->addr[info->subtitle_param.text.len] = '\0';
SO_CHK_FUN_RET_VOID(memcpy_s(&node->soInfo.subtitle_param.text, sizeof(uapi_so_text),
&info->subtitle_param.text, sizeof(uapi_so_text)));
} else if (info->subt_type == UAPI_SUBTITLE_ASS) {
node->soInfo.subt_type = UAPI_SUBTITLE_ASS;
SO_CHK_FUN_RET_VOID(memcpy_s(node->addr, GetBufLen(info), info->subtitle_param.ass.frame_data,
info->subtitle_param.ass.frame_len));
node->addr[info->subtitle_param.ass.frame_len] = '\0';
SO_CHK_FUN_RET_VOID(memcpy_s(&node->soInfo.subtitle_param.ass, sizeof(uapi_so_ass),
&info->subtitle_param.ass, sizeof(uapi_so_ass)));
} else {
return;
}
return;
}
td_s32 SO_QueueInit(td_u32 bufsize, td_u32 maxNodeNum, SO_QUEUE_HANDLE *handle)
{
td_s32 ret = TD_SUCCESS;
SoQueue *soQueue = NULL;
SO_RETURN(bufsize < SO_NORMAL_BUFF_SIZE, TD_FAILURE, "### Queue size is less than 1024!\n");
soQueue = (SoQueue *)SO_MALLOC(sizeof(SoQueue));
SO_RETURN(soQueue == NULL, TD_FAILURE, "### No mem!\n");
INIT_LIST_HEAD(&soQueue->list);
(td_void) pthread_mutex_init(&soQueue->lock, NULL);
soQueue->num = 0;
soQueue->bufferSize = 0;
soQueue->maxBufferSize = bufsize;
soQueue->maxNodeNum = maxNodeNum;
*handle = soQueue;
return ret;
}
td_s32 SO_QueueDeinit(SO_QUEUE_HANDLE handle)
{
SoQueue *soQueue = (SoQueue *)handle;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_QueueRemove(handle);
(td_void) pthread_mutex_destroy(&soQueue->lock);
SO_FREE(soQueue);
return TD_SUCCESS;
}
td_s32 SO_QueuePut(SO_QUEUE_HANDLE handle, const SO_INFO_S *info)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
td_s32 len;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_RETURN(info == NULL, TD_FAILURE, "");
len = GetBufLen(info);
SO_RETURN(len < 0, TD_FAILURE, "");
SO_QUEUE_LOCK();
SO_CALL_RETURN(soQueue->maxBufferSize <= (td_u32)soQueue->bufferSize &&
(td_u32)soQueue->num >= soQueue->maxNodeNum, SO_QUEUE_UNLOCK(), TD_FAILURE);
node = (SoNode *)SO_MALLOC(SO_NODE_SIZE + (td_u32)len + SO_ADD_EXT_BYTE_NUM);
SO_CALL_RETURN(node == NULL, SO_QUEUE_UNLOCK(), TD_FAILURE);
memset_s(&node->soInfo, sizeof(node->soInfo), 0, sizeof(node->soInfo));
memset_s(node->addr, len, 0, len);
/* copy node info, len(4bytes)+data(len bytes) */
InitNode(info, node);
list_add_tail(&node->list, &soQueue->list);
soQueue->num++;
soQueue->bufferSize += len;
SO_QUEUE_UNLOCK();
return TD_SUCCESS;
}
td_s32 SO_QueueGet(SO_QUEUE_HANDLE handle, SO_INFO_S *info)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
td_s32 len = 0;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_RETURN(info == NULL, TD_FAILURE, "");
SO_QUEUE_LOCK();
if (!list_empty(&soQueue->list)) {
node = list_entry(soQueue->list.next, SoNode, list);
list_del(&node->list);
soQueue->num--;
memcpy_s(info, sizeof(SO_INFO_S), &node->soInfo, sizeof(SO_INFO_S));
len = GetBufLen(info);
soQueue->bufferSize -= len;
if (node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP) {
info->subtitle_param.gfx.pix_data = node->addr;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_TEXT) {
info->subtitle_param.text.data = node->addr;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_ASS) {
info->subtitle_param.ass.frame_data = node->addr;
}
SO_QUEUE_UNLOCK();
return TD_SUCCESS;
}
SO_QUEUE_UNLOCK();
return TD_FAILURE;
}
td_s32 SO_QueueGetNodeInfoNotDel(SO_QUEUE_HANDLE handle, SO_INFO_S *info)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_RETURN(info == NULL, TD_FAILURE, "");
SO_QUEUE_LOCK();
if (!list_empty(&soQueue->list)) {
node = list_entry(soQueue->list.next, SoNode, list);
memcpy_s(info, sizeof(SO_INFO_S), &node->soInfo, sizeof(SO_INFO_S));
if (node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP) {
info->subtitle_param.gfx.pix_data = node->addr;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_TEXT) {
info->subtitle_param.text.data = node->addr;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_ASS) {
info->subtitle_param.ass.frame_data = node->addr;
}
SO_QUEUE_UNLOCK();
return TD_SUCCESS;
}
SO_QUEUE_UNLOCK();
return TD_FAILURE;
}
td_void SO_QueueFree(SO_QUEUE_HANDLE handle, const SO_INFO_S *info)
{
SoQueue *soQueue = (SoQueue *)handle;
td_u8 *data = NULL;
if (soQueue == NULL || info == NULL) {
return;
}
if (info->subt_type == UAPI_SUBTITLE_BITMAP) {
data = info->subtitle_param.gfx.pix_data;
} else if (info->subt_type == UAPI_SUBTITLE_TEXT) {
data = info->subtitle_param.text.data;
} else if (info->subt_type == UAPI_SUBTITLE_ASS) {
data = info->subtitle_param.ass.frame_data;
}
if (data == NULL) {
return;
}
SO_QUEUE_LOCK();
data = data - SO_NODE_SIZE;
SO_FREE(data);
SO_QUEUE_UNLOCK();
return;
}
td_void SO_QueueRemove(SO_QUEUE_HANDLE handle)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
SoNode *n = NULL;
if (soQueue == NULL) {
return;
}
SO_QUEUE_LOCK();
list_for_each_entry_safe(node, n, &soQueue->list, list) {
list_del(&node->list);
SO_FREE(node);
}
soQueue->num = 0;
soQueue->bufferSize = 0;
SO_QUEUE_UNLOCK();
return;
}
td_void SO_QueueReset(SO_QUEUE_HANDLE handle)
{
SO_QueueRemove(handle);
return;
}
td_s32 SO_QueueResetByPts(SO_QUEUE_HANDLE handle, td_s64 pts)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
SoNode *n = NULL;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_QUEUE_LOCK();
list_for_each_entry_safe(node, n, &soQueue->list, list) {
if ((node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP && node->soInfo.subtitle_param.gfx.pts < pts) ||
(node->soInfo.subt_type == UAPI_SUBTITLE_TEXT && node->soInfo.subtitle_param.text.pts < pts) ||
(node->soInfo.subt_type == UAPI_SUBTITLE_ASS && node->soInfo.subtitle_param.ass.pts < pts)) {
soQueue->num--;
if (node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP && node->soInfo.subtitle_param.gfx.pts < pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.gfx.len;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_TEXT &&
node->soInfo.subtitle_param.text.pts < pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.text.len;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_ASS &&
node->soInfo.subtitle_param.ass.pts < pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.ass.frame_len;
}
list_del(&node->list);
SO_FREE(node);
}
}
SO_QUEUE_UNLOCK();
return TD_SUCCESS;
}
td_s32 SO_QueueResetAfterPts(SO_QUEUE_HANDLE handle, td_s64 pts)
{
SoQueue *soQueue = (SoQueue *)handle;
SoNode *node = NULL;
SoNode *n = NULL;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_QUEUE_LOCK();
list_for_each_entry_safe(node, n, &soQueue->list, list) {
if ((node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP && node->soInfo.subtitle_param.gfx.pts > pts) ||
(node->soInfo.subt_type == UAPI_SUBTITLE_TEXT && node->soInfo.subtitle_param.text.pts > pts) ||
(node->soInfo.subt_type == UAPI_SUBTITLE_ASS && node->soInfo.subtitle_param.ass.pts > pts)) {
soQueue->num--;
if (node->soInfo.subt_type == UAPI_SUBTITLE_BITMAP && node->soInfo.subtitle_param.gfx.pts > pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.gfx.len;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_TEXT &&
node->soInfo.subtitle_param.text.pts > pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.text.len;
} else if (node->soInfo.subt_type == UAPI_SUBTITLE_ASS &&
node->soInfo.subtitle_param.ass.pts > pts) {
soQueue->bufferSize -= (td_s32)node->soInfo.subtitle_param.ass.frame_len;
}
list_del(&node->list);
SO_FREE(node);
}
}
SO_QUEUE_UNLOCK();
return TD_SUCCESS;
}
td_u32 SO_QueueNum(SO_QUEUE_HANDLE handle)
{
SoQueue *soQueue = (SoQueue *)handle;
td_u32 num;
SO_RETURN(soQueue == NULL, TD_FAILURE, "");
SO_QUEUE_LOCK();
num = (td_u32)soQueue->num;
SO_QUEUE_UNLOCK();
return num;
}