Files
luban-lite-t3e-pro/packages/artinchip/mpp/middle_media/openmax/component/OMX_AudioRenderComponent.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

1277 lines
53 KiB
C

/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: OMX_AudioRenderComponent
*/
#include "OMX_AudioRenderComponent.h"
#define aic_pthread_mutex_lock(mutex)\
{\
/*loge("before lock\n");*/\
pthread_mutex_lock(mutex);\
/*loge("after lock\n");*/\
}
#define aic_pthread_mutex_unlock(mutex)\
{\
/*loge("before unlock\n");*/\
pthread_mutex_unlock(mutex);\
/*loge("after unlock\n");*/\
}
#define OMX_AudioRenderListEmpty(list,mutex)\
({\
int ret = 0;\
aic_pthread_mutex_lock(&mutex);\
ret = mpp_list_empty(list);\
aic_pthread_mutex_unlock(&mutex);\
(ret);\
})
static OMX_ERRORTYPE OMX_AudioRenderSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData);
static OMX_ERRORTYPE OMX_AudioRenderGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_AudioRenderSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_AudioRenderGetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_AudioRenderSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_AudioRenderGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState);
static OMX_ERRORTYPE OMX_AudioRenderComponentTunnelRequest(
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_AudioRenderEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_AudioRenderFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_AudioRenderSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData);
static OMX_ERRORTYPE OMX_AudioRenderSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData)
{
AUDIO_RENDER_DATA_TYPE *pAudioRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
struct aic_message sMsg;
pAudioRenderDataType = (AUDIO_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(&pAudioRenderDataType->sMsgQue, &sMsg);
return eError;
}
static void* OMX_AudioRenderComponentThread(void* pThreadData);
static int OMX_AudioRenderGiveBackAllFrames(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType);
static OMX_ERRORTYPE OMX_AudioRenderGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure)
{
AUDIO_RENDER_DATA_TYPE *pAudioRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_U32 tmp1,tmp2;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch ((OMX_S32)nParamIndex) {
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 == 0) {
sBufferSupplier->eBufferSupplier = pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].eBufferSupplier;
} else {
loge("error nPortIndex\n");
eError = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexVendorAudioRenderVolume: {
OMX_S32 vol = pAudioRenderDataType->render->get_volume(pAudioRenderDataType->render);
((OMX_PARAM_AUDIO_VOLUME *)pComponentParameterStructure)->nVolume = vol;
break;
}
default:
eError = OMX_ErrorNotImplemented;
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR pComponentParameterStructure)
{
AUDIO_RENDER_DATA_TYPE *pAudioRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_S32 tmp1,tmp2;
OMX_PARAM_FRAMEEND *sFrameEnd;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
if (pComponentParameterStructure == NULL) {
loge("param error!!!\n");
return OMX_ErrorBadParameter;
}
switch ((OMX_S32)nParamIndex) {
case OMX_IndexParamPortDefinition:
break;
case OMX_IndexParamVideoPortFormat:
break;
case OMX_IndexVendorStreamFrameEnd:
sFrameEnd = (OMX_PARAM_FRAMEEND*)pComponentParameterStructure;
if (sFrameEnd->bFrameEnd == OMX_TRUE) {
pAudioRenderDataType->nFrameEndFlag = OMX_TRUE;
logi("setup nFrameEndFlag\n");
} else {
pAudioRenderDataType->nFrameEndFlag = OMX_FALSE;
logi("cancel nFrameEndFlag\n");
}
break;
case OMX_IndexParamVideoMpeg4:
break;
case OMX_IndexVendorAudioRenderVolume: {
OMX_S32 vol = ((OMX_PARAM_AUDIO_VOLUME *)pComponentParameterStructure)->nVolume;
if (vol < 0) {
pAudioRenderDataType->nVolume = 0;
} else if (vol < 101) {
pAudioRenderDataType->nVolume = vol;
} else {
pAudioRenderDataType->nVolume = 100;
}
pAudioRenderDataType->nVolumeChange = 1;
logd("nVolume:%"PRId32",change:%"PRId32"\n",pAudioRenderDataType->nVolume,pAudioRenderDataType->nVolumeChange);
break;
}
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderGetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch ((OMX_S32)nIndex) {
case OMX_IndexConfigTimePosition:
//1 clear input buffer list
OMX_AudioRenderGiveBackAllFrames(pAudioRenderDataType);
//2 reset flag
pAudioRenderDataType->nFrameFisrtShowFlag = OMX_TRUE;
pAudioRenderDataType->nFlags = 0;
pAudioRenderDataType->eClockState = OMX_TIME_ClockStateWaitingForStartTime;
// 3 reset render
//aic_audio_render_reset(pAudioRenderDataType->render);
aic_audio_render_clear_cache(pAudioRenderDataType->render);
break;
case OMX_IndexConfigTimeSeekMode:
break;
case OMX_IndexConfigTimeClockState: {
OMX_TIME_CONFIG_CLOCKSTATETYPE* state = (OMX_TIME_CONFIG_CLOCKSTATETYPE *)pComponentConfigStructure;
pAudioRenderDataType->eClockState = state->eState;
printf("[%s:%d]pAudioRenderDataType->eClockState:%d\n",__FUNCTION__,__LINE__,pAudioRenderDataType->eClockState);
break;
}
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState)
{
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pAudioRenderDataType->stateLock);
*pState = pAudioRenderDataType->state;
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderComponentTunnelRequest(
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;
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComp)->pComponentPrivate);
if (pAudioRenderDataType->state != OMX_StateLoaded)
{
loge("Component is not in OMX_StateLoaded,it is in%d,it can not tunnel\n",pAudioRenderDataType->state);
return OMX_ErrorInvalidState;
}
if (nPort == AUDIO_RENDER_PORT_IN_AUDIO_INDEX) {
pPort = &pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX];
pTunneledInfo = &pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX];
pBufSupplier = &pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_AUDIO_INDEX];
} else if (nPort == AUDIO_RENDER_PORT_IN_CLOCK_INDEX) {
pPort = &pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX];
pTunneledInfo = &pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_CLOCK_INDEX];
pBufSupplier = &pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_CLOCK_INDEX];
} else {
loge("component can not find port:%"PRId32"\n",nPort);
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_AudioRenderEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType;
AUDIO_RENDER_IN_FRAME *pFrame;
struct aic_message sMsg;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pAudioRenderDataType->stateLock);
if (pAudioRenderDataType->state != OMX_StateExecuting) {
logw("component is not in OMX_StateExecuting,it is in [%d]!!!\n",pAudioRenderDataType->state);
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
if (OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInEmptyFrame,pAudioRenderDataType->sInFrameLock)) {
loge("OMX_ErrorInsufficientResources\n");
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
return OMX_ErrorInsufficientResources;
}
if (pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].nTunneledFlag) {// now Tunneled and non-Tunneled are same
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
pFrame = mpp_list_first_entry(&pAudioRenderDataType->sInEmptyFrame, AUDIO_RENDER_IN_FRAME, sList);
memcpy(&pFrame->sFrameInfo,pBuffer->pBuffer,sizeof(struct aic_audio_frame));
mpp_list_del(&pFrame->sList);
mpp_list_add_tail(&pFrame->sList, &pAudioRenderDataType->sInReadyFrame);
if (pAudioRenderDataType->nWaitReayFrameFlag) {
sMsg.message_id = OMX_CommandNops;
sMsg.data_size = 0;
aic_msg_put(&pAudioRenderDataType->sMsgQue, &sMsg);
pAudioRenderDataType->nWaitReayFrameFlag = 0;
}
pAudioRenderDataType->nReceiveFrameNum++;
logd("nReceiveFrameNum:%"PRId32"\n",pAudioRenderDataType->nReceiveFrameNum);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
{
static int nRenderFrameNum = 0;
static struct timespec pre = {0},cur = {0};
long diff;
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\n",__FUNCTION__,__LINE__,diff,nRenderFrameNum);
pre = cur;
nRenderFrameNum = 0;
}
}
} else { // now Tunneled and non-Tunneled are same
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
pFrame = mpp_list_first_entry(&pAudioRenderDataType->sInEmptyFrame, AUDIO_RENDER_IN_FRAME, sList);
memcpy(&pFrame->sFrameInfo,pBuffer->pBuffer,sizeof(struct aic_audio_frame));
mpp_list_del(&pFrame->sList);
mpp_list_add_tail(&pFrame->sList, &pAudioRenderDataType->sInReadyFrame);
if (pAudioRenderDataType->nWaitReayFrameFlag) {
sMsg.message_id = OMX_CommandNops;
sMsg.data_size = 0;
aic_msg_put(&pAudioRenderDataType->sMsgQue, &sMsg);
pAudioRenderDataType->nWaitReayFrameFlag = 0;
}
pAudioRenderDataType->nReceiveFrameNum++;
logd("nReceiveFrameNum:%"PRId32"\n",pAudioRenderDataType->nReceiveFrameNum);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
return eError;
}
static OMX_ERRORTYPE OMX_AudioRenderSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
pAudioRenderDataType->pCallbacks = pCallbacks;
pAudioRenderDataType->pAppData = pAppData;
return eError;
}
OMX_ERRORTYPE OMX_AudioRenderComponentDeInit(
OMX_IN OMX_HANDLETYPE hComponent) {
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_COMPONENTTYPE *pComp;
AUDIO_RENDER_DATA_TYPE *pAudioRenderDataType;
// AUDIO_RENDER_IN_FRAME *pFrameNode = NULL,*pFrameNode1 = NULL;
pComp = (OMX_COMPONENTTYPE *)hComponent;
struct aic_message sMsg;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)pComp->pComponentPrivate;
aic_pthread_mutex_lock(&pAudioRenderDataType->stateLock);
if (pAudioRenderDataType->state != OMX_StateLoaded) {
loge("compoent is in %d,but not in OMX_StateLoaded(1),can ont FreeHandle.\n",pAudioRenderDataType->state);
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
sMsg.message_id = OMX_CommandStop;
sMsg.data_size = 0;
aic_msg_put(&pAudioRenderDataType->sMsgQue, &sMsg);
pthread_join(pAudioRenderDataType->threadId, (void*)&eError);
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
if (pAudioRenderDataType->pInFrameNodeHead) {
mpp_free(pAudioRenderDataType->pInFrameNodeHead);
pAudioRenderDataType->pInFrameNodeHead = NULL;
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
pthread_mutex_destroy(&pAudioRenderDataType->sInFrameLock);
pthread_mutex_destroy(&pAudioRenderDataType->stateLock);
aic_msg_destroy(&pAudioRenderDataType->sMsgQue);
mpp_free(pAudioRenderDataType);
pAudioRenderDataType = NULL;
logi("OMX_AudioRenderComponentDeInit\n");
return eError;
}
static int audio_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 = 32*1024;
attr->schedparam.sched_priority = 22;
return 0;
}
OMX_ERRORTYPE OMX_AudioRenderComponentInit(
OMX_IN OMX_HANDLETYPE hComponent)
{
OMX_COMPONENTTYPE *pComp;
AUDIO_RENDER_DATA_TYPE *pAudioRenderDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_U32 err;
OMX_U32 i;
AUDIO_RENDER_IN_FRAME *pFrameNode = NULL;
AUDIO_RENDER_IN_FRAME *pFrameNodeHead = NULL;
OMX_S8 nMsgCreateOk = 0;
OMX_S8 nInFrameLockInitOk = 0;
OMX_S8 nSateLockInitOk = 0;
pthread_attr_t attr;
audio_thread_attr_init(&attr);
logi("OMX_AudioRenderComponentInit....\n");
pComp = (OMX_COMPONENTTYPE *)hComponent;
pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE *)mpp_alloc(sizeof(AUDIO_RENDER_DATA_TYPE));
if (NULL == pAudioRenderDataType) {
loge("mpp_alloc(sizeof(AUDIO_RENDER_DATA_TYPE) fail!");
return OMX_ErrorInsufficientResources;
}
memset(pAudioRenderDataType, 0x0, sizeof(AUDIO_RENDER_DATA_TYPE));
pComp->pComponentPrivate = (void*) pAudioRenderDataType;
pAudioRenderDataType->nFrameFisrtShowFlag = OMX_TRUE;
pAudioRenderDataType->state = OMX_StateLoaded;
pAudioRenderDataType->hSelf = pComp;
pComp->SetCallbacks = OMX_AudioRenderSetCallbacks;
pComp->SendCommand = OMX_AudioRenderSendCommand;
pComp->GetState = OMX_AudioRenderGetState;
pComp->GetParameter = OMX_AudioRenderGetParameter;
pComp->SetParameter = OMX_AudioRenderSetParameter;
pComp->GetConfig = OMX_AudioRenderGetConfig;
pComp->SetConfig = OMX_AudioRenderSetConfig;
pComp->ComponentTunnelRequest = OMX_AudioRenderComponentTunnelRequest;
pComp->ComponentDeInit = OMX_AudioRenderComponentDeInit;
pComp->FillThisBuffer = OMX_AudioRenderFillThisBuffer;
pComp->EmptyThisBuffer = OMX_AudioRenderEmptyThisBuffer;
pAudioRenderDataType->sPortParam.nPorts = 2;
pAudioRenderDataType->sPortParam.nStartPortNumber = 0x0;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].nPortIndex = AUDIO_RENDER_PORT_IN_AUDIO_INDEX;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].bPopulated = OMX_TRUE;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].bEnabled = OMX_TRUE;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].eDomain = OMX_PortDomainAudio;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].eDir = OMX_DirInput;
pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].nPortIndex = AUDIO_RENDER_PORT_IN_AUDIO_INDEX;
pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].eBufferSupplier = OMX_BufferSupplyOutput;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].nPortIndex = AUDIO_RENDER_PORT_IN_CLOCK_INDEX;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].bPopulated = OMX_TRUE;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].bEnabled = OMX_TRUE;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].eDomain = OMX_PortDomainOther;
pAudioRenderDataType->sInPortDef[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].eDir = OMX_DirInput;
pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].nPortIndex = AUDIO_RENDER_PORT_IN_CLOCK_INDEX;
pAudioRenderDataType->sInBufSupplier[AUDIO_RENDER_PORT_IN_CLOCK_INDEX].eBufferSupplier = OMX_BufferSupplyOutput;
pAudioRenderDataType->nInFrameNodeNum = 0;
mpp_list_init(&pAudioRenderDataType->sInEmptyFrame);
mpp_list_init(&pAudioRenderDataType->sInReadyFrame);
mpp_list_init(&pAudioRenderDataType->sInProcessedFrmae);
if (pthread_mutex_init(&pAudioRenderDataType->sInFrameLock, NULL)) {
loge("pthread_mutex_init fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT;
}
nInFrameLockInitOk = 1;
pFrameNodeHead = (AUDIO_RENDER_IN_FRAME*)mpp_alloc(sizeof(AUDIO_RENDER_IN_FRAME) * AUDIO_RENDER_FRAME_ONE_TIME_CREATE_NUM);
if (pFrameNodeHead == NULL) {
loge("mpp_alloc empty VDEC_IN_PACKET node fail\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT;
}
memset(pFrameNodeHead,0x00,sizeof(AUDIO_RENDER_IN_FRAME) * AUDIO_RENDER_FRAME_ONE_TIME_CREATE_NUM);
pAudioRenderDataType->nInFrameNodeNum = AUDIO_RENDER_FRAME_ONE_TIME_CREATE_NUM;
pFrameNode = pFrameNodeHead;
for(i = 0; i < AUDIO_RENDER_FRAME_ONE_TIME_CREATE_NUM; i++) {
mpp_list_init(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInEmptyFrame);
pFrameNode++;
}
pAudioRenderDataType->pInFrameNodeHead = pFrameNodeHead;
if (aic_msg_create(&pAudioRenderDataType->sMsgQue)<0) {
loge("aic_msg_create fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT;
}
pAudioRenderDataType->eClockState = OMX_TIME_ClockStateStopped;
if (pthread_mutex_init(&pAudioRenderDataType->stateLock, NULL)) {
loge("pthread_mutex_init fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT;
}
nSateLockInitOk = 1;
// Create the component thread
err = pthread_create(&pAudioRenderDataType->threadId, &attr, OMX_AudioRenderComponentThread, pAudioRenderDataType);
if (err) {
loge("pthread_create fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT;
}
logi("OMX_AudioRenderComponentInit OK\n");
#ifdef AUDIO_RENDRE_DUMP_ENABLE
pAudioRenderDataType->pDumpAudioFilePath = (OMX_S8*)AUDIO_RENDRE_DUMP_FILEPATH;
pAudioRenderDataType->nDumpAudioFd = 0;
#endif
return eError;
_EXIT:
if (nInFrameLockInitOk) {
pthread_mutex_destroy(&pAudioRenderDataType->sInFrameLock);
}
if (nSateLockInitOk) {
pthread_mutex_destroy(&pAudioRenderDataType->stateLock);
}
if (nMsgCreateOk) {
aic_msg_destroy(&pAudioRenderDataType->sMsgQue);
}
if (pAudioRenderDataType->pInFrameNodeHead) {
mpp_free(pAudioRenderDataType->pInFrameNodeHead);
pAudioRenderDataType->pInFrameNodeHead = NULL;
}
if (pAudioRenderDataType) {
mpp_free(pAudioRenderDataType);
pAudioRenderDataType = NULL;
}
return eError;
}
static int OMX_AudioRenderGiveBackAllFrames(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
int ret = 0;
// 1 move ready node to using list
logi("Before OMX_AudioRenderComponentThread exit,move node in sInReadyFrame to sInProcessedFrmae\n");
if (!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInReadyFrame,pAudioRenderDataType->sInFrameLock)) {
logi("sInReadyFrame is not empty\n");
AUDIO_RENDER_IN_FRAME *pFrameNode,*pFrameNode1;
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pAudioRenderDataType->sInReadyFrame, sList) {
pAudioRenderDataType->nLeftReadyFrameWhenCompoentExitNum++;
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInProcessedFrmae);
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
}
// 2 give back frames in processed list to adec or app
logi("Before OMX_AudioRenderComponentThread exit,give all frames back to Adec\n");
if (!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInProcessedFrmae,pAudioRenderDataType->sInFrameLock)) {
logi("sInProcessedFrmae is not empty\n");
AUDIO_RENDER_IN_FRAME *pFrameNode = NULL;
OMX_BUFFERHEADERTYPE sBuffHead;
while(!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInProcessedFrmae,pAudioRenderDataType->sInFrameLock)) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pAudioRenderDataType->sInProcessedFrmae, AUDIO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
ret =-1;
if (pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].nTunneledFlag) {
sBuffHead.nInputPortIndex = AUDIO_RENDER_PORT_IN_AUDIO_INDEX;
sBuffHead.nOutputPortIndex = pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].nTunnelPortIndex;
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
ret = OMX_FillThisBuffer(pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX].pTunneledComp,&sBuffHead);
} else {
if (pAudioRenderDataType->pCallbacks != NULL && pAudioRenderDataType->pCallbacks->EmptyBufferDone!= NULL) {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
ret = pAudioRenderDataType->pCallbacks->EmptyBufferDone(pAudioRenderDataType->hSelf,pAudioRenderDataType->pAppData,&sBuffHead);
}
}
if (ret == 0) {
logd("give back frame to vdec ok");
pAudioRenderDataType->nGiveBackFrameOkNum++;
} else {
loge("give back frame to vdec fail\n");
pAudioRenderDataType->nGiveBackFrameFailNum++;
usleep(5*1000);
continue;// must give back ok ,so retry to give back
}
logi("nGiveBackFrameOkNum:%"PRId32",nGiveBackFrameFailNum:%"PRId32"\n"
,pAudioRenderDataType->nGiveBackFrameOkNum
,pAudioRenderDataType->nGiveBackFrameFailNum);
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInEmptyFrame);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
}
}
return 0;
}
static void OMX_AudioRenderEventNotify(
AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType,
OMX_EVENTTYPE event,
OMX_U32 nData1,
OMX_U32 nData2,
OMX_PTR pEventData)
{
if (pAudioRenderDataType && pAudioRenderDataType->pCallbacks && pAudioRenderDataType->pCallbacks->EventHandler) {
pAudioRenderDataType->pCallbacks->EventHandler(
pAudioRenderDataType->hSelf,
pAudioRenderDataType->pAppData,event,
nData1, nData2, pEventData);
}
}
static void OMX_AudioRenderStateChangeToInvalid(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
pAudioRenderDataType->state = OMX_StateInvalid;
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorInvalidState,0,NULL);
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAudioRenderDataType->state,NULL);
}
static void OMX_AudioRenderStateChangeToLoaded(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
if (pAudioRenderDataType->state == OMX_StateIdle) {
OMX_AudioRenderGiveBackAllFrames(pAudioRenderDataType);
} else if (pAudioRenderDataType->state == OMX_StateExecuting) {
} else if (pAudioRenderDataType->state == OMX_StatePause) {
} else {
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAudioRenderDataType->state = OMX_StateLoaded;
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
, pAudioRenderDataType->state,NULL);
}
static void OMXAudioRenderStateChangeToIdle(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
int ret = 0;
if (pAudioRenderDataType->state == OMX_StateLoaded) {
//create Audio_handle
if (!pAudioRenderDataType->render) {
ret = aic_audio_render_create(&pAudioRenderDataType->render);
}
if (ret != 0) {
loge("aic_create_Audio_render fail\n");
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
} else if (pAudioRenderDataType->state == OMX_StatePause) {
aic_audio_render_pause(pAudioRenderDataType->render);
} else if (pAudioRenderDataType->state == OMX_StateExecuting) {
} else {
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAudioRenderDataType->state = OMX_StateIdle;
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
, pAudioRenderDataType->state,NULL);
}
static void OMX_AudioRenderStateChangeToExcuting(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
if (pAudioRenderDataType->state == OMX_StateLoaded) {
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
} else if (pAudioRenderDataType->state == OMX_StateIdle) {
} else if (pAudioRenderDataType->state == OMX_StatePause) {
aic_audio_render_pause(pAudioRenderDataType->render);
} else {
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAudioRenderDataType->state = OMX_StateExecuting;
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
, pAudioRenderDataType->state,NULL);
}
static void OMX_AudioRenderStateChangeToPause(AUDIO_RENDER_DATA_TYPE * pAudioRenderDataType)
{
if (pAudioRenderDataType->state == OMX_StateLoaded) {
} else if (pAudioRenderDataType->state == OMX_StateIdle) {
} else if (pAudioRenderDataType->state == OMX_StateExecuting) {
aic_audio_render_pause(pAudioRenderDataType->render);
} else {
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
, pAudioRenderDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAudioRenderDataType->state = OMX_StatePause;
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
, pAudioRenderDataType->state,NULL);
}
// need to define in OMX_Core_Ext1.h
#define CORRECT_REF_CLOCK_TIME (1*1000*1000)
//#define CORRECT_REF_CLOCK_TIME (30*1000*1000)
static int OMX_ProcessAudioSync(AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType,struct aic_audio_frame *pFrameInfo)
{
OMX_TICKS sDiffTime;
OMX_TICKS sRealAudioTime;
OMX_TICKS sAudioCacheDuration;
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
OMX_S32 data1,data2;
OMX_PORT_TUNNELEDINFO *pTunneldClock = &pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_CLOCK_INDEX];
sAudioCacheDuration = pAudioRenderDataType->render->get_cached_time(pAudioRenderDataType->render);
sRealAudioTime = pFrameInfo->pts - sAudioCacheDuration;
if (pTunneldClock->nTunneledFlag) {
OMX_GetConfig(pTunneldClock->pTunneledComp, OMX_IndexConfigTimeCurrentMediaTime,&sTimeStamp);
sDiffTime = sTimeStamp.nTimestamp - pAudioRenderDataType->sPreCorrectMediaTime;
// correct ref clock per 10s
if (sDiffTime > CORRECT_REF_CLOCK_TIME) { //correct ref time
pAudioRenderDataType->sPreCorrectMediaTime = sTimeStamp.nTimestamp;
sTimeStamp.nTimestamp = sRealAudioTime;
OMX_SetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeCurrentAudioReference,&sTimeStamp);
//loge("OMX_IndexConfigTimeCurrentAudioReference:%ld,sDiffTime:%ld\n",sTimeStamp.nTimestamp,sDiffTime);
}
}
data1 = (sRealAudioTime >> 32) & 0x00000000ffffffff;
data2 = sRealAudioTime & 0x00000000ffffffff;
OMX_AudioRenderEventNotify(pAudioRenderDataType,OMX_EventAudioRenderPts,data1,data2,NULL);
return 0;
}
#ifdef AUDIO_RENDRE_DUMP_ENABLE
static int OMX_AudioRenderDump(AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType,char * data,int len,int end)
{
if (pAudioRenderDataType->nDumpAudioFd == 0) {
s32 fd;
fd = open((char *)pAudioRenderDataType->pDumpAudioFilePath, O_RDWR|O_CREAT);
if (fd < 0) {
loge("open %s failed!!!!!\n",pAudioRenderDataType->pDumpAudioFilePath);
return -1;
} else {
pAudioRenderDataType->nDumpAudioFd = fd;
}
}
write(pAudioRenderDataType->nDumpAudioFd,data,len);
if (end == 1) {
close(pAudioRenderDataType->nDumpAudioFd);
pAudioRenderDataType->nDumpAudioFd = 0;
}
return 0;
}
#endif
static int OMX_AudioGiveBackFrames(AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType)
{
int ret = 0;
AUDIO_RENDER_IN_FRAME *pFrameNode;
OMX_PORT_TUNNELEDINFO *pTunneldAudio;
pTunneldAudio = &pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_AUDIO_INDEX];
if (!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInProcessedFrmae,pAudioRenderDataType->sInFrameLock)) {
OMX_BUFFERHEADERTYPE sBuffHead;
while(!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInProcessedFrmae,pAudioRenderDataType->sInFrameLock)) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pAudioRenderDataType->sInProcessedFrmae, AUDIO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
ret = -1;
if (pTunneldAudio->nTunneledFlag) {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
sBuffHead.nInputPortIndex = AUDIO_RENDER_PORT_IN_AUDIO_INDEX;
sBuffHead.nOutputPortIndex = pTunneldAudio->nTunnelPortIndex;
ret = OMX_FillThisBuffer(pTunneldAudio->pTunneledComp,&sBuffHead);
} else {
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
if (pAudioRenderDataType->pCallbacks->EmptyBufferDone) {
ret = pAudioRenderDataType->pCallbacks->EmptyBufferDone(pAudioRenderDataType->hSelf,
pAudioRenderDataType->pAppData,&sBuffHead);
}
}
if (ret == 0) { // how to do
//loge("give back frame to adec ok");
pAudioRenderDataType->nGiveBackFrameOkNum++;
} else {
logw("give back frame to adec fail\n");
pAudioRenderDataType->nGiveBackFrameFailNum++;
}
logi("nGiveBackFrameOkNum:%"PRId32",nGiveBackFrameFailNum:%"PRId32"\n"
,pAudioRenderDataType->nGiveBackFrameOkNum
,pAudioRenderDataType->nGiveBackFrameFailNum);
if (ret == 0) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInEmptyFrame);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
} else { // how to do ,do nothing or move to empty list,now move to empty list
usleep(5*1000);
continue;
}
}
} else {
//loge("no processed frame!!!!\n");
}
return ret;
}
static void* OMX_AudioRenderComponentThread(void* pThreadData)
{
struct aic_message message;
OMX_S32 nCmd; //OMX_COMMANDTYPE
OMX_S32 nCmdData; //OMX_STATETYPE
AUDIO_RENDER_DATA_TYPE* pAudioRenderDataType = (AUDIO_RENDER_DATA_TYPE*)pThreadData;
OMX_S32 ret;
//OMX_S32 i;
AUDIO_RENDER_IN_FRAME *pFrameNode;
OMX_S32 bNotifyFrameEnd = 0;
//prctl(PR_SET_NAME,(u32)"AudioRender");
OMX_PORT_TUNNELEDINFO *pTunneldClock;
//u32 nPktSize = 0;
pTunneldClock = &pAudioRenderDataType->sInPortTunneledInfo[AUDIO_RENDER_PORT_IN_CLOCK_INDEX];
pAudioRenderDataType->nWaitReayFrameFlag = 1;
OMX_S32 nEmptyNum = 0;
while(1) {
_AIC_MSG_GET_:
if (aic_msg_get(&pAudioRenderDataType->sMsgQue, &message) == 0) {
nCmd = message.message_id;
nCmdData = message.param;
logi("nCmd:%"PRId32", nCmdData:%"PRId32"\n",nCmd,nCmdData);
if (OMX_CommandStateSet == nCmd) {
aic_pthread_mutex_lock(&pAudioRenderDataType->stateLock);
if (pAudioRenderDataType->state == (OMX_STATETYPE)(nCmdData)) {
logi("OMX_ErrorSameState\n");
OMX_AudioRenderEventNotify(pAudioRenderDataType
,OMX_EventError
,OMX_ErrorSameState,0,NULL);
aic_pthread_mutex_unlock(&pAudioRenderDataType->stateLock);
continue;
}
switch(nCmdData) {
case OMX_StateInvalid:
OMX_AudioRenderStateChangeToInvalid(pAudioRenderDataType);
break;
case OMX_StateLoaded:
OMX_AudioRenderStateChangeToLoaded(pAudioRenderDataType);
break;
case OMX_StateIdle:
OMXAudioRenderStateChangeToIdle(pAudioRenderDataType);
break;
case OMX_StateExecuting:
OMX_AudioRenderStateChangeToExcuting(pAudioRenderDataType);
break;
case OMX_StatePause:
OMX_AudioRenderStateChangeToPause(pAudioRenderDataType);
break;
default:
break;
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->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_AudioRenderComponentThread ready to exit!!!\n");
goto _EXIT;
} else {
}
}
if (pAudioRenderDataType->state != OMX_StateExecuting) {
//usleep(1000);
aic_msg_wait_new_msg(&pAudioRenderDataType->sMsgQue, 0);
continue;
}
if (pAudioRenderDataType->nFlags & AUDIO_RENDER_INPORT_SEND_ALL_FRAME_FLAG) {
if (!bNotifyFrameEnd) {
OMX_AudioRenderEventNotify(pAudioRenderDataType,OMX_EventBufferFlag,0,0,NULL);
bNotifyFrameEnd = 1;
}
//usleep(1000);
aic_msg_wait_new_msg(&pAudioRenderDataType->sMsgQue, 0);
continue;
}
bNotifyFrameEnd = 0;
OMX_AudioGiveBackFrames(pAudioRenderDataType);
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
if (mpp_list_empty(&pAudioRenderDataType->sInReadyFrame)) {
struct timespec before = {0},after = {0};
long diff;
pAudioRenderDataType->nWaitReayFrameFlag = 1;
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
clock_gettime(CLOCK_REALTIME,&before);
aic_msg_wait_new_msg(&pAudioRenderDataType->sMsgQue, AUDIO_RENDER_WAIT_FRAME_INTERVAL);
clock_gettime(CLOCK_REALTIME,&after);
diff = (after.tv_sec - before.tv_sec)*1000*1000 + (after.tv_nsec - before.tv_nsec)/1000;
if (diff > AUDIO_RENDER_WAIT_FRAME_MAX_TIME) {
printf("[%s:%d]:%ld\n",__FUNCTION__,__LINE__,diff);
pAudioRenderDataType->nFlags |= AUDIO_RENDER_INPORT_SEND_ALL_FRAME_FLAG;
}
nEmptyNum++;
goto _AIC_MSG_GET_;
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
while(!OMX_AudioRenderListEmpty(&pAudioRenderDataType->sInReadyFrame,pAudioRenderDataType->sInFrameLock)) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
pFrameNode = mpp_list_first_entry(&pAudioRenderDataType->sInReadyFrame, AUDIO_RENDER_IN_FRAME, sList);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
if (pAudioRenderDataType->nFrameFisrtShowFlag) {
struct aic_audio_render_attr ao_attr;
if (!pAudioRenderDataType->nAudioRenderInitFlag) {
pAudioRenderDataType->render->init(pAudioRenderDataType->render,pAudioRenderDataType->nDevId);
pAudioRenderDataType->nAudioRenderInitFlag = 1;
}
ao_attr.bits_per_sample = pFrameNode->sFrameInfo.bits_per_sample;
ao_attr.channels = pFrameNode->sFrameInfo.channels;
ao_attr.sample_rate = pFrameNode->sFrameInfo.sample_rate;
ao_attr.smples_per_frame = 32*1024;/*need to define a member of struct*/
pAudioRenderDataType->sAudioRenderArrt = ao_attr;
pAudioRenderDataType->render->set_attr(pAudioRenderDataType->render,&ao_attr);
if (pAudioRenderDataType->nVolumeChange) {
if (pAudioRenderDataType->render->set_volume(pAudioRenderDataType->render,pAudioRenderDataType->nVolume) == 0) {
pAudioRenderDataType->nVolumeChange = 0;
} else {
loge("set_volume error\n");
}
} else {
pAudioRenderDataType->nVolume = pAudioRenderDataType->render->get_volume(pAudioRenderDataType->render);
logd("nVolume :%"PRId32"\n",pAudioRenderDataType->nVolume);
}
if (pTunneldClock->nTunneledFlag) { // set clock start time
OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp;
sTimeStamp.nPortIndex = pTunneldClock->nTunnelPortIndex;
sTimeStamp.nTimestamp = pFrameNode->sFrameInfo.pts;
pAudioRenderDataType->sPreFramePts = pFrameNode->sFrameInfo.pts;
pAudioRenderDataType->sFirstFramePts = pFrameNode->sFrameInfo.pts;
OMX_SetConfig(pTunneldClock->pTunneledComp,OMX_IndexConfigTimeClientStartTime, &sTimeStamp);
pAudioRenderDataType->sPreCorrectMediaTime = pFrameNode->sFrameInfo.pts;
// whether need to wait????
if (pAudioRenderDataType->eClockState != OMX_TIME_ClockStateRunning) {
aic_msg_wait_new_msg(&pAudioRenderDataType->sMsgQue, 10*1000);
goto _AIC_MSG_GET_;
}
printf("[%s:%d]video start time arrive\n",__FUNCTION__,__LINE__);
}
printf("[%s:%d]bits_per_sample:%d,channels:%d,sample_rate:%d,pts:"FMT_d64"\n"
,__FUNCTION__,__LINE__
,pFrameNode->sFrameInfo.bits_per_sample
,pFrameNode->sFrameInfo.channels
,pFrameNode->sFrameInfo.sample_rate
,pFrameNode->sFrameInfo.pts);
ret = 0;
if (pFrameNode->sFrameInfo.size > 0) {// frame size maybe 0.
ret = pAudioRenderDataType->render->rend(pAudioRenderDataType->render,pFrameNode->sFrameInfo.data,pFrameNode->sFrameInfo.size);
}
if (ret == 0) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInProcessedFrmae);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
pAudioRenderDataType->nShowFrameOkNum++;
pAudioRenderDataType->nFrameFisrtShowFlag = OMX_FALSE;
OMX_AudioRenderEventNotify(pAudioRenderDataType,OMX_EventAudioRenderFirstFrame,0,0,NULL);
#ifdef AUDIO_RENDRE_DUMP_ENABLE
{
int end = 0;
if (pFrameNode->sFrameInfo.flag & FRAME_FLAG_EOS) {
end = 1;
printf("[%s:%d]audio stream end \n",__FUNCTION__,__LINE__);
}
OMX_AudioRenderDump(pAudioRenderDataType,pFrameNode->sFrameInfo.data,pFrameNode->sFrameInfo.size,end);
}
#endif
} else {// how to do ,video can deal with same success,drop this frame,but audio can not drop it.
loge("first frame error,there is something wrong!!!!\n");
//mpp_list_del(&pFrameNode->sList);
//mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInProcessedFrmae);
pAudioRenderDataType->nShowFrameFailNum++;
}
logd("nReceiveFrameNum:%"PRId32",nShowFrameOkNum:%"PRId32",nShowFrameFailNum:%"PRId32"\n"
,pAudioRenderDataType->nReceiveFrameNum
,pAudioRenderDataType->nShowFrameOkNum
,pAudioRenderDataType->nShowFrameFailNum);
} else {// not first frame
if (pAudioRenderDataType->nVolumeChange) {
if (pAudioRenderDataType->render->set_volume(pAudioRenderDataType->render,pAudioRenderDataType->nVolume) == 0) {
pAudioRenderDataType->nVolumeChange = 0;
} else {
loge("set_volume error\n");
}
}
OMX_ProcessAudioSync(pAudioRenderDataType,&pFrameNode->sFrameInfo);
ret = 0;
if (pFrameNode->sFrameInfo.size > 0) {// last frame size maybe 0.
ret = pAudioRenderDataType->render->rend(pAudioRenderDataType->render,pFrameNode->sFrameInfo.data,pFrameNode->sFrameInfo.size);
//nPktSize = pFrameNode->sFrameInfo.size;
}
if (ret == 0) {
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAudioRenderDataType->sInProcessedFrmae);
aic_pthread_mutex_unlock(&pAudioRenderDataType->sInFrameLock);
pAudioRenderDataType->nShowFrameOkNum++;
//loge("nShowFrameOkNum:%d\n",pAudioRenderDataType->nShowFrameOkNum);
#ifdef AUDIO_RENDRE_DUMP_ENABLE
{
int end = 0;
if (pFrameNode->sFrameInfo.flag & FRAME_FLAG_EOS) {
end = 1;
printf("[%s:%d]audio stream end \n",__FUNCTION__,__LINE__);
}
OMX_AudioRenderDump(pAudioRenderDataType,pFrameNode->sFrameInfo.data,pFrameNode->sFrameInfo.size,end);
}
#endif
if (pFrameNode->sFrameInfo.flag & FRAME_FLAG_EOS) {
pAudioRenderDataType->nFlags |= AUDIO_RENDER_INPORT_SEND_ALL_FRAME_FLAG;
//pAudioRenderDataType->nFrameEndFlag = OMX_TRUE;
printf("[%s:%d]receive nFrameEndFlag\n",__FUNCTION__,__LINE__);
}
{
static int nRenderFrameNum = 0;
static struct timespec pre = {0},cur = {0};
long diff;
int nCnt = 0;
aic_pthread_mutex_lock(&pAudioRenderDataType->sInFrameLock);
mpp_list_for_each_entry(pFrameNode, &pAudioRenderDataType->sInReadyFrame, sList) {
nCnt++;
}
aic_pthread_mutex_unlock(&pAudioRenderDataType->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:%u\n",__FUNCTION__,__LINE__,diff,nRenderFrameNum,nCnt,nPktSize);
pre = cur;
nRenderFrameNum = 0;
}
}
} else {
loge("frame erro!!!!\n");
pAudioRenderDataType->nShowFrameFailNum++;
break;
}
logd("nReceiveFrameNum:%"PRId32",nShowFrameOkNum:%"PRId32",nShowFrameFailNum:%"PRId32"\n"
,pAudioRenderDataType->nReceiveFrameNum
,pAudioRenderDataType->nShowFrameOkNum
,pAudioRenderDataType->nShowFrameFailNum);
}
}
}
_EXIT:
if (pAudioRenderDataType->render) {
aic_audio_render_destroy(pAudioRenderDataType->render);
pAudioRenderDataType->render = NULL;
}
printf("[%s:%d]nReceiveFrameNum:%"PRId32","\
"nLeftReadyFrameWhenCompoentExitNum:%"PRId32","\
"nShowFrameOkNum:%"PRId32","\
"nShowFrameFailNum:%"PRId32","\
"nGiveBackFrameOkNum:%"PRId32","\
"nGiveBackFrameFailNum:%"PRId32","\
"nEmptyNum:%"PRId32"\n"
,__FUNCTION__,__LINE__
,pAudioRenderDataType->nReceiveFrameNum
,pAudioRenderDataType->nLeftReadyFrameWhenCompoentExitNum
,pAudioRenderDataType->nShowFrameOkNum
,pAudioRenderDataType->nShowFrameFailNum
,pAudioRenderDataType->nGiveBackFrameOkNum
,pAudioRenderDataType->nGiveBackFrameFailNum
,nEmptyNum);
printf("OMX_AudioRenderComponentThread EXIT\n");
return (void*)OMX_ErrorNone;
}