sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/component/TextEnc_Component.c

1469 lines
53 KiB
C
Executable File

#include <utils/plat_log.h>
//ref platform headers
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include <assert.h>
#include "plat_type.h"
#include "plat_errno.h"
#include "plat_defines.h"
#include "plat_math.h"
#include "cdx_list.h"
//media api headers to app
#include "SystemBase.h"
#include "mm_common.h"
#include "mm_comm_tenc.h"
#include "mpi_tenc.h"
//media internal common headers.
#include "media_common.h"
#include "mm_component.h"
#include "ComponentCommon.h"
#include "tmessage.h"
#include "tsemaphore.h"
#include "TextEncApi.h"
#include "TextEnc_Component.h"
#include "TencCompStream.h"
#include "EncodedStream.h"
extern ERRORTYPE TextEncResetChannel(PARAM_IN COMP_HANDLETYPE hComponent);
extern int TextEncLibInit(TEXTENCDATATYPE *pTextEncData);
static void* TextComponentThread(void* pThreadData)
{
int cmddata;
CompInternalMsgType cmd;
TEXTENCDATATYPE* pTextEncData = (TEXTENCDATATYPE*) pThreadData;
message_t cmd_msg;
int ret = 0;
aloge("TextEncoder TextEncComponentThread start run...");
sprintf(pTextEncData->mThreadName, "TEncChn%d", pTextEncData->mMppChnInfo.mChnId);
prctl(PR_SET_NAME, (unsigned long)pTextEncData->mThreadName, 0, 0, 0);
while(1)
{
PROCESS_MESSAGE:
if(get_message(&pTextEncData->cmd_queue, &cmd_msg) == 0)
{
cmd = cmd_msg.command;
cmddata = cmd_msg.para0;
// State transition command
if (cmd == SetState)
{
// If the parameter states a transition to the same state
// raise a same state transition error.
if (pTextEncData->state == (COMP_STATETYPE) (cmddata))
pTextEncData->pCallbacks->EventHandler(pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_SAMESTATE,
0,
NULL);
else
{
// transitions/callbacks made based on state transition table
// cmddata contains the target state
switch ((COMP_STATETYPE) (cmddata))
{
case COMP_StateInvalid:
{
pTextEncData->state = COMP_StateInvalid;
pTextEncData->pCallbacks->EventHandler(pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_INVALIDSTATE,
0,
NULL);
pTextEncData->pCallbacks->EventHandler(pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
break;
}
case COMP_StateLoaded:
{
if (pTextEncData->state != COMP_StateIdle)
{
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
TextEncResetChannel(pTextEncData->hSelf);
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
pTextEncData->mWaitOutFrameFullFlag = TRUE;
//wait all outFrame return.
int cnt;
struct list_head *pList;
while(1)
{
cnt = 0;
list_for_each(pList, &pTextEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt < pTextEncData->mFrameNodeNum)
{
pthread_cond_wait(&pTextEncData->mOutFrameFullCondition, &pTextEncData->mOutFrameListMutex);
}
else
{
break;
}
}
pTextEncData->mWaitOutFrameFullFlag = FALSE;
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
pTextEncData->state = COMP_StateLoaded;
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf, pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
break;
}
case COMP_StateIdle:
{
if(pTextEncData->state == COMP_StateLoaded)
{
if(NULL == pTextEncData->htext_enc)
{
TextEncLibInit(pTextEncData);
}
pTextEncData->state = COMP_StateIdle;
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
}
else if(pTextEncData->state == COMP_StatePause || pTextEncData->state == COMP_StateExecuting)
{
pTextEncData->state = COMP_StateIdle;
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
}
else
{
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
}
case COMP_StateExecuting:
{
// Transition can only happen from pause or idle state
if (pTextEncData->state == COMP_StateIdle || pTextEncData->state == COMP_StatePause)
{
pTextEncData->state = COMP_StateExecuting;
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
}
else
{
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
}
case COMP_StatePause:
{
// Transition can only happen from idle or executing state
if (pTextEncData->state == COMP_StateIdle || pTextEncData->state == COMP_StateExecuting)
{
pTextEncData->state = COMP_StatePause;
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf,
pTextEncData->pAppData,
COMP_EventCmdComplete,
COMP_CommandStateSet,
pTextEncData->state,
NULL);
}
else
{
pTextEncData->pCallbacks->EventHandler(
pTextEncData->hSelf, pTextEncData->pAppData,
COMP_EventError,
ERR_TENC_INCORRECT_STATE_TRANSITION,
0,
NULL);
}
break;
}
default:
break;
}
}
}
else if (cmd == Flush)
{
}
else if (cmd == Stop)
{
// Kill thread
goto EXIT;
}
else if(cmd == TEncComp_InputTextAvailable)
{
pTextEncData->mNoInputTextFlag = 0;
}
else if(cmd == TEncComp_OutFrameAvailable)
{
pTextEncData->mNoOutFrameFlag = 0;
}
//precede to process message
goto PROCESS_MESSAGE;
}
if(pTextEncData->state == COMP_StateExecuting)
{
// to enc one text frame
ret = pTextEncData->htext_enc->TextEncodePro(pTextEncData->htext_enc);
if(0 == ret)
{
TryGetTextEncBuf:
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
if(list_empty(&pTextEncData->mIdleOutFrameList))
{
alogw("Low probability! TEnc_Comp IdleOutFrameList is empty, malloc more!");
ENCODER_NODE_T *pNode = (ENCODER_NODE_T*)malloc(sizeof(ENCODER_NODE_T));
if(pNode)
{
memset(pNode, 0, sizeof(ENCODER_NODE_T));
list_add_tail(&pNode->mList, &pTextEncData->mIdleOutFrameList);
pTextEncData->mFrameNodeNum++;
}
else
{
aloge("Fatal error! malloc fail!");
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
if(TMessage_WaitQueueNotEmpty(&pTextEncData->cmd_queue, 200) > 0)
{
goto PROCESS_MESSAGE;
}
else
{
goto TryGetTextEncBuf;
}
}
}
ENCODER_NODE_T *pEntry = list_first_entry(&pTextEncData->mIdleOutFrameList, ENCODER_NODE_T, mList);
ret = pTextEncData->htext_enc->RequestTextEncBuf(pTextEncData->htext_enc,
(void **)&pEntry->stEncodedStream.pBuffer
,(unsigned int*)&pEntry->stEncodedStream.nBufferLen
,&pEntry->stEncodedStream.nTimeStamp
,&pEntry->stEncodedStream.nID
);
pEntry->stEncodedStream.nFilledLen = pEntry->stEncodedStream.nBufferLen;
//pEntry->stEncodedStream.nTimeStamp = pEntry->stEncodedStream.nTimeStamp * 1000; //unit ms-->us
pEntry->stEncodedStream.pBufferExtra = NULL;
pEntry->stEncodedStream.nBufferExtraLen = 0;
pEntry->stEncodedStream.media_type = CDX_PacketSubtitle;
if (ret != 0)
{
alogw("(f:%s, l:%d) getTextEncBuf fail.", __FUNCTION__, __LINE__);
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
continue;
}
if(pTextEncData->mOutputPortTunnelFlag)
{
list_move_tail(&pEntry->mList, &pTextEncData->mUsedOutFrameList); //Notes:Must move buf node to UsedList before calling EmptyThisBuffer
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
MM_COMPONENTTYPE *pOutTunnelComp = (MM_COMPONENTTYPE*)(pTextEncData->sOutPortTunnelInfo.hTunnel);
COMP_BUFFERHEADERTYPE obh;
obh.nOutputPortIndex = pTextEncData->sOutPortTunnelInfo.nPortIndex;
obh.nInputPortIndex = pTextEncData->sOutPortTunnelInfo.nTunnelPortIndex;
obh.pOutputPortPrivate = (void*)&pEntry->stEncodedStream;
int omxRet = pOutTunnelComp->EmptyThisBuffer(pOutTunnelComp, &obh);
if(SUCCESS == omxRet)
{
ret = pTextEncData->htext_enc->GetValidEncPktCnt(pTextEncData->htext_enc);
if (ret != 0) {
alogw("(f:%s, l:%d) Low probability! why not pick enced_pkt(cnt: %d) in time?!", __FUNCTION__, __LINE__, ret);
goto TryGetTextEncBuf;
}
}
else
{
ret = pTextEncData->htext_enc->ReleaseTextEncBuf(pTextEncData->htext_enc,
pEntry->stEncodedStream.pBuffer,
pEntry->stEncodedStream.nBufferLen,
pEntry->stEncodedStream.nTimeStamp,
pEntry->stEncodedStream.nID);
if(0 != ret)
{
aloge("fatal error,releas text enc frm fail");
}
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
list_move_tail(&pEntry->mList, &pTextEncData->mIdleOutFrameList);
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
}
else
{
list_move_tail(&pEntry->mList, &pTextEncData->mReadyOutFrameList);
if(pTextEncData->mWaitOutFrameFlag)
{
pthread_cond_signal(&pTextEncData->mOutFrameCondition);
}
char tmpWrCh = 'T';
write(pTextEncData->mOutputFrameNotifyPipeFds[1], &tmpWrCh, 1);
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
}
else if(ERR_TEXT_ENC_INPUT_UNDERFLOW == ret)
{
pthread_mutex_lock(&pTextEncData->mInputTextMutex);
int cnt = pTextEncData->htext_enc->GetValidInputPktCnt(pTextEncData->htext_enc);
if (0 < cnt)
{
alogw("(f:%s, l:%d) Low probability! TextEnc Component has input, cnt: [%ld]", __FUNCTION__, __LINE__, cnt);
pthread_mutex_unlock(&pTextEncData->mInputTextMutex);
}
else
{
pTextEncData->mNoInputTextFlag = 1;
pthread_mutex_unlock(&pTextEncData->mInputTextMutex);
TMessage_WaitQueueNotEmpty(&pTextEncData->cmd_queue, 0);
}
}
else if(ERR_TEXT_ENC_OUTFRM_UNDERFLOW == ret)
{
alogw("TextEncComp_no out frm");
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
int emptyFrameCnt = pTextEncData->htext_enc->GetEmptyOutFrameCnt(pTextEncData->htext_enc);
if(0 < emptyFrameCnt)
{
alogw("(f:%s, l:%d) Low probability! TextEnc Component has empty frames[%ld]", __FUNCTION__, __LINE__, emptyFrameCnt);
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
else
{
pTextEncData->mNoOutFrameFlag = 1;
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
TMessage_WaitQueueNotEmpty(&pTextEncData->cmd_queue, 0);
}
}
}
else
{
aloge("TextEnc_Comp not ind StateExecuting");
TMessage_WaitQueueNotEmpty(&pTextEncData->cmd_queue, 0);
}
}
EXIT:
alogv("TextEncoder ComponentThread stopped");
return (void*) SUCCESS;
}
static ERRORTYPE TextEncSetCallbacks(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_CALLBACKTYPE* pCallbacks, PARAM_IN void* pAppData)
{
TEXTENCDATATYPE *pTextEncData = NULL;
ERRORTYPE eError = SUCCESS;
pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pTextEncData || !pCallbacks || !pAppData)
{
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
pTextEncData->pCallbacks = pCallbacks;
pTextEncData->pAppData = pAppData;
COMP_CONF_CMD_FAIL:
return eError;
}
static ERRORTYPE TextEncSendCommand( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_COMMANDTYPE Cmd, PARAM_IN unsigned int nParam1, PARAM_IN void* pCmdData)
{
TEXTENCDATATYPE *pTextEncData = NULL;
CompInternalMsgType eCmd;
ERRORTYPE eError = SUCCESS;
message_t msg;
alogv("TextEncSendCommand: %d", Cmd);
pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(!pTextEncData)
{
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CONF_CMD_FAIL;
}
if (pTextEncData->state == COMP_StateInvalid)
{
eError = ERR_TENC_SYS_NOTREADY;
goto COMP_CONF_CMD_FAIL;
}
switch (Cmd)
{
case COMP_CommandStateSet:
eCmd = SetState;
break;
case COMP_CommandFlush:
eCmd = Flush;
break;
default:
alogw("impossible comp_command[0x%x]", Cmd);
eCmd = -1;
break;
}
msg.command = eCmd;
msg.para0 = nParam1;
put_message(&pTextEncData->cmd_queue, &msg);
COMP_CONF_CMD_FAIL: return eError;
}
static ERRORTYPE TextEncSetPortDefinition( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if (pPortDef->nPortIndex == pTextEncData->sInPortDef.nPortIndex)
memcpy(&pTextEncData->sInPortDef, pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
else if (pPortDef->nPortIndex == pTextEncData->sOutPortDef.nPortIndex)
memcpy(&pTextEncData->sOutPortDef, pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
else
eError = ERR_TENC_ILLEGAL_PARAM;
return eError;
}
static ERRORTYPE TextEncSetCompBufferSupplier( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i = 0;
for(i=0; i<MAX_TENCODER_PORTS; i++)
{
if(pPortBufSupplier->nPortIndex == pTextEncData->sPortBufSupplier[i].nPortIndex)
{
bFindFlag = TRUE;
memcpy(&pTextEncData->sPortBufSupplier[i], pPortBufSupplier, sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_TENC_ILLEGAL_PARAM;
}
return eError;
}
static ERRORTYPE TextEncReleaseStream( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN TEXT_STREAM_S *pStream)
{
ERRORTYPE eError;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(COMP_StateIdle != pTextEncData->state && COMP_StateExecuting != pTextEncData->state)
{
alogw("call getStream in wrong state[0x%x]", pTextEncData->state);
return ERR_TENC_NOT_PERM;
}
if(pTextEncData->mOutputPortTunnelFlag)
{
aloge("fatal error! can't call getStream() in tunnel mode!");
return ERR_TENC_NOT_PERM;
}
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
if(!list_empty(&pTextEncData->mUsedOutFrameList))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pTextEncData->mUsedOutFrameList, ENCODER_NODE_T, mList);
if( pStream->pStream == pEntry->stEncodedStream.pBuffer
&& pStream->mLen == pEntry->stEncodedStream.nBufferLen )
{
int ret = pTextEncData->htext_enc->ReleaseTextEncBuf(pTextEncData->htext_enc,
pEntry->stEncodedStream.pBuffer,
pEntry->stEncodedStream.nBufferLen,
pEntry->stEncodedStream.nTimeStamp,
pEntry->stEncodedStream.nID);
list_move_tail(&pEntry->mList, &pTextEncData->mIdleOutFrameList);
eError = SUCCESS;
}
else
{
aloge("fatal error! tenc stream[%p][%u] is not match UsedOutFrameList first entry[%p][%d]",
pStream->pStream, pStream->mLen, pEntry->stEncodedStream.pBuffer, pEntry->stEncodedStream.nBufferLen);
eError = ERR_TENC_ILLEGAL_PARAM;
}
}
else
{
alogw("Be careful! tenc stream[%p][%u] is not find, maybe reset channel before call this function?", pStream->pStream, pStream->mLen);
eError = ERR_TENC_ILLEGAL_PARAM; // samuel
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
if(pTextEncData->mNoOutFrameFlag)
{
message_t msg;
msg.command = TEncComp_OutFrameAvailable;
put_message(&pTextEncData->cmd_queue, &msg);
}
return eError;
}
ERRORTYPE TextEncResetChannel(PARAM_IN COMP_HANDLETYPE hComponent)
{
//ERRORTYPE eError;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pTextEncData->state != COMP_StateIdle)
{
aloge("fatal error! must reset channel in stateIdle!");
return ERR_TENC_NOT_PERM;
}
// not need return input pcm.
// return output frames to tenclib.
if(FALSE == pTextEncData->mOutputPortTunnelFlag)
{
//return output streams to tenclib directly. Don't worry about user take streams,
//if user return stream after it, return ERR_TENC_ILLEGAL_PARAM.
//user must guarantee that he return all streams before call this function.
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
if(!list_empty(&pTextEncData->mUsedOutFrameList))
{
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pTextEncData->mUsedOutFrameList, mList)
{
int ret = pTextEncData->htext_enc->ReleaseTextEncBuf(pTextEncData->htext_enc,
pEntry->stEncodedStream.pBuffer,
pEntry->stEncodedStream.nBufferLen,
pEntry->stEncodedStream.nTimeStamp,
pEntry->stEncodedStream.nID);
list_move_tail(&pEntry->mList, &pTextEncData->mIdleOutFrameList);
}
}
if(!list_empty(&pTextEncData->mReadyOutFrameList))
{
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pTextEncData->mReadyOutFrameList, mList)
{
int ret = pTextEncData->htext_enc->ReleaseTextEncBuf(pTextEncData->htext_enc,
pEntry->stEncodedStream.pBuffer,
pEntry->stEncodedStream.nBufferLen,
pEntry->stEncodedStream.nTimeStamp,
pEntry->stEncodedStream.nID);
list_move_tail(&pEntry->mList, &pTextEncData->mIdleOutFrameList);
}
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
else
{
//verify all output frames back to tenclib.
//when component turn to stateIdle, it will guarantee all output frames back.
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
if(!list_empty(&pTextEncData->mUsedOutFrameList))
{
aloge("fatal error! tenc is in tunnel mode!");
}
if(!list_empty(&pTextEncData->mReadyOutFrameList))
{
aloge("fatal error! tenc is in tunnel mode!");
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pTextEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt != pTextEncData->mFrameNodeNum)
{
alogw("Be careful! tenc output frames count not match [%d]!=[%d]", cnt, pTextEncData->mFrameNodeNum);
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
return SUCCESS;
}
static ERRORTYPE TextEncSetMPPChannelInfo( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN MPP_CHN_S *pChn)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pTextEncData->mMppChnInfo = *pChn;
return SUCCESS;
}
int TextEncLibInit(TEXTENCDATATYPE *pTextEncData)
{
int ret = 0;
TEXTENCCONTENT_t *tenc_handle;
tenc_handle = TextEncInit(&pTextEncData->text_info);
if (tenc_handle == NULL) {
ret = -1;
aloge("TextEncInit failed");
}
pTextEncData->htext_enc = tenc_handle;
return ret;
}
static ERRORTYPE TextEncSetChnAttr( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN TENC_CHN_ATTR_S *pChnAttr)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pTextEncData->text_info.enc_type_enable_flag = pChnAttr->tInfo.enc_enable_type;
pTextEncData->text_info.video_frame_rate = pChnAttr->tInfo.video_frame_rate;
pTextEncData->text_info.gsensor_rate = pChnAttr->tInfo.gsensor_rate;
pTextEncData->text_info.adas_rate = pChnAttr->tInfo.adas_rate;
if (TextEncLibInit(pTextEncData) != 0)
{
return FAILURE;
}
return SUCCESS;
}
static ERRORTYPE TextEncSetConfig( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex, PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
switch (nIndex)
{
case COMP_IndexParamPortDefinition:
{
eError = TextEncSetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = TextEncSetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = TextEncSetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTencChnAttr:
{
eError = TextEncSetChnAttr(hComponent, (TENC_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTencReleaseStream:
{
eError = TextEncReleaseStream(hComponent, (TEXT_STREAM_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTencResetChannel:
{
eError = TextEncResetChannel(hComponent);
break;
}
default:
{
aloge("unknown Index[0x%x]", nIndex);
eError = ERR_TENC_ILLEGAL_PARAM;
break;
}
}
return eError;
}
static ERRORTYPE TextEncGetPortDefinition( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_PORTDEFINITIONTYPE *pPortDef)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
if (pPortDef->nPortIndex == pTextEncData->sInPortDef.nPortIndex)
memcpy(pPortDef, &pTextEncData->sInPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
else if (pPortDef->nPortIndex == pTextEncData->sOutPortDef.nPortIndex)
memcpy(pPortDef, &pTextEncData->sOutPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
else
eError = ERR_TENC_ILLEGAL_PARAM;
return eError;
}
static ERRORTYPE TextEncGetCompBufferSupplier( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = SUCCESS;
//find nPortIndex
BOOL bFindFlag = FALSE;
int i;
for(i=0; i<MAX_TENCODER_PORTS; i++)
{
if(pPortBufSupplier->nPortIndex == pTextEncData->sPortBufSupplier[i].nPortIndex)
{
bFindFlag = TRUE;
memcpy(pPortBufSupplier, &pTextEncData->sPortBufSupplier[i], sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
break;
}
}
if(bFindFlag)
{
eError = SUCCESS;
}
else
{
eError = ERR_TENC_ILLEGAL_PARAM;
}
return eError;
}
static ERRORTYPE TextEncGetMPPChannelInfo( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT MPP_CHN_S *pChn)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pChn = pTextEncData->mMppChnInfo;
return SUCCESS;
}
static ERRORTYPE TextEncGetChnAttr( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT TENC_CHN_ATTR_S *pChnAttr)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
pChnAttr->tInfo.enc_enable_type = pTextEncData->text_info.enc_type_enable_flag;
pChnAttr->tInfo.video_frame_rate = pTextEncData->text_info.video_frame_rate;
pChnAttr->tInfo.gsensor_rate = pTextEncData->text_info.gsensor_rate;
pChnAttr->tInfo.adas_rate = pTextEncData->text_info.adas_rate;
return SUCCESS;
}
static ERRORTYPE TextEncGetChannelFd(PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT int *pChnFd)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pChnFd = pTextEncData->mOutputFrameNotifyPipeFds[0];
return SUCCESS;
}
static ERRORTYPE TextEncGetTunnelInfo( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_INOUT COMP_INTERNAL_TUNNELINFOTYPE *pTunnelInfo)
{
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
ERRORTYPE eError = ERR_TENC_UNEXIST;
if(pTunnelInfo->nPortIndex == pTextEncData->sInPortTunnelInfo.nPortIndex)
{
memcpy(pTunnelInfo, &pTextEncData->sInPortTunnelInfo, sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
eError = SUCCESS;
}
else if(pTunnelInfo->nPortIndex == pTextEncData->sOutPortTunnelInfo.nPortIndex)
{
memcpy(pTunnelInfo, &pTextEncData->sOutPortTunnelInfo, sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
eError = SUCCESS;
}
else
{
eError = ERR_TENC_UNEXIST;
}
return eError;
}
static ERRORTYPE config_TENC_STREAM_S_by_TencOutputBuffer(TEXT_STREAM_S *pDst, EncodedStream *pSrc,
TEXTENCDATATYPE *pTextEncData)
{
memset(pDst, 0, sizeof(TEXT_STREAM_S));
pDst->pStream = (unsigned char*)pSrc->pBuffer;
pDst->mLen = pSrc->nBufferLen;
pDst->mTimeStamp = pSrc->nTimeStamp;
pDst->mId = pSrc->nID;
return SUCCESS;
}
static ERRORTYPE TextEncGetStream( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT TEXT_STREAM_S *pStream, PARAM_IN int nMilliSec)
{
ERRORTYPE eError;
int ret;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(COMP_StateIdle != pTextEncData->state && COMP_StateExecuting != pTextEncData->state)
{
alogw("call getStream in wrong state[0x%x]", pTextEncData->state);
return ERR_TENC_NOT_PERM;
}
if(pTextEncData->mOutputPortTunnelFlag)
{
aloge("fatal error! can't call getStream() in tunnel mode!");
return ERR_TENC_NOT_PERM;
}
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
_TryToGetOutFrame:
if(!list_empty(&pTextEncData->mReadyOutFrameList))
{
ENCODER_NODE_T *pEntry = list_first_entry(&pTextEncData->mReadyOutFrameList, ENCODER_NODE_T, mList);
config_TENC_STREAM_S_by_TencOutputBuffer(pStream, &pEntry->stEncodedStream, pTextEncData);
list_move_tail(&pEntry->mList, &pTextEncData->mUsedOutFrameList);
char tmpRdCh;
read(pTextEncData->mOutputFrameNotifyPipeFds[0], &tmpRdCh, 1);
eError = SUCCESS;
}
else
{
if(0 == nMilliSec)
{
eError = ERR_TENC_BUF_EMPTY;
}
else if(nMilliSec < 0)
{
pTextEncData->mWaitOutFrameFlag = TRUE;
while(list_empty(&pTextEncData->mReadyOutFrameList))
{
pthread_cond_wait(&pTextEncData->mOutFrameCondition, &pTextEncData->mOutFrameListMutex);
}
pTextEncData->mWaitOutFrameFlag = FALSE;
goto _TryToGetOutFrame;
}
else
{
pTextEncData->mWaitOutFrameFlag = TRUE;
ret = pthread_cond_wait_timeout(&pTextEncData->mOutFrameCondition, &pTextEncData->mOutFrameListMutex, nMilliSec);
if(ETIMEDOUT == ret)
{
alogv("wait output frame timeout[%d]ms, ret[%d]", nMilliSec, ret);
eError = ERR_TENC_BUF_EMPTY;
pTextEncData->mWaitOutFrameFlag = FALSE;
}
else if(0 == ret)
{
pTextEncData->mWaitOutFrameFlag = FALSE;
goto _TryToGetOutFrame;
}
else
{
aloge("fatal error! pthread cond wait timeout ret[%d]", ret);
eError = ERR_TENC_BUF_EMPTY;
pTextEncData->mWaitOutFrameFlag = FALSE;
}
}
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
return eError;
}
static ERRORTYPE TextEncGetConfig( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_INDEXTYPE nIndex, PARAM_IN void* pComponentConfigStructure)
{
ERRORTYPE eError = SUCCESS;
switch(nIndex)
{
case COMP_IndexParamPortDefinition:
{
eError = TextEncGetPortDefinition(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexParamCompBufferSupplier:
{
eError = TextEncGetCompBufferSupplier(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelInfo:
{
eError = TextEncGetMPPChannelInfo(hComponent, (MPP_CHN_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorMPPChannelFd:
{
eError = TextEncGetChannelFd(hComponent, (int*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTunnelInfo:
{
eError = TextEncGetTunnelInfo(hComponent, (COMP_INTERNAL_TUNNELINFOTYPE*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTencChnAttr:
{
eError = TextEncGetChnAttr(hComponent, (TENC_CHN_ATTR_S*)pComponentConfigStructure);
break;
}
case COMP_IndexVendorTencGetStream:
{
TEncStream *pStream = (TEncStream*)pComponentConfigStructure;
eError = TextEncGetStream(hComponent, pStream->pStream, pStream->nMilliSec);
break;
}
default:
{
aloge("fatal error! unknown getConfig Index[0x%x]", nIndex);
eError = ERR_TENC_NOT_SUPPORT;
break;
}
}
return eError;
}
static ERRORTYPE TextEncGetState( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_OUT COMP_STATETYPE* pState)
{
ERRORTYPE eError = SUCCESS;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
*pState = pTextEncData->state;
return eError;
}
static ERRORTYPE TextEncComponentTunnelRequest( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN unsigned int nPort,
PARAM_IN COMP_HANDLETYPE hTunneledComp, PARAM_IN unsigned int nTunneledPort,
PARAM_INOUT COMP_TUNNELSETUPTYPE* pTunnelSetup)
{
ERRORTYPE eError = SUCCESS;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pTextEncData->state == COMP_StateExecuting)
{
alogw("Be careful! tunnel request may be some danger in StateExecuting");
}
else if(pTextEncData->state != COMP_StateIdle)
{
aloge("fatal error! tunnel request can't be in state[0x%x]", pTextEncData->state);
eError = ERR_TENC_INCORRECT_STATE_OPERATION;
goto COMP_CMD_FAIL;
}
COMP_PARAM_PORTDEFINITIONTYPE *pPortDef;
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo;
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier;
BOOL bFindFlag;
int i;
bFindFlag = FALSE;
if(pTextEncData->sInPortDef.nPortIndex == nPort)
{
pPortDef = &pTextEncData->sInPortDef;
bFindFlag = TRUE;
}
if(FALSE == bFindFlag)
{
if(pTextEncData->sOutPortDef.nPortIndex == nPort)
{
pPortDef = &pTextEncData->sOutPortDef;
bFindFlag = TRUE;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
if(pTextEncData->sInPortTunnelInfo.nPortIndex == nPort)
{
pPortTunnelInfo = &pTextEncData->sInPortTunnelInfo;
bFindFlag = TRUE;
}
if(FALSE == bFindFlag)
{
if(pTextEncData->sOutPortTunnelInfo.nPortIndex == nPort)
{
pPortTunnelInfo = &pTextEncData->sOutPortTunnelInfo;
bFindFlag = TRUE;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
bFindFlag = FALSE;
for(i=0; i<MAX_TENCODER_PORTS; i++)
{
if(pTextEncData->sPortBufSupplier[i].nPortIndex == nPort)
{
pPortBufSupplier = &pTextEncData->sPortBufSupplier[i];
bFindFlag = TRUE;
break;
}
}
if(FALSE == bFindFlag)
{
aloge("fatal error! portIndex[%d] wrong!", nPort);
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortTunnelInfo->nPortIndex = nPort;
pPortTunnelInfo->hTunnel = hTunneledComp;
pPortTunnelInfo->nTunnelPortIndex = nTunneledPort;
pPortTunnelInfo->eTunnelType = (pPortDef->eDomain == COMP_PortDomainOther) ? TUNNEL_TYPE_CLOCK : TUNNEL_TYPE_COMMON;
if(NULL==hTunneledComp && 0==nTunneledPort && NULL==pTunnelSetup)
{
alogd("omx_core cancel setup tunnel on port[%d]", nPort);
eError = SUCCESS;
if(pPortDef->eDir == COMP_DirOutput)
{
pTextEncData->mOutputPortTunnelFlag = FALSE;
}
else
{
pTextEncData->mInputPortTunnelFlag = FALSE;
}
goto COMP_CMD_FAIL;
}
if(pPortDef->eDir == COMP_DirOutput)
{
if (pTextEncData->mOutputPortTunnelFlag) {
aloge("TEnc_Comp outport already bind, why bind again?!");
eError = FAILURE;
goto COMP_CMD_FAIL;
}
pTunnelSetup->nTunnelFlags = 0;
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
pTextEncData->mOutputPortTunnelFlag = TRUE;
}
else
{
if (pTextEncData->mInputPortTunnelFlag) {
aloge("TEnc_Comp inport already bind, why bind again?!");
eError = FAILURE;
goto COMP_CMD_FAIL;
}
//Check the data compatibility between the ports using one or more GetParameter calls.
//B checks if its input port is compatible with the output port of component A.
COMP_PARAM_PORTDEFINITIONTYPE out_port_def;
out_port_def.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamPortDefinition, &out_port_def);
if(out_port_def.eDir != COMP_DirOutput)
{
aloge("fatal error! tunnel port index[%d] direction is not output!", nTunneledPort);
eError = ERR_TENC_ILLEGAL_PARAM;
goto COMP_CMD_FAIL;
}
pPortDef->format = out_port_def.format;
//The component B informs component A about the final result of negotiation.
if(pTunnelSetup->eSupplier != pPortBufSupplier->eBufferSupplier)
{
alogw("Low probability! use input portIndex[%d] buffer supplier[%d] as final!", nPort, pPortBufSupplier->eBufferSupplier);
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
}
COMP_PARAM_BUFFERSUPPLIERTYPE oSupplier;
oSupplier.nPortIndex = nTunneledPort;
((MM_COMPONENTTYPE*)hTunneledComp)->GetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
oSupplier.eBufferSupplier = pTunnelSetup->eSupplier;
((MM_COMPONENTTYPE*)hTunneledComp)->SetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
pTextEncData->mInputPortTunnelFlag = TRUE;
}
COMP_CMD_FAIL:
return eError;
}
static ERRORTYPE TextEncEmptyThisBuffer( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
{
ERRORTYPE eError = SUCCESS;
TEXTENCDATATYPE *pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if (pTextEncData->state != COMP_StateExecuting)
{
alogw("send frame when tenc state[0x%x] isn't executing", pTextEncData->state);
//eError = COMP_ErrorInvalidState;
//goto ERROR;
}
if ((pTextEncData->mInputPortTunnelFlag==TRUE && pBuffer->nInputPortIndex==pTextEncData->sInPortDef.nPortIndex) ||
(pTextEncData->mInputPortTunnelFlag==FALSE))
{
TEXT_FRAME_S *pFrm = (TEXT_FRAME_S *)pBuffer->pOutputPortPrivate; // samuel
void *pTextBuf = pFrm->mpAddr;
unsigned int dataSize = pFrm->mLen;
int ret = pTextEncData->htext_enc->RequestWriteBuf(pTextEncData->htext_enc, pTextBuf, dataSize, pFrm->mTimeStamp);
if (ret != 0)
{
pTextEncData->mSendTextFailCnt++;
eError = FAILURE;
goto ERROR;
}
if(pTextEncData->mNoInputTextFlag)
{
message_t msg;
msg.command = TEncComp_InputTextAvailable;
put_message(&pTextEncData->cmd_queue, &msg);
}
}
else
{
aloge("fatal error! RecRender should not call this function!");
eError = FAILURE;
}
ERROR:
return eError;
}
static ERRORTYPE TextEncFillThisBuffer( PARAM_IN COMP_HANDLETYPE hComponent,
PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
{
TEXTENCDATATYPE *pTextEncData = NULL;
ERRORTYPE eError = SUCCESS;
int ret;
pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(pBuffer->nOutputPortIndex == pTextEncData->sOutPortDef.nPortIndex)
{
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
EncodedStream *pOutFrame = (EncodedStream*)pBuffer->pOutputPortPrivate;
BOOL bFind = FALSE;
ENCODER_NODE_T *pEntry;
list_for_each_entry(pEntry, &pTextEncData->mUsedOutFrameList, mList)
{
if (pEntry->stEncodedStream.nID == pOutFrame->nID)
{
bFind = TRUE;
break;
}
}
if (!bFind)
{
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
aloge("fatal error! try to release one output buffer that never be used! ID = %d", pOutFrame->nID);
return ERR_TENC_ILLEGAL_PARAM;
}
ret = pTextEncData->htext_enc->ReleaseTextEncBuf(pTextEncData->htext_enc,
pEntry->stEncodedStream.pBuffer, pEntry->stEncodedStream.nBufferLen,
pEntry->stEncodedStream.nTimeStamp, pEntry->stEncodedStream.nID);
if (ret != 0)
{
aloge("textenc_to_releas_frm_fail");
eError = FAILURE;
}
list_move_tail(&pEntry->mList, &pTextEncData->mIdleOutFrameList);
if (pTextEncData->mNoOutFrameFlag)
{
message_t msg;
msg.command = TEncComp_OutFrameAvailable;
put_message(&pTextEncData->cmd_queue, &msg);
}
if(pTextEncData->mWaitOutFrameFullFlag)
{
int cnt = 0;
struct list_head *pList;
list_for_each(pList, &pTextEncData->mIdleOutFrameList)
{
cnt++;
}
if(cnt>=pTextEncData->mFrameNodeNum)
{
pthread_cond_signal(&pTextEncData->mOutFrameFullCondition);
}
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
}
else
{
aloge("fatal error! outPortIndex[%d]!=[%d]", pBuffer->nOutputPortIndex, pTextEncData->sOutPortDef.nPortIndex);
eError = FAILURE;
}
return eError;
}
ERRORTYPE TextEncComponentInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
MM_COMPONENTTYPE *pComp = NULL;
TEXTENCDATATYPE *pTextEncData = NULL;
ERRORTYPE eError = SUCCESS;
unsigned int err;
int i = 0;
pComp = (MM_COMPONENTTYPE *)hComponent;
// Create private data
pTextEncData = (TEXTENCDATATYPE *) malloc(sizeof(TEXTENCDATATYPE));
memset(pTextEncData, 0x0, sizeof(TEXTENCDATATYPE));
err = pipe(pTextEncData->mOutputFrameNotifyPipeFds);
if (err)
{
eError = ERR_TENC_NOMEM;
goto EXIT;
}
pComp->pComponentPrivate = (void*)pTextEncData;
pTextEncData->state = COMP_StateLoaded;
pthread_mutex_init(&pTextEncData->mStateLock,NULL);
pTextEncData->hSelf = hComponent;
pTextEncData->mNoInputTextFlag = 0;
pTextEncData->mNoOutFrameFlag = 0;
INIT_LIST_HEAD(&pTextEncData->mIdleOutFrameList);
INIT_LIST_HEAD(&pTextEncData->mReadyOutFrameList);
INIT_LIST_HEAD(&pTextEncData->mUsedOutFrameList);
for(i=0; i<TENC_FRAME_COUNT; i++)
{
ENCODER_NODE_T *pNode = (ENCODER_NODE_T*)malloc(sizeof(ENCODER_NODE_T));
if(NULL == pNode)
{
aloge("fatal error! malloc fail[%s]!", strerror(errno));
break;
}
memset(pNode, 0, sizeof(ENCODER_NODE_T));
list_add_tail(&pNode->mList, &pTextEncData->mIdleOutFrameList);
pTextEncData->mFrameNodeNum++;
}
err = pthread_mutex_init(&pTextEncData->mInputTextMutex, NULL);
if(err != 0)
{
aloge("pthread mutex init fail!");
eError = ERR_TENC_NOMEM;
goto EXIT;
}
err = pthread_mutex_init(&pTextEncData->mOutFrameListMutex, NULL);
if(err != 0)
{
aloge("pthread mutex init fail!");
eError = ERR_TENC_NOMEM;
goto EXIT;
}
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
err = pthread_cond_init(&pTextEncData->mOutFrameFullCondition, &condAttr);
if(err != 0)
{
aloge("pthread cond init fail!");
eError = ERR_TENC_NOMEM;
goto EXIT;
}
pthread_cond_init(&pTextEncData->mOutFrameCondition, &condAttr); // used to notify the new frame is produced
// Fill in function pointers
pComp->SetCallbacks = TextEncSetCallbacks;
pComp->SendCommand = TextEncSendCommand;
pComp->GetConfig = TextEncGetConfig;
pComp->SetConfig = TextEncSetConfig;
pComp->GetState = TextEncGetState;
pComp->ComponentTunnelRequest = TextEncComponentTunnelRequest;
pComp->ComponentDeInit = TextEncComponentDeInit;
pComp->EmptyThisBuffer = TextEncEmptyThisBuffer;
pComp->FillThisBuffer = TextEncFillThisBuffer;
// Initialize component data structures to default values
pTextEncData->sPortParam.nPorts = 0x2;
pTextEncData->sPortParam.nStartPortNumber = 0x0;
// Initialize the audio parameters for input port
pTextEncData->sInPortDef.nPortIndex = 0x0;
pTextEncData->sInPortDef.bEnabled = TRUE;
pTextEncData->sInPortDef.eDomain = COMP_PortDomainText;
pTextEncData->sInPortDef.eDir = COMP_DirInput;
// pTextEncData->sInPortDef.format.audio.cMIMEType = "AAC";
// pTextEncData->sInPortDef.format.audio.eEncoding = PT_AAC;
// Initialize the audio parameters for output port
pTextEncData->sOutPortDef.nPortIndex = 0x1;
pTextEncData->sOutPortDef.bEnabled = TRUE;
pTextEncData->sOutPortDef.eDomain = COMP_PortDomainText;
pTextEncData->sOutPortDef.eDir = COMP_DirOutput;
// pTextEncData->sOutPortDef.format.audio.cMIMEType = "AAC";
// pTextEncData->sOutPortDef.format.audio.eEncoding = PT_AAC;
pTextEncData->sPortBufSupplier[0].nPortIndex = 0x0;
pTextEncData->sPortBufSupplier[0].eBufferSupplier = COMP_BufferSupplyOutput;
pTextEncData->sPortBufSupplier[1].nPortIndex = 0x1;
pTextEncData->sPortBufSupplier[1].eBufferSupplier = COMP_BufferSupplyOutput;
pTextEncData->sInPortTunnelInfo.nPortIndex = 0x0;
pTextEncData->sInPortTunnelInfo.eTunnelType = TUNNEL_TYPE_COMMON;
pTextEncData->sOutPortTunnelInfo.nPortIndex = 0x1;
pTextEncData->sOutPortTunnelInfo.eTunnelType = TUNNEL_TYPE_COMMON;
if (message_create(&pTextEncData->cmd_queue)<0)
{
aloge("message error!");
eError = ERR_TENC_NOMEM;
goto EXIT;
}
// Create the component thread
err = pthread_create(&pTextEncData->thread_id, NULL, TextComponentThread, pTextEncData);
if (err || !pTextEncData->thread_id)
{
eError = ERR_TENC_NOMEM;
goto EXIT;
}
EXIT: return eError;
}
ERRORTYPE TextEncComponentDeInit(PARAM_IN COMP_HANDLETYPE hComponent)
{
TEXTENCDATATYPE *pTextEncData = NULL;
ERRORTYPE eError = SUCCESS;
CompInternalMsgType eCmd = Stop;
message_t msg;
memset(&msg,0,sizeof(msg));
alogv("TextEnc Component DeInit");
pTextEncData = (TEXTENCDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
if(NULL == pTextEncData)
{
aloge("pTextEncData is NULL!!!\n");
return FAILURE;
}
msg.command = eCmd;
put_message(&pTextEncData->cmd_queue, &msg);
alogv("wait TextEnc component exit!...");
pthread_join(pTextEncData->thread_id, (void*) &eError);
if(NULL != pTextEncData->htext_enc)
{
TextEncExit(pTextEncData->htext_enc);
pTextEncData->htext_enc = NULL;
}
message_destroy(&pTextEncData->cmd_queue);
pthread_mutex_lock(&pTextEncData->mOutFrameListMutex);
if(!list_empty(&pTextEncData->mUsedOutFrameList))
{
aloge("fatal error! outUsedFrame must be 0!");
}
if(!list_empty(&pTextEncData->mReadyOutFrameList))
{
aloge("fatal error! outReadyFrame must be 0!");
}
int nodeNum = 0;
if(!list_empty(&pTextEncData->mIdleOutFrameList))
{
ENCODER_NODE_T *pEntry, *pTmp;
list_for_each_entry_safe(pEntry, pTmp, &pTextEncData->mIdleOutFrameList, mList)
{
list_del(&pEntry->mList);
free(pEntry);
nodeNum++;
}
}
if(nodeNum != pTextEncData->mFrameNodeNum)
{
aloge("Fatal error! TextEnc frame_node number is not match: [%d][%d]", nodeNum, pTextEncData->mFrameNodeNum);
}
pthread_mutex_unlock(&pTextEncData->mOutFrameListMutex);
pthread_mutex_destroy(&pTextEncData->mInputTextMutex);
pthread_mutex_destroy(&pTextEncData->mOutFrameListMutex);
pthread_mutex_destroy(&pTextEncData->mStateLock);
pthread_cond_destroy(&pTextEncData->mOutFrameFullCondition);
pthread_cond_destroy(&pTextEncData->mOutFrameCondition);
if(NULL != pTextEncData)
{
close(pTextEncData->mOutputFrameNotifyPipeFds[0]);
close(pTextEncData->mOutputFrameNotifyPipeFds[1]);
}
if (pTextEncData)
{
free(pTextEncData);
}
alogd("TextEnc component exited!");
return eError;
}