1864 lines
58 KiB
C
Executable File
1864 lines
58 KiB
C
Executable File
|
|
/*
|
|
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
|
|
* All rights reserved.
|
|
*
|
|
* File : fbm.c
|
|
* Description :
|
|
* History :
|
|
* Author : xyliu <xyliu@allwinnertech.com>
|
|
* Date : 2016/04/13
|
|
* Comment :
|
|
*
|
|
*
|
|
*/
|
|
|
|
//#define CONFIG_LOG_LEVEL OPTION_LOG_LEVEL_DETAIL
|
|
#define LOG_TAG "fbm.c"
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
#include "fbm.h"
|
|
#include "log.h"
|
|
|
|
#include "CdcUtil.h"
|
|
|
|
|
|
extern const char* strPixelFormat[];
|
|
extern int GetBufferSize(int ePixelFormat, int nWidth, int nHeight,int*nYBufferSize,
|
|
int *nCBufferSize, int* nYLineStride, int* nCLineStride, int nAlignValue);
|
|
|
|
#define FRM_FORBID_USE_TAG 0xff
|
|
#define FRM_RELEASE_TAG 0xee
|
|
#define FBM_NEW_DISP_INVALID_TAG 0xdd
|
|
#define FBM_NEED_FLUSH_CACHE_SIZE 480
|
|
|
|
#define MAJOR_DECODER_USE_FLAG 1
|
|
#define MINOR_DECODER_USE_FLAG 2
|
|
#define MAJOR_DISP_USE_FLAG 4
|
|
#define MINOR_DISP_USE_FLAG 8
|
|
#define MINOR_NEED_USE_FLAG 16
|
|
|
|
void FbmDebugPrintStatus(Fbm* pFbm)
|
|
{
|
|
int i = 0;
|
|
if(pFbm == NULL)
|
|
return;
|
|
for(i=0; i<pFbm->nMaxFrameNum; i++)
|
|
{
|
|
logd("i=%d, picture=%p, displed=%d, valid=%d, decode=%d, render=%d\n", \
|
|
i, &pFbm->pFrames[i].vpicture, pFbm->pFrames[i].Flag.bAlreadyDisplayed, \
|
|
pFbm->pFrames[i].Flag.bInValidPictureQueue, pFbm->pFrames[i].Flag.bUsedByDecoder, \
|
|
pFbm->pFrames[i].Flag.bUsedByRender);
|
|
}
|
|
}
|
|
|
|
static void FbmEnqueue(FrameNode** ppHead, FrameNode* p)
|
|
{
|
|
FrameNode* pCur;
|
|
|
|
pCur = *ppHead;
|
|
|
|
if(pCur == NULL)
|
|
{
|
|
*ppHead = p;
|
|
p->pNext = NULL;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
while(pCur->pNext != NULL)
|
|
pCur = pCur->pNext;
|
|
|
|
pCur->pNext = p;
|
|
p->pNext = NULL;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void FbmEnqueueToHead(FrameNode ** ppHead, FrameNode* p)
|
|
{
|
|
CEDARC_UNUSE(FbmEnqueueToHead);
|
|
|
|
FrameNode* pCur;
|
|
|
|
pCur = *ppHead;
|
|
*ppHead = p;
|
|
p->pNext = pCur;
|
|
return;
|
|
}
|
|
|
|
static FrameNode* FbmDequeue(FrameNode** ppHead)
|
|
{
|
|
FrameNode* pHead;
|
|
|
|
pHead = *ppHead;
|
|
|
|
if(pHead == NULL)
|
|
return NULL;
|
|
else
|
|
{
|
|
*ppHead = pHead->pNext;
|
|
pHead->pNext = NULL;
|
|
return pHead;
|
|
}
|
|
}
|
|
|
|
Fbm* FbmCreateBuffer(FbmCreateInfo* pFbmCreateInfo, VideoFbmInfo* pFbmInfo)
|
|
{
|
|
Fbm* p;
|
|
int i;
|
|
//int nAllocFrameNum;
|
|
FrameNode* pFrameNode;
|
|
|
|
int nWidth = pFbmCreateInfo->nWidth;
|
|
int nHeight = pFbmCreateInfo->nHeight;
|
|
int nAlignStride = pFbmCreateInfo->nAlignStride;
|
|
|
|
logd("FbmCreate, total fbm number: %d, decoder needed: %d, \
|
|
nWidth=%d, nHeight=%d nAlignStride = %d",
|
|
pFbmCreateInfo->nFrameNum,
|
|
pFbmCreateInfo->nDecoderNeededMiniFrameNum,
|
|
nWidth, nHeight, nAlignStride);
|
|
|
|
p = (Fbm*)malloc(sizeof(Fbm));
|
|
if(p == NULL)
|
|
{
|
|
loge("memory alloc fail.");
|
|
return NULL;
|
|
}
|
|
memset(p, 0, sizeof(Fbm));
|
|
|
|
p->memops = pFbmCreateInfo->memops;
|
|
p->nMaxFrameNum = pFbmCreateInfo->nFrameNum;
|
|
p->sVeops = pFbmCreateInfo->veOpsS;
|
|
p->pVeOpsSelf = pFbmCreateInfo->pVeOpsSelf;
|
|
pFbmInfo->bIsSoftDecoderFlag = pFbmCreateInfo->bIsSoftDecoderFlag;
|
|
|
|
#if 0 //added by xyliu at 2015-02-12
|
|
if((pFbmCreateInfo->bGpuBufValid==1) && (pFbmCreateInfo->nBufferType!=BUF_TYPE_ONLY_REFERENCE))
|
|
{
|
|
pFbmCreateInfo->nFrameNum -= 3; //
|
|
p->nMaxFrameNum = pFbmCreateInfo->nFrameNum;
|
|
|
|
p->nMaxFrameNum += 5;
|
|
if(pFbmCreateInfo->bProgressiveFlag == 0)
|
|
{
|
|
p->nMaxFrameNum += 2;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//* allocate frame nodes.
|
|
pFrameNode = (FrameNode*)malloc(p->nMaxFrameNum*sizeof(FrameNode));
|
|
if(pFrameNode == NULL)
|
|
{
|
|
loge("memory alloc fail, alloc %d bytes.", (int)(p->nMaxFrameNum*sizeof(FrameNode)));
|
|
free(p);
|
|
return NULL;
|
|
}
|
|
memset(pFrameNode, 0, p->nMaxFrameNum*sizeof(FrameNode));
|
|
|
|
pthread_mutex_init(&p->mutex, NULL);
|
|
|
|
p->pEmptyBufferQueue = NULL;
|
|
p->pValidPictureQueue = NULL;
|
|
p->bThumbnailMode = pFbmCreateInfo->bThumbnailMode;
|
|
p->pFrames = pFrameNode;
|
|
p->bUseGpuBuf = 0;
|
|
if((pFbmInfo->pFbmBufInfo.nRightOffset==0) || (pFbmInfo->pFbmBufInfo.nBottomOffset==0))
|
|
{
|
|
pFbmInfo->pFbmBufInfo.nRightOffset = nWidth;
|
|
pFbmInfo->pFbmBufInfo.nBottomOffset = nHeight;
|
|
pFbmInfo->pFbmBufInfo.nTopOffset = 0;
|
|
pFbmInfo->pFbmBufInfo.nLeftOffset = 0;
|
|
}
|
|
|
|
for(i=0; i<p->nMaxFrameNum; i++)
|
|
{
|
|
memset((void*)(&pFrameNode->vpicture), 0, sizeof(VideoPicture));
|
|
pFrameNode->Flag.bUsedByDecoder = 0;
|
|
pFrameNode->Flag.bUsedByRender = 0;
|
|
pFrameNode->Flag.bInValidPictureQueue = 0;
|
|
pFrameNode->Flag.bAlreadyDisplayed = 0;
|
|
pFrameNode->pNext = NULL;
|
|
|
|
pFrameNode->vpicture.nBufId = FBM_NEW_DISP_INVALID_TAG;
|
|
pFrameNode->vpicture.nID = i;
|
|
pFrameNode->vpicture.ePixelFormat = pFbmCreateInfo->ePixelFormat;
|
|
if(nAlignStride != 0)
|
|
{
|
|
pFrameNode->vpicture.nWidth = \
|
|
(nWidth+nAlignStride-1) &~ (nAlignStride-1);
|
|
pFrameNode->vpicture.nHeight = \
|
|
(nHeight+nAlignStride-1) &~ (nAlignStride-1);
|
|
}
|
|
else
|
|
{
|
|
pFrameNode->vpicture.nWidth = nWidth;
|
|
pFrameNode->vpicture.nHeight = nHeight;
|
|
}
|
|
pFrameNode->vpicture.nLineStride = pFrameNode->vpicture.nWidth;
|
|
pFrameNode->vpicture.bIsProgressive = pFbmCreateInfo->bProgressiveFlag;
|
|
pFrameNode->vpicture.nLeftOffset = 0;
|
|
pFrameNode->vpicture.nTopOffset = 0;
|
|
pFrameNode->vpicture.nRightOffset = nWidth;
|
|
pFrameNode->vpicture.nBottomOffset = nHeight;
|
|
pFrameNode->vpicture.b10BitPicFlag = pFbmCreateInfo->b10BitStreamFlag;
|
|
pFrameNode->vpicture.bEnableAfbcFlag = pFbmInfo->pFbmBufInfo.bAfbcModeFlag;
|
|
|
|
if(pFbmCreateInfo->bGpuBufValid==0 || \
|
|
pFbmCreateInfo->nBufferType==BUF_TYPE_ONLY_REFERENCE)
|
|
{
|
|
if(!pFbmCreateInfo->bThumbnailMode || i==0)
|
|
{
|
|
logd("** call allocate pic buf, i = %d, maxNum = %d",i,p->nMaxFrameNum);
|
|
if(FbmAllocatePictureBuffer(p, \
|
|
&pFrameNode->vpicture, &nAlignStride, nWidth, nHeight) != 0)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//* thumbnail mode, other pictures share picture buffer with the first one.
|
|
pFrameNode->vpicture.pData0 = p->pFrames[0].vpicture.pData0;
|
|
pFrameNode->vpicture.pData1 = p->pFrames[0].vpicture.pData1;
|
|
pFrameNode->vpicture.pData2 = p->pFrames[0].vpicture.pData2;
|
|
pFrameNode->vpicture.pData3 = p->pFrames[0].vpicture.pData3;
|
|
pFrameNode->vpicture.phyYBufAddr = p->pFrames[0].vpicture.phyYBufAddr;
|
|
pFrameNode->vpicture.phyCBufAddr = p->pFrames[0].vpicture.phyCBufAddr;
|
|
}
|
|
pFrameNode->vpicture.nColorPrimary = 0xffffffff;
|
|
}
|
|
|
|
if(pFbmCreateInfo->bGpuBufValid==1)
|
|
{
|
|
int nLower2BitBufOffset = 0;
|
|
int nLower2BitBufStride = 0;
|
|
int nAfbcBufSize = 0;
|
|
int nAlignWidht = pFrameNode->vpicture.nWidth;
|
|
int nAlignHeight = pFrameNode->vpicture.nHeight;
|
|
if(pFrameNode->vpicture.b10BitPicFlag)
|
|
{
|
|
int frmbuf_c_size = 0;
|
|
int PriChromaStride = ((nWidth/2) + 31)&0xffffffe0;
|
|
frmbuf_c_size = 2 * (PriChromaStride * (((nHeight/2)+15)&0xfffffff0)/4);
|
|
nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (512 + 16) + 32 + 1024;
|
|
//nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (512 + 16) + 1024;
|
|
nLower2BitBufStride = ((((nWidth+3)>>2) + 31) & 0xffffffe0);
|
|
|
|
if(pFrameNode->vpicture.bEnableAfbcFlag == 1)
|
|
{
|
|
nLower2BitBufOffset = nAfbcBufSize + frmbuf_c_size;
|
|
pFrameNode->vpicture.nAfbcSize = nAfbcBufSize;
|
|
}
|
|
else
|
|
{
|
|
int nNormalYuvBufSize = nAlignWidht*nAlignHeight*3/2;
|
|
nLower2BitBufOffset = nNormalYuvBufSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pFrameNode->vpicture.bEnableAfbcFlag == 1)
|
|
{
|
|
nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (384 + 16) + 1024 + 32;
|
|
//nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (384 + 16) + 1024 ;
|
|
pFrameNode->vpicture.nAfbcSize = nAfbcBufSize;
|
|
}
|
|
}
|
|
logd("*** calcute nLower2BitBufOffset = %d, stride = %d",
|
|
nLower2BitBufOffset, nLower2BitBufStride);
|
|
pFrameNode->vpicture.nLower2BitBufOffset = nLower2BitBufOffset;
|
|
pFrameNode->vpicture.nLower2BitBufStride = nLower2BitBufStride;
|
|
}
|
|
pFrameNode++;
|
|
}
|
|
p->nAlignValue = nAlignStride;
|
|
|
|
//* check whether all picture buffer allocated.
|
|
if(i < p->nMaxFrameNum)
|
|
{
|
|
//* not all picture buffer allocated, abort the Fbm creating.
|
|
int j;
|
|
loge("memory alloc fail, only %d frames allocated, \
|
|
we need %d frames.", i, pFbmCreateInfo->nFrameNum);
|
|
for(j = 0; j < i; j++)
|
|
FbmFreePictureBuffer(p, &p->pFrames[j].vpicture);
|
|
pthread_mutex_destroy(&p->mutex);
|
|
free(p->pFrames);
|
|
free(p);
|
|
return NULL;
|
|
}
|
|
|
|
if((pFbmCreateInfo->bGpuBufValid==1) && \
|
|
(pFbmCreateInfo->nBufferType!=BUF_TYPE_ONLY_REFERENCE))
|
|
{
|
|
//****************************TO DO*******************************************//
|
|
if((pFbmInfo->pFbmFirst != NULL)&&(pFbmInfo->bIs3DStream==1))
|
|
{
|
|
//pFbmInfo->pFbmSecond = (void*)p;
|
|
p->bUseGpuBuf = 1;
|
|
p->pFbmInfo = (void*)pFbmInfo;
|
|
}
|
|
else
|
|
{
|
|
pFbmInfo->pFbmBufInfo.nBufNum = pFbmCreateInfo->nFrameNum;
|
|
if(pFbmCreateInfo->bThumbnailMode == 1)
|
|
{
|
|
pFbmInfo->pFbmBufInfo.nBufNum = 1;
|
|
}
|
|
if(nAlignStride != 0)
|
|
{
|
|
pFbmInfo->pFbmBufInfo.nBufWidth = \
|
|
(nWidth+nAlignStride-1) &~ (nAlignStride-1);
|
|
pFbmInfo->pFbmBufInfo.nBufHeight = \
|
|
(nHeight+nAlignStride-1) &~ (nAlignStride-1);
|
|
}
|
|
else
|
|
{
|
|
pFbmInfo->pFbmBufInfo.nBufWidth = nWidth;
|
|
pFbmInfo->pFbmBufInfo.nBufHeight = nHeight;
|
|
}
|
|
pFbmInfo->pFbmBufInfo.nAlignValue = nAlignStride;
|
|
pFbmInfo->pFbmBufInfo.ePixelFormat = pFbmCreateInfo->ePixelFormat;
|
|
pFbmInfo->pFbmBufInfo.bProgressiveFlag = pFbmCreateInfo->bProgressiveFlag;
|
|
pFbmInfo->pFbmBufInfo.bIsSoftDecoderFlag = pFbmCreateInfo->bIsSoftDecoderFlag;
|
|
pFbmInfo->pFbmBufInfo.b10bitVideoFlag = pFbmCreateInfo->b10BitStreamFlag;
|
|
//pFbmInfo->pFbmFirst = (void*)p;
|
|
p->pFbmInfo = (void*)pFbmInfo;
|
|
p->bUseGpuBuf = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//* put all frame to the empty frame queue.
|
|
for(i=0; i<pFbmCreateInfo->nFrameNum; i++)
|
|
{
|
|
pFrameNode = &p->pFrames[i];
|
|
FbmEnqueue(&p->pEmptyBufferQueue, pFrameNode);
|
|
}
|
|
p->nEmptyBufferNum = pFbmCreateInfo->nFrameNum;
|
|
|
|
p->pFbmInfo = (void*)pFbmInfo;
|
|
}
|
|
|
|
logd("*** finish fbmCreateBuffer");
|
|
return p;
|
|
}
|
|
|
|
Fbm* FbmCreate(FbmCreateInfo* pFbmCreateInfo, VideoFbmInfo* pFbmInfo)
|
|
{
|
|
int nYBufferSize = 0;
|
|
int nCBufSize = 0;
|
|
int nYLineStride = 0;
|
|
int nCLineStride = 0;
|
|
if((pFbmInfo->bIs3DStream==1)&&(pFbmCreateInfo->bGpuBufValid==1))
|
|
{
|
|
pFbmInfo->bTwoStreamShareOneFbm = 1;
|
|
if(pFbmInfo->pFbmFirst == NULL)
|
|
{
|
|
pFbmInfo->pFbmFirst = (void*)FbmCreateBuffer(pFbmCreateInfo, pFbmInfo);
|
|
if(pFbmInfo->pFbmFirst != NULL)
|
|
{
|
|
pFbmInfo->pFbmSecond = (void*)FbmCreateBuffer(pFbmCreateInfo, pFbmInfo);
|
|
if(pFbmInfo->pFbmSecond == NULL)
|
|
{
|
|
loge("pFbmInfo->pFbmSecond=NULL\n");
|
|
}
|
|
GetBufferSize(pFbmInfo->pFbmBufInfo.ePixelFormat, \
|
|
pFbmInfo->pFbmBufInfo.nBufWidth, pFbmInfo->pFbmBufInfo.nBufHeight, \
|
|
&nYBufferSize, &nCBufSize, &nYLineStride, &nCLineStride, \
|
|
pFbmInfo->pFbmBufInfo.nAlignValue);
|
|
pFbmInfo->nMinorYBufOffset = nYBufferSize;
|
|
pFbmInfo->nMinorCBufOffset = 2*nCBufSize;
|
|
}
|
|
return (Fbm*)pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
return (Fbm*)pFbmInfo->pFbmSecond;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pFbmInfo->pFbmFirst == NULL)
|
|
{
|
|
pFbmInfo->pFbmFirst = FbmCreateBuffer(pFbmCreateInfo, pFbmInfo);
|
|
return pFbmInfo->pFbmFirst;
|
|
}
|
|
else if(pFbmInfo->pFbmSecond == NULL)
|
|
{
|
|
pFbmInfo->pFbmSecond = FbmCreateBuffer(pFbmCreateInfo, pFbmInfo);
|
|
pFbmInfo->nMinorYBufOffset = 0;
|
|
pFbmInfo->nMinorCBufOffset = 0;
|
|
return pFbmInfo->pFbmSecond;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void FbmDestroy(Fbm* pFbm)
|
|
{
|
|
logv("FbmDestroy");
|
|
if(pFbm == NULL)
|
|
return;
|
|
pthread_mutex_destroy(&pFbm->mutex);
|
|
if(pFbm->bUseGpuBuf == 0)
|
|
{
|
|
//* in thumbnail mode, we only allocate one picture buffer.
|
|
if(pFbm->bThumbnailMode)
|
|
FbmFreePictureBuffer(pFbm, &pFbm->pFrames[0].vpicture);
|
|
else
|
|
{
|
|
int i;
|
|
for(i=0; i<pFbm->nMaxFrameNum; i++)
|
|
FbmFreePictureBuffer(pFbm, &pFbm->pFrames[i].vpicture);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
for(i=0; i<pFbm->nMaxFrameNum; i++)
|
|
{
|
|
if(CdcIonGetMemType() == MEMORY_IOMMU)
|
|
{
|
|
struct user_iommu_param sUserIommuBuf;
|
|
sUserIommuBuf.fd = pFbm->pFrames[i].vpicture.nBufFd;
|
|
VideoFbmInfo* pFbmInfo = (VideoFbmInfo*)(pFbm->pFbmInfo);
|
|
if(pFbmInfo->bIsSoftDecoderFlag==0)
|
|
{
|
|
CdcVeFreeIommuAddr(pFbm->sVeops, pFbm->pVeOpsSelf, &sUserIommuBuf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(pFbm->pFrames);
|
|
free(pFbm);
|
|
|
|
return;
|
|
}
|
|
|
|
VideoPicture* FbmRequestBuffer(Fbm* pFbm)
|
|
{
|
|
//int i;
|
|
//int ret = 0;
|
|
FrameNode* pFrameNode;
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
struct ScMemOpsS *_memops = NULL;
|
|
|
|
logi("FbmRequestBuffer");
|
|
if(pFbm == NULL)
|
|
return NULL;
|
|
|
|
_memops = pFbm->memops;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
pFrameNode = NULL;
|
|
if(pFbmInfo == NULL)
|
|
return NULL;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) &&(pFbm == pFbmInfo->pFbmSecond))
|
|
{
|
|
if(pFbmInfo->pMajorDecoderFrame == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pFbmInfo->pMajorDecoderFrame->nBufStatus |= MINOR_DECODER_USE_FLAG;
|
|
pFbmInfo->pMajorDecoderFrame->nBufStatus &= ~MINOR_NEED_USE_FLAG;
|
|
return pFbmInfo->pMajorDecoderFrame;
|
|
}
|
|
|
|
pFbmInfo->pMajorDecoderFrame = NULL;
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
pFrameNode = FbmDequeue(&pFbm->pEmptyBufferQueue);
|
|
|
|
if(pFrameNode != NULL)
|
|
{
|
|
//* check the picture status.
|
|
if(pFrameNode->Flag.bUsedByDecoder ||
|
|
pFrameNode->Flag.bInValidPictureQueue ||
|
|
pFrameNode->Flag.bUsedByRender ||
|
|
pFrameNode->Flag.bAlreadyDisplayed)
|
|
{
|
|
//* the picture is in the pEmptyBufferQueue, these four flags
|
|
//* shouldn't be set.
|
|
loge("invalid frame status, a picture is just pick out from the pEmptyBufferQueue, \
|
|
but bUsedByDecoder=%d, bInValidPictureQueue=%d, bUsedByRender=%d,\
|
|
bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bUsedByDecoder, pFrameNode->Flag.bInValidPictureQueue,
|
|
pFrameNode->Flag.bUsedByRender, pFrameNode->Flag.bAlreadyDisplayed);
|
|
// abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return NULL;
|
|
}
|
|
pFbm->nEmptyBufferNum--;
|
|
pFbm->nDecoderHoldingNum++;
|
|
pFrameNode->Flag.bUsedByDecoder = 1;
|
|
if(pFbmInfo->bTwoStreamShareOneFbm == 1)
|
|
{
|
|
pFbmInfo->pMajorDecoderFrame = &pFrameNode->vpicture;
|
|
pFbmInfo->pMajorDecoderFrame->nBufStatus |= MAJOR_DECODER_USE_FLAG;
|
|
pFbmInfo->pMajorDecoderFrame->nBufStatus |= MINOR_NEED_USE_FLAG;
|
|
}
|
|
|
|
//CdcMemSet(_memops,(void*)pFrameNode->vpicture.pData0,0,pFrameNode->vpicture.nBufSize);
|
|
//CdcMemFlushCache(_memops, (void*)pFrameNode->vpicture.pData0,
|
|
//pFrameNode->vpicture.nBufSize);
|
|
}
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
if((pFbmInfo->bIsFrameCtsTestFlag)&&(pFrameNode != NULL)
|
|
&& (pFrameNode->vpicture.nWidth < FBM_NEED_FLUSH_CACHE_SIZE))
|
|
{
|
|
CdcMemFlushCache(_memops, (void*)pFrameNode->vpicture.pData0,
|
|
pFrameNode->vpicture.nWidth*pFrameNode->vpicture.nHeight*3/2);
|
|
}
|
|
return (pFrameNode==NULL)? NULL: &pFrameNode->vpicture;
|
|
}
|
|
|
|
void FbmReturnBuffer(Fbm* pFbm, VideoPicture* pVPicture, int bValidPicture)
|
|
{
|
|
int index;
|
|
FrameNode* pFrameNode;
|
|
//VideoPicture fbmPicBufInfo;
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
if(pFbm == NULL)
|
|
return;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return;
|
|
|
|
if(pVPicture == NULL)
|
|
{
|
|
return;
|
|
}
|
|
logv("FbmReturnBuffer pVPicture=%p, bValidPicture=%d, id=%d", \
|
|
pVPicture, bValidPicture, pVPicture->nID);
|
|
|
|
//* 3d -- newDisplay case
|
|
if(pFbmInfo->bTwoStreamShareOneFbm == 1)
|
|
{
|
|
if(pFbm == pFbmInfo->pFbmFirst)
|
|
{
|
|
pVPicture->nBufStatus &= ~MAJOR_DECODER_USE_FLAG;
|
|
if(pVPicture->nBufStatus & MINOR_DECODER_USE_FLAG)
|
|
{
|
|
return;
|
|
}
|
|
else if((bValidPicture==1) &&(pVPicture->nBufStatus & MINOR_NEED_USE_FLAG))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else if(pFbm == pFbmInfo->pFbmSecond)
|
|
{
|
|
pVPicture->nBufStatus &= ~MINOR_DECODER_USE_FLAG;
|
|
if(pVPicture->nBufStatus & MAJOR_DECODER_USE_FLAG)
|
|
{
|
|
return;
|
|
}
|
|
pFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
}
|
|
|
|
index = pVPicture->nID;
|
|
|
|
//* check the index is valid.
|
|
if(index < 0 || index >= pFbm->nMaxFrameNum)
|
|
{
|
|
loge("FbmReturnBuffer: the picture id is invalid, pVPicture=%p, pVPicture->nID=%d",
|
|
pVPicture, pVPicture->nID);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if(pVPicture != &pFbm->pFrames[index].vpicture)
|
|
{
|
|
loge("FbmReturnBuffer: the picture id is invalid, pVPicture=%p, pVPicture->nID=%d",
|
|
pVPicture, pVPicture->nID);
|
|
return;
|
|
}
|
|
}
|
|
|
|
pFrameNode = &pFbm->pFrames[index];
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
if(pFrameNode->Flag.bUsedByDecoder == 0)
|
|
{
|
|
loge("invalid picture status, bUsedByDecoder=0 when picture buffer is returned.");
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return;
|
|
}
|
|
pFrameNode->Flag.bUsedByDecoder = 0;
|
|
|
|
if((pFrameNode->Flag.bNeedRelease==1) &&(pFrameNode->Flag.bInValidPictureQueue==0))
|
|
{
|
|
FbmEnqueue(&pFbm->pReleaseBufferQueue, pFrameNode);
|
|
pFbm->nReleaseBufferNum++;
|
|
pFrameNode->Flag.bAlreadyDisplayed = 0;
|
|
pFrameNode->Flag.bInValidPictureQueue = 0;
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
logv("return buffer end\n");
|
|
return;
|
|
}
|
|
|
|
//*the buffer was share before and in valid pic queue
|
|
if(pFrameNode->Flag.bInValidPictureQueue)
|
|
{
|
|
//* check status.
|
|
if(pFrameNode->Flag.bUsedByRender || pFrameNode->Flag.bAlreadyDisplayed)
|
|
{
|
|
loge("invalid frame status, a picture in pValidPictureQueue, \
|
|
but bUsedByRender=%d and Flag.bAlreadyDisplayed=%d",
|
|
pFrameNode->Flag.bUsedByRender, pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return;
|
|
}
|
|
}
|
|
//*the buffer was share before and used By Render
|
|
else if(pFrameNode->Flag.bInValidPictureQueue == 0 && pFrameNode->Flag.bUsedByRender == 1)
|
|
{
|
|
//*do nothing
|
|
}
|
|
//*the buffer was share before and had already displayed
|
|
else if(pFrameNode->Flag.bInValidPictureQueue == 0 && pFrameNode->Flag.bUsedByRender == 0
|
|
&& pFrameNode->Flag.bAlreadyDisplayed == 1)
|
|
{
|
|
pFrameNode->Flag.bAlreadyDisplayed = 0;
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
//*the buffer was not share before
|
|
else if(pFrameNode->Flag.bInValidPictureQueue == 0 && pFrameNode->Flag.bUsedByRender == 0
|
|
&& pFrameNode->Flag.bAlreadyDisplayed == 0)
|
|
{
|
|
if(bValidPicture)
|
|
{
|
|
FbmEnqueue(&pFbm->pValidPictureQueue, pFrameNode);
|
|
pFbm->nValidPictureNum++;
|
|
pFbm->nWaitForDispNum++;
|
|
pFrameNode->Flag.bInValidPictureQueue = 1;
|
|
}
|
|
else
|
|
{
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
}
|
|
|
|
pFbm->nDecoderHoldingNum--;
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
logv("return buffer end\n");
|
|
return;
|
|
}
|
|
|
|
void FbmShareBuffer(Fbm* pFbm, VideoPicture* pVPicture)
|
|
{
|
|
int index;
|
|
FrameNode* pFrameNode;
|
|
//VideoPicture* pDispVPicture = NULL;
|
|
//VideoPicture fbmPicBufInfo;
|
|
//int bNeedDispBuffer = 0;
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
if(pFbm == NULL)
|
|
return;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return;
|
|
|
|
if(pVPicture == NULL)
|
|
{
|
|
return;
|
|
}
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm == pFbmInfo->pFbmSecond))
|
|
{
|
|
return;
|
|
}
|
|
|
|
logv("FbmShareBuffer pVPicture=%p", pVPicture);
|
|
|
|
index = pVPicture->nID;
|
|
|
|
//* check the index is valid.
|
|
if(index < 0 || index >= pFbm->nMaxFrameNum)
|
|
{
|
|
loge("FbmShareBuffer: the picture id is invalid, \
|
|
pVPicture=%p, pVPicture->nID=%d, pFbm->nMaxFrameNum=%d",
|
|
pVPicture, pVPicture->nID, pFbm->nMaxFrameNum);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if(pVPicture != &pFbm->pFrames[index].vpicture)
|
|
{
|
|
loge("FbmShareBuffer: the picture id is invalid, pVPicture=%p, pVPicture->nID=%d",
|
|
pVPicture, pVPicture->nID);
|
|
return;
|
|
}
|
|
}
|
|
|
|
pFrameNode = &pFbm->pFrames[index];
|
|
if(pFrameNode->Flag.bNeedRelease == 1)
|
|
{
|
|
logv("the buffer need release\n");
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
//* check status.
|
|
if(pFrameNode->Flag.bUsedByDecoder == 0 ||
|
|
pFrameNode->Flag.bInValidPictureQueue == 1 ||
|
|
pFrameNode->Flag.bAlreadyDisplayed == 1)
|
|
{
|
|
loge("invalid frame status, a picture is shared but bUsedByDecoder=%d, \
|
|
bInValidPictureQueue=%d, bUsedByDecoder=%d, bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bUsedByDecoder, pFrameNode->Flag.bInValidPictureQueue,
|
|
pFrameNode->Flag.bUsedByDecoder, pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return;
|
|
}
|
|
|
|
//* put the picture to pValidPictureQueue.
|
|
pFrameNode->Flag.bInValidPictureQueue = 1;
|
|
FbmEnqueue(&pFbm->pValidPictureQueue, pFrameNode);
|
|
pFbm->nValidPictureNum++;
|
|
pFbm->nWaitForDispNum++;
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
logv("end sharebuffer\n");
|
|
return;
|
|
}
|
|
|
|
VideoPicture* FbmRequestPicture(Fbm* pFbm)
|
|
{
|
|
VideoPicture* pVPicture;
|
|
FrameNode* pFrameNode;
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
if(pFbm == NULL)
|
|
return NULL;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return NULL;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm ==pFbmInfo->pFbmSecond))
|
|
{
|
|
pFbmInfo->pMajorDispFrame->nBufStatus |= MINOR_DISP_USE_FLAG;
|
|
logv("**************here7: pVPicture->nBufStatus =%x\n",
|
|
pFbmInfo->pMajorDispFrame->nBufStatus);
|
|
return pFbmInfo->pMajorDispFrame;
|
|
}
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
// logi("FbmRequestPicture");
|
|
|
|
pVPicture = NULL;
|
|
pFbmInfo->pMajorDispFrame = NULL;
|
|
pFrameNode = FbmDequeue(&pFbm->pValidPictureQueue);
|
|
|
|
if(pFrameNode != NULL)
|
|
{
|
|
if(pFrameNode->Flag.bInValidPictureQueue == 0 ||
|
|
pFrameNode->Flag.bUsedByRender == 1 ||
|
|
pFrameNode->Flag.bAlreadyDisplayed == 1)
|
|
{
|
|
//* the picture is in the pValidPictureQueue, one of these three flags is invalid.
|
|
loge("invalid frame status, a picture is just pick out from the pValidPictureQueue, \
|
|
but bInValidPictureQueue=%d, bUsedByRender=%d, bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bInValidPictureQueue,
|
|
pFrameNode->Flag.bUsedByRender,
|
|
pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return NULL;
|
|
}
|
|
|
|
pFbm->nValidPictureNum--;
|
|
pFbm->nWaitForDispNum--;
|
|
pFbm->nRenderHoldingNum++;
|
|
pFrameNode->Flag.bInValidPictureQueue = 0;
|
|
pVPicture = &pFrameNode->vpicture;
|
|
pFrameNode->Flag.bUsedByRender = 1;
|
|
pFbmInfo->pMajorDispFrame = pVPicture;
|
|
pVPicture->nBufStatus |= MAJOR_DISP_USE_FLAG;
|
|
logv("**************here8: pVPicture->nBufStatus =%x\n", pVPicture->nBufStatus);
|
|
}
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
|
|
return (pFrameNode==NULL)? NULL: pVPicture;
|
|
}
|
|
|
|
int FbmReturnPicture(Fbm* pFbm, VideoPicture* pVPicture)
|
|
{
|
|
int index;
|
|
FrameNode* pFrameNode;
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if(pVPicture == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
logi("**************FbmReturnPicture pVPicture=%p", pVPicture,pVPicture->nID);
|
|
if(pFbmInfo->bTwoStreamShareOneFbm == 1)
|
|
{
|
|
if(pFbm == pFbmInfo->pFbmFirst)
|
|
{
|
|
pVPicture->nBufStatus &= ~MAJOR_DISP_USE_FLAG;
|
|
if(pVPicture->nBufStatus & MINOR_DISP_USE_FLAG)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else if(pFbm == pFbmInfo->pFbmSecond)
|
|
{
|
|
pVPicture->nBufStatus &= ~MINOR_DISP_USE_FLAG;
|
|
if(pVPicture->nBufStatus & MAJOR_DISP_USE_FLAG)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
index = pVPicture->nID;
|
|
|
|
//* check the index is valid.
|
|
if(index < 0 || index >= pFbm->nMaxFrameNum)
|
|
{
|
|
if(index >= FRM_FORBID_USE_TAG)
|
|
{
|
|
pFrameNode = &pFbm->pFrames[index-FRM_FORBID_USE_TAG];
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
if(pFrameNode->Flag.bUsedByRender!=0 ||
|
|
pFrameNode->Flag.bInValidPictureQueue != 0 ||
|
|
pFrameNode->Flag.bAlreadyDisplayed != 0)
|
|
{
|
|
loge(" check index valid error. bUsedByRender: \
|
|
%d, bInValidPictureQueue: %d, bAlreadyDisplayed: %d ", \
|
|
pFrameNode->Flag.bUsedByRender, pFrameNode->Flag.bInValidPictureQueue, \
|
|
pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return -1;
|
|
}
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
pVPicture->nID -= FRM_FORBID_USE_TAG;
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return 0;
|
|
}
|
|
logw("FbmReturnPicture: the picture id is invalid, pVPicture=%p, pVPicture->nID=%d",\
|
|
pVPicture, pVPicture->nID);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
if(pVPicture != &pFbm->pFrames[index].vpicture)
|
|
{
|
|
logw("FbmReturnPicture: the picture id is invalid, pVPicture=%p, pVPicture->nID=%d",\
|
|
pVPicture, pVPicture->nID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
pFrameNode = &pFbm->pFrames[index];
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
if(pFrameNode->Flag.bUsedByRender == 0 ||
|
|
pFrameNode->Flag.bInValidPictureQueue == 1 ||
|
|
pFrameNode->Flag.bAlreadyDisplayed == 1)
|
|
{
|
|
//* the picture is being returned, but one of these three flags is invalid.
|
|
loge("invalid frame status, a picture being returned, \
|
|
but bUsedByRender=%d, bInValidPictureQueue=%d, bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bUsedByRender,
|
|
pFrameNode->Flag.bInValidPictureQueue,
|
|
pFrameNode->Flag.bAlreadyDisplayed);
|
|
loge("**picture[%p],id[%d]",&pFrameNode->vpicture,pFrameNode->vpicture.nID);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return -1;
|
|
}
|
|
|
|
pFrameNode->Flag.bUsedByRender = 0;
|
|
pFbm->nRenderHoldingNum--;
|
|
if(pFrameNode->Flag.bUsedByDecoder)
|
|
pFrameNode->Flag.bAlreadyDisplayed = 1;
|
|
else
|
|
{
|
|
if(pFrameNode->Flag.bNeedRelease == 0)
|
|
{
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
else
|
|
{
|
|
FbmEnqueue(&pFbm->pReleaseBufferQueue, pFrameNode);
|
|
pFbm->nReleaseBufferNum++;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
VideoPicture* FbmNextPictureInfo(Fbm* pFbm)
|
|
{
|
|
FrameNode* pFrameNode;
|
|
|
|
// logi("FbmNextPictureInfo");
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
|
|
if(pFbm == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return NULL;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
|
|
if(ppFbm->pValidPictureQueue != NULL)
|
|
{
|
|
pFrameNode = ppFbm->pValidPictureQueue;
|
|
return &pFrameNode->vpicture;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
void FbmFlush(Fbm* pFbm)
|
|
{
|
|
FrameNode* pFrameNode;
|
|
//VideoPicture fbmPicBufInfo;
|
|
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
|
|
if(pFbm == NULL)
|
|
return;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
logv("FbmFlush");
|
|
|
|
while((pFrameNode = FbmDequeue(&pFbm->pValidPictureQueue)) != NULL)
|
|
{
|
|
pFrameNode->vpicture.nBufStatus = 0;
|
|
pFbm->nValidPictureNum--;
|
|
|
|
//* check the picture status.
|
|
if(pFrameNode->Flag.bUsedByRender || pFrameNode->Flag.bAlreadyDisplayed)
|
|
{
|
|
//* the picture is in the pValidPictureQueue, these two flags
|
|
//* shouldn't be set.
|
|
loge("invalid frame status, a picture is just pick out from the pValidPictureQueue, \
|
|
but bUsedByRender=%d and bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bUsedByRender, pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return;
|
|
}
|
|
|
|
pFrameNode->Flag.bInValidPictureQueue = 0;
|
|
if(pFrameNode->Flag.bUsedByDecoder == 0)
|
|
{
|
|
//* the picture is not used, put it into pEmptyBufferQueue.
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
else
|
|
{
|
|
//* the picture was shared by the video engine,
|
|
//* set the bAlreadyDisplayed so the picture won't be put into
|
|
//* the pValidPictureQueue when it is returned by the video engine.
|
|
pFrameNode->Flag.bAlreadyDisplayed = 1;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
|
|
return;
|
|
}
|
|
|
|
int FbmGetBufferInfo(Fbm* pFbm, VideoPicture* pVPicture)
|
|
{
|
|
CEDARC_UNUSE(FbmGetBufferInfo);
|
|
|
|
FrameNode* pFrameNode;
|
|
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
|
|
logi("FbmGetBufferInfo");
|
|
|
|
//* give the general information of the video pictures.
|
|
pFrameNode = &ppFbm->pFrames[0];
|
|
pVPicture->ePixelFormat = pFrameNode->vpicture.ePixelFormat;
|
|
pVPicture->nWidth = pFrameNode->vpicture.nWidth;
|
|
pVPicture->nHeight = pFrameNode->vpicture.nHeight;
|
|
pVPicture->nLineStride = pFrameNode->vpicture.nLineStride;
|
|
pVPicture->nTopOffset = pFrameNode->vpicture.nTopOffset;
|
|
pVPicture->nLeftOffset = pFrameNode->vpicture.nLeftOffset;
|
|
pVPicture->nFrameRate = pFrameNode->vpicture.nFrameRate;
|
|
pVPicture->nAspectRatio = pFrameNode->vpicture.nAspectRatio;
|
|
pVPicture->bIsProgressive = pFrameNode->vpicture.bIsProgressive;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int FbmTotalBufferNum(Fbm* pFbm)
|
|
{
|
|
logi("FbmTotalBufferNum");
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
return ppFbm->nMaxFrameNum;
|
|
}
|
|
|
|
int FbmEmptyBufferNum(Fbm* pFbm)
|
|
{
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
int nEmptyBufferNum = 0;
|
|
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
nEmptyBufferNum = ppFbm->nEmptyBufferNum;
|
|
return nEmptyBufferNum;
|
|
}
|
|
|
|
int FbmGetDecoderHoldingBufferNum(Fbm* pFbm)
|
|
{
|
|
CEDARC_UNUSE(FbmGetDecoderHoldingBufferNum);
|
|
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
int Num = 0;
|
|
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
Num = ppFbm->nDecoderHoldingNum;
|
|
return Num;
|
|
}
|
|
int FbmGetRenderHoldingBufferNum(Fbm* pFbm)
|
|
{
|
|
CEDARC_UNUSE(FbmGetRenderHoldingBufferNum);
|
|
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
int Num = 0;
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
Num = ppFbm->nRenderHoldingNum;
|
|
return Num;
|
|
}
|
|
int FbmGetDisplayBufferNum(Fbm* pFbm)
|
|
{
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
int Num = 0;
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
Num = ppFbm->nRenderHoldingNum + ppFbm->nValidPictureNum;
|
|
return Num;
|
|
}
|
|
int FbmValidPictureNum(Fbm* pFbm)
|
|
{
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
int nValidPictureNum = 0;
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
nValidPictureNum = ppFbm->nValidPictureNum;
|
|
return nValidPictureNum;
|
|
}
|
|
|
|
int FbmGetAlignValue(Fbm* pFbm)
|
|
{
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
Fbm* ppFbm = NULL;
|
|
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bTwoStreamShareOneFbm == 1) && (pFbm==pFbmInfo->pFbmSecond))
|
|
{
|
|
ppFbm = pFbmInfo->pFbmFirst;
|
|
}
|
|
else
|
|
{
|
|
ppFbm = pFbm;
|
|
}
|
|
return ppFbm->nAlignValue;
|
|
}
|
|
|
|
int FbmAllocatePictureBuffer(Fbm* pFbm, VideoPicture* pPicture,
|
|
int* nAlignValue, int nWidth, int nHeight)
|
|
{
|
|
int ePixelFormat;
|
|
int nHeight16Align;
|
|
int nHeight32Align;
|
|
char* pMem;
|
|
int nMemSizeY;
|
|
int nMemSizeC;
|
|
int nLineStride;
|
|
int nHeight64Align;
|
|
|
|
//void *veOps = NULL;
|
|
//void *pVeopsSelf = NULL;
|
|
|
|
ePixelFormat = pPicture->ePixelFormat;
|
|
nHeight16Align = (nHeight+15) & ~15;
|
|
nHeight32Align = (nHeight+31) & ~31;
|
|
nHeight64Align = (nHeight+63) & ~63;
|
|
|
|
pPicture->pData0 = NULL;
|
|
pPicture->pData1 = NULL;
|
|
pPicture->pData2 = NULL;
|
|
pPicture->pData3 = NULL;
|
|
|
|
switch(ePixelFormat)
|
|
{
|
|
case PIXEL_FORMAT_P010_UV:
|
|
case PIXEL_FORMAT_P010_VU:
|
|
{
|
|
|
|
if(*nAlignValue == 0)
|
|
{
|
|
nLineStride = (nWidth+15) &~ 15;
|
|
pPicture->nLineStride = nLineStride;
|
|
pPicture->nWidth = pPicture->nLineStride;
|
|
pPicture->nHeight = nHeight16Align;
|
|
nMemSizeY = pPicture->nWidth*pPicture->nHeight*2;
|
|
*nAlignValue = 16;
|
|
}
|
|
else
|
|
{
|
|
nLineStride = (nWidth+*nAlignValue-1) &~ (*nAlignValue-1);
|
|
pPicture->nLineStride = nLineStride;
|
|
pPicture->nWidth = pPicture->nLineStride;
|
|
pPicture->nHeight = (nHeight+*nAlignValue-1) &~ (*nAlignValue-1);;
|
|
nMemSizeY = pPicture->nWidth*pPicture->nHeight*2;
|
|
}
|
|
nMemSizeC = nMemSizeY>>2;
|
|
pMem = (char*)CdcMemPalloc(pFbm->memops, nMemSizeY + nMemSizeC*2,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture buffer.", \
|
|
nMemSizeY + nMemSizeC*2);
|
|
return -1;
|
|
}
|
|
|
|
pPicture->pData0 = pMem;
|
|
|
|
pPicture->pData1 = pMem+nMemSizeY;
|
|
pPicture->pData2 = NULL;
|
|
pPicture->nBufSize = nMemSizeY+2*nMemSizeC;
|
|
break;
|
|
}
|
|
case PIXEL_FORMAT_YUV_PLANER_420:
|
|
case PIXEL_FORMAT_YUV_PLANER_422:
|
|
case PIXEL_FORMAT_YUV_PLANER_444:
|
|
case PIXEL_FORMAT_YV12:
|
|
case PIXEL_FORMAT_NV21:
|
|
case PIXEL_FORMAT_NV12:
|
|
{
|
|
//* for decoder,
|
|
//* height of Y component is required to be 16 aligned, for example,
|
|
//* 1080 becomes to 1088.
|
|
//* width and height of U or V component are both required to be 8 aligned.
|
|
//* nLineStride should be 16 aligned.
|
|
if(*nAlignValue == 0)
|
|
{
|
|
nLineStride = (nWidth+15) &~ 15;
|
|
pPicture->nLineStride = nLineStride;
|
|
pPicture->nWidth = pPicture->nLineStride;
|
|
pPicture->nHeight = nHeight16Align;
|
|
nMemSizeY = pPicture->nWidth*pPicture->nHeight;
|
|
*nAlignValue = 16;
|
|
}
|
|
else
|
|
{
|
|
nLineStride = (nWidth+*nAlignValue-1) &~ (*nAlignValue-1);
|
|
pPicture->nLineStride = nLineStride;
|
|
pPicture->nWidth = pPicture->nLineStride;
|
|
pPicture->nHeight = (nHeight+*nAlignValue-1) &~ (*nAlignValue-1);;
|
|
nMemSizeY = pPicture->nWidth*pPicture->nHeight;
|
|
}
|
|
|
|
if(ePixelFormat == PIXEL_FORMAT_YUV_PLANER_420 ||
|
|
ePixelFormat == PIXEL_FORMAT_YV12 ||
|
|
ePixelFormat == PIXEL_FORMAT_NV21)
|
|
nMemSizeC = nMemSizeY>>2;
|
|
else if(ePixelFormat == PIXEL_FORMAT_YUV_PLANER_422)
|
|
nMemSizeC = nMemSizeY>>1;
|
|
else
|
|
nMemSizeC = nMemSizeY; //* PIXEL_FORMAT_YUV_PLANER_444
|
|
|
|
int nLower2BitBufSize = 0;
|
|
int nAfbcBufSize = 0;
|
|
int nNormalYuvBufSize = nMemSizeY + nMemSizeC*2;
|
|
int nTotalPicPhyBufSize = 0;
|
|
int frmbuf_c_size = 0;
|
|
|
|
nLower2BitBufSize = ((((nWidth+3)>>2) + 31) & 0xffffffe0) * nHeight * 3/2;
|
|
int PriChromaStride = ((nWidth/2) + 31)&0xffffffe0;
|
|
frmbuf_c_size = 2 * (PriChromaStride * (((nHeight/2)+15)&0xfffffff0)/4);
|
|
logd("****nAfbcBufSize = %d, nWidth = %d, nHeight = %d ",
|
|
nAfbcBufSize, nWidth, nHeight);
|
|
if(pPicture->b10BitPicFlag)
|
|
{
|
|
if(pPicture->bEnableAfbcFlag == 1)
|
|
{
|
|
//nAfbcBufSize += frmbuf_c_size;
|
|
nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (512 + 16) + 32 + 1024;
|
|
//nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (512 + 16) + 1024;
|
|
nTotalPicPhyBufSize = nAfbcBufSize + frmbuf_c_size + nLower2BitBufSize;
|
|
logd("nTotalSize = %d, nAfbcBufSize = %d,\
|
|
frmbuf_c_size = %d, nLower2BitBufSize = %d",
|
|
nTotalPicPhyBufSize, nAfbcBufSize,
|
|
frmbuf_c_size, nLower2BitBufSize);
|
|
}
|
|
else
|
|
{
|
|
nTotalPicPhyBufSize = nNormalYuvBufSize + nLower2BitBufSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pPicture->bEnableAfbcFlag == 1)
|
|
{
|
|
nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (384 + 16) + 32 + 1024;
|
|
//nAfbcBufSize = ((nWidth+15)>>4) * ((nHeight+4+15)>>4) * (384 + 16) + 1024;
|
|
nTotalPicPhyBufSize = nAfbcBufSize + frmbuf_c_size;
|
|
}
|
|
else
|
|
{
|
|
nTotalPicPhyBufSize = nNormalYuvBufSize;
|
|
}
|
|
}
|
|
|
|
pMem = (char*)CdcMemPalloc(pFbm->memops, nTotalPicPhyBufSize/*nMemSizeY + nMemSizeC*2*/,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture buffer.", \
|
|
nMemSizeY + nMemSizeC*2);
|
|
return -1;
|
|
}
|
|
logd("pPicture->bEnableAfbcFlag = %d",pPicture->bEnableAfbcFlag);
|
|
if(pPicture->bEnableAfbcFlag == 1)
|
|
{
|
|
logd("** set buf to 0, pMem = %p",pMem);
|
|
memset(pMem, 0, nTotalPicPhyBufSize);
|
|
CdcMemFlushCache(pFbm->memops,pMem, nTotalPicPhyBufSize);
|
|
}
|
|
|
|
if(pPicture->b10BitPicFlag)
|
|
{
|
|
if(pPicture->bEnableAfbcFlag == 1)
|
|
{
|
|
pPicture->pData0 = pMem;
|
|
//pPicture->pLower2BitVirtAddr = pMem + nAfbcBufSize;
|
|
pPicture->nLower2BitBufSize = nLower2BitBufSize;
|
|
pPicture->nLower2BitBufOffset = nAfbcBufSize + frmbuf_c_size;
|
|
pPicture->nLower2BitBufStride = ((((nWidth+3)>>2) + 31) & 0xffffffe0);
|
|
pPicture->nAfbcSize = nAfbcBufSize;
|
|
}
|
|
else
|
|
{
|
|
pPicture->pData0 = pMem;
|
|
pPicture->pData1 = pMem + nMemSizeY;
|
|
//pPicture->pLower2BitVirtAddr = pMem + nNormalYuvBufSize;
|
|
pPicture->nLower2BitBufSize = nLower2BitBufSize;
|
|
pPicture->nLower2BitBufOffset = nNormalYuvBufSize;
|
|
pPicture->nLower2BitBufStride = ((((nWidth+3)>>2) + 31) & 0xffffffe0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pPicture->bEnableAfbcFlag == 1)
|
|
{
|
|
pPicture->pData0 = pMem;
|
|
pPicture->nAfbcSize = nAfbcBufSize;
|
|
}
|
|
else
|
|
{
|
|
pPicture->pData0 = pMem;
|
|
pPicture->pData1 = pMem + nMemSizeY;
|
|
if(ePixelFormat != PIXEL_FORMAT_NV21)
|
|
pPicture->pData2 = pMem + nMemSizeY + nMemSizeC;
|
|
else
|
|
pPicture->pData2 = NULL; //* U and V component are combined at pData1.
|
|
}
|
|
}
|
|
pPicture->pData3 = NULL;
|
|
pPicture->nBufSize = nTotalPicPhyBufSize;
|
|
|
|
pMem = (char*)malloc(4*1024);
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture metadata buffer", 4*1024);
|
|
return -1;
|
|
}
|
|
pPicture->pMetaData = (void*)pMem;
|
|
|
|
break;
|
|
}
|
|
case PIXEL_FORMAT_YUV_MB32_420:
|
|
case PIXEL_FORMAT_YUV_MB32_422:
|
|
case PIXEL_FORMAT_YUV_MB32_444:
|
|
{
|
|
//* for decoder,
|
|
//* height of Y component is required to be 32 aligned.
|
|
//* height of UV component are both required to be 32 aligned.
|
|
//* nLineStride should be 32 aligned.
|
|
#if 0
|
|
*nAlignValue = 32;
|
|
|
|
pPicture->nLineStride = (nWidth+31)&~31;
|
|
nLineStride = (pPicture->nWidth+63) &~ 63;
|
|
pPicture->nWidth = nLineStride;
|
|
pPicture->nHeight = nHeight64Align;
|
|
|
|
nMemSizeY = pPicture->nWidth*pPicture->nHeight;
|
|
|
|
if(ePixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
nMemSizeC = nLineStride*nHeight64Align/4;
|
|
else if(ePixelFormat == PIXEL_FORMAT_YUV_MB32_422)
|
|
nMemSizeC = nLineStride*nHeight64Align/2;
|
|
else
|
|
nMemSizeC = nLineStride*nHeight64Align;
|
|
|
|
pMem = (char*)CdcMemPalloc(memops, nMemSizeY);
|
|
#else
|
|
*nAlignValue = 32;
|
|
|
|
pPicture->nLineStride = (nWidth+31)&~31;
|
|
pPicture->nWidth = pPicture->nLineStride;
|
|
pPicture->nHeight = nHeight32Align;
|
|
nLineStride = (pPicture->nWidth+63) &~ 63;
|
|
nMemSizeY = nLineStride*nHeight64Align;
|
|
|
|
if(ePixelFormat == PIXEL_FORMAT_YUV_MB32_420)
|
|
nMemSizeC = nLineStride*nHeight64Align/4;
|
|
else if(ePixelFormat == PIXEL_FORMAT_YUV_MB32_422)
|
|
nMemSizeC = nLineStride*nHeight64Align/2;
|
|
else
|
|
nMemSizeC = nLineStride*nHeight64Align;
|
|
|
|
pMem = (char*)CdcMemPalloc(pFbm->memops, nMemSizeY,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
#endif
|
|
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture buffer.", nMemSizeY);
|
|
return -1;
|
|
}
|
|
pPicture->pData0 = pMem;
|
|
|
|
pMem = (char*)CdcMemPalloc(pFbm->memops, nMemSizeC*2,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf); //* UV is combined.
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture buffer.", nMemSizeC*2);
|
|
CdcMemPfree(pFbm->memops, pPicture->pData0,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
pPicture->pData0 = NULL;
|
|
return -1;
|
|
}
|
|
pPicture->pData1 = pMem;
|
|
pPicture->pData2 = NULL;
|
|
pPicture->pData3 = NULL;
|
|
|
|
break;
|
|
}
|
|
case PIXEL_FORMAT_RGBA:
|
|
case PIXEL_FORMAT_ARGB:
|
|
case PIXEL_FORMAT_ABGR:
|
|
case PIXEL_FORMAT_BGRA:
|
|
{
|
|
nLineStride = pPicture->nWidth*4;
|
|
pPicture->nLineStride = nLineStride;
|
|
|
|
nMemSizeY = nLineStride*nHeight;
|
|
pMem = (char *)CdcMemPalloc(pFbm->memops,nMemSizeY,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
if(pMem == NULL)
|
|
{
|
|
loge("memory alloc fail, require %d bytes for picture buffer.", nMemSizeY);
|
|
return -1;
|
|
}
|
|
// must memset pixels to oxFF, or jpeg_test in skia will failed
|
|
memset(pMem, 0xff, nMemSizeY);
|
|
CdcMemFlushCache(pFbm->memops,pMem, nMemSizeY);
|
|
|
|
pPicture->pData0 = pMem;
|
|
pPicture->pData1 = NULL;
|
|
pPicture->pData2 = NULL;
|
|
pPicture->pData3 = NULL;
|
|
break;
|
|
}
|
|
default:
|
|
loge("pixel format incorrect, ePixelFormat=%d", ePixelFormat);
|
|
return -1;
|
|
}
|
|
|
|
if(pPicture->pData0 != NULL)
|
|
{
|
|
pPicture->phyYBufAddr = (size_addr)CdcMemGetPhysicAddress(pFbm->memops, pPicture->pData0);
|
|
}
|
|
if(pPicture->pData1 != NULL)
|
|
{
|
|
pPicture->phyCBufAddr = (size_addr)CdcMemGetPhysicAddress(pFbm->memops, pPicture->pData1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int FbmFreePictureBuffer(Fbm* pFbm, VideoPicture* pPicture)
|
|
{
|
|
if(pPicture->pData0 != NULL)
|
|
{
|
|
CdcMemPfree(pFbm->memops, pPicture->pData0, pFbm->sVeops,
|
|
pFbm->pVeOpsSelf);
|
|
pPicture->pData0 = NULL;
|
|
}
|
|
|
|
if(pPicture->pMetaData != NULL && pFbm->bUseGpuBuf == 0)
|
|
{
|
|
free(pPicture->pMetaData);
|
|
pPicture->pMetaData = NULL;
|
|
}
|
|
|
|
if(pPicture->ePixelFormat < PIXEL_FORMAT_YUV_MB32_420)
|
|
{
|
|
return 0;
|
|
}
|
|
if(pPicture->pData1 != NULL)
|
|
{
|
|
CdcMemPfree(pFbm->memops,pPicture->pData1,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
pPicture->pData1 = NULL;
|
|
}
|
|
|
|
if(pPicture->pData2 != NULL)
|
|
{
|
|
CdcMemPfree(pFbm->memops,pPicture->pData2,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
pPicture->pData2 = NULL;
|
|
}
|
|
|
|
if(pPicture->pData3 != NULL)
|
|
{
|
|
CdcMemPfree(pFbm->memops,pPicture->pData3,
|
|
pFbm->sVeops, pFbm->pVeOpsSelf);
|
|
pPicture->pData3 = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if 1
|
|
/**************************************************************
|
|
* ******these functions only be used in new display structure.
|
|
***************************************************************/
|
|
FbmBufInfo* FbmGetVideoBufferInfo(VideoFbmInfo* pFbmInf)
|
|
{
|
|
if(pFbmInf == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
if(pFbmInf->bIs3DStream==1)
|
|
{
|
|
if((pFbmInf->pFbmFirst!=NULL) &&(pFbmInf->pFbmSecond!=NULL))
|
|
{
|
|
return &(pFbmInf->pFbmBufInfo);
|
|
}
|
|
}
|
|
//else if(pFbmInf->pFbmFirst != NULL)
|
|
else if(pFbmInf->pFbmBufInfo.nBufNum == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return &(pFbmInf->pFbmBufInfo);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
VideoPicture* FbmSetFbmBufAddress(VideoFbmInfo* pFbmInfo,
|
|
VideoPicture* pPicture, int bForbidUseFlag)
|
|
{
|
|
Fbm* pFbm = NULL;
|
|
|
|
FrameNode* pFrameNode = NULL;
|
|
//int nYBufferSize = 0;
|
|
if(pFbmInfo == NULL)
|
|
return NULL;
|
|
|
|
if((pFbmInfo->bIs3DStream==1)||(pFbmInfo->pFbmSecond==NULL))
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmFirst;
|
|
}
|
|
else if(pFbmInfo->pFbmSecond != NULL)
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmSecond;
|
|
}
|
|
|
|
if(pFbm == NULL)
|
|
{
|
|
loge("the handle is error:pFbm=%p\n",pFbm);
|
|
return 0;
|
|
}
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
pFrameNode = &pFbm->pFrames[pFbmInfo->nValidBufNum];
|
|
|
|
pFrameNode->vpicture.pData0 = pPicture->pData0;
|
|
pFrameNode->vpicture.pData1 = pPicture->pData1;
|
|
pFrameNode->vpicture.pData2 = pPicture->pData2;
|
|
pFrameNode->vpicture.phyYBufAddr = pPicture->phyYBufAddr;
|
|
pFrameNode->vpicture.phyCBufAddr = pPicture->phyCBufAddr;
|
|
pFrameNode->vpicture.nBufId = pPicture->nBufId;
|
|
pFrameNode->vpicture.nBufFd = pPicture->nBufFd;
|
|
pFrameNode->vpicture.pPrivate = pPicture->pPrivate;
|
|
pFrameNode->vpicture.pMetaData = pPicture->pMetaData;
|
|
pFrameNode->vpicture.nID = pFbmInfo->nValidBufNum;
|
|
pFrameNode->vpicture.nColorPrimary = 0xffffffff;
|
|
if(bForbidUseFlag == 0)
|
|
{
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
else
|
|
{
|
|
pFrameNode->vpicture.nID += FRM_FORBID_USE_TAG;
|
|
}
|
|
|
|
if(pFbmInfo->bIs3DStream==1)
|
|
{
|
|
pFrameNode->vpicture.phyCBufAddr = \
|
|
pFrameNode->vpicture.phyYBufAddr+2*pFbmInfo->nMinorYBufOffset;
|
|
pFrameNode->vpicture.pData1 = \
|
|
pFrameNode->vpicture.pData0+2*pFbmInfo->nMinorYBufOffset;
|
|
}
|
|
pFbmInfo->nValidBufNum++;
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return &pFrameNode->vpicture;
|
|
}
|
|
|
|
int FbmNewDispRelease(Fbm* pFbm)
|
|
{
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
while(1)
|
|
{
|
|
FrameNode* pFrameNode = FbmDequeue(&pFbm->pEmptyBufferQueue);
|
|
if(pFrameNode == NULL)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//* check the picture status.
|
|
if(pFrameNode->Flag.bUsedByDecoder ||
|
|
pFrameNode->Flag.bInValidPictureQueue ||
|
|
pFrameNode->Flag.bUsedByRender ||
|
|
pFrameNode->Flag.bAlreadyDisplayed)
|
|
{
|
|
//* the picture is in the pEmptyBufferQueue, these four flags
|
|
//* shouldn't be set.
|
|
loge("invalid frame status, \
|
|
a picture is just pick out from the pEmptyBufferQueue, \
|
|
but bUsedByDecoder=%d, bInValidPictureQueue=%d, bUsedByRender=%d,\
|
|
bAlreadyDisplayed=%d.",
|
|
pFrameNode->Flag.bUsedByDecoder, pFrameNode->Flag.bInValidPictureQueue,
|
|
pFrameNode->Flag.bUsedByRender, pFrameNode->Flag.bAlreadyDisplayed);
|
|
//abort();
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return 0;
|
|
}
|
|
pFbm->nEmptyBufferNum--;
|
|
FbmEnqueue(&pFbm->pReleaseBufferQueue, pFrameNode);
|
|
pFbm->nReleaseBufferNum++;
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return 0;
|
|
}
|
|
|
|
int FbmSetNewDispRelease(VideoFbmInfo* pFbmInfo)
|
|
{
|
|
Fbm* pFbm = NULL;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bIs3DStream==1) || (pFbmInfo->pFbmSecond==NULL))
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmFirst;
|
|
}
|
|
else if(pFbmInfo->pFbmSecond != NULL)
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmSecond;
|
|
}
|
|
|
|
if(pFbm != NULL)
|
|
{
|
|
int index;
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
for(index=0; index<pFbm->nMaxFrameNum; index++)
|
|
{
|
|
FrameNode* pFrameNode = &pFbm->pFrames[index];
|
|
if(pFrameNode->vpicture.nBufId != FBM_NEW_DISP_INVALID_TAG)
|
|
{
|
|
pFrameNode->Flag.bNeedRelease = 1;
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
FbmFlush(pFbm);
|
|
FbmNewDispRelease(pFbm);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
VideoPicture* FbmRequestReleasePicture(VideoFbmInfo* pFbmInfo)
|
|
{
|
|
Fbm* pFbm = NULL;
|
|
FrameNode* pFrameNode = NULL;
|
|
//int index = 0;
|
|
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
if((pFbmInfo->bIs3DStream==1) || (pFbmInfo->pFbmSecond==NULL))
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmFirst;
|
|
}
|
|
else if(pFbmInfo->pFbmSecond != NULL)
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmSecond;
|
|
}
|
|
if(pFbm == NULL)
|
|
{
|
|
loge("the handle is error:pFbm=%p\n", pFbm);
|
|
return NULL;
|
|
}
|
|
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
pFrameNode = FbmDequeue(&pFbm->pReleaseBufferQueue);
|
|
if(pFrameNode != NULL)
|
|
{
|
|
pFbm->nReleaseBufferNum--;
|
|
pFrameNode->vpicture.nID = FRM_RELEASE_TAG;
|
|
}
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return (pFrameNode==NULL)? NULL: &(pFrameNode->vpicture);
|
|
}
|
|
|
|
VideoPicture* FbmReturnReleasePicture(VideoFbmInfo* pFbmInfo,
|
|
VideoPicture* pVpicture, int bForbidUseFlag)
|
|
{
|
|
Fbm* pFbm = NULL;
|
|
FrameNode* pFrameNode = NULL;
|
|
int index = 0;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
|
|
if((pFbmInfo->bIs3DStream==1) || (pFbmInfo->pFbmSecond==NULL))
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmFirst;
|
|
}
|
|
else if(pFbmInfo->pFbmSecond != NULL)
|
|
{
|
|
pFbm = (Fbm*)pFbmInfo->pFbmSecond;
|
|
}
|
|
if(pFbm == NULL)
|
|
{
|
|
loge("the handle is error:pFbm=%p\n", pFbm);
|
|
return NULL;
|
|
}
|
|
pthread_mutex_lock(&pFbm->mutex);
|
|
|
|
for(index=0; index<pFbm->nMaxFrameNum; index++)
|
|
{
|
|
pFrameNode = &pFbm->pFrames[index];
|
|
if((pFrameNode->Flag.bNeedRelease==1)&&(pFrameNode->vpicture.nID == FRM_RELEASE_TAG))
|
|
{
|
|
//memcpy(&(pFrameNode->vpicture), pVpicture, sizeof(VideoPicture));
|
|
pFrameNode->vpicture.pData0 = pVpicture->pData0;
|
|
pFrameNode->vpicture.pData1 = pVpicture->pData1;
|
|
pFrameNode->vpicture.pData2 = pVpicture->pData2;
|
|
pFrameNode->vpicture.phyYBufAddr = pVpicture->phyYBufAddr;
|
|
pFrameNode->vpicture.phyCBufAddr = pVpicture->phyCBufAddr;
|
|
pFrameNode->vpicture.nBufId = pVpicture->nBufId;
|
|
pFrameNode->vpicture.nBufFd = pVpicture->nBufFd;
|
|
pFrameNode->vpicture.pPrivate = pVpicture->pPrivate;
|
|
pFrameNode->vpicture.pMetaData = pVpicture->pMetaData;
|
|
pFrameNode->Flag.bNeedRelease = 0;
|
|
pFrameNode->vpicture.nID = index;
|
|
pFrameNode->vpicture.nColorPrimary = 0xffffffff;
|
|
if(bForbidUseFlag == 0)
|
|
{
|
|
FbmEnqueue(&pFbm->pEmptyBufferQueue, pFrameNode);
|
|
pFbm->nEmptyBufferNum++;
|
|
}
|
|
else
|
|
{
|
|
pFrameNode->vpicture.nID += FRM_FORBID_USE_TAG;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VideoPicture* pPic = &pFrameNode->vpicture;
|
|
|
|
if(index >= pFbm->nMaxFrameNum)
|
|
{
|
|
logw("return release picture failed, as no frameNode");
|
|
pPic = NULL;
|
|
}
|
|
|
|
pthread_mutex_unlock(&pFbm->mutex);
|
|
return pPic;
|
|
}
|
|
|
|
unsigned int FbmGetBufferOffset(Fbm* pFbm, int isYBufferFlag)
|
|
{
|
|
VideoFbmInfo* pFbmInfo = NULL;
|
|
if(pFbm == NULL)
|
|
return 0;
|
|
pFbmInfo = (VideoFbmInfo*)pFbm->pFbmInfo;
|
|
if(pFbmInfo == NULL)
|
|
return 0;
|
|
if(pFbm == pFbmInfo->pFbmFirst)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return (isYBufferFlag==1)? pFbmInfo->nMinorYBufOffset: pFbmInfo->nMinorCBufOffset;
|
|
}
|
|
}
|
|
#endif
|