mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-15 19:08:54 +00:00
1963 lines
83 KiB
C
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;
|
|
}
|
|
|