/* * 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 #include #include #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; }