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
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;
|
|
}
|