sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/utils/video_buffer_manager.c

289 lines
8.7 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2018-2020, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name : video buffer list manager.c
Version : Initial Draft
Author : huangbohan
Created : 2018/10/26
Last Modified :
Description : utils for mpi components' buffer list manager
Function List :
History :
******************************************************************************/
#define LOG_NDEBUG 0
#define LOG_TAG "video_buffer_manager"
#include <string.h>
#include <utils/plat_log.h>
#include "cdx_list.h"
#include "video_buffer_manager.h"
static VIDEO_FRAME_INFO_S *VBMGetValidFrame(VideoBufferManager *pMgr)
{
VideoFrameListInfo *pEntry = NULL;
pthread_mutex_lock(&pMgr->mFrmListLock);
if (list_empty(&pMgr->mValidFrmList)) {
pthread_mutex_unlock(&pMgr->mFrmListLock);
return NULL;
}
pEntry = list_first_entry(&pMgr->mValidFrmList, VideoFrameListInfo, mList);
list_move_tail(&pEntry->mList, &pMgr->mUsingFrmList);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return &pEntry->mFrame;
}
static VIDEO_FRAME_INFO_S *VBMGetAllValidUsingFrame(VideoBufferManager *pMgr)
{
VideoFrameListInfo *pEntry = NULL;
pthread_mutex_lock(&pMgr->mFrmListLock);
if (list_empty(&pMgr->mUsingFrmList) && list_empty(&pMgr->mValidFrmList)) {
pthread_mutex_unlock(&pMgr->mFrmListLock);
return NULL;
}
if (!list_empty(&pMgr->mUsingFrmList)) {
pEntry = list_first_entry(&pMgr->mUsingFrmList, VideoFrameListInfo, mList);
list_move_tail(&pEntry->mList, &pMgr->mFreeFrmList);
goto EDone;
}
if (!list_empty(&pMgr->mValidFrmList)) {
pEntry = list_first_entry(&pMgr->mValidFrmList, VideoFrameListInfo, mList);
list_move_tail(&pEntry->mList, &pMgr->mFreeFrmList);
goto EDone;
}
EDone:
pthread_mutex_unlock(&pMgr->mFrmListLock);
return &pEntry->mFrame;
}
static VIDEO_FRAME_INFO_S *VBMGetOldestUsingFrame(VideoBufferManager *pMgr)
{
VideoFrameListInfo *pEntry;
pthread_mutex_lock(&pMgr->mFrmListLock);
pEntry = list_first_entry_or_null(&pMgr->mUsingFrmList, VideoFrameListInfo, mList);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return (pEntry == NULL) ? NULL : &pEntry->mFrame;
}
static VIDEO_FRAME_INFO_S *VBMGetOldestValidFrame(VideoBufferManager *pMgr)
{
VideoFrameListInfo *pEntry;
pthread_mutex_lock(&pMgr->mFrmListLock);
pEntry = list_first_entry_or_null(&pMgr->mValidFrmList, VideoFrameListInfo, mList);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return (pEntry == NULL) ? NULL : &pEntry->mFrame;
}
static VIDEO_FRAME_INFO_S *VBMGetSpecUsingFrameWithAddr(VideoBufferManager *pMgr, void *pVirAddr)
{
VideoFrameListInfo *pEntry, *pTmp;
int found = 0;
pthread_mutex_lock(&pMgr->mFrmListLock);
list_for_each_entry_safe(pEntry, pTmp, &pMgr->mUsingFrmList, mList)
{
if (pEntry->mFrame.VFrame.mpVirAddr[0] == pVirAddr) {
found = 1;
break;
}
}
if (found) {
pthread_mutex_unlock(&pMgr->mFrmListLock);
return &pEntry->mFrame;
} else {
aloge("Unknown video virvi frame, frame virtual address[%p]!", pVirAddr);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return NULL;
}
}
static int VBMReleaseFrame(VideoBufferManager *pMgr, VIDEO_FRAME_INFO_S *pFrame)
{
VideoFrameListInfo *pEntry, *pTmp;
int found = 0;
pthread_mutex_lock(&pMgr->mFrmListLock);
list_for_each_entry_safe(pEntry, pTmp, &pMgr->mUsingFrmList, mList)
{
if (pEntry->mFrame.VFrame.mpVirAddr[0] == pFrame->VFrame.mpVirAddr[0] ||
pEntry->mFrame.mId == pFrame->mId) {
*pFrame = pEntry->mFrame;
list_del(&pEntry->mList);
found = 1;
break;
}
}
if (found) {
list_add_tail(&pEntry->mList, &pMgr->mFreeFrmList);
} else {
aloge("fatal error! Unknown video frame, frame id[%d]!", pFrame->mId);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return FAILURE;
}
if(pMgr->mbWaitUsingFrmEmptyFlag && list_empty(&pMgr->mUsingFrmList)) {
pthread_cond_signal(&pMgr->mCondUsingFrmEmpty);
}
pthread_mutex_unlock(&pMgr->mFrmListLock);
return SUCCESS;
}
static int VBMPushFrame(VideoBufferManager *pMgr, VIDEO_FRAME_INFO_S *pFrame)
{
VideoFrameListInfo *pEntry = NULL;
pthread_mutex_lock(&pMgr->mFrmListLock);
if (list_empty(&pMgr->mFreeFrmList)) {
pthread_mutex_unlock(&pMgr->mFrmListLock);
return FAILURE;
}
pEntry = list_first_entry(&pMgr->mFreeFrmList, VideoFrameListInfo, mList);
pEntry->mFrame = *pFrame;
list_move_tail(&pEntry->mList, &pMgr->mValidFrmList);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return SUCCESS;
}
static int VBMIsUsingFrmEmpty(VideoBufferManager *pMgr)
{
int iRet;
pthread_mutex_lock(&pMgr->mFrmListLock);
iRet = list_empty(&pMgr->mUsingFrmList);
pthread_mutex_unlock(&pMgr->mFrmListLock);
return iRet;
}
static int VBMWaitUsingFrmEmpty(VideoBufferManager *pMgr)
{
pthread_mutex_lock(&pMgr->mFrmListLock);
pMgr->mbWaitUsingFrmEmptyFlag = TRUE;
int nCondWaitFlag = 0;
while(!list_empty(&pMgr->mUsingFrmList)) {
alogd("wait all Using frame return");
nCondWaitFlag++;
pthread_cond_wait(&pMgr->mCondUsingFrmEmpty, &pMgr->mFrmListLock);
}
if(nCondWaitFlag != 0)
{
alogd("wait all Using frame return done[%d]!", nCondWaitFlag);
}
pMgr->mbWaitUsingFrmEmptyFlag = FALSE;
pthread_mutex_unlock(&pMgr->mFrmListLock);
return SUCCESS;
}
static int VBMGetValidUsingFrameNum(struct VideoBufferManager *pMgr)
{
int n = 0;
pthread_mutex_lock(&pMgr->mFrmListLock);
struct list_head *pNode;
list_for_each(pNode, &pMgr->mUsingFrmList){n++;}
list_for_each(pNode, &pMgr->mValidFrmList){n++;}
pthread_mutex_unlock(&pMgr->mFrmListLock);
return n;
}
VideoBufferManager *VideoBufMgrCreate(int frmNum, int frmSize)
{
VideoBufferManager *pMgr = (VideoBufferManager *)malloc(sizeof(VideoBufferManager));
if (pMgr == NULL) {
aloge("Alloc VideoBufferManager error!");
return NULL;
}
memset(pMgr, 0, sizeof(VideoBufferManager));
INIT_LIST_HEAD(&pMgr->mFreeFrmList);
INIT_LIST_HEAD(&pMgr->mValidFrmList);
INIT_LIST_HEAD(&pMgr->mUsingFrmList);
pthread_mutex_init(&pMgr->mFrmListLock, NULL);
pthread_cond_init(&pMgr->mCondUsingFrmEmpty, NULL);
int i;
for (i = 0; i < frmNum; ++i) {
VideoFrameListInfo *pNode = (VideoFrameListInfo *)malloc(sizeof(VideoFrameListInfo));
if (pNode == NULL) {
aloge("Alloc VideoFrameListInfo error!");
break;
}
memset(pNode, 0, sizeof(VideoFrameListInfo));
list_add_tail(&pNode->mList, &pMgr->mFreeFrmList);
pMgr->mFrameNodeNum++;
}
//aloge("Alloc %d input frame buffers in list manager.", pMgr->mFrameNodeNum);
pMgr->GetOldestUsingFrame = VBMGetOldestUsingFrame;
pMgr->GetOldestValidFrame = VBMGetOldestValidFrame;
pMgr->GetSpecUsingFrameWithAddr = VBMGetSpecUsingFrameWithAddr;
pMgr->getValidFrame = VBMGetValidFrame;
pMgr->GetAllValidUsingFrame = VBMGetAllValidUsingFrame;
pMgr->releaseFrame = VBMReleaseFrame;
pMgr->pushFrame = VBMPushFrame;
pMgr->usingFrmEmpty = VBMIsUsingFrmEmpty; /* is usingFrm Empty */
pMgr->waitUsingFrmEmpty = VBMWaitUsingFrmEmpty;
pMgr->GetValidUsingFrameNum = VBMGetValidUsingFrameNum;
return pMgr;
}
void VideoBufMgrDestroy(VideoBufferManager *pMgr)
{
VideoFrameListInfo *pEntry, *pTmp;
int frmnum = 0;
if (pMgr == NULL) {
aloge("video input buffer manager has been unexist!!\n");
return;
}
pthread_mutex_lock(&pMgr->mFrmListLock);
if (!list_empty(&pMgr->mUsingFrmList)) {
// TODO: if we should release this frame list nodes
aloge("Fatal error! UsingFrmList is not empty! maybe some frames not release!");
}
if (!list_empty(&pMgr->mValidFrmList)) {
list_for_each_entry_safe(pEntry, pTmp, &pMgr->mValidFrmList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
++frmnum;
}
}
if (!list_empty(&pMgr->mFreeFrmList)) {
list_for_each_entry_safe(pEntry, pTmp, &pMgr->mFreeFrmList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
++frmnum;
}
}
pthread_mutex_unlock(&pMgr->mFrmListLock);
if (frmnum != pMgr->mFrameNodeNum) {
aloge("Fatal error! frame node number is not match[%d][%d]", frmnum, pMgr->mFrameNodeNum);
}
pthread_cond_destroy(&pMgr->mCondUsingFrmEmpty);
pthread_mutex_destroy(&pMgr->mFrmListLock);
free(pMgr);
}