Files
luban-lite-t3e-pro/packages/artinchip/mpp/middle_media/openmax/component/OMX_VideoRenderComponent.c
刘可亮 aaa66c7b20 V1.0.1
2023-11-09 20:19:51 +08:00

1963 lines
83 KiB
C

/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: OMX_VideoRenderComponent
*/
#include "OMX_VideoRenderComponent.h"
#define aic_pthread_mutex_lock(mutex)\
{\
pthread_mutex_lock(mutex);\
}
#define aic_pthread_mutex_unlock(mutex)\
{\
pthread_mutex_unlock(mutex);\
}
#define OMX_VideoRenderListEmpty(list,mutex)\
({\
int ret = 0;\
aic_pthread_mutex_lock(&mutex);\
ret = mpp_list_empty(list);\
aic_pthread_mutex_unlock(&mutex);\
(ret);\
})
static OMX_S64 OMX_ClockGetSystemTime();
static OMX_ERRORTYPE OMX_VideoRenderSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData);
static OMX_ERRORTYPE OMX_VideoRenderGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_VideoRenderSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_VideoRenderGetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_VideoRenderSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_VideoRenderGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState);
static OMX_ERRORTYPE OMX_VideoRenderComponentTunnelRequest(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_U32 nPort,
OMX_IN OMX_HANDLETYPE hTunneledComp,
OMX_IN OMX_U32 nTunneledPort,
OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup);
static OMX_ERRORTYPE OMX_VideoRenderEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_VideoRenderFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_VideoRenderSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData);
static int OMX_VideoRenderGiveBackAllFrames(VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType);
static s32 OMX_VideoRenderGetComponentNum(enum mpp_pixel_format format)
{
int component_num = 0;
if (format == MPP_FMT_ARGB_8888) {
component_num = 1;
} else if (format == MPP_FMT_RGBA_8888) {
component_num = 1;
} else if (format == MPP_FMT_RGB_888) {
component_num = 1;
} else if (format == MPP_FMT_YUV420P) {
component_num = 3;
} else if (format == MPP_FMT_NV12 || format == MPP_FMT_NV21) {
component_num = 2;
} else if (format == MPP_FMT_YUV444P) {
component_num = 3;
} else if (format == MPP_FMT_YUV422P) {
component_num = 3;
} else if (format == MPP_FMT_YUV400) {
component_num = 1;
} else {
loge("no support picture foramt %d, default argb8888", format);
}
return component_num;
}
static int OMX_VideoRenderAllocFrameBuffer(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,struct mpp_frame* pFrame)
{
int height;
int buf_size;
if (pFrame == NULL) {
return -1;
}
height = pFrame->buf.size.height;
buf_size = height * pFrame->buf.stride[0];
pFrame->buf.phy_addr[0] = 0;
pFrame->buf.phy_addr[1] = 0;
pFrame->buf.phy_addr[2] = 0;
switch(pFrame->buf.format) {
case MPP_FMT_YUV420P:
pFrame->buf.phy_addr[0] = mpp_phy_alloc(buf_size);
pFrame->buf.phy_addr[1] = mpp_phy_alloc(buf_size >> 2);
pFrame->buf.phy_addr[2] = mpp_phy_alloc(buf_size >> 2);
break;
case MPP_FMT_YUV444P:
pFrame->buf.phy_addr[0] = mpp_phy_alloc(buf_size);
pFrame->buf.phy_addr[1] = mpp_phy_alloc(buf_size);
pFrame->buf.phy_addr[2] = mpp_phy_alloc(buf_size);
break;
case MPP_FMT_YUV422P:
pFrame->buf.phy_addr[0] = mpp_phy_alloc(buf_size);
pFrame->buf.phy_addr[1] = mpp_phy_alloc(buf_size >> 1);
pFrame->buf.phy_addr[2] = mpp_phy_alloc(buf_size >> 1);
break;
case MPP_FMT_NV12:
case MPP_FMT_NV21:
pFrame->buf.phy_addr[0] = mpp_phy_alloc(buf_size);
pFrame->buf.phy_addr[1] = mpp_phy_alloc(buf_size >> 1);
break;
case MPP_FMT_YUV400:
case MPP_FMT_ABGR_8888:
case MPP_FMT_ARGB_8888:
case MPP_FMT_RGBA_8888:
case MPP_FMT_BGRA_8888:
case MPP_FMT_BGR_888:
case MPP_FMT_RGB_888:
case MPP_FMT_BGR_565:
case MPP_FMT_RGB_565:
loge("unsupport format");
return -1;
default:
break;
}
return 0;
}
static int OMX_VideoRenderFreeFrameBuffer(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,struct mpp_frame* pFrame)
{
int i = 0;
int comp = 0;
if (!pVideoRenderDataType || !pFrame) {
return -1;
}
comp = OMX_VideoRenderGetComponentNum(pFrame->buf.format);
for (i = 0; i < comp;i++) {
if (pFrame->buf.phy_addr[i]) {
mpp_phy_free(pFrame->buf.phy_addr[i]);
pFrame->buf.phy_addr[i] = 0;
}
}
return 0;
}
static int OMX_VideoRenderSetRotationFrameInfo(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,struct mpp_frame* pFrame)
{
int i = 0;
int cnt;
cnt = sizeof(pVideoRenderDataType->sRotationFrames)/sizeof(pVideoRenderDataType->sRotationFrames[0]);
for (i = 0; i < cnt; i++) {
pVideoRenderDataType->sRotationFrames[i].buf.buf_type = pFrame->buf.buf_type;
pVideoRenderDataType->sRotationFrames[i].buf.format = pFrame->buf.format;
if (pVideoRenderDataType->nRotationAngle == MPP_ROTATION_90 || pVideoRenderDataType->nRotationAngle == MPP_ROTATION_270) {
if (pFrame->buf.crop_en) {
pVideoRenderDataType->sRotationFrames[i].buf.size.width = pFrame->buf.crop.height & (~0x01);
pVideoRenderDataType->sRotationFrames[i].buf.size.height = pFrame->buf.crop.width & (~0x01);
} else {
pVideoRenderDataType->sRotationFrames[i].buf.size.width = pFrame->buf.size.height;
pVideoRenderDataType->sRotationFrames[i].buf.size.height = pFrame->buf.size.width;
}
} else if (pVideoRenderDataType->nRotationAngle == MPP_ROTATION_180 || pVideoRenderDataType->nRotationAngle == MPP_ROTATION_0) {
if (pFrame->buf.crop_en) {
pVideoRenderDataType->sRotationFrames[i].buf.size.width = pFrame->buf.crop.width & (~0x01);
pVideoRenderDataType->sRotationFrames[i].buf.size.height =pFrame->buf.crop.height & (~0x01);
} else {
pVideoRenderDataType->sRotationFrames[i].buf.size.width = pFrame->buf.size.width;
pVideoRenderDataType->sRotationFrames[i].buf.size.height = pFrame->buf.size.height;
}
}
}
for (i = 0;i < cnt; i++) {
switch(pFrame->buf.format) {
case MPP_FMT_YUV420P:
pVideoRenderDataType->sRotationFrames[i].buf.stride[0] = (pVideoRenderDataType->sRotationFrames[i].buf.size.width+15)/16*16;
pVideoRenderDataType->sRotationFrames[i].buf.stride[1] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0]>>1;
pVideoRenderDataType->sRotationFrames[i].buf.stride[2] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0]>>1;
break;
case MPP_FMT_YUV444P:
pVideoRenderDataType->sRotationFrames[i].buf.stride[0] = (pVideoRenderDataType->sRotationFrames[i].buf.size.width+15)/16*16;
pVideoRenderDataType->sRotationFrames[i].buf.stride[1] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0];
pVideoRenderDataType->sRotationFrames[i].buf.stride[2] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0];
break;
case MPP_FMT_YUV422P:
pVideoRenderDataType->sRotationFrames[i].buf.stride[0] = (pVideoRenderDataType->sRotationFrames[i].buf.size.width+15)/16*16;
pVideoRenderDataType->sRotationFrames[i].buf.stride[1] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0]>>1;
pVideoRenderDataType->sRotationFrames[i].buf.stride[2] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0]>>1;
break;
case MPP_FMT_NV12:
case MPP_FMT_NV21:
pVideoRenderDataType->sRotationFrames[i].buf.stride[0] = (pVideoRenderDataType->sRotationFrames[i].buf.size.width+15)/16*16;
pVideoRenderDataType->sRotationFrames[i].buf.stride[1] = pVideoRenderDataType->sRotationFrames[i].buf.stride[0]>>1;
pVideoRenderDataType->sRotationFrames[i].buf.stride[2] = 0;
break;
case MPP_FMT_YUV400:
case MPP_FMT_ABGR_8888:
case MPP_FMT_ARGB_8888:
case MPP_FMT_RGBA_8888:
case MPP_FMT_BGRA_8888:
case MPP_FMT_BGR_888:
case MPP_FMT_RGB_888:
case MPP_FMT_BGR_565:
case MPP_FMT_RGB_565:
pVideoRenderDataType->sRotationFrames[i].buf.stride[0] = (pVideoRenderDataType->sRotationFrames[i].buf.size.width+15)/16*16;
pVideoRenderDataType->sRotationFrames[i].buf.stride[1] = 0;
pVideoRenderDataType->sRotationFrames[i].buf.stride[2] = 0;
break;
default:
loge("unsupport format");
return -1;
}
}
return 0;
}
static int OMX_VideoRenderInitRotationParam(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,struct mpp_frame* pFrame)
{
int i = 0;
int cnt = 0;
pVideoRenderDataType->nInitRotationParam = 0;
if (pVideoRenderDataType->nRotationAngle == MPP_ROTATION_0) {
pVideoRenderDataType->nInitRotationParam = 1;
return 0;
}
//set rotation frame info
if (OMX_VideoRenderSetRotationFrameInfo(pVideoRenderDataType,pFrame) != 0) {
loge("OMX_VideoRenderSetRotationFrameInfo\n");
pVideoRenderDataType->nInitRotationParam = -1;
return -1;
}
//open GE
if (pVideoRenderDataType->sGeHandle == NULL) {
pVideoRenderDataType->sGeHandle = mpp_ge_open();
if (pVideoRenderDataType->sGeHandle == NULL) {
loge("open ge device error\n");
pVideoRenderDataType->nInitRotationParam = -1;
return -1;
}
}
cnt = sizeof(pVideoRenderDataType->sRotationFrames)/sizeof(pVideoRenderDataType->sRotationFrames[0]);
// free last DMA
for (i = 0; i < cnt; i++) {
if (OMX_VideoRenderFreeFrameBuffer(pVideoRenderDataType,&pVideoRenderDataType->sRotationFrames[i]) < 0) {
loge("OMX_VideoRenderFreeFrameBuffer error\n");
break;
}
}
// alloc this DMA
for (i = 0; i < cnt; i++) {
if (OMX_VideoRenderAllocFrameBuffer(pVideoRenderDataType,&pVideoRenderDataType->sRotationFrames[i]) < 0) {
loge("OMX_VideoRenderAllocFrameBuffer error\n");
break;
}
}
if (i < cnt) {
goto _exit;
}
pVideoRenderDataType->nInitRotationParam = 1;
return 0;
_exit:
for (; i >= 0; i--) {
OMX_VideoRenderFreeFrameBuffer(pVideoRenderDataType,&pVideoRenderDataType->sRotationFrames[i]);
}
if (pVideoRenderDataType->sGeHandle) {
mpp_ge_close(pVideoRenderDataType->sGeHandle);
pVideoRenderDataType->sGeHandle = NULL;
}
pVideoRenderDataType->nInitRotationParam = -1;
return -1;
}
static int OMX_VideoRenderDeInitRotationParam(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
int i = 0;
int cnt = 0;
if (pVideoRenderDataType->nInitRotationParam != 1) {// init fail ,so do not need to deinit
return 0;
}
cnt = sizeof(pVideoRenderDataType->sRotationFrames)/sizeof(pVideoRenderDataType->sRotationFrames[0]);
for (i = 0; i < cnt; i++) {
OMX_VideoRenderFreeFrameBuffer(pVideoRenderDataType,&pVideoRenderDataType->sRotationFrames[i]);
}
if (pVideoRenderDataType->sGeHandle) {
mpp_ge_close(pVideoRenderDataType->sGeHandle);
pVideoRenderDataType->sGeHandle = NULL;
}
return 0;
}
static int OMX_VideoRenderRotateFrame(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,struct mpp_frame* pFrame)
{
int ret = 0;
struct ge_bitblt blt;
struct mpp_ge *ge = NULL;
if (pVideoRenderDataType == NULL || pFrame == NULL) {
loge("param error !!!\n");
return -1;
}
if (pVideoRenderDataType->nRotationAngle == MPP_ROTATION_0) {
pVideoRenderDataType->pCurDisplayFrame = pFrame;
return 0;
}
if (pVideoRenderDataType->nInitRotationParam != 1) {
pVideoRenderDataType->pCurDisplayFrame = pFrame;
loge("RotationParam do not init ok !!!\n");
return -1;
}
memset(&blt,0x00,sizeof(struct ge_bitblt));
blt.src_buf.buf_type = MPP_PHY_ADDR;
blt.src_buf.format = pFrame->buf.format;
blt.src_buf.phy_addr[0] = pFrame->buf.phy_addr[0];
blt.src_buf.phy_addr[1] = pFrame->buf.phy_addr[1];
blt.src_buf.phy_addr[2] = pFrame->buf.phy_addr[2];
blt.src_buf.stride[0] = pFrame->buf.stride[0];
blt.src_buf.stride[1] = pFrame->buf.stride[1];
blt.src_buf.stride[2] = pFrame->buf.stride[2];
blt.src_buf.size.width = pFrame->buf.size.width;
blt.src_buf.size.height = pFrame->buf.size.height;
blt.src_buf.crop_en = pFrame->buf.crop_en;
blt.src_buf.crop.x = pFrame->buf.crop.x;
blt.src_buf.crop.y = pFrame->buf.crop.y;
blt.src_buf.crop.width = pFrame->buf.crop.width&(~0x01);
blt.src_buf.crop.height = pFrame->buf.crop.height&(~0x01);
if (pVideoRenderDataType->pCurDisplayFrame == &pVideoRenderDataType->sRotationFrames[0]) {
pVideoRenderDataType->pCurDisplayFrame = &pVideoRenderDataType->sRotationFrames[1];
} else {
pVideoRenderDataType->pCurDisplayFrame = &pVideoRenderDataType->sRotationFrames[0];
}
blt.dst_buf.buf_type = pVideoRenderDataType->pCurDisplayFrame->buf.buf_type;
blt.dst_buf.format =pVideoRenderDataType->pCurDisplayFrame->buf.format;
blt.dst_buf.phy_addr[0] = pVideoRenderDataType->pCurDisplayFrame->buf.phy_addr[0];
blt.dst_buf.phy_addr[1] = pVideoRenderDataType->pCurDisplayFrame->buf.phy_addr[1];
blt.dst_buf.phy_addr[2] = pVideoRenderDataType->pCurDisplayFrame->buf.phy_addr[2];
blt.dst_buf.stride[0] = pVideoRenderDataType->pCurDisplayFrame->buf.stride[0];
blt.dst_buf.stride[1] = pVideoRenderDataType->pCurDisplayFrame->buf.stride[1];
blt.dst_buf.stride[2] = pVideoRenderDataType->pCurDisplayFrame->buf.stride[2];
blt.dst_buf.size.width = pVideoRenderDataType->pCurDisplayFrame->buf.size.width;
blt.dst_buf.size.height = pVideoRenderDataType->pCurDisplayFrame->buf.size.height;
blt.dst_buf.crop_en = 0;
blt.ctrl.flags = pVideoRenderDataType->nRotationAngle;
pVideoRenderDataType->pCurDisplayFrame->id = pFrame->id;
pVideoRenderDataType->pCurDisplayFrame->pts = pFrame->pts;
pVideoRenderDataType->pCurDisplayFrame->flags = pFrame->flags;
pVideoRenderDataType->pCurDisplayFrame->buf.crop_en = 0;
ge = pVideoRenderDataType->sGeHandle;
ret = mpp_ge_bitblt(ge, &blt);
if (ret) {
loge("mpp_ge_bitblt task failed: %d\n", ret);
ret = -1;
goto _exit0;
}
ret = mpp_ge_emit(ge);
if (ret) {
loge("mpp_ge_emit task failed: %d\n", ret);
ret = -1;
goto _exit0;
}
ret = mpp_ge_sync(ge);
if (ret) {
loge("mpp_ge_sync task failed: %d\n", ret);
ret = -1;
goto _exit0;
}
_exit0:
return ret;
}
static int OMX_VideoRenderGiveBackAllFrames(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
int ret;
// 1 move ready node to using list
logi("Before OMX_VideoRenderComponentThread exit,move node in sInReadyFrame to sInProcessedFrmae\n");
if (!OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInReadyFrame,pVideoRenderDataType->sInFrameLock)) {
VIDEO_RENDER_IN_FRAME *pFrameNode,*pFrameNode1;
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pVideoRenderDataType->sInReadyFrame, sList) {
pVideoRenderDataType->nLeftReadyFrameWhenCompoentExitNum++;
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
}
// 2 give back frames in using list to vdec or app
logi("Before OMX_AudioRenderComponentThread exit,give all frames back to Vdec\n");
if (!OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInProcessedFrmae,pVideoRenderDataType->sInFrameLock)) {
VIDEO_RENDER_IN_FRAME *pFrameNode = NULL;
OMX_BUFFERHEADERTYPE sBuffHead;
while(!OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInProcessedFrmae,pVideoRenderDataType->sInFrameLock)) {
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pVideoRenderDataType->sInProcessedFrmae, VIDEO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
ret = -1;
if (pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].nTunneledFlag) {
sBuffHead.nInputPortIndex = VIDEO_RENDER_PORT_IN_VIDEO_INDEX;
sBuffHead.nOutputPortIndex = pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].nTunnelPortIndex;
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
ret = OMX_FillThisBuffer(pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].pTunneledComp,&sBuffHead);
} else {
if (pVideoRenderDataType->pCallbacks != NULL && pVideoRenderDataType->pCallbacks->EmptyBufferDone!= NULL) {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
ret = pVideoRenderDataType->pCallbacks->EmptyBufferDone(pVideoRenderDataType->hSelf,pVideoRenderDataType->pAppData,&sBuffHead);
}
}
if (ret == 0) {
logd("give back frame to vdec ok");
pVideoRenderDataType->nGiveBackFrameOkNum++;
} else {
loge("give back frame to vdec fail\n");
pVideoRenderDataType->nGiveBackFrameFailNum++;
continue;// must give back ok ,so retry to give back
}
logi("nGiveBackFrameOkNum:%d,nGiveBackFrameFailNum:%d\n"
,pVideoRenderDataType->nGiveBackFrameOkNum
,pVideoRenderDataType->nGiveBackFrameFailNum);
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInEmptyFrame);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
}
}
return 0;
}
static OMX_ERRORTYPE OMX_VideoRenderSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData)
{
VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
struct aic_message sMsg;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
sMsg.message_id = Cmd;
sMsg.param = nParam1;
sMsg.data_size = 0;
//now not use always NULL
if (pCmdData != NULL)
{
sMsg.data = pCmdData;
sMsg.data_size = strlen((char*)pCmdData);
}
aic_msg_put(&pVideoRenderDataType->sMsgQue, &sMsg);
return eError;
}
static void* OMX_VideoRenderComponentThread(void* pThreadData);
static OMX_ERRORTYPE OMX_VideoRenderGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure)
{
VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_U32 tmp1,tmp2;
OMX_S32 index =(OMX_S32)nParamIndex;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch (index) {
case OMX_IndexParamPortDefinition:
break;
case OMX_IndexParamVideoAvc:
break;
case OMX_IndexParamVideoProfileLevelQuerySupported:
break;
case OMX_IndexParamVideoPortFormat:
break;
case OMX_IndexParamVideoProfileLevelCurrent:
break;
case OMX_IndexParamVideoMpeg4:
break;
case OMX_IndexParamCompBufferSupplier: {
OMX_PARAM_BUFFERSUPPLIERTYPE *sBufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE*)pComponentParameterStructure;
if (sBufferSupplier->nPortIndex == VIDEO_RENDER_PORT_IN_VIDEO_INDEX) {
sBufferSupplier->eBufferSupplier = pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].eBufferSupplier;
} else if (sBufferSupplier->nPortIndex == VIDEO_RENDER_PORT_IN_CLOCK_INDEX) {
sBufferSupplier->eBufferSupplier = pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].eBufferSupplier;
} else {
loge("error nPortIndex\n");
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexConfigCommonOutputCrop:
((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nLeft = pVideoRenderDataType->sDisRect.x;
((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nTop = pVideoRenderDataType->sDisRect.y;
((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nWidth = pVideoRenderDataType->sDisRect.width;
((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nHeight = pVideoRenderDataType->sDisRect.height;
break;
case OMX_IndexVendorVideoRenderScreenSize: {
struct mpp_size sSize;
if (pVideoRenderDataType->nVideoRenderInitFlag != 1) {
loge("pVideoRenderDataType->render not init!!!\n");
eError = OMX_ErrorUndefined;
break;
}
pVideoRenderDataType->render->get_screen_size(pVideoRenderDataType->render,&sSize);
((OMX_PARAM_SCREEN_SIZE*)pComponentParameterStructure)->nWidth = sSize.width;
((OMX_PARAM_SCREEN_SIZE*)pComponentParameterStructure)->nHeight = sSize.height;
break;
}
default:
eError = OMX_ErrorNotImplemented;
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR pComponentParameterStructure)
{
VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_S32 tmp1,tmp2;
OMX_PARAM_FRAMEEND *sFrameEnd;
OMX_S32 index = (OMX_S32)nParamIndex;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
if (pComponentParameterStructure == NULL) {
loge("param error!!!\n");
return OMX_ErrorBadParameter;
}
switch (index) {
case OMX_IndexParamPortDefinition:
break;
case OMX_IndexParamVideoPortFormat:
break;
case OMX_IndexParamVideoAvc:
break;
case OMX_IndexParamVideoProfileLevelQuerySupported:
break;
case OMX_IndexParamVideoProfileLevelCurrent:
break;
case OMX_IndexParamVideoMpeg4:
break;
case OMX_IndexConfigCommonOutputCrop:
pVideoRenderDataType->sDisRect.x = ((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nLeft;
pVideoRenderDataType->sDisRect.y = ((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nTop;
pVideoRenderDataType->sDisRect.width = ((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nWidth;
pVideoRenderDataType->sDisRect.height =((OMX_CONFIG_RECTTYPE*)pComponentParameterStructure)->nHeight;
pVideoRenderDataType->nDisRectChange = OMX_TRUE;
break;
case OMX_IndexVendorStreamFrameEnd:
sFrameEnd = (OMX_PARAM_FRAMEEND*)pComponentParameterStructure;
if (sFrameEnd->bFrameEnd == OMX_TRUE) {
pVideoRenderDataType->nFrameEndFlag = OMX_TRUE;
logi("setup nFrameEndFlag\n");
} else {
pVideoRenderDataType->nFrameEndFlag = OMX_FALSE;
logi("cancel nFrameEndFlag\n");
}
break;
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderGetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
OMX_S32 index = (OMX_S32)nIndex;
switch (index) {
case OMX_IndexConfigCommonRotate: {
OMX_CONFIG_ROTATIONTYPE * pRotation = (OMX_CONFIG_ROTATIONTYPE *)pComponentConfigStructure;
pRotation->nRotation = pVideoRenderDataType->nRotationAngle;
break;
}
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
int ret;
OMX_S32 index = (OMX_S32)nIndex;
switch (index) {
case OMX_IndexConfigTimePosition:
//1 clear input buffer list
OMX_VideoRenderGiveBackAllFrames(pVideoRenderDataType);
//2 reset flag
pVideoRenderDataType->nFrameFisrtShowFlag = OMX_TRUE;
pVideoRenderDataType->nFlags = 0;
pVideoRenderDataType->eClockState = OMX_TIME_ClockStateWaitingForStartTime;
if ((pVideoRenderDataType->sDisRect.width != 0) && (pVideoRenderDataType->sDisRect.width != 0)) {
pVideoRenderDataType->nDisRectChange = OMX_TRUE;
}
break;
case OMX_IndexConfigTimeSeekMode:
break;
case OMX_IndexConfigTimeClockState: {
OMX_TIME_CONFIG_CLOCKSTATETYPE* state = (OMX_TIME_CONFIG_CLOCKSTATETYPE *)pComponentConfigStructure;
pVideoRenderDataType->eClockState = state->eState;
printf("[%s:%d]pVideoRenderDataType->eClockState:%d\n",__FUNCTION__,__LINE__,pVideoRenderDataType->eClockState);
break;
}
case OMX_IndexVendorVideoRenderInit:
if (!pVideoRenderDataType->render) {
ret = aic_video_render_create(&pVideoRenderDataType->render);
if (ret) {
eError = OMX_ErrorInsufficientResources;
loge("aic_video_render_create error!!!!\n");
break;
}
ret = pVideoRenderDataType->render->init(pVideoRenderDataType->render,
pVideoRenderDataType->nLayerId,pVideoRenderDataType->nDevId);
if (!ret) {
printf("[%s:%d]pVideoRenderDataType->render->init ok\n",__FUNCTION__,__LINE__);
pVideoRenderDataType->nVideoRenderInitFlag = 1;
} else {
loge("pVideoRenderDataType->render->init fail\n");
eError = OMX_ErrorInsufficientResources;
}
} else {
loge("pVideoRenderDataType->render has been created!!1!\n");
}
break;
case OMX_IndexConfigCommonRotate: {
OMX_CONFIG_ROTATIONTYPE * pRotation = (OMX_CONFIG_ROTATIONTYPE *)pComponentConfigStructure;
if (pVideoRenderDataType->nRotationAngle != pRotation->nRotation) {//MPP_ROTATION_0 MPP_ROTATION_90 MPP_ROTATION_180 MPP_ROTATION_270
pVideoRenderDataType->nRotationAngle = pRotation->nRotation;
pVideoRenderDataType->nRotationAngleChange = 1;
}
break;
}
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState)
{
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pVideoRenderDataType->stateLock);
*pState = pVideoRenderDataType->state;
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderComponentTunnelRequest(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_U32 nPort,
OMX_IN OMX_HANDLETYPE hTunneledComp,
OMX_IN OMX_U32 nTunneledPort,
OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_PARAM_PORTDEFINITIONTYPE *pPort;
OMX_PORT_TUNNELEDINFO *pTunneledInfo;
OMX_PARAM_BUFFERSUPPLIERTYPE *pBufSupplier;
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComp)->pComponentPrivate);
if (pVideoRenderDataType->state != OMX_StateLoaded)
{
loge("Component is not in OMX_StateLoaded,it is in%d,it can not tunnel\n",pVideoRenderDataType->state);
return OMX_ErrorInvalidState;
}
if (nPort == VIDEO_RENDER_PORT_IN_VIDEO_INDEX) {
pPort = &pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX];
pTunneledInfo = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX];
pBufSupplier = &pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_VIDEO_INDEX];
} else if (nPort == VIDEO_RENDER_PORT_IN_CLOCK_INDEX) {
pPort = &pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
pTunneledInfo = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
pBufSupplier = &pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
} else {
loge("component can not find port :%d,VIDEO_RENDER_PORT_IN_VIDEO_INDEX:%d\n",nPort,VIDEO_RENDER_PORT_IN_VIDEO_INDEX);
return OMX_ErrorBadParameter;
}
// cancle setup tunnel
if (NULL == hTunneledComp && 0 == nTunneledPort && NULL == pTunnelSetup) {
pTunneledInfo->nTunneledFlag = OMX_FALSE;
pTunneledInfo->nTunnelPortIndex = nTunneledPort;
pTunneledInfo->pTunneledComp = hTunneledComp;
return OMX_ErrorNone;
}
if (pPort->eDir == OMX_DirOutput) {
pTunneledInfo->nTunnelPortIndex = nTunneledPort;
pTunneledInfo->pTunneledComp = hTunneledComp;
pTunneledInfo->nTunneledFlag = OMX_TRUE;
pTunnelSetup->nTunnelFlags = 0;
pTunnelSetup->eSupplier = pBufSupplier->eBufferSupplier;
} else if (pPort->eDir == OMX_DirInput) {
OMX_PARAM_PORTDEFINITIONTYPE sTunneledPort;
OMX_PARAM_BUFFERSUPPLIERTYPE sBuffSupplier;
sTunneledPort.nPortIndex = nTunneledPort;
sBuffSupplier.nPortIndex = nTunneledPort;
if (pTunnelSetup->eSupplier == OMX_BufferSupplyMax)
{
loge("both ports are input.\n");
return OMX_ErrorPortsNotCompatible;
}
OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition,&sTunneledPort);
if (pPort->eDomain != sTunneledPort.eDomain) {
loge("ports domain are not compatible: %d %d.\n",
pPort->eDomain, sTunneledPort.eDomain);
return OMX_ErrorPortsNotCompatible;
}
if (sTunneledPort.eDir != OMX_DirOutput) {
loge("both ports are input.\n");
return OMX_ErrorPortsNotCompatible;
}
//negotiate buffer supplier
OMX_GetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier,&sBuffSupplier);
if (sBuffSupplier.eBufferSupplier != pTunnelSetup->eSupplier) {
loge("out_port and in_port supplier are different,please check code!!!!\n");
return OMX_ErrorPortsNotCompatible;
}
pTunneledInfo->nTunnelPortIndex = nTunneledPort;
pTunneledInfo->pTunneledComp = hTunneledComp;
pTunneledInfo->nTunneledFlag = OMX_TRUE;
pBufSupplier->eBufferSupplier = pTunnelSetup->eSupplier;
} else {
loge("port is neither output nor input.\n");
return OMX_ErrorPortsNotCompatible;
}
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType;
VIDEO_RENDER_IN_FRAME *pFrame;
struct aic_message sMsg;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pVideoRenderDataType->stateLock);
if (pVideoRenderDataType->state != OMX_StateExecuting && (pVideoRenderDataType->state != OMX_StateIdle)) {
logw("component is not in OMX_StateExecuting,it is in [%d]!!!\n",pVideoRenderDataType->state);
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
// if (OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInEmptyFrame,pVideoRenderDataType->sInFrameLock))
// {
// if (pVideoRenderDataType->nInFrameNodeNum + 1> VIDEO_RENDER_FRAME_NUM_MAX) {
// loge("empty node has aready increase to max [%d]!!!\n",pVideoRenderDataType->nInFrameNodeNum);
// eError = OMX_ErrorInsufficientResources;
// return eError;
// } else {
// int i;
// loge("no empty node,need to extend!!!\n");
// for(i =0 ; i < VIDEO_RENDER_FRAME_ONE_TIME_CREATE_NUM; i++ ) {
// VIDEO_RENDER_IN_FRAME *pFrameNode = (VIDEO_RENDER_IN_FRAME*)mpp_alloc(sizeof(VIDEO_RENDER_IN_FRAME));
// if (NULL == pFrameNode) {
// break;
// }
// memset(pFrameNode,0x00,sizeof(VIDEO_RENDER_IN_FRAME));
// aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
// mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInEmptyFrame);
// aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
// pVideoRenderDataType->nInFrameNodeNum++;
// }
// if (i == 0) {
// loge("mpp_alloc empty video node fail\n");
// eError = OMX_ErrorInsufficientResources;
// return eError;
// }
// }
// }
if (OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInEmptyFrame,pVideoRenderDataType->sInFrameLock)) {
VIDEO_RENDER_IN_FRAME *pFrameNode = (VIDEO_RENDER_IN_FRAME*)mpp_alloc(sizeof(VIDEO_RENDER_IN_FRAME));
if (NULL == pFrameNode) {
loge("OMX_ErrorInsufficientResources\n");
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
return OMX_ErrorInsufficientResources;
}
memset(pFrameNode,0x00,sizeof(VIDEO_RENDER_IN_FRAME));
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInEmptyFrame);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
pVideoRenderDataType->nInFrameNodeNum++;
}
if (pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].nTunneledFlag) {// now Tunneled and non-Tunneled are same
// static struct timespec pev = {0},cur = {0};
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
pFrame = mpp_list_first_entry(&pVideoRenderDataType->sInEmptyFrame, VIDEO_RENDER_IN_FRAME, sList);
memcpy(&pFrame->sFrameInfo,pBuffer->pBuffer,sizeof(struct mpp_frame));
mpp_list_del(&pFrame->sList);
mpp_list_add_tail(&pFrame->sList, &pVideoRenderDataType->sInReadyFrame);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
pVideoRenderDataType->nReceiveFrameNum++;
logd("nReceiveFrameNum:%d\n",pVideoRenderDataType->nReceiveFrameNum);
{
static int nRenderFrameNum = 0;
static struct timespec pre = {0},cur = {0};
long diff;
int nCnt = 0;
VIDEO_RENDER_IN_FRAME *pFrameNode;
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_for_each_entry(pFrameNode, &pVideoRenderDataType->sInReadyFrame, sList) {
nCnt++;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
nRenderFrameNum++;
clock_gettime(CLOCK_REALTIME,&cur);
diff = (cur.tv_sec - pre.tv_sec)*1000*1000 + (cur.tv_nsec - pre.tv_nsec)/1000;
if (diff > 1*1000*1000) {
//printf("[%s:%d]:%ld:%d:%d\n",__FUNCTION__,__LINE__,diff,nRenderFrameNum,nCnt);
pre = cur;
nRenderFrameNum = 0;
}
}
} else { // now Tunneled and non-Tunneled are same
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
pFrame = mpp_list_first_entry(&pVideoRenderDataType->sInEmptyFrame, VIDEO_RENDER_IN_FRAME, sList);
memcpy(&pFrame->sFrameInfo,pBuffer->pBuffer,sizeof(struct mpp_frame));
mpp_list_del(&pFrame->sList);
mpp_list_add_tail(&pFrame->sList, &pVideoRenderDataType->sInReadyFrame);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
pVideoRenderDataType->nReceiveFrameNum++;
logw("nReceiveFrameNum:%d\n",pVideoRenderDataType->nReceiveFrameNum);
}
aic_pthread_mutex_lock(&pVideoRenderDataType->sWaitReayFrameLock);
if (pVideoRenderDataType->nWaitReayFrameFlag) {
sMsg.message_id = OMX_CommandNops;
sMsg.data_size = 0;
aic_msg_put(&pVideoRenderDataType->sMsgQue, &sMsg);
pVideoRenderDataType->nWaitReayFrameFlag = 0;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sWaitReayFrameLock);
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
return eError;
#if 0
pFrame->sFrameInfo.flags = pFrame1->sFrameInfo.flags;
pFrame->sFrameInfo.id = pFrame1->sFrameInfo.id;
pFrame->sFrameInfo.pts = pFrame1->sFrameInfo.pts;
pFrame->sFrameInfo.buf.buf_type = pFrame1->sFrameInfo.buf.buf_type;
pFrame->sFrameInfo.buf.crop.x = pFrame1->sFrameInfo.buf.crop.x;
pFrame->sFrameInfo.buf.crop.y = pFrame1->sFrameInfo.buf.crop.y;
pFrame->sFrameInfo.buf.crop.width = pFrame1->sFrameInfo.buf.crop.width;
pFrame->sFrameInfo.buf.crop.height = pFrame1->sFrameInfo.buf.crop.height;
pFrame->sFrameInfo.buf.crop_en = pFrame1->sFrameInfo.buf.crop_en;
pFrame->sFrameInfo.buf.phy_addr[0] = pFrame1->sFrameInfo.buf.phy_addr[0];
pFrame->sFrameInfo.buf.phy_addr[1] = pFrame1->sFrameInfo.buf.phy_addr[1];
pFrame->sFrameInfo.buf.phy_addr[2] = pFrame1->sFrameInfo.buf.phy_addr[2];
pFrame->sFrameInfo.buf.fd[0] = pFrame1->sFrameInfo.buf.fd[0];
pFrame->sFrameInfo.buf.fd[1] = pFrame1->sFrameInfo.buf.fd[1];
pFrame->sFrameInfo.buf.fd[2] = pFrame1->sFrameInfo.buf.fd[2];
pFrame->sFrameInfo.buf.flags = pFrame1->sFrameInfo.buf.flags;
pFrame->sFrameInfo.buf.format = pFrame1->sFrameInfo.buf.format;
pFrame->sFrameInfo.buf.size.width = pFrame1->sFrameInfo.buf.size.width;
pFrame->sFrameInfo.buf.size.height = pFrame1->sFrameInfo.buf.size.height;
pFrame->sFrameInfo.buf.stride[0] = pFrame1->sFrameInfo.buf.stride[0];
pFrame->sFrameInfo.buf.stride[1] = pFrame1->sFrameInfo.buf.stride[1];
pFrame->sFrameInfo.buf.stride[2] = pFrame1->sFrameInfo.buf.stride[2];
#endif
}
static OMX_ERRORTYPE OMX_VideoRenderFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
return eError;
}
static OMX_ERRORTYPE OMX_VideoRenderSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
pVideoRenderDataType->pCallbacks = pCallbacks;
pVideoRenderDataType->pAppData = pAppData;
return eError;
}
OMX_ERRORTYPE OMX_VideoRenderComponentDeInit(
OMX_IN OMX_HANDLETYPE hComponent) {
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_COMPONENTTYPE *pComp;
VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType;
VIDEO_RENDER_IN_FRAME *pFrameNode = NULL,*pFrameNode1 = NULL;
pComp = (OMX_COMPONENTTYPE *)hComponent;
struct aic_message sMsg;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)pComp->pComponentPrivate;
aic_pthread_mutex_lock(&pVideoRenderDataType->stateLock);
if (pVideoRenderDataType->state != OMX_StateLoaded) {
logw("compoent is in %d,but not in OMX_StateLoaded(1),can ont FreeHandle.\n",pVideoRenderDataType->state);
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
sMsg.message_id = OMX_CommandStop;
sMsg.data_size = 0;
aic_msg_put(&pVideoRenderDataType->sMsgQue, &sMsg);
pthread_join(pVideoRenderDataType->threadId, (void*)&eError);
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
if (!mpp_list_empty(&pVideoRenderDataType->sInEmptyFrame)) {
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pVideoRenderDataType->sInEmptyFrame, sList) {
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
if (!mpp_list_empty(&pVideoRenderDataType->sInReadyFrame)) {
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pVideoRenderDataType->sInReadyFrame, sList) {
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
if (!mpp_list_empty(&pVideoRenderDataType->sInProcessedFrmae)) {
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pVideoRenderDataType->sInProcessedFrmae, sList) {
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
pthread_mutex_destroy(&pVideoRenderDataType->sInFrameLock);
pthread_mutex_destroy(&pVideoRenderDataType->stateLock);
pthread_mutex_destroy(&pVideoRenderDataType->sWaitReayFrameLock);
aic_msg_destroy(&pVideoRenderDataType->sMsgQue);
OMX_VideoRenderDeInitRotationParam(pVideoRenderDataType);
if (pVideoRenderDataType->render) {
pVideoRenderDataType->render->set_on_off(pVideoRenderDataType->render,0);
aic_video_render_destroy(pVideoRenderDataType->render);
pVideoRenderDataType->render = NULL;
}
mpp_free(pVideoRenderDataType);
pVideoRenderDataType = NULL;
logw("OMX_VideoRenderComponentDeInit\n");
return eError;
}
static int dec_thread_attr_init(pthread_attr_t *attr)
{
// default stack size is 2K, it is not enough for decode thread
if (attr == NULL) {
return EINVAL;
}
pthread_attr_init(attr);
attr->stacksize = 16*1024;
//attr->schedparam.sched_priority = 23;
attr->schedparam.sched_priority = 21;
return 0;
}
OMX_ERRORTYPE OMX_VideoRenderComponentInit(
OMX_IN OMX_HANDLETYPE hComponent)
{
OMX_COMPONENTTYPE *pComp;
VIDEO_RENDER_DATA_TYPE *pVideoRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_U32 err;
OMX_U32 i;
//OMX_U32 cnt;
pthread_attr_t *attr = NULL;
attr = (pthread_attr_t*)mpp_alloc(sizeof(pthread_attr_t));
dec_thread_attr_init(attr);
logw("OMX_VideoRenderComponentInit....");
pComp = (OMX_COMPONENTTYPE *)hComponent;
pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE *)mpp_alloc(sizeof(VIDEO_RENDER_DATA_TYPE));
if (NULL == pVideoRenderDataType) {
loge("mpp_alloc(sizeof(VIDEO_RENDER_DATA_TYPE) fail!");
eError = OMX_ErrorInsufficientResources;
goto _EXIT1;
}
memset(pVideoRenderDataType, 0x0, sizeof(VIDEO_RENDER_DATA_TYPE));
pComp->pComponentPrivate = (void*) pVideoRenderDataType;
pVideoRenderDataType->nFrameFisrtShowFlag = OMX_TRUE;
pVideoRenderDataType->state = OMX_StateLoaded;
pVideoRenderDataType->hSelf = pComp;
pComp->SetCallbacks = OMX_VideoRenderSetCallbacks;
pComp->SendCommand = OMX_VideoRenderSendCommand;
pComp->GetState = OMX_VideoRenderGetState;
pComp->GetParameter = OMX_VideoRenderGetParameter;
pComp->SetParameter = OMX_VideoRenderSetParameter;
pComp->GetConfig = OMX_VideoRenderGetConfig;
pComp->SetConfig = OMX_VideoRenderSetConfig;
pComp->ComponentTunnelRequest = OMX_VideoRenderComponentTunnelRequest;
pComp->ComponentDeInit = OMX_VideoRenderComponentDeInit;
pComp->FillThisBuffer = OMX_VideoRenderFillThisBuffer;
pComp->EmptyThisBuffer = OMX_VideoRenderEmptyThisBuffer;
pVideoRenderDataType->sPortParam.nPorts = 2;
pVideoRenderDataType->sPortParam.nStartPortNumber = 0x0;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].nPortIndex = VIDEO_RENDER_PORT_IN_VIDEO_INDEX;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].bPopulated = OMX_TRUE;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].bEnabled = OMX_TRUE;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].eDomain = OMX_PortDomainVideo;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].eDir = OMX_DirInput;
pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].nPortIndex = 0x0;
pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_VIDEO_INDEX].eBufferSupplier = OMX_BufferSupplyOutput;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].nPortIndex = VIDEO_RENDER_PORT_IN_CLOCK_INDEX;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].bPopulated = OMX_TRUE;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].bEnabled = OMX_TRUE;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].eDomain = OMX_PortDomainOther;
pVideoRenderDataType->sInPortDef[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].eDir = OMX_DirInput;
pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].nPortIndex = 0x0;
pVideoRenderDataType->sInBufSupplier[VIDEO_RENDER_PORT_IN_CLOCK_INDEX].eBufferSupplier = OMX_BufferSupplyOutput;
pVideoRenderDataType->nInFrameNodeNum = 0;
mpp_list_init(&pVideoRenderDataType->sInEmptyFrame);
mpp_list_init(&pVideoRenderDataType->sInReadyFrame);
mpp_list_init(&pVideoRenderDataType->sInProcessedFrmae);
pthread_mutex_init(&pVideoRenderDataType->sInFrameLock, NULL);
for(i =0 ; i < VIDEO_RENDER_FRAME_ONE_TIME_CREATE_NUM; i++) {
VIDEO_RENDER_IN_FRAME *pFrameNode = (VIDEO_RENDER_IN_FRAME*)mpp_alloc(sizeof(VIDEO_RENDER_IN_FRAME));
if (NULL == pFrameNode) {
break;
}
memset(pFrameNode,0x00,sizeof(VIDEO_RENDER_IN_FRAME));
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInEmptyFrame);
pVideoRenderDataType->nInFrameNodeNum++;
}
if (pVideoRenderDataType->nInFrameNodeNum == 0) {
loge("mpp_alloc empty video node fail\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT2;
}
if (aic_msg_create(&pVideoRenderDataType->sMsgQue)<0)
{
loge("aic_msg_create fail!");
eError = OMX_ErrorInsufficientResources;
goto _EXIT4;
}
pVideoRenderDataType->eClockState = OMX_TIME_ClockStateStopped;
pVideoRenderDataType->nRotationAngle = MPP_ROTATION_0;
pVideoRenderDataType->nRotationAngleChange = 0;
pVideoRenderDataType->nInitRotationParam = 0;
pthread_mutex_init(&pVideoRenderDataType->sWaitReayFrameLock, NULL);
pthread_mutex_init(&pVideoRenderDataType->stateLock, NULL);
// Create the component thread
err = pthread_create(&pVideoRenderDataType->threadId, attr, OMX_VideoRenderComponentThread, pVideoRenderDataType);
//if (err || !pVideoRenderDataType->threadId)
if (err)
{
loge("pthread_create fail!");
eError = OMX_ErrorInsufficientResources;
goto _EXIT5;
}
return eError;
_EXIT5:
aic_msg_destroy(&pVideoRenderDataType->sMsgQue);
pthread_mutex_destroy(&pVideoRenderDataType->stateLock);
pthread_mutex_destroy(&pVideoRenderDataType->sWaitReayFrameLock);
_EXIT4:
if (!mpp_list_empty(&pVideoRenderDataType->sInEmptyFrame)) {
VIDEO_RENDER_IN_FRAME *pFrameNode = NULL,*pFrameNode1 = NULL;
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pVideoRenderDataType->sInEmptyFrame, sList) {
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
_EXIT2:
if (pVideoRenderDataType) {
mpp_free(pVideoRenderDataType);
pVideoRenderDataType = NULL;
}
_EXIT1:
return eError;
}
static void OMX_VideoRenderEventNotify(
VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType,
OMX_EVENTTYPE event,
OMX_U32 nData1,
OMX_U32 nData2,
OMX_PTR pEventData)
{
if (pVideoRenderDataType && pVideoRenderDataType->pCallbacks && pVideoRenderDataType->pCallbacks->EventHandler) {
pVideoRenderDataType->pCallbacks->EventHandler(
pVideoRenderDataType->hSelf,
pVideoRenderDataType->pAppData,event,
nData1, nData2, pEventData);
}
}
static void OMX_VideoRenderStateChangeToInvalid(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
pVideoRenderDataType->state = OMX_StateInvalid;
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorInvalidState,0,NULL);
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pVideoRenderDataType->state,NULL);
}
static void OMX_VideoRenderStateChangeToLoaded(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
if (pVideoRenderDataType->state == OMX_StateIdle) {
OMX_VideoRenderGiveBackAllFrames(pVideoRenderDataType);
} else if (pVideoRenderDataType->state == OMX_StateExecuting) {
} else if (pVideoRenderDataType->state == OMX_StatePause) {
} else {
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
}
pVideoRenderDataType->state = OMX_StateLoaded;
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pVideoRenderDataType->state,NULL);
}
static void OMX_VideoRenderStateChangeToIdle(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
int ret = 0;
if (pVideoRenderDataType->state == OMX_StateLoaded) {
//create video_handle
if (!pVideoRenderDataType->render) {
ret = aic_video_render_create(&pVideoRenderDataType->render);
}
if (ret != 0) {
loge("aic_video_render_create fail\n");
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
}
} else if (pVideoRenderDataType->state == OMX_StatePause) {
} else if (pVideoRenderDataType->state == OMX_StateExecuting) {
} else {
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
}
pVideoRenderDataType->state = OMX_StateIdle;
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pVideoRenderDataType->state,NULL);
}
static void OMX_VideoRenderStateChangeToPause(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
OMX_PORT_TUNNELEDINFO *pTunneldClock = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
if (pVideoRenderDataType->state == OMX_StateLoaded) {
} else if (pVideoRenderDataType->state == OMX_StateIdle) {
} else if (pVideoRenderDataType->state == OMX_StateExecuting) {
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
if (pTunneldClock->nTunneledFlag) {
OMX_GetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeCurrentMediaTime, &sTimeStamp);
printf("[%s:%d]Excuting--->Pause,sTimeStamp:%ld\n",__FUNCTION__,__LINE__,sTimeStamp.nTimestamp);
} else {
pVideoRenderDataType->sPauseTimePoint = OMX_ClockGetSystemTime();
printf("[%s:%d]Excuting--->Pause,sPauseTimePoint:%ld\n",__FUNCTION__,__LINE__,pVideoRenderDataType->sPauseTimePoint);
}
} else {
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
}
pVideoRenderDataType->state = OMX_StatePause;
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pVideoRenderDataType->state,NULL);
}
static void OMX_VideoRenderStateChangeToExecuting(VIDEO_RENDER_DATA_TYPE * pVideoRenderDataType)
{
if (pVideoRenderDataType->state == OMX_StateLoaded) {
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
} else if (pVideoRenderDataType->state == OMX_StateIdle) {
} else if (pVideoRenderDataType->state == OMX_StatePause) {
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
OMX_PORT_TUNNELEDINFO *pTunneldClock = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
if (pTunneldClock->nTunneledFlag) {
OMX_GetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeCurrentMediaTime, &sTimeStamp);
printf("[%s:%d]Pause--->Excuting,sTimeStamp:%ld\n",__FUNCTION__,__LINE__,sTimeStamp.nTimestamp);
} else {
pVideoRenderDataType->sPauseTimeDurtion += (OMX_ClockGetSystemTime() - pVideoRenderDataType->sPauseTimePoint);
printf("[%s:%d]Pause--->Excuting,sPauseTimePoint:%ld,curTime:%ld,pauseDura:%ld\n"
,__FUNCTION__,__LINE__,pVideoRenderDataType->sPauseTimePoint,OMX_ClockGetSystemTime(),pVideoRenderDataType->sPauseTimeDurtion);
}
} else {
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pVideoRenderDataType->state,NULL);
return;
}
pVideoRenderDataType->state = OMX_StateExecuting;
OMX_VideoRenderEventNotify(pVideoRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pVideoRenderDataType->state,NULL);
}
static OMX_S64 OMX_ClockGetSystemTime()
{
struct timespec ts = {0,0};
OMX_S64 tick = 0;
//clock_gettime(CLOCK_MONOTONIC,&ts);
clock_gettime(CLOCK_REALTIME,&ts);
tick = ts.tv_sec*1000000 + ts.tv_nsec/1000;
return tick;
}
/*
static int OMX_VideoRenderDumpPic(struct mpp_buf* video,int index)
{
int i;
int data_size[3] = {0, 0, 0};
unsigned char* hw_data[3] = {0};
int comp = 3;
FILE* fp_save = NULL;
char fileName[255] = {0};
if (video->format == MPP_FMT_YUV420P) {
comp = 3;
data_size[0] = video->size.height * video->stride[0];
data_size[1] = data_size[2] = data_size[0]/4;
} else if (video->format == MPP_FMT_NV12 || video->format == MPP_FMT_NV21) {
comp = 2;
data_size[0] = video->size.height * video->stride[0];
data_size[1] = data_size[0]/2;
} else if (video->format == MPP_FMT_YUV444P) {
comp = 3;
data_size[0] = video->size.height * video->stride[0];
data_size[1] = data_size[2] = data_size[0];
} else if (video->format == MPP_FMT_YUV422P) {
comp = 3;
data_size[0] = video->size.height * video->stride[0];
data_size[1] = data_size[2] = data_size[0]/2;
} else if (video->format == MPP_FMT_RGBA_8888 || video->format == MPP_FMT_BGRA_8888
|| video->format == MPP_FMT_ARGB_8888 || video->format == MPP_FMT_ABGR_8888) {
comp = 1;
data_size[0] = video->size.height * video->stride[0];
} else if (video->format == MPP_FMT_RGB_888 || video->format == MPP_FMT_BGR_888) {
comp = 1;
data_size[0] = video->size.height * video->stride[0];
} else if (video->format == MPP_FMT_RGB_565 || video->format == MPP_FMT_BGR_565) {
comp = 1;
data_size[0] = video->size.height * video->stride[0];
}
loge("data_size: %d %d %d, height: %d, stride: %d, format: %d",
data_size[0], data_size[1], data_size[2],
video->size.height, video->stride[0], video->format);
snprintf(fileName,sizeof(fileName),"Pic%d.yuv",index);
fp_save = fopen(fileName, "wb");
if (fp_save == NULL) {
loge("fopen %s error\n",fileName);
return -1;
}
loge("fopen %s ok\n",fileName);
// mmap dmabuf to virtual space and save the frame yuv data
for(i=0; i<comp; i++) {
hw_data[i] = mmap(NULL, data_size[i], PROT_READ, MAP_SHARED, video->fd[i], 0);
if (hw_data[i] == MAP_FAILED) {
loge("dmabuf alloc mmap failed!");
return -1;
}
if (fp_save)
fwrite(hw_data[i], 1, data_size[i], fp_save);
}
fclose(fp_save);
for(i=0; i<comp; i++) {
munmap(hw_data[i], data_size[i]);
}
return 0;
}
*/
typedef enum OMX_VIDEO_SYNC_TYPE {
OMX_VIDEO_SYNC_INVAILD = -1,
OMX_VIDEO_SYNC_DROP = 0,
OMX_VIDEO_SYNC_DEALY,
OMX_VIDEO_SYNC_SHOW,
}OMX_VIDEO_SYNC_TYPE;
static OMX_TICKS OMX_VdieoRenderGetMediaTime(VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType)
{
OMX_TICKS sMeidaTime;
sMeidaTime = OMX_ClockGetSystemTime()- pVideoRenderDataType->sWallTimeBase
- pVideoRenderDataType->sPauseTimeDurtion + pVideoRenderDataType->sFisrtShowPts;
return sMeidaTime;
}
static void OMX_VdieoRenderSetMediaClock(VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType,struct mpp_frame *pFrameInfo)
{
pVideoRenderDataType->sWallTimeBase = OMX_ClockGetSystemTime();
pVideoRenderDataType->sPauseTimeDurtion = 0;
pVideoRenderDataType->sFisrtShowPts = pFrameInfo->pts;
pVideoRenderDataType->sPreFramePts = pFrameInfo->pts;
logw("pVideoRenderDataType->sFisrtShowPts:%ld,pVideoRenderDataType->sWallTimeBase:%ld\n"
,pVideoRenderDataType->sFisrtShowPts
,pVideoRenderDataType->sWallTimeBase);
}
static int OMX_GiveBackProcessedFrames(VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType)
{
int ret = 0;
OMX_S32 nCntInUsingList = 0;
VIDEO_RENDER_IN_FRAME *pFrameNode;
OMX_PORT_TUNNELEDINFO *pTunneldVideo;
pTunneldVideo = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_VIDEO_INDEX];
mpp_list_for_each_entry(pFrameNode, &pVideoRenderDataType->sInProcessedFrmae, sList) {
nCntInUsingList++;
}
while(nCntInUsingList > 1) {
OMX_BUFFERHEADERTYPE sBuffHead;
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pVideoRenderDataType->sInProcessedFrmae, VIDEO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
ret = -1;
if (pTunneldVideo->nTunneledFlag) {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
sBuffHead.nInputPortIndex = VIDEO_RENDER_PORT_IN_VIDEO_INDEX;
sBuffHead.nOutputPortIndex = pTunneldVideo->nTunnelPortIndex;
ret = OMX_FillThisBuffer(pTunneldVideo->pTunneledComp,&sBuffHead);
} else {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
if (pVideoRenderDataType->pCallbacks->EmptyBufferDone) {
ret = pVideoRenderDataType->pCallbacks->EmptyBufferDone(pVideoRenderDataType->hSelf
,pVideoRenderDataType->pAppData,&sBuffHead);
}
}
if (ret == 0) {
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInEmptyFrame);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
pVideoRenderDataType->nGiveBackFrameOkNum++;
logd("give back frame to vdec ok");
nCntInUsingList--;
} else { // how to do ,do nothing or move to empty list,now move to empty list
logw("give back frame to vdec fail\n");
pVideoRenderDataType->nGiveBackFrameFailNum++;
break;
}
logi("nGiveBackFrameOkNum:%d,nGiveBackFrameFailNum:%d\n"
,pVideoRenderDataType->nGiveBackFrameOkNum,pVideoRenderDataType->nGiveBackFrameFailNum);
}
return ret;
}
#define MAX_DIFFF_TIME (10*1000) // 5ms need to to discuss
static OMX_VIDEO_SYNC_TYPE OMX_VdieoRenderProcessVideoSync(VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType,struct mpp_frame *pFrameInfo,OMX_TICKS *nDelay)
{
OMX_TICKS sDelayime;
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
OMX_VIDEO_SYNC_TYPE eSyncType;
OMX_PORT_TUNNELEDINFO *pTunneldClock = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
if (pVideoRenderDataType == NULL || pFrameInfo == NULL || nDelay == NULL) {
return OMX_VIDEO_SYNC_INVAILD;
}
if (pTunneldClock->nTunneledFlag) {
sTimeStamp.nPortIndex = pTunneldClock->nTunnelPortIndex;
OMX_GetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeCurrentMediaTime, &sTimeStamp);
if (sTimeStamp.nTimestamp == -1) {
/*
1 need to define valid pts,suppose pts = -1.
2 after start up or seek, audio do not come yet,so get media time is invaild.
when vaild audio do not come,control by video self
*/
sDelayime = pFrameInfo->pts - OMX_VdieoRenderGetMediaTime(pVideoRenderDataType);
//
if (sDelayime > 10*1000*1000 || sDelayime < -10*1000*1000) {
loge("tunneld clock ,but audio do not come ,vidoe pts jump event!!!\n");
sDelayime = 40*1000;//this should arccording to fame rate
OMX_VdieoRenderSetMediaClock(pVideoRenderDataType,pFrameInfo);
}
} else {
sDelayime = pFrameInfo->pts - sTimeStamp.nTimestamp;
// if (sDelayime > 100*1000 || sDelayime <-100*1000)
// printf("pFrameInfo->pts:%lld,sTimeStamp.nTimestamp:%ld\n",pFrameInfo->pts,sTimeStamp.nTimestamp);
if (sDelayime > 10*1000*1000 || sDelayime < -10*1000*1000) {
if ( pFrameInfo->pts - pVideoRenderDataType->sPreFramePts > 10*1000*1000
|| pFrameInfo->pts - pVideoRenderDataType->sPreFramePts < -10*1000*1000)
{// case by video pts jump event
/*
video pts jump,
*/
loge("video pts jump event!!!\n");
} else {//case by audio pts jump event
/*
audio pts jump
*/
loge("audio pts jump event!!!\n");
}
}
}
} else {// frame rate control by videoRender self
sDelayime = pFrameInfo->pts - OMX_VdieoRenderGetMediaTime(pVideoRenderDataType);
if (sDelayime > 10*1000*1000 || sDelayime < -10*1000*1000) {//pts jump event
loge("not tunneled clock ,vidoe pts jump event!!!\n");
sDelayime = 40*1000;//this should arccording to fame rate
OMX_VdieoRenderSetMediaClock(pVideoRenderDataType,pFrameInfo);
}
}
if (pFrameInfo->flags & FRAME_FLAG_EOS) {
printf("[%s:%d]pts:%lld,sDiffTime:%ld\n",__FUNCTION__,__LINE__,pFrameInfo->pts,sDelayime);
}
if (sDelayime > 2*MAX_DIFFF_TIME) {
eSyncType = OMX_VIDEO_SYNC_DEALY;
} else if (sDelayime > (-2)*MAX_DIFFF_TIME) {
eSyncType = OMX_VIDEO_SYNC_SHOW;
} else {
eSyncType = OMX_VIDEO_SYNC_DROP;
}
*nDelay = sDelayime;
return eSyncType;
}
static void* OMX_VideoRenderComponentThread(void* pThreadData)
{
struct aic_message message;
OMX_S32 nCmd; //OMX_COMMANDTYPE
OMX_S32 nCmdData; //OMX_STATETYPE
VIDEO_RENDER_DATA_TYPE* pVideoRenderDataType = (VIDEO_RENDER_DATA_TYPE*)pThreadData;
OMX_S32 ret;
//OMX_S32 i;
OMX_S32 bNotifyFrameEnd = 0;
//struct mpp_frame sFrame;
VIDEO_RENDER_IN_FRAME *pFrameNode;
//prctl(PR_SET_NAME,(u32)"VideoRender");
OMX_PORT_TUNNELEDINFO *pTunneldClock;
pTunneldClock = &pVideoRenderDataType->sInPortTunneledInfo[VIDEO_RENDER_PORT_IN_CLOCK_INDEX];
OMX_S32 nEmptyNum = 0;
pVideoRenderDataType->nWaitReayFrameFlag = 1;
while(1) {
_AIC_MSG_GET_:
if (aic_msg_get(&pVideoRenderDataType->sMsgQue, &message) == 0) {
nCmd = message.message_id;
nCmdData = message.param;
logi("nCmd:%d, nCmdData:%d\n",nCmd,nCmdData);
if (OMX_CommandStateSet == nCmd) {
aic_pthread_mutex_lock(&pVideoRenderDataType->stateLock);
if (pVideoRenderDataType->state == (OMX_STATETYPE)(nCmdData)) {
OMX_VideoRenderEventNotify(pVideoRenderDataType,OMX_EventError,OMX_ErrorSameState,0,NULL);
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
continue;
}
switch(nCmdData) {
case OMX_StateInvalid:
OMX_VideoRenderStateChangeToInvalid(pVideoRenderDataType);
break;
case OMX_StateLoaded:
OMX_VideoRenderStateChangeToLoaded(pVideoRenderDataType);
break;
case OMX_StateIdle:
OMX_VideoRenderStateChangeToIdle(pVideoRenderDataType);
break;
case OMX_StateExecuting:
OMX_VideoRenderStateChangeToExecuting(pVideoRenderDataType);
break;
case OMX_StatePause:
OMX_VideoRenderStateChangeToPause(pVideoRenderDataType);
break;
default:
break;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->stateLock);
} else if (OMX_CommandFlush == nCmd) {
} else if (OMX_CommandPortDisable == nCmd) {
} else if (OMX_CommandPortEnable == nCmd) {
} else if (OMX_CommandMarkBuffer == nCmd) {
} else if (OMX_CommandStop == nCmd) {
logi("OMX_VideoRenderComponentThread ready to exit!!!\n");
goto _EXIT;
} else {
}
}
if (pVideoRenderDataType->state != OMX_StateExecuting) {
//usleep(1000);
aic_msg_wait_new_msg(&pVideoRenderDataType->sMsgQue, 0);
continue;
}
if (pVideoRenderDataType->nFlags & VIDEO_RENDER_INPORT_SEND_ALL_FRAME_FLAG) {
if (!bNotifyFrameEnd) {
OMX_VideoRenderEventNotify(pVideoRenderDataType,OMX_EventBufferFlag,0,0,NULL);
bNotifyFrameEnd = 1;
}
aic_msg_wait_new_msg(&pVideoRenderDataType->sMsgQue, 0);
//usleep(1000);
continue;
}
bNotifyFrameEnd = 0;
OMX_GiveBackProcessedFrames(pVideoRenderDataType);
if (OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInReadyFrame,pVideoRenderDataType->sInFrameLock))
{
struct timespec before = {0},after = {0};
long diff;
aic_pthread_mutex_lock(&pVideoRenderDataType->sWaitReayFrameLock);
pVideoRenderDataType->nWaitReayFrameFlag = 1;
aic_pthread_mutex_unlock(&pVideoRenderDataType->sWaitReayFrameLock);
clock_gettime(CLOCK_REALTIME,&before);
aic_msg_wait_new_msg(&pVideoRenderDataType->sMsgQue, 0);
clock_gettime(CLOCK_REALTIME,&after);
diff = (after.tv_sec - before.tv_sec)*1000*1000 + (after.tv_nsec - before.tv_nsec)/1000;
if (diff > 50*1000) {
printf("[%s:%d]:%ld\n",__FUNCTION__,__LINE__,diff);
}
nEmptyNum++;
goto _AIC_MSG_GET_;
}
while(!OMX_VideoRenderListEmpty(&pVideoRenderDataType->sInReadyFrame,pVideoRenderDataType->sInFrameLock)) {
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pVideoRenderDataType->sInReadyFrame, VIDEO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
if (pVideoRenderDataType->nFrameFisrtShowFlag) {
struct mpp_size sSize;
struct mpp_rect sDisRect;
if (!pVideoRenderDataType->nVideoRenderInitFlag) {
ret = pVideoRenderDataType->render->init(pVideoRenderDataType->render,pVideoRenderDataType->nLayerId,pVideoRenderDataType->nDevId);
if (!ret) {
printf("[%s:%d]pVideoRenderDataType->render->init ok\n",__FUNCTION__,__LINE__);
pVideoRenderDataType->nVideoRenderInitFlag = 1;
} else {
loge("pVideoRenderDataType->render->init fail\n");
}
}
if (pTunneldClock->nTunneledFlag) {
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
sTimeStamp.nPortIndex = pTunneldClock->nTunnelPortIndex;
sTimeStamp.nTimestamp = pFrameNode->sFrameInfo.pts;
OMX_SetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeClientStartTime, &sTimeStamp);
// whether need to wait????
if (pVideoRenderDataType->eClockState != OMX_TIME_ClockStateRunning) {
aic_msg_wait_new_msg(&pVideoRenderDataType->sMsgQue, 1*1000);
goto _AIC_MSG_GET_;
}
printf("[%s:%d]audio start time arrive\n",__FUNCTION__,__LINE__);
} else {//if it does not tunneld with clock ,it need calcuaute media time by self for control frame rate
OMX_VdieoRenderSetMediaClock(pVideoRenderDataType,&pFrameNode->sFrameInfo);
}
//pVideoRenderDataType->render->set_on_off(pVideoRenderDataType->render,0);
pVideoRenderDataType->render->get_screen_size(pVideoRenderDataType->render,&sSize);
sDisRect.x = 0;
sDisRect.y = 0;
sDisRect.width = sSize.width;
sDisRect.height = sSize.height;
//sDisRect.width = 1024;
//sDisRect.height = 600;
if (pVideoRenderDataType->nDisRectChange) {
pVideoRenderDataType->render->set_dis_rect(pVideoRenderDataType->render,&pVideoRenderDataType->sDisRect);
logi("init dis rect:[%d,%d,%d,%d]!!!\n"
,pVideoRenderDataType->sDisRect.x
,pVideoRenderDataType->sDisRect.y
,pVideoRenderDataType->sDisRect.width
,pVideoRenderDataType->sDisRect.height);
pVideoRenderDataType->nDisRectChange = OMX_FALSE;
} else {
pVideoRenderDataType->render->set_dis_rect(pVideoRenderDataType->render,&sDisRect);
printf("[%s:%d]init dis rect:[%d,%d,%d,%d]!!!\n",__FUNCTION__,__LINE__,sDisRect.x,sDisRect.y,sDisRect.width,sDisRect.height);
}
//pVideoRenderDataType->render->set_on_off(pVideoRenderDataType->render,1);
printf("[%s:%d]stride[0]:%d,stride[1]:%d,stride[2]:%d,format:%d,width:%d,height:%d"\
"crop_en:%d,crop.x:%d,crop.y:%d,crop.width:%d,crop.height:%d\n"
,__FUNCTION__,__LINE__
,pFrameNode->sFrameInfo.buf.stride[0]
,pFrameNode->sFrameInfo.buf.stride[1]
,pFrameNode->sFrameInfo.buf.stride[2]
,pFrameNode->sFrameInfo.buf.format
,pFrameNode->sFrameInfo.buf.size.width
,pFrameNode->sFrameInfo.buf.size.height
,pFrameNode->sFrameInfo.buf.crop_en
,pFrameNode->sFrameInfo.buf.crop.x
,pFrameNode->sFrameInfo.buf.crop.y
,pFrameNode->sFrameInfo.buf.crop.width
,pFrameNode->sFrameInfo.buf.crop.height);
pVideoRenderDataType->nDumpIndex = 0;
if (pVideoRenderDataType->nRotationAngleChange) {
OMX_VideoRenderInitRotationParam(pVideoRenderDataType,&pFrameNode->sFrameInfo);
pVideoRenderDataType->nRotationAngleChange = 0;
}
OMX_VideoRenderRotateFrame(pVideoRenderDataType,&pFrameNode->sFrameInfo);
#ifdef OMX_VIDEORENDER_ENABLE_DUMP_PIC
OMX_VideoRenderDumpPic(&pVideoRenderDataType->pCurDisplayFrame->buf,pVideoRenderDataType->nDumpIndex++);
#endif
ret = pVideoRenderDataType->render->rend(pVideoRenderDataType->render,pVideoRenderDataType->pCurDisplayFrame);
//ret = pVideoRenderDataType->render->rend(pVideoRenderDataType->render,&pFrameNode->sFrameInfo);
//pVideoRenderDataType->render->set_on_off(pVideoRenderDataType->render,1);
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
if (ret == 0) {
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
pVideoRenderDataType->nShowFrameOkNum++;
pVideoRenderDataType->nFrameFisrtShowFlag = OMX_FALSE;
OMX_VideoRenderEventNotify(pVideoRenderDataType,OMX_EventVideoRenderFirstFrame,0,0,NULL);
if (pFrameNode->sFrameInfo.flags & FRAME_FLAG_EOS) {
pVideoRenderDataType->nFlags |= VIDEO_RENDER_INPORT_SEND_ALL_FRAME_FLAG;
//pVideoRenderDataType->nFrameEndFlag = OMX_TRUE;
printf("[%s:%d]receive nFrameEndFlag\n",__FUNCTION__,__LINE__);
}
} else {
// how to do ,now deal with same success
loge("render error");
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
pVideoRenderDataType->nShowFrameFailNum++;
break;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
logd("nReceiveFrameNum:%d,nShowFrameOkNum:%d,nShowFrameFailNum:%d\n"
,pVideoRenderDataType->nReceiveFrameNum
,pVideoRenderDataType->nShowFrameOkNum
,pVideoRenderDataType->nShowFrameFailNum);
} else {// not fisrt show
OMX_S32 data1,data2;
OMX_TICKS sDelayime;
OMX_VIDEO_SYNC_TYPE eSyncType;
static struct timespec pev = {0},cur = {0};
//loge("!!!!!!!!!!!!!!! ReadyFrame!!!!!!!!! \n");
eSyncType = OMX_VdieoRenderProcessVideoSync(pVideoRenderDataType,&pFrameNode->sFrameInfo,&sDelayime);
//eSyncType = OMX_VIDEO_SYNC_SHOW;
if (pev.tv_sec == 0) {
clock_gettime(CLOCK_REALTIME,&pev);
} else {
long diff = 0;
clock_gettime(CLOCK_REALTIME,&cur);
diff = (cur.tv_sec - pev.tv_sec)*1000*1000 + (cur.tv_nsec - pev.tv_nsec)/1000;
if (diff > 42*1000) {
printf("[%s:%d]:%ld,sDelayime:%ld,eSyncType:%d,pts:%lld\n"
,__FUNCTION__,__LINE__
,diff
,sDelayime
,eSyncType
,pFrameNode->sFrameInfo.pts);
}
pev = cur;
}
if (eSyncType == OMX_VIDEO_SYNC_SHOW) {
if (pVideoRenderDataType->nRotationAngleChange) {
OMX_VideoRenderInitRotationParam(pVideoRenderDataType,&pFrameNode->sFrameInfo);
pVideoRenderDataType->nRotationAngleChange = 0;
}
//time_start(RotateFrame);
OMX_VideoRenderRotateFrame(pVideoRenderDataType,&pFrameNode->sFrameInfo);
//time_end(RotateFrame);
#ifdef OMX_VIDEORENDER_ENABLE_DUMP_PIC
if (pVideoRenderDataType->nDumpIndex < 24) {
OMX_VideoRenderDumpPic(&pVideoRenderDataType->pCurDisplayFrame->buf,pVideoRenderDataType->nDumpIndex++);
}
#endif
ret = pVideoRenderDataType->render->rend(pVideoRenderDataType->render,pVideoRenderDataType->pCurDisplayFrame);
//ret = pVideoRenderDataType->render->rend(pVideoRenderDataType->render,&pFrameNode->sFrameInfo);
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
if (ret == 0) {
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
pVideoRenderDataType->nShowFrameOkNum++;
if (pFrameNode->sFrameInfo.flags & FRAME_FLAG_EOS) {
pVideoRenderDataType->nFlags |= VIDEO_RENDER_INPORT_SEND_ALL_FRAME_FLAG;
//pVideoRenderDataType->nFrameEndFlag = OMX_TRUE;
printf("[%s:%d]receive nFrameEndFlag\n",__FUNCTION__,__LINE__);
}
} else {
// how to do ,now deal with same success
loge("render error");
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
pVideoRenderDataType->nShowFrameFailNum++;
break;
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
//OMX_GiveBackProcessedFrames(pVideoRenderDataType);
data1 = (pFrameNode->sFrameInfo.pts >> 32) & 0x00000000ffffffff;
data2 = pFrameNode->sFrameInfo.pts & 0x00000000ffffffff;
//loge("OMX_VIDEO_SYNC_SHOW:%ld\n",sDelayime);
OMX_VideoRenderEventNotify(pVideoRenderDataType,OMX_EventVideoRenderPts,data1,data2,NULL);
} else if (eSyncType == OMX_VIDEO_SYNC_DROP) {
static int nDropNum = 0;
if (pFrameNode->sFrameInfo.flags & FRAME_FLAG_EOS) {
pVideoRenderDataType->nFlags |= VIDEO_RENDER_INPORT_SEND_ALL_FRAME_FLAG;
printf("[%s:%d]receive nFrameEndFlag\n",__FUNCTION__,__LINE__);
}
aic_pthread_mutex_lock(&pVideoRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pVideoRenderDataType->sInProcessedFrmae);
pVideoRenderDataType->nDropFrameNum++;
nDropNum++;
if (nDropNum > 50) {
nDropNum = 0;
printf("[%s:%d]OMX_VIDEO_SYNC_DROP:nDropFrameNum:%d,sDelayime:%ld:%d\n",__FUNCTION__,__LINE__,pVideoRenderDataType->nDropFrameNum,sDelayime,nEmptyNum);
}
aic_pthread_mutex_unlock(&pVideoRenderDataType->sInFrameLock);
//OMX_GiveBackProcessedFrames(pVideoRenderDataType);
} else if (eSyncType == OMX_VIDEO_SYNC_DEALY) {
struct timespec delay_before = {0},delay_after = {0};
//long delay = 0;
//loge("OMX_VIDEO_SYNC_DEALY:%ld,%ld\n",sDelayime,sDelayime-MAX_DIFFF_TIME);
clock_gettime(CLOCK_REALTIME,&delay_before);
aic_msg_wait_new_msg(&pVideoRenderDataType->sMsgQue, sDelayime - MAX_DIFFF_TIME);
//usleep(sDelayime - MAX_DIFFF_TIME);
//aic_udelay(sDelayime - MAX_DIFFF_TIME);
clock_gettime(CLOCK_REALTIME,&delay_after);
//delay = (delay_after.tv_sec - delay_before.tv_sec)*1000*1000 + (delay_after.tv_nsec - delay_before.tv_nsec)/1000;
//printf("[%s:%d]:%ld,%ld\n",__FUNCTION__,__LINE__,delay,sDelayime - MAX_DIFFF_TIME);
} else {
//logd("OMX_VIDEO_SYNC_DEALY:%lld\n",sDelayime);
}
}
if (pVideoRenderDataType->nDisRectChange)
{
pVideoRenderDataType->render->set_dis_rect(pVideoRenderDataType->render,&pVideoRenderDataType->sDisRect);
logi("init dis rect:[%d,%d,%d,%d]!!!\n"
,pVideoRenderDataType->sDisRect.x
,pVideoRenderDataType->sDisRect.y
,pVideoRenderDataType->sDisRect.width
,pVideoRenderDataType->sDisRect.height);
pVideoRenderDataType->nDisRectChange = OMX_FALSE;
}
}
}
_EXIT:
printf("[%s:%d]nReceiveFrameNum:%d,"\
"nLeftReadyFrameWhenCompoentExitNum:%d,"\
"nShowFrameOkNum:%d,"\
"nShowFrameFailNum:%d,"\
"nGiveBackFrameOkNum:%d,"\
"nGiveBackFrameFailNum:%d\n"
,__FUNCTION__,__LINE__
,pVideoRenderDataType->nReceiveFrameNum
,pVideoRenderDataType->nLeftReadyFrameWhenCompoentExitNum
,pVideoRenderDataType->nShowFrameOkNum
,pVideoRenderDataType->nShowFrameFailNum
,pVideoRenderDataType->nGiveBackFrameOkNum
,pVideoRenderDataType->nGiveBackFrameFailNum);
printf("[%s:%d]OMX_VideoRenderComponentThread EXIT\n",__FUNCTION__,__LINE__);
return (void*)OMX_ErrorNone;
}