Files
luban-lite/packages/artinchip/mpp/middle_media/openmax/component/OMX_AdecComponent.c
刘可亮 564e22b32f v0.7.5
2023-08-28 09:48:01 +08:00

1412 lines
46 KiB
C
Executable File

/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: OMX_AdecComponent
*/
#include "OMX_AdecComponent.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_AdecListEmpty(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_AdecSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData);
static OMX_ERRORTYPE OMX_AdecGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_AdecSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentParameterStructure);
static OMX_ERRORTYPE OMX_AdecGetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_AdecSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure);
static OMX_ERRORTYPE OMX_AdecGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState);
static OMX_ERRORTYPE OMX_AdecComponentTunnelRequest(
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_AdecEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_AdecFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
static OMX_ERRORTYPE OMX_AdecSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData);
static OMX_ERRORTYPE OMX_AdecSendCommand(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_COMMANDTYPE Cmd,
OMX_IN OMX_U32 nParam1,
OMX_IN OMX_PTR pCmdData)
{
ADEC_DATA_TYPE *pAdecDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
struct aic_message sMsg;
pAdecDataType = (ADEC_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(&pAdecDataType->sMsgQue, &sMsg);
return eError;
}
static void* OMX_AdecComponentThread(void* pThreadData);
static OMX_ERRORTYPE OMX_AdecGetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR pComponentParameterStructure)
{
ADEC_DATA_TYPE *pAdecDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_U32 tmp1,tmp2;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch (nParamIndex){
case OMX_IndexParamPortDefinition:{
OMX_PARAM_PORTDEFINITIONTYPE *port = (OMX_PARAM_PORTDEFINITIONTYPE*)pComponentParameterStructure;
if(port->nPortIndex == ADEC_PORT_IN_INDEX){
memcpy(port,&pAdecDataType->sInPortDef,sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
}else if(port->nPortIndex == ADEC_PORT_OUT_INDEX){
memcpy(port,&pAdecDataType->sOutPortDef,sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
}else{
eError = OMX_ErrorBadParameter;
}
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 = pAdecDataType->sInBufSupplier.eBufferSupplier;
}else if(sBufferSupplier->nPortIndex == 1){
sBufferSupplier->eBufferSupplier = pAdecDataType->sOutBufSupplier.eBufferSupplier;
}else{
loge("error nPortIndex\n");
eError = OMX_ErrorBadPortIndex;
}
break;
}
default:
eError = OMX_ErrorNotImplemented;
break;
}
return eError;
}
static OMX_S32 OMX_AdecAudioFormatTrans(enum aic_audio_codec_type *eDesType,OMX_AUDIO_CODINGTYPE *eSrcType)
{
OMX_S32 ret = 0;
if( eDesType== NULL || eSrcType == NULL){
loge("bad params!!!!\n");
return -1;
}
if(*eSrcType == OMX_AUDIO_CodingMP3){
*eDesType = MPP_CODEC_AUDIO_DECODER_MP3;
}else{
*eDesType = MPP_CODEC_AUDIO_DECODER_MP3;
loge("unsupport codec!!!!\n");
ret = -1;
}
return ret;
}
static OMX_ERRORTYPE OMX_AdecSetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR pComponentParameterStructure)
{
ADEC_DATA_TYPE *pAdecDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
//OMX_S32 tmp1,tmp2;
OMX_U32 index;
enum aic_audio_codec_type eCodecType;
OMX_PARAM_FRAMEEND *sFrameEnd;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch ((OMX_S32)nParamIndex){
case OMX_IndexParamAudioPortFormat:{
OMX_AUDIO_PARAM_PORTFORMATTYPE *sPortFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)pComponentParameterStructure;
index = sPortFormat->nPortIndex;
if(index == ADEC_PORT_IN_INDEX){
pAdecDataType->sInPortDef.format.audio.eEncoding = sPortFormat->eEncoding;
logw("eEncoding:%d\n",pAdecDataType->sInPortDef.format.audio.eEncoding );
if(OMX_AdecAudioFormatTrans(&eCodecType,&sPortFormat->eEncoding) != 0){
eError = OMX_ErrorUnsupportedSetting;
loge("OMX_ErrorUnsupportedSetting\n");
break;
}
pAdecDataType->eCodeType = eCodecType;
logw("eCodeType:%d\n",pAdecDataType->eCodeType);
/*need to define extened OMX_Index or decide by inner*/
pAdecDataType->sDecoderConfig.packet_buffer_size = 16*1024;
pAdecDataType->sDecoderConfig.packet_count = 8;
pAdecDataType->sDecoderConfig.frame_count = 16;
}else if(index == ADEC_PORT_OUT_INDEX){
logw("now no need to set out port param\n");
}else{
loge("OMX_ErrorBadParameter\n");
}
break;
}
case OMX_IndexParamPortDefinition:{
OMX_PARAM_PORTDEFINITIONTYPE *port = (OMX_PARAM_PORTDEFINITIONTYPE*)pComponentParameterStructure;
index = port->nPortIndex;
if(index == ADEC_PORT_IN_INDEX){
pAdecDataType->sInPortDef.format.audio.eEncoding = port->format.audio.eEncoding;
logw("eEncoding:%d\n",pAdecDataType->sInPortDef.format.audio.eEncoding );
if(OMX_AdecAudioFormatTrans(&eCodecType,&port->format.audio.eEncoding) != 0){
eError = OMX_ErrorUnsupportedSetting;
loge("OMX_ErrorUnsupportedSetting\n");
break;
}
/*need to convert */
pAdecDataType->eCodeType = eCodecType;
logw("eCompressionFormat:%d\n",pAdecDataType->eCodeType);
/*need to define extened OMX_Index or decide by inner*/
pAdecDataType->sDecoderConfig.packet_buffer_size = 16*1024;
pAdecDataType->sDecoderConfig.packet_count = 8;
pAdecDataType->sDecoderConfig.frame_count = 16;
}else if(index == ADEC_PORT_OUT_INDEX){
logw("now no need to set out port param\n");
}else{
loge("OMX_ErrorBadParameter\n");
eError = OMX_ErrorBadParameter;
}
}
break;
case OMX_IndexParamVideoAvc:
break;
case OMX_IndexParamVideoProfileLevelQuerySupported:
break;
case OMX_IndexParamVideoProfileLevelCurrent:
break;
case OMX_IndexParamVideoMpeg4:
break;
case OMX_IndexVendorStreamFrameEnd:
sFrameEnd = (OMX_PARAM_FRAMEEND*)pComponentParameterStructure;
if(sFrameEnd->bFrameEnd == OMX_TRUE){
pAdecDataType->nStreamEndFlag = OMX_TRUE;
logi("setup nStreamEndFlag\n");
}else{
pAdecDataType->nStreamEndFlag = OMX_FALSE;
pAdecDataType->nDecodeEndFlag = OMX_FALSE;
pAdecDataType->nFrameEndFlag = OMX_FALSE;
logi("cancel nStreamEndFlag\n");
}
break;
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_AdecGetConfig(
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_AdecSetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE nIndex,
OMX_IN OMX_PTR pComponentConfigStructure)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
//ADEC_DATA_TYPE* pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
switch (nIndex){
case OMX_IndexConfigTimePosition:
// 1 clear input buffer
// 2 clear output buffer
//
break;
case OMX_IndexConfigTimeSeekMode:
break;
default:
break;
}
return eError;
}
static OMX_ERRORTYPE OMX_AdecGetState(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_OUT OMX_STATETYPE* pState)
{
ADEC_DATA_TYPE* pAdecDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pAdecDataType->stateLock);
*pState = pAdecDataType->state;
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
return eError;
}
static OMX_ERRORTYPE OMX_AdecComponentTunnelRequest(
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;
ADEC_DATA_TYPE* pAdecDataType;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComp)->pComponentPrivate);
if(pAdecDataType->state != OMX_StateLoaded)
{
loge("Component is not in OMX_StateLoaded,it is in%d,it can not tunnel\n",pAdecDataType->state);
return OMX_ErrorInvalidState;
}
if(nPort == ADEC_PORT_IN_INDEX){
pPort = &pAdecDataType->sInPortDef;
pTunneledInfo = &pAdecDataType->sInPortTunneledInfo;
pBufSupplier = &pAdecDataType->sInBufSupplier;
}else if(nPort == ADEC_PORT_OUT_INDEX){
pPort = &pAdecDataType->sOutPortDef;
pTunneledInfo = &pAdecDataType->sOutPortTunneledInfo;
pBufSupplier = &pAdecDataType->sOutBufSupplier;
}else{
loge("component can not find port :%d\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_AdecEmptyThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
ADEC_DATA_TYPE* pAdecDataType;
ADEC_IN_PACKET *pktNode;
int ret = 0;
struct aic_message sMsg;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
aic_pthread_mutex_lock(&pAdecDataType->stateLock);
if(pAdecDataType->state != OMX_StateExecuting){
loge("component is not in OMX_StateExecuting,it is in [%d]!!!\n",pAdecDataType->state);
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
if(pAdecDataType->sInPortTunneledInfo.nTunneledFlag){
if(pAdecDataType->sInBufSupplier.eBufferSupplier == OMX_BufferSupplyOutput){
if(OMX_AdecListEmpty(&pAdecDataType->sInEmptyPkt,pAdecDataType->sInPktLock)){
if(pAdecDataType->nInPktNodeNum + 1> ADEC_PACKET_NUM_MAX){
loge("empty node has aready increase to max [%d]!!!\n",pAdecDataType->nInPktNodeNum);
eError = OMX_ErrorInsufficientResources;
pAdecDataType->nReceivePacktFailNum++;
return eError;
}else{
int i;
logw("no empty node,need to extend!!!\n");
for(i =0 ; i < ADEC_PACKET_ONE_TIME_CREATE_NUM; i++ ){
ADEC_IN_PACKET *pPktNode = (ADEC_IN_PACKET*)mpp_alloc(sizeof(ADEC_IN_PACKET));
if(NULL == pPktNode){
break;
}
memset(pPktNode,0x00,sizeof(ADEC_IN_PACKET));
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_add_tail(&pPktNode->sList, &pAdecDataType->sInEmptyPkt);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
pAdecDataType->nInPktNodeNum++;
}
if(i == 0){
loge("mpp_alloc empty video node fail\n");
eError = OMX_ErrorInsufficientResources;
pAdecDataType->nReceivePacktFailNum++;
return eError;
}
}
}
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
pktNode = mpp_list_first_entry(&pAdecDataType->sInEmptyPkt, ADEC_IN_PACKET, sList);
pktNode->sBuff.nOutputPortIndex = pBuffer->nOutputPortIndex;
pktNode->sBuff.pBuffer = pBuffer->pBuffer;
pktNode->sBuff.nFilledLen = pBuffer->nFilledLen;
pktNode->sBuff.nTimeStamp = pBuffer->nTimeStamp;
pktNode->sBuff.nFlags = pBuffer->nFlags;
if(pktNode->sBuff.nFlags & PACKET_FLAG_EOS){
pAdecDataType->nFlags |= ADEC_INPORT_STREAM_END_FLAG;
//pAdecDataType->nStreamEndFlag = OMX_TRUE;
logw("nStreamEndFlag");
}
mpp_list_del(&pktNode->sList);
mpp_list_add_tail(&pktNode->sList, &pAdecDataType->sInReadyPkt);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
sMsg.message_id = OMX_CommandNops;
sMsg.data_size = 0;
aic_msg_put(&pAdecDataType->sMsgQue, &sMsg);
pAdecDataType->nReceivePacktOkNum++;
logi("pAdecDataType->nReceivePacktOkNum:%d\n",pAdecDataType->nReceivePacktOkNum);
}else if(pAdecDataType->sInBufSupplier.eBufferSupplier == OMX_BufferSupplyInput){
eError = OMX_ErrorNotImplemented;
logw("OMX_ErrorNotImplemented\n");
}else{
eError = OMX_ErrorNotImplemented;
logw("OMX_ErrorNotImplemented\n");
}
}else{
struct mpp_packet pkt;
pkt.size = pBuffer->nFilledLen;
ret = aic_audio_decoder_get_packet(pAdecDataType->pDecoder, &pkt, pkt.size);
if(ret != 0){
//loge("get pkt from decoder error ret:%d!!!\n",ret);
if(ret == DEC_NO_EMPTY_PACKET){
pAdecDataType->nReceivePacktFailNum++;
return OMX_ErrorOverflow;
}else{
pAdecDataType->nReceivePacktFailNum++;
return OMX_ErrorInsufficientResources;
}
}else{
//logw("get pkt from decoder ok!!!\n");
}
memcpy(pkt.data,pBuffer->pBuffer,pkt.size);
pkt.flag =pBuffer->nFlags;
pkt.pts = pBuffer->nTimeStamp;
//mpp_decoder_get_packet is ok then mpp_decoder_put_packet is also ok
aic_audio_decoder_put_packet(pAdecDataType->pDecoder, &pkt);
if(pkt.flag & PACKET_FLAG_EOS){
pAdecDataType->nFlags |= ADEC_INPORT_STREAM_END_FLAG;
//pAdecDataType->nStreamEndFlag = OMX_TRUE;
logi("StreamEndFlag!!!\n");
}
pAdecDataType->nReceivePacktOkNum++;
pAdecDataType->nGiveBackPacktOkNum++;
}
return eError;
}
static OMX_ERRORTYPE OMX_AdecFillThisBuffer(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
ADEC_DATA_TYPE* pAdecDataType;
struct aic_audio_frame *pFrame;
ADEC_OUT_FRAME *pFrameNode1 = NULL,*pFrameNode2 = NULL;
OMX_BOOL bMatch = OMX_FALSE;
OMX_S32 ret;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
if(pBuffer->nOutputPortIndex != ADEC_PORT_OUT_INDEX){
loge("port not match\n");
return OMX_ErrorBadParameter;
}
if(!OMX_AdecListEmpty(&pAdecDataType->sOutProcessingFrame,pAdecDataType->sOutFrameLock)){
pFrame = (struct aic_audio_frame *)pBuffer->pBuffer;
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
mpp_list_for_each_entry_safe(pFrameNode1,pFrameNode2,&pAdecDataType->sOutProcessingFrame,sList){
if(pFrameNode1->sFrameInfo.data == pFrame->data){
bMatch = OMX_TRUE;
break;
}
}
if(bMatch){//give frame back to decoder
ret = aic_audio_decoder_put_frame(pAdecDataType->pDecoder, &pFrameNode1->sFrameInfo);
if(ret != 0){// how to do
loge("mpp_decoder_put_frame error!!!!\n");
}
// now, no matter whether is back to decoder ok,move pFrameNode1 to sOutEmptyFrame
pAdecDataType->nSendBackFrameOkNum++;
mpp_list_del(&pFrameNode1->sList);
mpp_list_add_tail(&pFrameNode1->sList, &pAdecDataType->sOutEmptyFrame);
}else{
pAdecDataType->nSendBackFrameErrorNum++;
loge("frame not match!!!\n");
eError = OMX_ErrorBadParameter;
}
logi("pAdecDataType->nSendBackFrameOkNum:%d,pAdecDataType->nSendBackFrameErrorNum:%d\n"
,pAdecDataType->nSendBackFrameOkNum
,pAdecDataType->nSendBackFrameErrorNum);
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
}else{
logw("no frame need to back \n");
eError = OMX_ErrorBadParameter;
}
return eError;
}
static OMX_ERRORTYPE OMX_AdecSetCallbacks(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_CALLBACKTYPE* pCallbacks,
OMX_IN OMX_PTR pAppData)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
ADEC_DATA_TYPE* pAdecDataType;
pAdecDataType = (ADEC_DATA_TYPE *)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate);
pAdecDataType->pCallbacks = pCallbacks;
pAdecDataType->pAppData = pAppData;
return eError;
}
OMX_ERRORTYPE OMX_AdecComponentDeInit(
OMX_IN OMX_HANDLETYPE hComponent)
{
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_COMPONENTTYPE *pComp;
ADEC_DATA_TYPE *pAdecDataType;
ADEC_IN_PACKET *pPktNode = NULL,*pPktNode1 = NULL;
ADEC_OUT_FRAME *pFrameNode = NULL,*pFrameNode1 = NULL;
pComp = (OMX_COMPONENTTYPE *)hComponent;
struct aic_message sMsg;
pAdecDataType = (ADEC_DATA_TYPE *)pComp->pComponentPrivate;
aic_pthread_mutex_lock(&pAdecDataType->stateLock);
if(pAdecDataType->state != OMX_StateLoaded){
loge("compoent is in %d,but not in OMX_StateLoaded(1),can not FreeHandle.\n",pAdecDataType->state);
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
return OMX_ErrorIncorrectStateOperation;
}
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
sMsg.message_id = OMX_CommandStop;
sMsg.data_size = 0;
aic_msg_put(&pAdecDataType->sMsgQue, &sMsg);
pthread_join(pAdecDataType->threadId, (void*)&eError);
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
if(!mpp_list_empty(&pAdecDataType->sInEmptyPkt)){
mpp_list_for_each_entry_safe(pPktNode, pPktNode1, &pAdecDataType->sInEmptyPkt, sList){
mpp_list_del(&pPktNode->sList);
mpp_free(pPktNode);
}
}
if(!mpp_list_empty(&pAdecDataType->sInReadyPkt)){
mpp_list_for_each_entry_safe(pPktNode, pPktNode1, &pAdecDataType->sInReadyPkt, sList){
mpp_list_del(&pPktNode->sList);
mpp_free(pPktNode);
}
}
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
if(!mpp_list_empty(&pAdecDataType->sOutEmptyFrame)){
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pAdecDataType->sOutEmptyFrame, sList){
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
if(!mpp_list_empty(&pAdecDataType->sOutReadyFrame)){
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pAdecDataType->sOutReadyFrame, sList){
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
if(!mpp_list_empty(&pAdecDataType->sOutProcessingFrame)){
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pAdecDataType->sOutProcessingFrame, sList){
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
pthread_mutex_destroy(&pAdecDataType->sInPktLock);
pthread_mutex_destroy(&pAdecDataType->sOutFrameLock);
pthread_mutex_destroy(&pAdecDataType->stateLock);
aic_msg_destroy(&pAdecDataType->sMsgQue);
if (pAdecDataType->pDecoder) {
aic_audio_decoder_destroy(pAdecDataType->pDecoder);
pAdecDataType->pDecoder = NULL;
}
mpp_free(pAdecDataType);
pAdecDataType = NULL;
logi("OMX_VideoRenderComponentDeInit\n");
return eError;
}
OMX_ERRORTYPE OMX_AdecComponentInit(
OMX_IN OMX_HANDLETYPE hComponent)
{
OMX_COMPONENTTYPE *pComp;
ADEC_DATA_TYPE *pAdecDataType;
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMX_U32 err;
OMX_U32 i;
//OMX_U32 cnt;
logi("OMX_AdecComponentInit....\n");
pComp = (OMX_COMPONENTTYPE *)hComponent;
pAdecDataType = (ADEC_DATA_TYPE *)mpp_alloc(sizeof(ADEC_DATA_TYPE));
if (NULL == pAdecDataType) {
loge("mpp_alloc(sizeof(ADEC_DATA_TYPE) fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT1;
}
memset(pAdecDataType, 0x0, sizeof(ADEC_DATA_TYPE));
pComp->pComponentPrivate = (void*) pAdecDataType;
pAdecDataType->state = OMX_StateLoaded;
pAdecDataType->hSelf = pComp;
pComp->SetCallbacks = OMX_AdecSetCallbacks;
pComp->SendCommand = OMX_AdecSendCommand;
pComp->GetState = OMX_AdecGetState;
pComp->GetParameter = OMX_AdecGetParameter;
pComp->SetParameter = OMX_AdecSetParameter;
pComp->GetConfig = OMX_AdecGetConfig;
pComp->SetConfig = OMX_AdecSetConfig;
pComp->ComponentTunnelRequest = OMX_AdecComponentTunnelRequest;
pComp->ComponentDeInit = OMX_AdecComponentDeInit;
pComp->FillThisBuffer = OMX_AdecFillThisBuffer;
pComp->EmptyThisBuffer = OMX_AdecEmptyThisBuffer;
pAdecDataType->sPortParam.nPorts = 2;
pAdecDataType->sPortParam.nStartPortNumber = 0x0;
pAdecDataType->sInPortDef.nPortIndex = ADEC_PORT_IN_INDEX;
pAdecDataType->sInPortDef.bPopulated = OMX_TRUE;
pAdecDataType->sInPortDef.bEnabled = OMX_TRUE;
pAdecDataType->sInPortDef.eDomain = OMX_PortDomainAudio;
pAdecDataType->sInPortDef.eDir = OMX_DirInput;
pAdecDataType->sOutPortDef.nPortIndex = ADEC_PORT_OUT_INDEX;
pAdecDataType->sOutPortDef.bPopulated = OMX_TRUE;
pAdecDataType->sOutPortDef.bEnabled = OMX_TRUE;
pAdecDataType->sOutPortDef.eDomain = OMX_PortDomainAudio;
pAdecDataType->sOutPortDef.eDir = OMX_DirOutput;
pAdecDataType->sInPortTunneledInfo.nPortIndex = ADEC_PORT_IN_INDEX;
pAdecDataType->sInPortTunneledInfo.pSelfComp = hComponent;
pAdecDataType->sOutPortTunneledInfo.nPortIndex = ADEC_PORT_OUT_INDEX;
pAdecDataType->sOutPortTunneledInfo.pSelfComp = hComponent;
//now demux support buffers ,later modify
pAdecDataType->sInBufSupplier.nPortIndex = ADEC_PORT_IN_INDEX;
pAdecDataType->sInBufSupplier.eBufferSupplier = OMX_BufferSupplyOutput;
pAdecDataType->nInPktNodeNum = 0;
mpp_list_init(&pAdecDataType->sInEmptyPkt);
mpp_list_init(&pAdecDataType->sInReadyPkt);
mpp_list_init(&pAdecDataType->sInProcessedPkt);
pthread_mutex_init(&pAdecDataType->sInPktLock, NULL);
for(i =0 ; i < ADEC_PACKET_ONE_TIME_CREATE_NUM; i++ ){
ADEC_IN_PACKET *pPktNode = (ADEC_IN_PACKET*)mpp_alloc(sizeof(ADEC_IN_PACKET));
if(NULL == pPktNode){
break;
}
memset(pPktNode,0x00,sizeof(ADEC_IN_PACKET));
mpp_list_add_tail(&pPktNode->sList, &pAdecDataType->sInEmptyPkt);
pAdecDataType->nInPktNodeNum++;
}
if(pAdecDataType->nInPktNodeNum == 0){
loge("mpp_alloc empty video node fail\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT2;
}
// vdec support out pot buffer
pAdecDataType->sOutBufSupplier.nPortIndex = ADEC_PORT_OUT_INDEX;
pAdecDataType->sOutBufSupplier.eBufferSupplier = OMX_BufferSupplyOutput;
pAdecDataType->nOutFrameNodeNum = 0;
mpp_list_init(&pAdecDataType->sOutEmptyFrame);
mpp_list_init(&pAdecDataType->sOutReadyFrame);
mpp_list_init(&pAdecDataType->sOutProcessingFrame);
pthread_mutex_init(&pAdecDataType->sOutFrameLock, NULL);
for(i =0 ; i < ADEC_FRAME_ONE_TIME_CREATE_NUM; i++ ){
ADEC_OUT_FRAME *pFrameNode = (ADEC_OUT_FRAME*)mpp_alloc(sizeof(ADEC_OUT_FRAME));
if(NULL == pFrameNode){
break;
}
memset(pFrameNode,0x00,sizeof(ADEC_OUT_FRAME));
mpp_list_add_tail(&pFrameNode->sList, &pAdecDataType->sOutEmptyFrame);
pAdecDataType->nOutFrameNodeNum++;
}
if(pAdecDataType->nOutFrameNodeNum == 0){
loge("mpp_alloc empty video node fail\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT3;
}
if(aic_msg_create(&pAdecDataType->sMsgQue)<0)
{
loge("aic_msg_create fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT4;
}
pthread_mutex_init(&pAdecDataType->stateLock, NULL);
// Create the component thread
err = pthread_create(&pAdecDataType->threadId, NULL, OMX_AdecComponentThread, pAdecDataType);
if (err || !pAdecDataType->threadId)
{
loge("pthread_create fail!\n");
eError = OMX_ErrorInsufficientResources;
goto _EXIT5;
}
logi("OMX_AdecComponentInit OK \n");
return eError;
_EXIT5:
aic_msg_destroy(&pAdecDataType->sMsgQue);
pthread_mutex_destroy(&pAdecDataType->stateLock);
_EXIT4:
if(!mpp_list_empty(&pAdecDataType->sInEmptyPkt)){
ADEC_IN_PACKET *pPktNode = NULL,*pPktNode1 = NULL;
mpp_list_for_each_entry_safe(pPktNode, pPktNode1, &pAdecDataType->sInEmptyPkt, sList){
mpp_list_del(&pPktNode->sList);
mpp_free(pPktNode);
}
}
_EXIT3:
if(!mpp_list_empty(&pAdecDataType->sOutEmptyFrame)){
ADEC_OUT_FRAME *pFrameNode = NULL,*pFrameNode1 = NULL;
mpp_list_for_each_entry_safe(pFrameNode, pFrameNode1, &pAdecDataType->sOutEmptyFrame, sList){
mpp_list_del(&pFrameNode->sList);
mpp_free(pFrameNode);
}
}
_EXIT2:
if(pAdecDataType){
mpp_free(pAdecDataType);
pAdecDataType = NULL;
}
_EXIT1:
return eError;
}
/*
static void* OMX_DecodeThread(void *pThreadData)
{
ADEC_DATA_TYPE* pAdecDataType = (ADEC_DATA_TYPE*)pThreadData;
logi("decode_thread start!!!!!\n");
aic_audio_decoder_decode(pAdecDataType->pDecoder);
pAdecDataType->nFlags |= ADEC_DECODER_CONSUME_ALL_INPORT_STREAM_FLAG;
//pAdecDataType->nDecodeEndFlag = 1;
logi("decode_thread exit!!!!!\n");
return NULL;
}
*/
static void OMX_AdecEventNotify(
ADEC_DATA_TYPE * pAdecDataType,
OMX_EVENTTYPE event,
OMX_U32 nData1,
OMX_U32 nData2,
OMX_PTR pEventData)
{
if(pAdecDataType && pAdecDataType->pCallbacks && pAdecDataType->pCallbacks->EventHandler) {
pAdecDataType->pCallbacks->EventHandler(
pAdecDataType->hSelf,
pAdecDataType->pAppData,event,
nData1, nData2, pEventData);
}
}
static void OMX_AdecStateChangeToInvalid(ADEC_DATA_TYPE * pAdecDataType)
{
pAdecDataType->state = OMX_StateInvalid;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorInvalidState,0,NULL);
OMX_AdecEventNotify(pAdecDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAdecDataType->state,NULL);
}
static void OMX_AdecStateChangeLoaded(ADEC_DATA_TYPE * pAdecDataType)
{
int ret;
if(pAdecDataType->state == OMX_StateIdle){
logi("Before OMX_AdecComponentThread exit,move node in sInReadyFrame to sInProcessedFrmae\n");
if(!OMX_AdecListEmpty(&pAdecDataType->sInReadyPkt,pAdecDataType->sInPktLock)){
logi("sInReadyFrame is not empty\n");
ADEC_IN_PACKET *pktNode1,*pktNode2;
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_for_each_entry_safe(pktNode1, pktNode2, &pAdecDataType->sInReadyPkt, sList){
pAdecDataType->nLeftReadyFrameWhenCompoentExitNum++;
mpp_list_del(&pktNode1->sList);
mpp_list_add_tail(&pktNode1->sList, &pAdecDataType->sInProcessedPkt);
}
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
}
/*
1 give back all in port pkts,
pAdecDataType->sInBufSupplier.eBufferSupplier = OMX_BufferSupplyOutput
*/
logi("Before OMX_AdecComponentThread exit,it must give back all in port pkts\n");
if(!OMX_AdecListEmpty(&pAdecDataType->sInProcessedPkt,pAdecDataType->sInPktLock)){
logi("sInProcessedPkt is not empty\n");
//ADEC_IN_PACKET *pktNode1,*pktNode2;
ADEC_IN_PACKET *pktNode1 = NULL;
//struct mpp_packet pkt;
while(!OMX_AdecListEmpty(&pAdecDataType->sInProcessedPkt,pAdecDataType->sInPktLock)){
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
pktNode1 = mpp_list_first_entry(&pAdecDataType->sInProcessedPkt, ADEC_IN_PACKET, sList);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
ret = 0;
if(pAdecDataType->sInPortTunneledInfo.nTunneledFlag){
ret = OMX_FillThisBuffer(pAdecDataType->sInPortTunneledInfo.pTunneledComp,&pktNode1->sBuff);
if(ret != 0){ // how to do ,deal with problem by TunneledComp, do nothing here
logw("OMX_FillThisBuffer error \n");
}
}else{
if(pAdecDataType->pCallbacks != NULL && pAdecDataType->pCallbacks->EmptyBufferDone!= NULL){
ret = pAdecDataType->pCallbacks->EmptyBufferDone(pAdecDataType->hSelf,pAdecDataType->pAppData,&pktNode1->sBuff);
if(ret != 0){// how to do ,deal with problem by app, do nothing here
logw("EmptyBufferDone error \n");
}
}
}
if(ret == 0){
pAdecDataType->nGiveBackPacktOkNum++;
}else{
pAdecDataType->nGiveBackPacktFailNum++;
}
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_del(&pktNode1->sList);
mpp_list_add_tail(&pktNode1->sList, &pAdecDataType->sInEmptyPkt);
logi("pAdecDataType->nGiveBackPacktOkNum:%d,pAdecDataType->nGiveBackPacktFailNum:%d\n"
,pAdecDataType->nGiveBackPacktOkNum
,pAdecDataType->nGiveBackPacktFailNum);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
}
}
/*
2 wait for all out port frames from other component or app to back.
pAdecDataType->sOutBufSupplier.eBufferSupplier = OMX_BufferSupplyOutput;
*/
logi("Before OMX_AdecComponentThread exit,it must wait for sOutProcessingFrame empty\n");
while(!OMX_AdecListEmpty(&pAdecDataType->sOutProcessingFrame,pAdecDataType->sOutFrameLock)){
usleep(1000);
}
/*
3 give back all frames in sOutReadyFrame to decoder
*/
logi("Before OMX_AdecComponentThread exit,it must give back all frames in sOutReadyFrame to decoder\n");
if(!OMX_AdecListEmpty(&pAdecDataType->sOutReadyFrame,pAdecDataType->sOutFrameLock)){
logi("sOutReadyFrame is not empty\n");
ADEC_OUT_FRAME *pFrameNode1,*pFrameNode2;
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
mpp_list_for_each_entry_safe(pFrameNode1,pFrameNode2,&pAdecDataType->sOutReadyFrame,sList){
ret = aic_audio_decoder_put_frame(pAdecDataType->pDecoder, &pFrameNode1->sFrameInfo);
pAdecDataType->nLeftReadyFrameWhenCompoentExitNum++;
if(ret != 0){// how to do
logw("mpp_decoder_put_frame error!!!!\n");
}else{
}
// now, no matter whether is back to decoder ok,move pFrameNode1 to sOutEmptyFrame
mpp_list_del(&pFrameNode1->sList);
mpp_list_add_tail(&pFrameNode1->sList, &pAdecDataType->sOutEmptyFrame);
}
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
}
logi("OMX_AdecComponentThread ready to exit\n");
}else if(pAdecDataType->state == OMX_StateExecuting){
}else if(pAdecDataType->state == OMX_StatePause){
}else {
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAdecDataType->state = OMX_StateLoaded;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAdecDataType->state,NULL);
}
static void OMX_AdecStateChangeToIdle(ADEC_DATA_TYPE * pAdecDataType)
{
int ret;
if(pAdecDataType->state == OMX_StateLoaded){
//create decoder
if(pAdecDataType->pDecoder == NULL){
pAdecDataType->pDecoder = aic_audio_decoder_create(pAdecDataType->eCodeType);
if(pAdecDataType->pDecoder == NULL){
loge("mpp_decoder_create fail!!!!\n ");
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
logi("aic_audio_decoder_create ok!\n ");
ret = aic_audio_decoder_init(pAdecDataType->pDecoder, &pAdecDataType->sDecoderConfig);
if (ret) {
loge("mpp_decoder_init %d failed\n", pAdecDataType->eCodeType);
aic_audio_decoder_destroy(pAdecDataType->pDecoder);
pAdecDataType->pDecoder = NULL;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
logi("aic_audio_decoder_init ok!\n ");
}
}else if(pAdecDataType->state == OMX_StatePause){
}else if(pAdecDataType->state == OMX_StateExecuting){
}else{
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAdecDataType->state = OMX_StateIdle;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAdecDataType->state,NULL);
}
static void OMX_AdecStateChangeToExcuting(ADEC_DATA_TYPE * pAdecDataType)
{
if(pAdecDataType->state == OMX_StateLoaded){
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}else if(pAdecDataType->state == OMX_StateIdle){
}else if(pAdecDataType->state == OMX_StatePause){
}else{
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return;
}
pAdecDataType->state = OMX_StateExecuting;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAdecDataType->state,NULL);
}
static void OMX_AdecStateChangeToPause(ADEC_DATA_TYPE * pAdecDataType)
{
if(pAdecDataType->state == OMX_StateLoaded){
}else if(pAdecDataType->state == OMX_StateIdle){
}else if(pAdecDataType->state == OMX_StateExecuting){
}else{
OMX_AdecEventNotify(pAdecDataType
,OMX_EventError
,OMX_ErrorIncorrectStateTransition
,pAdecDataType->state,NULL);
loge("OMX_ErrorIncorrectStateTransition\n");
return ;
}
pAdecDataType->state = OMX_StatePause;
OMX_AdecEventNotify(pAdecDataType
,OMX_EventCmdComplete
,OMX_CommandStateSet
,pAdecDataType->state,NULL);
}
static void* OMX_AdecComponentThread(void* pThreadData)
{
struct aic_message message;
OMX_S32 nCmd; //OMX_COMMANDTYPE
OMX_S32 nCmdData; //OMX_STATETYPE
ADEC_DATA_TYPE* pAdecDataType = (ADEC_DATA_TYPE*)pThreadData;
OMX_S32 ret;
//OMX_S32 i;
ADEC_OUT_FRAME *pFrameNode;
struct aic_audio_frame sFrame;
OMX_S32 bNotifyFrameEnd = 0;
//prctl(PR_SET_NAME,(u32)"Adec");
while(1){
if (aic_msg_get(&pAdecDataType->sMsgQue, &message) == 0){
nCmd = message.message_id;
nCmdData = message.param;
logw("nCmd:%d, nCmdData:%d\n",nCmd,nCmdData);
if(OMX_CommandStateSet == nCmd){
aic_pthread_mutex_lock(&pAdecDataType->stateLock);
if(pAdecDataType->state == (OMX_STATETYPE)(nCmdData)){
OMX_AdecEventNotify(pAdecDataType,OMX_EventError,OMX_ErrorSameState,0,NULL);
aic_pthread_mutex_unlock(&pAdecDataType->stateLock);
continue;
}
switch(nCmdData){
case OMX_StateInvalid:
OMX_AdecStateChangeToInvalid(pAdecDataType);
break;
case OMX_StateLoaded:
OMX_AdecStateChangeLoaded(pAdecDataType);
break;
case OMX_StateIdle:
OMX_AdecStateChangeToIdle(pAdecDataType);
break;
case OMX_StateExecuting:
OMX_AdecStateChangeToExcuting(pAdecDataType);
break;
case OMX_StatePause:
OMX_AdecStateChangeToPause(pAdecDataType);
break;
default:
break;
}
aic_pthread_mutex_unlock(&pAdecDataType->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_AdecComponentThread ready to exit!!!\n");
goto _EXIT;
}else{
}
}
if(pAdecDataType->state != OMX_StateExecuting){
//usleep(1000);
aic_msg_wait_new_msg(&pAdecDataType->sMsgQue, 0);
continue;
}
if(pAdecDataType->nFlags & ADEC_OUTPORT_SEND_ALL_FRAME_FLAG){
if(!bNotifyFrameEnd){
//notify app decoder end
OMX_AdecEventNotify(pAdecDataType,OMX_EventBufferFlag,0,0,NULL);
/*
//notify tunneld component decoder end
if(pAdecDataType->sOutPortTunneledInfo.nTunneledFlag){
OMX_PARAM_FRAMEEND sFrameEnd;
sFrameEnd.bFrameEnd = OMX_TRUE;
OMX_SetParameter(pAdecDataType->sOutPortTunneledInfo.pTunneledComp, OMX_IndexVendorStreamFrameEnd,&sFrameEnd);
}
*/
bNotifyFrameEnd = 1;
}
//usleep(1000);
aic_msg_wait_new_msg(&pAdecDataType->sMsgQue, 0);
continue;
}
bNotifyFrameEnd = 0;
// send packet to decoder
if(pAdecDataType->sInPortTunneledInfo.nTunneledFlag){
if(!OMX_AdecListEmpty(&pAdecDataType->sInReadyPkt,pAdecDataType->sInPktLock)){
ADEC_IN_PACKET *pktNode1 = NULL;
struct mpp_packet pkt;
while(!OMX_AdecListEmpty(&pAdecDataType->sInReadyPkt,pAdecDataType->sInPktLock)){
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
pktNode1 = mpp_list_first_entry(&pAdecDataType->sInReadyPkt, ADEC_IN_PACKET, sList);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
pkt.size = pktNode1->sBuff.nFilledLen;
ret = aic_audio_decoder_get_packet(pAdecDataType->pDecoder, &pkt, pkt.size);
logi("aic_audio_decoder_get_packet:%d\n",ret);
if(ret != 0){
//loge("get pkt from decoder error,ret:%d!!!\n",ret);
usleep(10*1000);
break;
}
memcpy(pkt.data,pktNode1->sBuff.pBuffer,pkt.size);
pkt.flag = pktNode1->sBuff.nFlags;
pkt.pts = pktNode1->sBuff.nTimeStamp;
/*if aic_audio_decoder_get_packet ok ,aic_audio_decoder_put_packet must be ok,so do need to justify*/
ret = aic_audio_decoder_put_packet(pAdecDataType->pDecoder, &pkt);
logi("aic_audio_decoder_put_packet ret:%d,pkt.data:%p,pkt.size:%d,pkt.flag:%d\n",ret,pkt.data,pkt.size,pkt.flag);
pAdecDataType->nPutPacktToDecoderOkNum++;
logi("pAdecDataType->nPutPacktToDecoderOkNum:%d\n",pAdecDataType->nPutPacktToDecoderOkNum);
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_del(&pktNode1->sList);
mpp_list_add_tail(&pktNode1->sList, &pAdecDataType->sInProcessedPkt);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
/*
ret = OMX_FillThisBuffer(pAdecDataType->sInPortTunneledInfo.pTunneledComp,&pktNode1->sBuff);
if(ret != 0){ // how to do
logw("OMX_FillThisBuffer error \n");
pAdecDataType->nGiveBackPacktFailNum++;
}else{
pAdecDataType->nGiveBackPacktOkNum++;
}
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_del(&pktNode1->sList);
mpp_list_add_tail(&pktNode1->sList, &pAdecDataType->sInEmptyPkt);
logi("pAdecDataType->nGiveBackPacktOkNum:%d,pAdecDataType->nGiveBackPacktFailNum:%d\n"
,pAdecDataType->nGiveBackPacktOkNum
,pAdecDataType->nGiveBackPacktFailNum);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
*/
}
}else{
aic_msg_wait_new_msg(&pAdecDataType->sMsgQue, 100*1000);
}
}
//give back packet to demux
if((pAdecDataType->sInPortTunneledInfo.nTunneledFlag)
&& (!OMX_AdecListEmpty(&pAdecDataType->sInProcessedPkt,pAdecDataType->sInPktLock))){
ADEC_IN_PACKET *pktNode1 = NULL;
//struct mpp_packet pkt;
while(!OMX_AdecListEmpty(&pAdecDataType->sInProcessedPkt,pAdecDataType->sInPktLock)){
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
pktNode1 = mpp_list_first_entry(&pAdecDataType->sInProcessedPkt, ADEC_IN_PACKET, sList);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
ret = OMX_FillThisBuffer(pAdecDataType->sInPortTunneledInfo.pTunneledComp,&pktNode1->sBuff);
if(ret == 0){
aic_pthread_mutex_lock(&pAdecDataType->sInPktLock);
mpp_list_del(&pktNode1->sList);
mpp_list_add_tail(&pktNode1->sList, &pAdecDataType->sInEmptyPkt);
pAdecDataType->nGiveBackPacktOkNum++;
logi("pAdecDataType->nGiveBackPacktOkNum:%d,pAdecDataType->nGiveBackPacktFailNum:%d\n"
,pAdecDataType->nGiveBackPacktOkNum
,pAdecDataType->nGiveBackPacktFailNum);
aic_pthread_mutex_unlock(&pAdecDataType->sInPktLock);
}else{
//loge("OMX_FillThisBuffer error \n");
pAdecDataType->nGiveBackPacktFailNum++;
logi("pAdecDataType->nGiveBackPacktOkNum:%d,pAdecDataType->nGiveBackPacktFailNum:%d\n"
,pAdecDataType->nGiveBackPacktOkNum
,pAdecDataType->nGiveBackPacktFailNum);
break;
}
}
}
// decode
/*mp3 using libmad */
if(!(pAdecDataType->nFlags & ADEC_DECODER_CONSUME_ALL_INPORT_STREAM_FLAG)){
ret = aic_audio_decoder_decode(pAdecDataType->pDecoder);
if(ret == DEC_OK){
logd("mpp_decoder_decode ok!!!\n");
}else if(ret == DEC_NO_READY_PACKET){
logw("mpp_decoder_decode error DEC_NO_READY_PACKET !!!\n");
if(pAdecDataType->nFlags & ADEC_INPORT_STREAM_END_FLAG){
//pAdecDataType->nDecodeEndFlag = OMX_TRUE;
pAdecDataType->nFlags |= ADEC_DECODER_CONSUME_ALL_INPORT_STREAM_FLAG;
logw("mpp_decoder_decode notify stream end !!!\n");
}else{
// wait some time
usleep(10*1000);
}
}else if(ret == DEC_NO_EMPTY_FRAME){// no decode on time wait sometime
logw("mpp_decoder_decode error DEC_NO_EMPTY_FRAME !!!\n");
usleep(10*1000);
}else if(ret == DEC_ERR_FM_NOT_CREATE){
}else{
loge("mpp_decoder_decode error serious,do not keep decoding !!!\n");
}
}
// get frame from decoder
if(!(pAdecDataType->nFlags & ADEC_GET_ALL_FRAME_FREOM_DECODER_FLAG)){
if(!OMX_AdecListEmpty(&pAdecDataType->sOutEmptyFrame,pAdecDataType->sOutFrameLock)){
ret = aic_audio_decoder_get_frame(pAdecDataType->pDecoder, &sFrame);
if(ret == DEC_OK){
logd("mpp_decoder_get_frame ok\n");
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
pFrameNode = mpp_list_first_entry(&pAdecDataType->sOutEmptyFrame, ADEC_OUT_FRAME, sList);
pFrameNode->sFrameInfo = sFrame;
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAdecDataType->sOutReadyFrame);
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
pAdecDataType->nGetFrameFromDecoderNum++;
}else if(ret == DEC_NO_RENDER_FRAME){
if(pAdecDataType->nFlags & ADEC_DECODER_CONSUME_ALL_INPORT_STREAM_FLAG){
pAdecDataType->nFlags |= ADEC_GET_ALL_FRAME_FREOM_DECODER_FLAG;
//pAdecDataType->nFrameEndFlag = OMX_TRUE;
logi("nFrameEndFlag");
}
logw("mpp_decoder_get_frame error DEC_NO_RENDER_FRAME !!!\n");
usleep(10*1000);
}else if(ret == DEC_ERR_FM_NOT_CREATE){
logw("mpp_decoder_get_frame error DEC_ERR_FM_NOT_CREATE !!!\n");
usleep(10*1000);
}else if(ret == DEC_NO_EMPTY_FRAME){
logw("mpp_decoder_get_frame error DEC_NO_EMPTY_FRAME !!!\n");
usleep(10*1000);
}else{
loge("mpp_decoder_get_frame other error \n");
}
}else{
usleep(10*1000);
}
}
// send frame to other compoent or app
if(!OMX_AdecListEmpty(&pAdecDataType->sOutReadyFrame,pAdecDataType->sOutFrameLock)){
ret = 0;
OMX_BUFFERHEADERTYPE sBuffHead;
while(!OMX_AdecListEmpty(&pAdecDataType->sOutReadyFrame,pAdecDataType->sOutFrameLock)){
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
pFrameNode = mpp_list_first_entry(&pAdecDataType->sOutReadyFrame, ADEC_OUT_FRAME, sList);
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
sBuffHead.nOutputPortIndex = ADEC_PORT_OUT_INDEX;
sBuffHead.pBuffer = (OMX_U8 *)&pFrameNode->sFrameInfo;
if(pAdecDataType->sOutPortTunneledInfo.nTunneledFlag){
sBuffHead.nInputPortIndex = pAdecDataType->sOutPortTunneledInfo.nTunnelPortIndex;
ret = OMX_EmptyThisBuffer(pAdecDataType->sOutPortTunneledInfo.pTunneledComp,&sBuffHead);
if(ret != 0){ // how to do,deal with by TunneledComp
logw("OMX_EmptyThisBuffer error \n");
}
}else{
if(pAdecDataType->pCallbacks != NULL && pAdecDataType->pCallbacks->FillBufferDone != NULL){
ret = pAdecDataType->pCallbacks->FillBufferDone(pAdecDataType->hSelf,pAdecDataType->pAppData,&sBuffHead);
if(ret != 0){// how to do,deal with by usr
logw("EmptyBufferDone error \n");
}
}
}
if(ret == 0){
logd("OMX_EmptyThisBuffer or FillBufferDone ok! move node to using list\n");
aic_pthread_mutex_lock(&pAdecDataType->sOutFrameLock);
mpp_list_del(&pFrameNode->sList);
mpp_list_add_tail(&pFrameNode->sList, &pAdecDataType->sOutProcessingFrame);
aic_pthread_mutex_unlock(&pAdecDataType->sOutFrameLock);
pAdecDataType->nSendFrameOkNum++;
}else{ // how to do ,// just only noitfy error,do not move empty list
if(pAdecDataType->pCallbacks && pAdecDataType->pCallbacks->EventHandler) {
pAdecDataType->pCallbacks->EventHandler(pAdecDataType->hSelf,
pAdecDataType->pAppData,OMX_EventError,
OMX_ErrorUndefined, pAdecDataType->state,NULL);
}
logw("OMX_EmptyThisBuffer or FillBufferDone fail!\n");
pAdecDataType->nSendFrameErrorNum++;
usleep(10*1000);
break;//fail, do not keep send frame to other compoent or app
}
}
}else{
if(pAdecDataType->nFlags & ADEC_GET_ALL_FRAME_FREOM_DECODER_FLAG){
pAdecDataType->nFlags |= ADEC_OUTPORT_SEND_ALL_FRAME_FLAG;
logi("ADEC_OUTPORT_SEND_ALL_FRAME_FLAG\n");
}
usleep(10*1000);
}
// send frame back to decoder in OMX_AdecFillThisBuffer
}
_EXIT:
loge("in port:nReceivePacktOkNum:%d,"\
"nReceivePacktFailNum:%d,"\
"nPutPacktToDecoderOkNum:%d,"\
"nPutPacktToDecoderFailNum:%d,"\
"nGiveBackPacktOkNum:%d"\
"nGiveBackPacktFailNum:%d\n"
,pAdecDataType->nReceivePacktOkNum
,pAdecDataType->nReceivePacktFailNum
,pAdecDataType->nPutPacktToDecoderOkNum
,pAdecDataType->nPutPacktToDecoderFailNum
,pAdecDataType->nGiveBackPacktOkNum
,pAdecDataType->nGiveBackPacktFailNum);
loge("out port:nGetFrameFromDecoderNum:%d,"\
"nDropFrameFromDecoderNum:%d,"\
"nSendFrameOkNum:%d,"\
"nSendFrameErrorNum:%d,"\
"nLeftReadyFrameWhenCompoentExitNum:%d\n"
,pAdecDataType->nGetFrameFromDecoderNum
,pAdecDataType->nDropFrameFromDecoderNum
,pAdecDataType->nSendFrameOkNum
,pAdecDataType->nSendFrameErrorNum
,pAdecDataType->nLeftReadyFrameWhenCompoentExitNum);
loge("OMX_AdecComponentThread EXIT\n");
return (void*)OMX_ErrorNone;
}