1738 lines
65 KiB
C
1738 lines
65 KiB
C
|
/******************************************************************************
|
||
|
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
|
||
|
******************************************************************************
|
||
|
File Name : AIChannel_Component.c
|
||
|
Version : Initial Draft
|
||
|
Author : Allwinner BU3-PD2 Team
|
||
|
Created : 2016/04/27
|
||
|
Last Modified :
|
||
|
Description : mpi functions implement
|
||
|
Function List :
|
||
|
History :
|
||
|
******************************************************************************/
|
||
|
|
||
|
//#define LOG_NDEBUG 0
|
||
|
#define LOG_TAG "AIChannel_Component"
|
||
|
#include <utils/plat_log.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <errno.h>
|
||
|
#include <pthread.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <memory.h>
|
||
|
#include <sys/prctl.h>
|
||
|
|
||
|
#include <mm_component.h>
|
||
|
#include <media_common_aio.h>
|
||
|
#include <tmessage.h>
|
||
|
#include <tsemaphore.h>
|
||
|
#include <SystemBase.h>
|
||
|
#include "AIChannel_Component.h"
|
||
|
#include <AIOCompStream.h>
|
||
|
|
||
|
#include <ConfigOption.h>
|
||
|
|
||
|
#include <cdx_list.h>
|
||
|
|
||
|
//#define AI_SAVE_AUDIO_PCM
|
||
|
|
||
|
static void *AIChannel_ComponentThread(void *pThreadData);
|
||
|
|
||
|
AudioCaptureFrameInfo* constructAudioCaptureFrameInfo(unsigned int id)
|
||
|
{
|
||
|
AudioCaptureFrameInfo *pNode = (AudioCaptureFrameInfo*)malloc(sizeof(AudioCaptureFrameInfo));
|
||
|
if(NULL == pNode)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail[%s]!", strerror(errno));
|
||
|
}
|
||
|
memset(pNode, 0, sizeof(*pNode));
|
||
|
pNode->mFrame.mId = id;
|
||
|
return pNode;
|
||
|
}
|
||
|
|
||
|
int clearAudioCaptureFrameInfo(AudioCaptureFrameInfo *pThiz)
|
||
|
{
|
||
|
if(pThiz->mpCaptureFrame)
|
||
|
{
|
||
|
pThiz->mpCaptureFrame->mTimeStamp = -1;
|
||
|
}
|
||
|
if(pThiz->mpAecFrame)
|
||
|
{
|
||
|
pThiz->mpAecFrame->stRefFrame.mTimeStamp = -1;
|
||
|
pThiz->mpAecFrame->bValid = FALSE;
|
||
|
}
|
||
|
if(pThiz->mbMallocFlag)
|
||
|
{
|
||
|
if(pThiz->mFrame.mpAddr)
|
||
|
{
|
||
|
free(pThiz->mFrame.mpAddr);
|
||
|
pThiz->mFrame.mpAddr = NULL;
|
||
|
pThiz->mFrame.mLen = 0;
|
||
|
}
|
||
|
pThiz->mbMallocFlag = FALSE;
|
||
|
}
|
||
|
pThiz->mFrame.mTimeStamp = -1;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void destructAudioCaptureFrameInfo(AudioCaptureFrameInfo *pThiz)
|
||
|
{
|
||
|
if(pThiz->mpCaptureFrame)
|
||
|
{
|
||
|
if(pThiz->mpCaptureFrame->mpAddr)
|
||
|
{
|
||
|
free(pThiz->mpCaptureFrame->mpAddr);
|
||
|
pThiz->mpCaptureFrame->mpAddr = NULL;
|
||
|
pThiz->mpCaptureFrame->mLen = 0;
|
||
|
}
|
||
|
free(pThiz->mpCaptureFrame);
|
||
|
pThiz->mpCaptureFrame = NULL;
|
||
|
}
|
||
|
if(pThiz->mpAecFrame)
|
||
|
{
|
||
|
if(pThiz->mpAecFrame->stRefFrame.mpAddr)
|
||
|
{
|
||
|
free(pThiz->mpAecFrame->stRefFrame.mpAddr);
|
||
|
pThiz->mpAecFrame->stRefFrame.mpAddr = NULL;
|
||
|
pThiz->mpAecFrame->stRefFrame.mLen = 0;
|
||
|
}
|
||
|
free(pThiz->mpAecFrame);
|
||
|
pThiz->mpAecFrame = NULL;
|
||
|
}
|
||
|
if(pThiz->mbMallocFlag)
|
||
|
{
|
||
|
if(pThiz->mFrame.mpAddr)
|
||
|
{
|
||
|
free(pThiz->mFrame.mpAddr);
|
||
|
pThiz->mFrame.mpAddr = NULL;
|
||
|
pThiz->mFrame.mLen = 0;
|
||
|
}
|
||
|
pThiz->mbMallocFlag = FALSE;
|
||
|
}
|
||
|
free(pThiz);
|
||
|
}
|
||
|
|
||
|
static AudioCaptureFrameInfo* SetPCMDataToAudioCaptureFrameInfoList(AI_CHN_DATA_S *pChnData, char *pOutBuf, int nSize,
|
||
|
char *pOutBufExtra, int nSizeExtra, int64_t nPts)
|
||
|
{
|
||
|
int nFrameBytes = nSize + nSizeExtra;
|
||
|
if(list_empty(&pChnData->mIdleOutFrameList))
|
||
|
{
|
||
|
AudioCaptureFrameInfo *pNode = constructAudioCaptureFrameInfo(pChnData->mFrameNodeNum);
|
||
|
list_add_tail(&pNode->mList, &pChnData->mIdleOutFrameList);
|
||
|
pChnData->mFrameNodeNum++;
|
||
|
if(0 == pChnData->mFrameNodeNum % 100)
|
||
|
{
|
||
|
alogw("Be careful! audio capture frame node num reach:%d", pChnData->mFrameNodeNum);
|
||
|
}
|
||
|
}
|
||
|
AudioCaptureFrameInfo *pFrameNode = list_first_entry(&pChnData->mIdleOutFrameList, AudioCaptureFrameInfo, mList);
|
||
|
pFrameNode->pOrigData = pOutBuf;
|
||
|
pFrameNode->nOrigDataLen = nSize;
|
||
|
pFrameNode->pOrigDataExtra = pOutBufExtra;
|
||
|
pFrameNode->nOrigDataExtraLen = nSizeExtra;
|
||
|
if(0 == pChnData->mpAioAttr->mbBypassAec)
|
||
|
{
|
||
|
pFrameNode->mFrame.mSamplerate = pChnData->mpAioAttr->enSamplerate;
|
||
|
pFrameNode->mFrame.mBitwidth = pChnData->mpAioAttr->enBitwidth;
|
||
|
pFrameNode->mFrame.mSoundmode = pChnData->mpAioAttr->enSoundmode;
|
||
|
pFrameNode->mFrame.mTimeStamp = nPts;
|
||
|
pFrameNode->mFrame.mLen = nFrameBytes;
|
||
|
if(NULL == pOutBufExtra)
|
||
|
{
|
||
|
pFrameNode->mFrame.mpAddr = pOutBuf;
|
||
|
pFrameNode->mbMallocFlag = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pFrameNode->mFrame.mpAddr = malloc(nFrameBytes);
|
||
|
if(NULL == pFrameNode->mFrame.mpAddr)
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] malloc fail!", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId);
|
||
|
}
|
||
|
memcpy(pFrameNode->mFrame.mpAddr, pOutBuf, nSize);
|
||
|
memcpy(pFrameNode->mFrame.mpAddr+nSize, pOutBufExtra, nSizeExtra);
|
||
|
pFrameNode->mbMallocFlag = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int nTotalChnNum = pChnData->mpPcmCfg->chnCnt;
|
||
|
int nCaptureChnNum = pChnData->mpAioAttr->mChnCnt;
|
||
|
int nRefChnNum = nTotalChnNum-nCaptureChnNum;
|
||
|
if(nRefChnNum <= 0)
|
||
|
{
|
||
|
aloge("fatal error! why refChnNum wrong?[%d-%d-%d]", nTotalChnNum, nCaptureChnNum, nRefChnNum);
|
||
|
}
|
||
|
if(NULL == pFrameNode->mpCaptureFrame)
|
||
|
{
|
||
|
pFrameNode->mpCaptureFrame = (AUDIO_FRAME_S*)malloc(sizeof(AUDIO_FRAME_S));
|
||
|
if(NULL == pFrameNode->mpCaptureFrame)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail");
|
||
|
}
|
||
|
memset(pFrameNode->mpCaptureFrame, 0, sizeof(AUDIO_FRAME_S));
|
||
|
pFrameNode->mpCaptureFrame->mId = pFrameNode->mFrame.mId;
|
||
|
}
|
||
|
pFrameNode->mpCaptureFrame->mSamplerate = pChnData->mpAioAttr->enSamplerate;
|
||
|
pFrameNode->mpCaptureFrame->mBitwidth = pChnData->mpAioAttr->enBitwidth;
|
||
|
pFrameNode->mpCaptureFrame->mSoundmode = pChnData->mpAioAttr->enSoundmode;
|
||
|
pFrameNode->mpCaptureFrame->mTimeStamp = nPts;
|
||
|
int nCaptureLen = nFrameBytes*nCaptureChnNum/nTotalChnNum;
|
||
|
if(pFrameNode->mpCaptureFrame->mLen < nCaptureLen)
|
||
|
{
|
||
|
if(pFrameNode->mpCaptureFrame->mpAddr)
|
||
|
{
|
||
|
alogw("fatal error! audio capture frame len:%d<%d, check code!", pFrameNode->mpCaptureFrame->mLen, nCaptureLen);
|
||
|
free(pFrameNode->mpCaptureFrame->mpAddr);
|
||
|
pFrameNode->mpCaptureFrame->mpAddr = NULL;
|
||
|
pFrameNode->mpCaptureFrame->mLen = 0;
|
||
|
}
|
||
|
}
|
||
|
if(NULL == pFrameNode->mpCaptureFrame->mpAddr)
|
||
|
{
|
||
|
pFrameNode->mpCaptureFrame->mLen = nFrameBytes*nCaptureChnNum/nTotalChnNum;
|
||
|
pFrameNode->mpCaptureFrame->mpAddr = malloc(pFrameNode->mpCaptureFrame->mLen);
|
||
|
if(NULL == pFrameNode->mpCaptureFrame->mpAddr)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail, len:%d", pFrameNode->mpCaptureFrame->mLen);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(NULL == pFrameNode->mpAecFrame)
|
||
|
{
|
||
|
pFrameNode->mpAecFrame = (AEC_FRAME_S*)malloc(sizeof(AEC_FRAME_S));
|
||
|
if(NULL == pFrameNode->mpAecFrame)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail");
|
||
|
}
|
||
|
memset(pFrameNode->mpAecFrame, 0, sizeof(AEC_FRAME_S));
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mId = pFrameNode->mFrame.mId;
|
||
|
}
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mSamplerate = pChnData->mpAioAttr->enSamplerate;
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mBitwidth = pChnData->mpAioAttr->enBitwidth;
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mSoundmode = pChnData->mpAioAttr->enSoundmode;
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mTimeStamp = nPts;
|
||
|
int nRefLen = nFrameBytes*nRefChnNum/nTotalChnNum;
|
||
|
if(pFrameNode->mpAecFrame->stRefFrame.mLen < nRefLen)
|
||
|
{
|
||
|
if(pFrameNode->mpAecFrame->stRefFrame.mpAddr)
|
||
|
{
|
||
|
alogw("fatal error! audio ref frame len:%d<%d, check code!", pFrameNode->mpAecFrame->stRefFrame.mLen, nRefLen);
|
||
|
free(pFrameNode->mpAecFrame->stRefFrame.mpAddr);
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mpAddr = NULL;
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mLen = 0;
|
||
|
}
|
||
|
}
|
||
|
if(NULL == pFrameNode->mpAecFrame->stRefFrame.mpAddr)
|
||
|
{
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mLen = nFrameBytes*nRefChnNum/nTotalChnNum;
|
||
|
pFrameNode->mpAecFrame->stRefFrame.mpAddr = malloc(pFrameNode->mpAecFrame->stRefFrame.mLen);
|
||
|
if(NULL == pFrameNode->mpAecFrame->stRefFrame.mpAddr)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail, len:%d", pFrameNode->mpAecFrame->stRefFrame.mLen);
|
||
|
}
|
||
|
}
|
||
|
//divide pcm data to capture frame and refFrame.
|
||
|
int nCapAlsaFrameBytes = pChnData->mAudioHwOutputAlsaFrameBytes*nCaptureChnNum/nTotalChnNum;
|
||
|
int nRefAlsaFrameBytes = pChnData->mAudioHwOutputAlsaFrameBytes*nRefChnNum/nTotalChnNum;
|
||
|
if(nCapAlsaFrameBytes + nRefAlsaFrameBytes != pChnData->mAudioHwOutputAlsaFrameBytes)
|
||
|
{
|
||
|
aloge("fatal error! why alsaFrame divide is wrong?[%d-%d-%d]", nCapAlsaFrameBytes, nRefAlsaFrameBytes,
|
||
|
pChnData->mAudioHwOutputAlsaFrameBytes);
|
||
|
}
|
||
|
int nAlsaFrameCnt = nSize/pChnData->mAudioHwOutputAlsaFrameBytes;
|
||
|
if(nSize%pChnData->mAudioHwOutputAlsaFrameBytes != 0)
|
||
|
{
|
||
|
aloge("fatal error! PCMBufDataLen error! [%d-%d]", nSize, pChnData->mAudioHwOutputAlsaFrameBytes);
|
||
|
}
|
||
|
if(pOutBuf)
|
||
|
{
|
||
|
char *pCaptureAddr = (char*)pFrameNode->mpCaptureFrame->mpAddr;
|
||
|
char *pRefAddr = (char*)pFrameNode->mpAecFrame->stRefFrame.mpAddr;
|
||
|
for(int i=0; i<nAlsaFrameCnt; i++)
|
||
|
{
|
||
|
memcpy(pCaptureAddr+i*nCapAlsaFrameBytes, pOutBuf+i*pChnData->mAudioHwOutputAlsaFrameBytes, nCapAlsaFrameBytes);
|
||
|
memcpy(pRefAddr+i*nRefAlsaFrameBytes, pOutBuf+i*pChnData->mAudioHwOutputAlsaFrameBytes+nCapAlsaFrameBytes, nRefAlsaFrameBytes);
|
||
|
}
|
||
|
}
|
||
|
int nExtraAlsaFrameCnt = nSizeExtra/pChnData->mAudioHwOutputAlsaFrameBytes;
|
||
|
if(nSizeExtra%pChnData->mAudioHwOutputAlsaFrameBytes != 0)
|
||
|
{
|
||
|
aloge("fatal error! PCMBufDataLenExtra error! [%d-%d]", nSizeExtra, pChnData->mAudioHwOutputAlsaFrameBytes);
|
||
|
}
|
||
|
if(pOutBufExtra)
|
||
|
{
|
||
|
char *pExtraCaptureAddr = (char*)pFrameNode->mpCaptureFrame->mpAddr + nAlsaFrameCnt*nCapAlsaFrameBytes;
|
||
|
char *pExtraRefAddr = (char*)pFrameNode->mpAecFrame->stRefFrame.mpAddr + nAlsaFrameCnt*nRefAlsaFrameBytes;
|
||
|
for(int i=0; i<nExtraAlsaFrameCnt; i++)
|
||
|
{
|
||
|
memcpy(pExtraCaptureAddr+i*nCapAlsaFrameBytes, pOutBufExtra+i*pChnData->mAudioHwOutputAlsaFrameBytes, nCapAlsaFrameBytes);
|
||
|
memcpy(pExtraRefAddr+i*nRefAlsaFrameBytes, pOutBufExtra+i*pChnData->mAudioHwOutputAlsaFrameBytes+nCapAlsaFrameBytes, nRefAlsaFrameBytes);
|
||
|
}
|
||
|
}
|
||
|
pFrameNode->mpAecFrame->bValid = TRUE;
|
||
|
}
|
||
|
list_move_tail(&pFrameNode->mList, &pChnData->mValidOutFrameList);
|
||
|
return pFrameNode;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE ReleaseAudioCaptureFrame(AI_CHN_DATA_S *pChnData, AUDIO_FRAME_S *pAudioFrame)
|
||
|
{
|
||
|
ERRORTYPE rc = SUCCESS;
|
||
|
int ret;
|
||
|
PCMBufferManager *pCapMgr = pChnData->mpCapMgr;
|
||
|
AudioCaptureFrameInfo *pFrameNode = list_first_entry_or_null(&pChnData->mValidOutFrameList, AudioCaptureFrameInfo, mList);
|
||
|
if(pFrameNode)
|
||
|
{
|
||
|
AUDIO_FRAME_S *pLocalFrame = NULL;
|
||
|
if(0 == pChnData->mpAioAttr->mbBypassAec)
|
||
|
{
|
||
|
pLocalFrame = &pFrameNode->mFrame;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pLocalFrame = pFrameNode->mpCaptureFrame;
|
||
|
if(NULL == pLocalFrame)
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] capture frame NULL!", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId);
|
||
|
}
|
||
|
}
|
||
|
if (pLocalFrame->mId == pAudioFrame->mId && pLocalFrame->mpAddr == pAudioFrame->mpAddr)
|
||
|
{
|
||
|
//release to PCMBufferManager.
|
||
|
if(0 == pChnData->mpAioAttr->mbBypassAec)
|
||
|
{
|
||
|
if(pFrameNode->nOrigDataLen + pFrameNode->nOrigDataExtraLen != pAudioFrame->mLen)
|
||
|
{
|
||
|
aloge("fatal error! dataLen not match:[%d-%d-%d-%d]", pFrameNode->nOrigDataLen, pFrameNode->nOrigDataExtraLen,
|
||
|
pFrameNode->mFrame.mLen, pAudioFrame->mLen);
|
||
|
}
|
||
|
if(false == pFrameNode->mbMallocFlag)
|
||
|
{
|
||
|
if(pFrameNode->mFrame.mpAddr != pFrameNode->pOrigData)
|
||
|
{
|
||
|
aloge("fatal error! pAddr not match[%p-%p]", pFrameNode->mFrame.mpAddr, pFrameNode->pOrigData);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ret = pCapMgr->releaseData(pCapMgr, pFrameNode->pOrigData, pFrameNode->nOrigDataLen+pFrameNode->nOrigDataExtraLen);
|
||
|
if(ret != 0)
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] release data[%p-%d-%p-%d] fail", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId,
|
||
|
pFrameNode->pOrigData, pFrameNode->nOrigDataLen, pFrameNode->pOrigDataExtra, pFrameNode->nOrigDataExtraLen);
|
||
|
}
|
||
|
//clear and move valid frame node to idle list.
|
||
|
clearAudioCaptureFrameInfo(pFrameNode);
|
||
|
list_move_tail(&pFrameNode->mList, &pChnData->mIdleOutFrameList);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] local frame not match![%d-%d,%p-%p]", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId,
|
||
|
pLocalFrame->mId, pAudioFrame->mId, pLocalFrame->mpAddr, pAudioFrame->mpAddr);
|
||
|
rc = ERR_AI_NOBUF;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] has no valid out frame?", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId);
|
||
|
rc = ERR_AI_NOBUF;
|
||
|
}
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* get frame, used in non-tunnel mode.
|
||
|
*
|
||
|
* @return SUCCESS.
|
||
|
* @param hComponent ai component.
|
||
|
* @param pAudioFrame store frame info, caller malloc.
|
||
|
* @param nMilliSec 0:return immediately, <0:wait forever, >0:wait some time.
|
||
|
*/
|
||
|
static ERRORTYPE AIChannel_GetFrame(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_OUT AUDIO_FRAME_S *pAudioFrame,
|
||
|
PARAM_OUT AEC_FRAME_S *pAecFrame,
|
||
|
PARAM_IN int nMilliSec)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
PCMBufferManager *pCapMgr = pChnData->mpCapMgr;
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
int ret;
|
||
|
|
||
|
if (COMP_StateIdle != pChnData->state && COMP_StateExecuting != pChnData->state)
|
||
|
{
|
||
|
alogw("call GetFrame() in wrong state[0x%x]", pChnData->state);
|
||
|
return ERR_AI_NOT_PERM;
|
||
|
}
|
||
|
if (pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC] || pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO])
|
||
|
{
|
||
|
aloge("fatal error! can't call GetFrame() in tunnel mode!");
|
||
|
return ERR_AI_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
int nFrameBytes = pChnData->mAiChnAttr.nFrameSize*pChnData->mAudioHwOutputAlsaFrameBytes;
|
||
|
char *pOutBuf = NULL;
|
||
|
int nSize = 0;
|
||
|
char *pOutBufExtra = NULL;
|
||
|
int nSizeExtra = 0;
|
||
|
int64_t nPts = 0;
|
||
|
_TryToGetOutFrame:
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
ret = pCapMgr->getData(pCapMgr, nFrameBytes, &pOutBuf, &nSize, &pOutBufExtra, &nSizeExtra, &nPts);
|
||
|
if (0 == ret)
|
||
|
{
|
||
|
if(nFrameBytes != (nSize+nSizeExtra))
|
||
|
{
|
||
|
aloge("fatal error! PCM buffer size is not match:%d-%d-%d", nFrameBytes, nSize, nSizeExtra);
|
||
|
}
|
||
|
//1. set PCMBuf data to AudioCaptureFrameInfo list.
|
||
|
AudioCaptureFrameInfo *pFrameNode = SetPCMDataToAudioCaptureFrameInfoList(pChnData, pOutBuf, nSize, pOutBufExtra, nSizeExtra, nPts);
|
||
|
if(NULL == pFrameNode)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail");
|
||
|
}
|
||
|
//2. fill pAudioFrame and pAecFrame.
|
||
|
if(0 == pChnData->mpAioAttr->mbBypassAec) //pChnData->mpAioAttr->mbBypassAec is 0. NULL == pFrameNode->mpCaptureFrame
|
||
|
{
|
||
|
memcpy(pAudioFrame, &pFrameNode->mFrame, sizeof(AUDIO_FRAME_S));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(pAudioFrame, pFrameNode->mpCaptureFrame, sizeof(AUDIO_FRAME_S));
|
||
|
if(pAecFrame)
|
||
|
{
|
||
|
memcpy(pAecFrame, pFrameNode->mpAecFrame, sizeof(AEC_FRAME_S));
|
||
|
}
|
||
|
}
|
||
|
eError = SUCCESS;
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
if (nMilliSec == 0)
|
||
|
{
|
||
|
eError = ERR_AI_BUF_EMPTY;
|
||
|
}
|
||
|
else if (nMilliSec < 0)
|
||
|
{
|
||
|
//pChnData->mWaitingOutFrameFlag = TRUE;
|
||
|
cdx_sem_down(&pChnData->mWaitOutFrameSem);
|
||
|
//pChnData->mWaitingOutFrameFlag = FALSE;
|
||
|
goto _TryToGetOutFrame;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//pChnData->mWaitingOutFrameFlag = TRUE;
|
||
|
ret = cdx_sem_down_timedwait(&pChnData->mWaitOutFrameSem, nMilliSec);
|
||
|
if (ETIMEDOUT == ret)
|
||
|
{
|
||
|
alogv("wait output frame timeout[%d]ms, ret[%d]", nMilliSec, ret);
|
||
|
eError = ERR_AI_BUF_EMPTY;
|
||
|
//pChnData->mWaitingOutFrameFlag = FALSE;
|
||
|
}
|
||
|
else if (0 == ret)
|
||
|
{
|
||
|
//pChnData->mWaitingOutFrameFlag = FALSE;
|
||
|
goto _TryToGetOutFrame;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! AI pthread cond wait timeout ret[%d]", ret);
|
||
|
eError = ERR_AI_BUF_EMPTY;
|
||
|
//pChnData->mWaitingOutFrameFlag = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* release frame, used in non-tunnel mode.
|
||
|
*
|
||
|
* @return SUCCESS.
|
||
|
* @param hComponent ai component.
|
||
|
* @param pAudioFrame frame info.
|
||
|
*/
|
||
|
static ERRORTYPE AIChannel_ReleaseFrame(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN AUDIO_FRAME_S *pAudioFrame)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
|
||
|
if (COMP_StateIdle != pChnData->state && COMP_StateExecuting != pChnData->state)
|
||
|
{
|
||
|
alogw("call ReleaseFrame in wrong state[0x%x]", pChnData->state);
|
||
|
return ERR_AI_SYS_NOTREADY;
|
||
|
}
|
||
|
if (pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC] || pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO])
|
||
|
{
|
||
|
aloge("fatal error! can't call ReleaseFrame in tunnel mode!");
|
||
|
return ERR_AI_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
bool bFound = false;
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
if(SUCCESS == ReleaseAudioCaptureFrame(pChnData, pAudioFrame))
|
||
|
{
|
||
|
bFound = true;
|
||
|
}
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
if (bFound)
|
||
|
{
|
||
|
if (pChnData->mWaitAllFrameReleaseFlag)
|
||
|
{
|
||
|
cdx_sem_up_unique(&pChnData->mAllFrameRelSem);
|
||
|
}
|
||
|
eError = SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d]AI frame[%p][%u] is not find, maybe reset channel before call this function?",
|
||
|
pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId, pAudioFrame->mpAddr, pAudioFrame->mLen);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
}
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_SetSaveFileInfo(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN AUDIO_SAVE_FILE_INFO_S *pFileInfo)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
|
||
|
if (COMP_StateIdle != pChnData->state && COMP_StateExecuting != pChnData->state)
|
||
|
{
|
||
|
aloge("call SetSaveFileInfo in wrong state[0x%x]!", pChnData->state);
|
||
|
return ERR_AI_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
int nPathLen = strlen(pFileInfo->mFilePath) + strlen(pFileInfo->mFileName) + 1;
|
||
|
pChnData->mpSaveFileFullPath = (char*)malloc(nPathLen);
|
||
|
if (NULL == pChnData->mpSaveFileFullPath)
|
||
|
{
|
||
|
aloge("malloc %d fail! FilePath:[%s], FileName:[%s]", nPathLen, pFileInfo->mFilePath, pFileInfo->mFileName);
|
||
|
return ERR_AI_NOMEM;
|
||
|
}
|
||
|
|
||
|
memset(pChnData->mpSaveFileFullPath, 0, nPathLen);
|
||
|
strcpy(pChnData->mpSaveFileFullPath, pFileInfo->mFilePath);
|
||
|
strcat(pChnData->mpSaveFileFullPath, pFileInfo->mFileName);
|
||
|
pChnData->mFpSaveFile = fopen(pChnData->mpSaveFileFullPath, "wb+");
|
||
|
if (pChnData->mFpSaveFile)
|
||
|
{
|
||
|
alogd("create file(%s) to save pcm file", pChnData->mpSaveFileFullPath);
|
||
|
pChnData->mSaveFileFlag = TRUE;
|
||
|
pChnData->mSaveFileSize = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("create file(%s) failed!", pChnData->mpSaveFileFullPath);
|
||
|
pChnData->mSaveFileFlag = FALSE;
|
||
|
}
|
||
|
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_QueryFileStatus(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_OUT AUDIO_SAVE_FILE_INFO_S *pFileInfo)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
|
||
|
if (COMP_StateIdle != pChnData->state && COMP_StateExecuting != pChnData->state)
|
||
|
{
|
||
|
aloge("call SetSaveFileInfo in wrong state[0x%x]!", pChnData->state);
|
||
|
return ERR_AI_NOT_PERM;
|
||
|
}
|
||
|
|
||
|
memset(pFileInfo, 0, sizeof(AUDIO_SAVE_FILE_INFO_S));
|
||
|
if (pChnData->mSaveFileFlag)
|
||
|
{
|
||
|
pFileInfo->bCfg = pChnData->mSaveFileFlag;
|
||
|
pFileInfo->mFileSize = pChnData->mSaveFileSize;
|
||
|
const char *ptr = strrchr(pChnData->mpSaveFileFullPath, '/');
|
||
|
int pathLen = ptr - pChnData->mpSaveFileFullPath;
|
||
|
strncpy(pFileInfo->mFilePath, pChnData->mpSaveFileFullPath, pathLen);
|
||
|
strcpy(pFileInfo->mFileName, ptr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
alogw("AI NOT in save file status!");
|
||
|
}
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_SetChnMute(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN BOOL bMute)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
pChnData->mbMute = bMute;
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_GetChnMute(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_OUT BOOL *pbMute)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
*pbMute = pChnData->mbMute;
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
static ERRORTYPE AIChannel_IgnoreData(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN BOOL bIgnore)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
pthread_mutex_lock(&pChnData->mIgnoreDataLock);
|
||
|
pChnData->mbIgnore = bIgnore;
|
||
|
pthread_mutex_unlock(&pChnData->mIgnoreDataLock);
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_SendCommand(PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN COMP_COMMANDTYPE Cmd, PARAM_IN unsigned int nParam1, PARAM_IN void* pCmdData)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S *)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
CompInternalMsgType eCmd;
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
message_t msg;
|
||
|
|
||
|
//alogv("Command: %d", Cmd);
|
||
|
if (NULL == pChnData) {
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
|
||
|
if (Cmd == COMP_CommandMarkBuffer) {
|
||
|
if (NULL == pCmdData) {
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pChnData->state == COMP_StateInvalid) {
|
||
|
eError = ERR_AI_SYS_NOTREADY;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
|
||
|
switch (Cmd) {
|
||
|
case COMP_CommandStateSet:
|
||
|
eCmd = SetState;
|
||
|
break;
|
||
|
|
||
|
case COMP_CommandFlush:
|
||
|
eCmd = Flush;
|
||
|
break;
|
||
|
|
||
|
case COMP_CommandPortDisable:
|
||
|
eCmd = StopPort;
|
||
|
break;
|
||
|
|
||
|
case COMP_CommandPortEnable:
|
||
|
eCmd = RestartPort;
|
||
|
break;
|
||
|
|
||
|
case COMP_CommandMarkBuffer:
|
||
|
eCmd = MarkBuf;
|
||
|
if (nParam1 > 0) {
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
eCmd = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
msg.command = eCmd;
|
||
|
msg.para0 = nParam1;
|
||
|
put_message(&pChnData->mCmdQueue, &msg);
|
||
|
|
||
|
COMP_CONF_CMD_BAIL:
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_GetState(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_OUT COMP_STATETYPE* pState)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
|
||
|
if (NULL == pChnData || NULL == pState) {
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
|
||
|
*pState = pChnData->state;
|
||
|
|
||
|
COMP_CONF_CMD_BAIL:
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_SetCallbacks(PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN COMP_CALLBACKTYPE* pCallbacks, PARAM_IN void* pAppData)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
|
||
|
if (NULL == pChnData || NULL == pCallbacks || NULL == pAppData) {
|
||
|
aloge("pChnData=%p, pCallbacks=%p, pAppData=%p", pChnData, pCallbacks, pAppData);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CONF_CMD_BAIL;
|
||
|
}
|
||
|
|
||
|
pChnData->pCallbacks = pCallbacks;
|
||
|
pChnData->pAppData = pAppData;
|
||
|
|
||
|
COMP_CONF_CMD_BAIL:
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_SetConfig(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN COMP_INDEXTYPE nIndex,
|
||
|
PARAM_IN void* pComponentConfigStructure)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
|
||
|
MM_COMPONENTTYPE *pAOTunnelComp = NULL;
|
||
|
COMP_INTERNAL_TUNNELINFOTYPE* pAOTunnel = NULL;
|
||
|
|
||
|
switch (nIndex)
|
||
|
{
|
||
|
case COMP_IndexParamPortDefinition:
|
||
|
{
|
||
|
COMP_PARAM_PORTDEFINITIONTYPE *port = (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure;
|
||
|
int i;
|
||
|
for(i = 0; i < AI_CHN_MAX_PORTS; i++) {
|
||
|
if (port->nPortIndex == pChnData->sPortDef[i].nPortIndex) {
|
||
|
memcpy(&pChnData->sPortDef[i], port, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
|
||
|
}
|
||
|
}
|
||
|
if (i == AI_CHN_MAX_PORTS) {
|
||
|
eError = FAILURE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexParamCompBufferSupplier:
|
||
|
{
|
||
|
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier = (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure;
|
||
|
int i;
|
||
|
for(i=0; i<AI_CHN_MAX_PORTS; i++) {
|
||
|
if(pChnData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex) {
|
||
|
memcpy(&pChnData->sPortBufSupplier[i], pPortBufSupplier, sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(i == AI_CHN_MAX_PORTS) {
|
||
|
eError = FAILURE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorMPPChannelInfo:
|
||
|
{
|
||
|
pChnData->mMppChnInfo = *(MPP_CHN_S*)pComponentConfigStructure;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnReleaseFrame:
|
||
|
{
|
||
|
AudioFrame *pAudioFrame = (AudioFrame*)pComponentConfigStructure;
|
||
|
eError = AIChannel_ReleaseFrame(hComponent, pAudioFrame->pFrame);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnAttr:
|
||
|
{
|
||
|
AI_CHN_ATTR_S *pChnAttr = (AI_CHN_ATTR_S*)pComponentConfigStructure;
|
||
|
if(pChnAttr)
|
||
|
{
|
||
|
pChnData->mAiChnAttr = *pChnAttr;
|
||
|
}
|
||
|
if(0 == pChnData->mAiChnAttr.nFrameSize)
|
||
|
{
|
||
|
pChnData->mAiChnAttr.nFrameSize = pChnData->mpPcmCfg->chunkSize;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnParameter:
|
||
|
{
|
||
|
pChnData->mParam = *(AI_CHN_PARAM_S*)pComponentConfigStructure;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOVqeAttr:
|
||
|
{//
|
||
|
memcpy(&pChnData->mVqeCfg, (AI_VQE_CONFIG_S*)pComponentConfigStructure, sizeof(AI_VQE_CONFIG_S));
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOVqeEnable:
|
||
|
{//
|
||
|
pChnData->mUseVqeLib = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOVqeDisable:
|
||
|
{
|
||
|
pChnData->mUseVqeLib = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOReSmpEnable:
|
||
|
{
|
||
|
// todo
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOReSmpDisable:
|
||
|
{
|
||
|
// todo
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAISetSaveFileInfo:
|
||
|
{
|
||
|
AUDIO_SAVE_FILE_INFO_S *pSaveFileInfo = (AUDIO_SAVE_FILE_INFO_S*)pComponentConfigStructure;
|
||
|
eError = AIChannel_SetSaveFileInfo(hComponent, pSaveFileInfo);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnMute:
|
||
|
{
|
||
|
eError = AIChannel_SetChnMute(hComponent, *(BOOL*)pComponentConfigStructure);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIIgnoreData:
|
||
|
{
|
||
|
eError = AIChannel_IgnoreData(hComponent, *(BOOL*)pComponentConfigStructure);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
eError = FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_GetConfig(
|
||
|
PARAM_IN COMP_HANDLETYPE hComponent,
|
||
|
PARAM_IN COMP_INDEXTYPE nIndex,
|
||
|
PARAM_INOUT void* pComponentConfigStructure)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
|
||
|
switch (nIndex)
|
||
|
{
|
||
|
case COMP_IndexParamPortDefinition:
|
||
|
{
|
||
|
COMP_PARAM_PORTDEFINITIONTYPE *port = (COMP_PARAM_PORTDEFINITIONTYPE*)pComponentConfigStructure;
|
||
|
int i;
|
||
|
for(i = 0; i < AI_CHN_MAX_PORTS; i++) {
|
||
|
if (port->nPortIndex == pChnData->sPortDef[i].nPortIndex) {
|
||
|
memcpy(port, &pChnData->sPortDef[i], sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
|
||
|
}
|
||
|
}
|
||
|
if (i == AI_CHN_MAX_PORTS) {
|
||
|
eError = FAILURE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexParamCompBufferSupplier:
|
||
|
{
|
||
|
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier = (COMP_PARAM_BUFFERSUPPLIERTYPE*)pComponentConfigStructure;
|
||
|
int i;
|
||
|
for(i=0; i<AI_CHN_MAX_PORTS; i++) {
|
||
|
if(pChnData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex) {
|
||
|
memcpy(pPortBufSupplier, &pChnData->sPortBufSupplier[i], sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(i == AI_CHN_MAX_PORTS) {
|
||
|
eError = FAILURE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorMPPChannelInfo:
|
||
|
{
|
||
|
*(MPP_CHN_S*)pComponentConfigStructure = pChnData->mMppChnInfo;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnGetValidFrame:
|
||
|
{
|
||
|
AudioFrame *pAudioFrame = (AudioFrame *)pComponentConfigStructure;
|
||
|
eError = AIChannel_GetFrame(hComponent, pAudioFrame->pFrame, pAudioFrame->pAecFrame, pAudioFrame->nMilliSec);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnAttr:
|
||
|
{
|
||
|
*(AI_CHN_ATTR_S*)pComponentConfigStructure = pChnData->mAiChnAttr;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnParameter:
|
||
|
{
|
||
|
*(AI_CHN_PARAM_S*)pComponentConfigStructure = pChnData->mParam;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIOVqeAttr:
|
||
|
{
|
||
|
*(AI_VQE_CONFIG_S*)pComponentConfigStructure = pChnData->mVqeCfg;
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnGetFreeFrame:
|
||
|
{
|
||
|
// if (pChnData->state != COMP_StateExecuting) {
|
||
|
// eError = FAILURE;
|
||
|
// break;
|
||
|
// }
|
||
|
|
||
|
// AUDIO_FRAME_S *tmp = pChnData->mpCapMgr->getFreeFrame(pChnData->mpCapMgr);
|
||
|
// if (tmp != NULL) {
|
||
|
// *(AUDIO_FRAME_S *)pComponentConfigStructure = *tmp;
|
||
|
// eError = SUCCESS;
|
||
|
// } else {
|
||
|
// eError = FAILURE;
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIQueryFileStatus:
|
||
|
{
|
||
|
AUDIO_SAVE_FILE_INFO_S *pSaveFileInfo = (AUDIO_SAVE_FILE_INFO_S*)pComponentConfigStructure;
|
||
|
eError = AIChannel_QueryFileStatus(hComponent, pSaveFileInfo);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_IndexVendorAIChnMute:
|
||
|
{
|
||
|
eError = AIChannel_GetChnMute(hComponent, (BOOL*)pComponentConfigStructure);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
eError = FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_ComponentTunnelRequest(
|
||
|
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;
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
COMP_PARAM_PORTDEFINITIONTYPE *pPortDef;
|
||
|
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo;
|
||
|
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier;
|
||
|
int i;
|
||
|
|
||
|
if (pChnData->state == COMP_StateExecuting)
|
||
|
{
|
||
|
alogw("Be careful! tunnel request may be some danger in StateExecuting");
|
||
|
}
|
||
|
else if(pChnData->state != COMP_StateIdle)
|
||
|
{
|
||
|
aloge("fatal error! tunnel request can't be in state[0x%x]", pChnData->state);
|
||
|
eError = ERR_AI_INCORRECT_STATE_OPERATION;
|
||
|
goto COMP_CMD_FAIL;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < AI_CHN_MAX_PORTS; ++i) {
|
||
|
if (pChnData->sPortDef[i].nPortIndex == nPort) {
|
||
|
pPortDef = &pChnData->sPortDef[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i == AI_CHN_MAX_PORTS) {
|
||
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CMD_FAIL;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < AI_CHN_MAX_PORTS; ++i) {
|
||
|
if (pChnData->sPortTunnelInfo[i].nPortIndex == nPort) {
|
||
|
pPortTunnelInfo = &pChnData->sPortTunnelInfo[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i == AI_CHN_MAX_PORTS) {
|
||
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
goto COMP_CMD_FAIL;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < AI_CHN_MAX_PORTS; ++i) {
|
||
|
if (pChnData->sPortBufSupplier[i].nPortIndex == nPort) {
|
||
|
pPortBufSupplier = &pChnData->sPortBufSupplier[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i == AI_CHN_MAX_PORTS) {
|
||
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
||
|
eError = ERR_AI_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("Cancel setup tunnel on port[%d]", nPort);
|
||
|
eError = SUCCESS;
|
||
|
goto COMP_CMD_FAIL;
|
||
|
}
|
||
|
if(pPortDef->eDir == COMP_DirOutput) {
|
||
|
if (pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC] || pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO]) {
|
||
|
aloge("AI_Comp outport already bind, why bind again?!");
|
||
|
eError = FAILURE;
|
||
|
goto COMP_CMD_FAIL;
|
||
|
}
|
||
|
pTunnelSetup->nTunnelFlags = 0;
|
||
|
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
|
||
|
// judge which B: aenc or ao?
|
||
|
COMP_PARAM_PORTDEFINITIONTYPE out_port_def;
|
||
|
out_port_def.nPortIndex = nTunneledPort;
|
||
|
if (pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].nPortIndex == nPort)
|
||
|
pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC] = TRUE;
|
||
|
else if (pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].nPortIndex == nPort)
|
||
|
pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO] = TRUE;
|
||
|
else
|
||
|
aloge("fatal error! ao bind with portIndex(%d, %d)", nPort, nTunneledPort);
|
||
|
|
||
|
} else {
|
||
|
//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_AI_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);
|
||
|
|
||
|
|
||
|
if (pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].nPortIndex == nPort)
|
||
|
{
|
||
|
pChnData->mInputPortTunnelFlag[AI_CHN_PORT_INDEX_CAP_IN] = TRUE;
|
||
|
}
|
||
|
else if (pChnData->sPortDef[AI_CHN_PORT_INDEX_AO_IN].nPortIndex == nPort)
|
||
|
{
|
||
|
pChnData->mInputPortTunnelFlag[AI_CHN_PORT_INDEX_AO_IN] = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
COMP_CMD_FAIL:
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_EmptyThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
|
||
|
{
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
int ret;
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
|
||
|
//pthread_mutex_lock(&pChnData->mStateLock);
|
||
|
if (pChnData->state != COMP_StateExecuting)
|
||
|
{
|
||
|
//aloge("send frame when AI channel state[0x%x] is not executing", pChnData->state);
|
||
|
eError = ERR_AI_SYS_NOTREADY;
|
||
|
goto EIXT;
|
||
|
}
|
||
|
|
||
|
if (pBuffer->nOutputPortIndex == pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].nPortIndex)
|
||
|
{
|
||
|
AUDIO_FRAME_S *pSrcFrm = (AUDIO_FRAME_S*)pBuffer->pOutputPortPrivate;
|
||
|
|
||
|
pthread_mutex_lock(&pChnData->mIgnoreDataLock);
|
||
|
BOOL bIgnoreFlag = pChnData->mbIgnore;
|
||
|
pthread_mutex_unlock(&pChnData->mIgnoreDataLock);
|
||
|
if(bIgnoreFlag != TRUE)
|
||
|
{
|
||
|
AISendDataInfo stAudioInfo;
|
||
|
memset(&stAudioInfo, 0, sizeof(AISendDataInfo));
|
||
|
stAudioInfo.mLen = pSrcFrm->mLen;
|
||
|
stAudioInfo.mbIgnore = 0;
|
||
|
stAudioInfo.mPts = pSrcFrm->mTimeStamp;
|
||
|
pChnData->pCallbacks->EventHandler(pChnData->hSelf, pChnData->pAppData, COMP_EventBufferPrefilled, 0, 0, (void*)&stAudioInfo);
|
||
|
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
ret = pChnData->mpCapMgr->writeData(pChnData->mpCapMgr, pSrcFrm->mpAddr, pSrcFrm->mLen, (int64_t)pSrcFrm->mTimeStamp, (bool)pChnData->mbMute);
|
||
|
if(0 == ret)
|
||
|
{
|
||
|
if (pChnData->mWaitingCapDataFlag)
|
||
|
{
|
||
|
pChnData->mWaitingCapDataFlag = FALSE;
|
||
|
message_t msg;
|
||
|
msg.command = AIChannel_CapDataAvailable;
|
||
|
put_message(&pChnData->mCmdQueue, &msg);
|
||
|
}
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
cdx_sem_up_unique(&pChnData->mWaitOutFrameSem);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
//aloge("no node in FreeFrameList!");
|
||
|
//PcmBufferManager *pBufMgr = pChnData->mpCapMgr;
|
||
|
//aloge("PcmBufMgrFrmCntInfo >> FillingList:%d, ValidList:%d, UsingList:%d", pBufMgr->fillingFrmCnt(pBufMgr),
|
||
|
// pBufMgr->validFrmCnt(pBufMgr), pBufMgr->usingFrmCnt(pBufMgr));
|
||
|
pChnData->mDiscardLen += pSrcFrm->mLen;
|
||
|
pChnData->mDiscardNum++;
|
||
|
if(pChnData->mDiscardNum%32 == 0)
|
||
|
{
|
||
|
alogw("Be careful! aiChn[%d-%d] discard audio block num:%d, discard audio data len:%d", pChnData->mMppChnInfo.mDevId,
|
||
|
pChnData->mMppChnInfo.mChnId, pChnData->mDiscardNum, pChnData->mDiscardLen);
|
||
|
}
|
||
|
eError = ERR_AI_BUF_FULL;
|
||
|
goto EIXT;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//CompSendEvent(pChnData, COMP_EventBufferPrefilled, pFrm->mLen, 1);
|
||
|
AISendDataInfo stAudioInfo;
|
||
|
memset(&stAudioInfo, 0, sizeof(AISendDataInfo));
|
||
|
stAudioInfo.mLen = pSrcFrm->mLen;
|
||
|
stAudioInfo.mbIgnore = 1;
|
||
|
stAudioInfo.mPts = pSrcFrm->mTimeStamp;
|
||
|
pChnData->pCallbacks->EventHandler(pChnData->hSelf, pChnData->pAppData, COMP_EventBufferPrefilled, 0, 0, (void*)&stAudioInfo);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! inputPortIndex[%d] match nothing!", pBuffer->nOutputPortIndex);
|
||
|
}
|
||
|
|
||
|
EIXT:
|
||
|
//pthread_mutex_unlock(&pChnData->mStateLock);
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* release frame, used in tunnel mode.
|
||
|
* usualy use it when ao return frame to ai
|
||
|
*
|
||
|
* @return SUCCESS.
|
||
|
* @param hComponent ai component.
|
||
|
* @param pAudioFrame frame info.
|
||
|
*/
|
||
|
static ERRORTYPE AIChannel_FillThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer)
|
||
|
{
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
|
||
|
if (pBuffer->nOutputPortIndex == pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].nPortIndex
|
||
|
|| pBuffer->nOutputPortIndex == pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].nPortIndex)
|
||
|
{
|
||
|
AUDIO_FRAME_S *pFrm = (AUDIO_FRAME_S*)pBuffer->pOutputPortPrivate;
|
||
|
bool bFound = false;
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
if(SUCCESS == ReleaseAudioCaptureFrame(pChnData, pFrm))
|
||
|
{
|
||
|
bFound = true;
|
||
|
}
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
if (bFound)
|
||
|
{
|
||
|
if (pChnData->mWaitAllFrameReleaseFlag)
|
||
|
{
|
||
|
cdx_sem_up_unique(&pChnData->mAllFrameRelSem);
|
||
|
}
|
||
|
eError = SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] return audio frame[%p-%d] is not find", pChnData->mMppChnInfo.mDevId,
|
||
|
pChnData->mMppChnInfo.mChnId, pFrm->mpAddr, pFrm->mLen);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aloge("fatal error! frame portIndex[%d-%d] wrong", pBuffer->nOutputPortIndex, pBuffer->nInputPortIndex);
|
||
|
eError = ERR_AI_ILLEGAL_PARAM;
|
||
|
}
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static ERRORTYPE AIChannel_ComponentDeInit(PARAM_IN COMP_HANDLETYPE hComponent)
|
||
|
{
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)(((MM_COMPONENTTYPE*)hComponent)->pComponentPrivate);
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
CompInternalMsgType eCmd = Stop;
|
||
|
message_t msg;
|
||
|
int ret = 0;
|
||
|
|
||
|
if(pChnData->mDiscardNum > 0)
|
||
|
{
|
||
|
alogw("Be careful! aiDev[%d]Chn[%d] discard audio block num:%d, discard audio data len:%d",
|
||
|
pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId, pChnData->mDiscardNum, pChnData->mDiscardLen);
|
||
|
}
|
||
|
msg.command = eCmd;
|
||
|
put_message(&pChnData->mCmdQueue, &msg);
|
||
|
alogv("wait AI channel component exit!...");
|
||
|
|
||
|
// Wait for thread to exit so we can get the status into "error"
|
||
|
pthread_join(pChnData->mThreadId, (void*) &eError);
|
||
|
message_destroy(&pChnData->mCmdQueue);
|
||
|
|
||
|
cdx_sem_deinit(&pChnData->mAllFrameRelSem);
|
||
|
cdx_sem_deinit(&pChnData->mWaitOutFrameSem);
|
||
|
//cdx_sem_deinit(&pChnData->mWaitGetAllOutFrameSem);
|
||
|
|
||
|
pthread_mutex_destroy(&pChnData->mStateLock);
|
||
|
pthread_mutex_destroy(&pChnData->mCapMgrLock);
|
||
|
pthread_mutex_destroy(&pChnData->mIgnoreDataLock);
|
||
|
|
||
|
if(!list_empty(&pChnData->mValidOutFrameList))
|
||
|
{
|
||
|
int cnt = 0;
|
||
|
struct list_head *pList;list_for_each(pList, &pChnData->mValidOutFrameList) { cnt++; }
|
||
|
aloge("fatal error! valid out frame list has %d nodes", cnt);
|
||
|
list_splice_tail_init(&pChnData->mValidOutFrameList, &pChnData->mIdleOutFrameList);
|
||
|
}
|
||
|
if(!list_empty(&pChnData->mIdleOutFrameList))
|
||
|
{
|
||
|
int cnt = 0;
|
||
|
AudioCaptureFrameInfo *pEntry, *pTmp;
|
||
|
list_for_each_entry_safe(pEntry, pTmp, &pChnData->mIdleOutFrameList, mList)
|
||
|
{
|
||
|
list_del(&pEntry->mList);
|
||
|
destructAudioCaptureFrameInfo(pEntry);
|
||
|
cnt++;
|
||
|
}
|
||
|
if(cnt != pChnData->mFrameNodeNum)
|
||
|
{
|
||
|
aloge("fatal error! audio frame number not match [%d!=%d]", cnt, pChnData->mFrameNodeNum);
|
||
|
}
|
||
|
}
|
||
|
if (pChnData->mpCapMgr != NULL)
|
||
|
{
|
||
|
PCMBufferMgr_Destroy(pChnData->mpCapMgr);
|
||
|
pChnData->mpCapMgr = NULL;
|
||
|
}
|
||
|
|
||
|
#ifdef AI_SAVE_AUDIO_PCM
|
||
|
fclose(pChnData->pcm_fp);
|
||
|
alogd("AI_Comp pcm_file size: %d", pChnData->pcm_sz);
|
||
|
#endif
|
||
|
if (pChnData->mSaveFileFlag)
|
||
|
{
|
||
|
fclose(pChnData->mFpSaveFile);
|
||
|
free(pChnData->mpSaveFileFullPath);
|
||
|
}
|
||
|
|
||
|
|
||
|
free(pChnData);
|
||
|
alogd("Ai component exited!");
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
#if defined(CFG_AUDIO_EFFECT_EQ) && CFG_AUDIO_EFFECT_EQ!=0
|
||
|
static int audioEQHandle(AI_CHN_DATA_S *pChnData, AUDIO_FRAME_S *pInFrm)
|
||
|
{
|
||
|
short *proc_ptr;
|
||
|
int sample_rate = pChnData->mpAioAttr->enSamplerate;
|
||
|
|
||
|
if (AUDIO_BIT_WIDTH_16 != pInFrm->mBitwidth)
|
||
|
{
|
||
|
aloge("audio pcm format error! bitwidth=%d", pInFrm->mBitwidth);
|
||
|
return FAILURE;
|
||
|
}
|
||
|
|
||
|
eq_prms_t prms[4] =
|
||
|
{
|
||
|
{4, 600, 1, BANDPASS_PEAK, sample_rate},
|
||
|
{4, 1000, 1, BANDPASS_PEAK, sample_rate},
|
||
|
{4, 2000, 2, BANDPASS_PEAK, sample_rate},
|
||
|
{4, 4000, 1, BANDPASS_PEAK, sample_rate},
|
||
|
};
|
||
|
|
||
|
if (pChnData->equalizer == NULL)
|
||
|
{
|
||
|
pChnData->equalizer = eq_create(&prms[0], sizeof(prms)/sizeof(prms[0]));
|
||
|
if (pChnData->equalizer == NULL)
|
||
|
{
|
||
|
aloge("eq create fail!");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc_ptr = (short*)pInFrm->mpAddr;
|
||
|
int left_item_cnt = sizeof(pInFrm->mLen);
|
||
|
while (left_item_cnt>0)
|
||
|
{
|
||
|
int proc_sz = (left_item_cnt>64)? 64:left_item_cnt;
|
||
|
eq_process(pChnData->equalizer, proc_ptr, proc_sz);
|
||
|
proc_ptr += proc_sz;
|
||
|
left_item_cnt -= proc_sz;
|
||
|
}
|
||
|
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static int audioEffectProc(AI_CHN_DATA_S *pChnData, AUDIO_FRAME_S *pInFrm)
|
||
|
{
|
||
|
if (1)
|
||
|
{
|
||
|
#ifdef CFG_AUDIO_EFFECT_EQ
|
||
|
if (pChnData->mVqeCfg.bEqOpen)
|
||
|
{
|
||
|
audioEQHandle(pChnData, pInFrm);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
ERRORTYPE AIChannel_ComponentInit(PARAM_IN COMP_HANDLETYPE hComponent)
|
||
|
{
|
||
|
MM_COMPONENTTYPE *pComp;
|
||
|
AI_CHN_DATA_S *pChnData;
|
||
|
ERRORTYPE eError = SUCCESS;
|
||
|
int err;
|
||
|
int i;
|
||
|
|
||
|
pComp = (MM_COMPONENTTYPE*)hComponent;
|
||
|
|
||
|
// Create private data
|
||
|
pChnData = (AI_CHN_DATA_S*)malloc(sizeof(AI_CHN_DATA_S));
|
||
|
if (pChnData == NULL) {
|
||
|
aloge("alloc AI_CHN_DATA_S error!");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
memset(pChnData, 0x0, sizeof(AI_CHN_DATA_S));
|
||
|
|
||
|
pComp->pComponentPrivate = (void*)pChnData;
|
||
|
pChnData->state = COMP_StateLoaded;
|
||
|
pChnData->hSelf = hComponent;
|
||
|
|
||
|
// Fill in function pointers
|
||
|
pComp->SetCallbacks = AIChannel_SetCallbacks;
|
||
|
pComp->SendCommand = AIChannel_SendCommand;
|
||
|
pComp->GetConfig = AIChannel_GetConfig;
|
||
|
pComp->SetConfig = AIChannel_SetConfig;
|
||
|
pComp->GetState = AIChannel_GetState;
|
||
|
pComp->ComponentTunnelRequest = AIChannel_ComponentTunnelRequest;
|
||
|
pComp->ComponentDeInit = AIChannel_ComponentDeInit;
|
||
|
pComp->EmptyThisBuffer = AIChannel_EmptyThisBuffer;
|
||
|
pComp->FillThisBuffer = AIChannel_FillThisBuffer;
|
||
|
|
||
|
pChnData->sPortParam.nPorts = 0;
|
||
|
pChnData->sPortParam.nStartPortNumber = 0x0;
|
||
|
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].bEnabled = TRUE;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].eDomain = COMP_PortDomainAudio;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_CAP_IN].eDir = COMP_DirInput;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_CAP_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_CAP_IN].eBufferSupplier = COMP_BufferSupplyOutput;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_CAP_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_CAP_IN].eTunnelType = TUNNEL_TYPE_COMMON;
|
||
|
pChnData->sPortParam.nPorts++;
|
||
|
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_AO_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_AO_IN].bEnabled = TRUE;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_AO_IN].eDomain = COMP_PortDomainAudio;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_AO_IN].eDir = COMP_DirInput;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_AO_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_AO_IN].eBufferSupplier = COMP_BufferSupplyOutput;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_AO_IN].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_AO_IN].eTunnelType = TUNNEL_TYPE_COMMON;
|
||
|
pChnData->sPortParam.nPorts++;
|
||
|
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].bEnabled = TRUE;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].eDomain = COMP_PortDomainAudio;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AENC].eDir = COMP_DirOutput;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_OUT_AENC].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_OUT_AENC].eBufferSupplier = COMP_BufferSupplyOutput;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AENC].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AENC].eTunnelType = TUNNEL_TYPE_COMMON;
|
||
|
pChnData->sPortParam.nPorts++;
|
||
|
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].bEnabled = TRUE;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].eDomain = COMP_PortDomainAudio;
|
||
|
pChnData->sPortDef[AI_CHN_PORT_INDEX_OUT_AO].eDir = COMP_DirOutput;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_OUT_AO].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortBufSupplier[AI_CHN_PORT_INDEX_OUT_AO].eBufferSupplier = COMP_BufferSupplyOutput;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AO].nPortIndex = pChnData->sPortParam.nPorts;
|
||
|
pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AO].eTunnelType = TUNNEL_TYPE_COMMON;
|
||
|
pChnData->sPortParam.nPorts++;
|
||
|
|
||
|
if (audioHw_AI_GetPcmConfig(pChnData->mMppChnInfo.mDevId, &pChnData->mpPcmCfg) != SUCCESS) {
|
||
|
aloge("audioHw_AI_GetPcmConfig error!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT0;
|
||
|
}
|
||
|
if (audioHw_AI_GetAIOAttr(pChnData->mMppChnInfo.mDevId, &pChnData->mpAioAttr) != SUCCESS) {
|
||
|
aloge("audioHw_AI_GetAIOAttr error!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT0;
|
||
|
}
|
||
|
|
||
|
int nAudioHwOutputChnNum = 0;
|
||
|
if(0 == pChnData->mpAioAttr->mbBypassAec)
|
||
|
{
|
||
|
nAudioHwOutputChnNum = judgeAudioChnNumBySoundMode(pChnData->mpAioAttr->enSoundmode, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nAudioHwOutputChnNum = pChnData->mpPcmCfg->chnCnt;
|
||
|
}
|
||
|
int nSampleBitWidth = map_AUDIO_BIT_WIDTH_E_to_BitWidth(pChnData->mpAioAttr->enBitwidth);
|
||
|
int nSampleRate = map_AUDIO_SAMPLE_RATE_E_to_SampleRate(pChnData->mpAioAttr->enSamplerate);
|
||
|
pChnData->mAudioHwOutputAlsaFrameBytes = nSampleBitWidth/8*nAudioHwOutputChnNum;
|
||
|
int nAudioHwOutputFrameBytes = pChnData->mpPcmCfg->chunkSize*pChnData->mAudioHwOutputAlsaFrameBytes;
|
||
|
pChnData->mpCapMgr = PCMBufferMgr_Create(AI_CHN_MAX_CACHE_FRAME, nAudioHwOutputFrameBytes, pChnData->mAudioHwOutputAlsaFrameBytes, nSampleRate);
|
||
|
if (pChnData->mpCapMgr == NULL)
|
||
|
{
|
||
|
aloge("BufMgrCreate error!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT0;
|
||
|
}
|
||
|
INIT_LIST_HEAD(&pChnData->mIdleOutFrameList);
|
||
|
INIT_LIST_HEAD(&pChnData->mValidOutFrameList);
|
||
|
for(i=0; i<AI_CHN_MAX_CACHE_FRAME; i++)
|
||
|
{
|
||
|
AudioCaptureFrameInfo *pNode = constructAudioCaptureFrameInfo(i);
|
||
|
list_add_tail(&pNode->mList, &pChnData->mIdleOutFrameList);
|
||
|
pChnData->mFrameNodeNum++;
|
||
|
}
|
||
|
err = pthread_mutex_init(&pChnData->mIgnoreDataLock, NULL);
|
||
|
if(err != 0)
|
||
|
{
|
||
|
aloge("pthread mutex init fail!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT3_3;
|
||
|
}
|
||
|
err = pthread_mutex_init(&pChnData->mStateLock, NULL);
|
||
|
if(err != 0)
|
||
|
{
|
||
|
aloge("pthread mutex init fail!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT3;
|
||
|
}
|
||
|
err = pthread_mutex_init(&pChnData->mCapMgrLock, NULL);
|
||
|
if(err != 0)
|
||
|
{
|
||
|
aloge("fatal error! pthread mutex init fail!");
|
||
|
}
|
||
|
|
||
|
if (message_create(&pChnData->mCmdQueue) < 0){
|
||
|
aloge("message_create error!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT4;
|
||
|
}
|
||
|
err = cdx_sem_init(&pChnData->mAllFrameRelSem, 0);
|
||
|
if (err != 0) {
|
||
|
aloge("cdx_sem_init AllFrameRelSem error!");
|
||
|
goto ERR_EXIT5;
|
||
|
}
|
||
|
|
||
|
err = cdx_sem_init(&pChnData->mWaitOutFrameSem, 0);
|
||
|
if (err != 0) {
|
||
|
aloge("cdx_sem_init mWaitOutFrameSem error!");
|
||
|
goto ERR_EXIT6;
|
||
|
}
|
||
|
|
||
|
// err = cdx_sem_init(&pChnData->mWaitGetAllOutFrameSem, 0);
|
||
|
// if (err != 0) {
|
||
|
// aloge("cdx_sem_init mWaitGetAllOutFrameSem error!");
|
||
|
// goto ERR_EXIT7;
|
||
|
// }
|
||
|
|
||
|
#ifdef AI_SAVE_AUDIO_PCM
|
||
|
pChnData->pcm_fp = fopen("/mnt/extsd/ai_pcm", "wb");
|
||
|
#endif
|
||
|
|
||
|
err = pthread_create(&pChnData->mThreadId, NULL, AIChannel_ComponentThread, pChnData);
|
||
|
if (err) {
|
||
|
aloge("pthread_create error!");
|
||
|
eError = FAILURE;
|
||
|
goto ERR_EXIT8;
|
||
|
}
|
||
|
alogd("create AiChannel threadId:0x%lx", pChnData->mThreadId);
|
||
|
return SUCCESS;
|
||
|
|
||
|
|
||
|
ERR_EXIT8:
|
||
|
//cdx_sem_deinit(&pChnData->mWaitGetAllOutFrameSem);
|
||
|
ERR_EXIT7:
|
||
|
cdx_sem_deinit(&pChnData->mWaitOutFrameSem);
|
||
|
ERR_EXIT6:
|
||
|
cdx_sem_deinit(&pChnData->mAllFrameRelSem);
|
||
|
ERR_EXIT5:
|
||
|
message_destroy(&pChnData->mCmdQueue);
|
||
|
ERR_EXIT4:
|
||
|
pthread_mutex_destroy(&pChnData->mStateLock);
|
||
|
ERR_EXIT3:
|
||
|
pthread_mutex_destroy(&pChnData->mIgnoreDataLock);
|
||
|
ERR_EXIT3_3:
|
||
|
ERR_EXIT2:
|
||
|
ERR_EXIT1:
|
||
|
if(!list_empty(&pChnData->mIdleOutFrameList))
|
||
|
{
|
||
|
AudioCaptureFrameInfo *pEntry, *pTmp;
|
||
|
list_for_each_entry_safe(pEntry, pTmp, &pChnData->mIdleOutFrameList, mList)
|
||
|
{
|
||
|
list_del(&pEntry->mList);
|
||
|
destructAudioCaptureFrameInfo(pEntry);
|
||
|
}
|
||
|
}
|
||
|
PCMBufferMgr_Destroy(pChnData->mpCapMgr);
|
||
|
ERR_EXIT0:
|
||
|
free(pChnData);
|
||
|
return eError;
|
||
|
}
|
||
|
|
||
|
static void *AIChannel_ComponentThread(void *pThreadData)
|
||
|
{
|
||
|
unsigned int cmddata;
|
||
|
CompInternalMsgType cmd;
|
||
|
message_t cmd_msg;
|
||
|
AI_CHN_DATA_S *pChnData = (AI_CHN_DATA_S*)pThreadData;
|
||
|
ERRORTYPE eError;
|
||
|
BOOL bIgnoreFlag;
|
||
|
alogv("AI channel ComponentThread start run...");
|
||
|
sprintf(pChnData->mThreadName, "AIChn[%d-%d]", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId);
|
||
|
prctl(PR_SET_NAME, (unsigned long)pChnData->mThreadName, 0, 0, 0);
|
||
|
|
||
|
while (1) {
|
||
|
PROCESS_MESSAGE:
|
||
|
if (get_message(&pChnData->mCmdQueue, &cmd_msg) == 0)
|
||
|
{
|
||
|
cmd = cmd_msg.command;
|
||
|
cmddata = (unsigned int)cmd_msg.para0;
|
||
|
if (cmd == SetState)
|
||
|
{
|
||
|
//alogv("cmd=SetState, cmddata=%d", cmddata);
|
||
|
//pthread_mutex_lock(&pChnData->mStateLock);
|
||
|
if (pChnData->state == (COMP_STATETYPE) (cmddata))
|
||
|
{
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_SAMESTATE, 0);
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
switch ((COMP_STATETYPE)cmddata)
|
||
|
{
|
||
|
case COMP_StateInvalid:
|
||
|
{
|
||
|
pChnData->state = COMP_StateInvalid;
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_INVALIDSTATE, 0);
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_StateLoaded:
|
||
|
{
|
||
|
if (pChnData->state != COMP_StateIdle)
|
||
|
{
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_INCORRECT_STATE_TRANSITION, 0);
|
||
|
}
|
||
|
alogv("AI_Comp: idle->loaded. StateLoaded begin...");
|
||
|
int ret;
|
||
|
pChnData->mWaitAllFrameReleaseFlag = 1;
|
||
|
while (1)
|
||
|
{
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
if(list_empty(&pChnData->mValidOutFrameList))
|
||
|
{
|
||
|
int nPrefetchSize = pChnData->mpCapMgr->getPrefetchSize(pChnData->mpCapMgr);
|
||
|
if(nPrefetchSize != 0)
|
||
|
{
|
||
|
aloge("fatal error! aiChn[%d-%d] prefetchSize[%d] not 0.", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId, nPrefetchSize);
|
||
|
}
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
ret = cdx_sem_down_timedwait(&pChnData->mAllFrameRelSem, 1000);
|
||
|
if(ret != 0)
|
||
|
{
|
||
|
alogw("AIChn[%d-%d] wait output Frames fail:0x%x", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId, ret);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
pChnData->mWaitAllFrameReleaseFlag = 0;
|
||
|
pChnData->state = COMP_StateLoaded;
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_StateIdle:
|
||
|
{
|
||
|
if (pChnData->state == COMP_StateLoaded)
|
||
|
{
|
||
|
alogv("AI_Comp: loaded->idle ...");
|
||
|
pChnData->state = COMP_StateIdle;
|
||
|
}
|
||
|
else if (pChnData->state == COMP_StatePause || pChnData->state == COMP_StateExecuting)
|
||
|
{
|
||
|
alogv("AI_Comp: pause/executing[0x%x]->idle ...", pChnData->state);
|
||
|
pChnData->state = COMP_StateIdle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_INCORRECT_STATE_TRANSITION, 0);
|
||
|
}
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_StateExecuting:
|
||
|
{
|
||
|
if (pChnData->state == COMP_StateIdle || pChnData->state == COMP_StatePause)
|
||
|
{
|
||
|
alogv("AI_Comp: idle/pause[0x%x]->executing ...", pChnData->state);
|
||
|
pChnData->state = COMP_StateExecuting;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_INCORRECT_STATE_TRANSITION, 0);
|
||
|
}
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
break;
|
||
|
}
|
||
|
case COMP_StatePause:
|
||
|
{
|
||
|
if (pChnData->state == COMP_StateIdle || pChnData->state == COMP_StateExecuting)
|
||
|
{
|
||
|
pChnData->state = COMP_StatePause;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CompSendEvent(pChnData, COMP_EventError, ERR_AI_INCORRECT_STATE_TRANSITION, 0);
|
||
|
}
|
||
|
CompSendEvent(pChnData, COMP_EventCmdComplete, COMP_CommandStateSet, pChnData->state);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
//pthread_mutex_unlock(&pChnData->mStateLock);
|
||
|
}
|
||
|
else if (cmd == AIChannel_CapDataAvailable)
|
||
|
{
|
||
|
pChnData->mWaitingCapDataFlag = FALSE;
|
||
|
}
|
||
|
else if (cmd == AIChannel_PlayDataAvailable)
|
||
|
{
|
||
|
}
|
||
|
else if (cmd == StopPort)
|
||
|
{
|
||
|
}
|
||
|
else if (cmd == Stop)
|
||
|
{
|
||
|
goto EXIT;
|
||
|
}
|
||
|
goto PROCESS_MESSAGE;
|
||
|
}
|
||
|
|
||
|
if (pChnData->state == COMP_StateExecuting)
|
||
|
{
|
||
|
if(pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC] || pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO])
|
||
|
{
|
||
|
PCMBufferManager *pCapMgr = pChnData->mpCapMgr;
|
||
|
int nFrameBytes = pChnData->mAiChnAttr.nFrameSize*pChnData->mAudioHwOutputAlsaFrameBytes;
|
||
|
char *pOutBuf = NULL;
|
||
|
int nSize = 0;
|
||
|
char *pOutBufExtra = NULL;
|
||
|
int nSizeExtra = 0;
|
||
|
int64_t nPts = 0;
|
||
|
pthread_mutex_lock(&pChnData->mCapMgrLock);
|
||
|
int ret = pCapMgr->getData(pCapMgr, nFrameBytes, &pOutBuf, &nSize, &pOutBufExtra, &nSizeExtra, &nPts);
|
||
|
if(ret != 0)
|
||
|
{
|
||
|
pChnData->mWaitingCapDataFlag = TRUE;
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
TMessage_WaitQueueNotEmpty(&pChnData->mCmdQueue, 0);
|
||
|
goto PROCESS_MESSAGE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//1. set PCMBuf data to AudioCaptureFrameInfo list.
|
||
|
AudioCaptureFrameInfo *pFrameNode = SetPCMDataToAudioCaptureFrameInfoList(pChnData, pOutBuf, nSize, pOutBufExtra, nSizeExtra, nPts);
|
||
|
pthread_mutex_unlock(&pChnData->mCapMgrLock);
|
||
|
if(NULL == pFrameNode)
|
||
|
{
|
||
|
aloge("fatal error! malloc fail");
|
||
|
}
|
||
|
//2. send frame out.
|
||
|
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo = NULL;
|
||
|
if(pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC])
|
||
|
{
|
||
|
pPortTunnelInfo = &pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AENC];
|
||
|
}
|
||
|
else if(pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AO])
|
||
|
{
|
||
|
pPortTunnelInfo = &pChnData->sPortTunnelInfo[AI_CHN_PORT_INDEX_OUT_AO];
|
||
|
}
|
||
|
MM_COMPONENTTYPE *pOutTunnelComp = (MM_COMPONENTTYPE*)pPortTunnelInfo->hTunnel;
|
||
|
AUDIO_FRAME_S *pFrm = &pFrameNode->mFrame;
|
||
|
#ifdef AI_SAVE_AUDIO_PCM
|
||
|
fwrite(pFrm->mpAddr, 1, pFrm->mLen, pChnData->pcm_fp);
|
||
|
pChnData->pcm_sz += pFrm->mLen;
|
||
|
#endif
|
||
|
if (pChnData->mSaveFileFlag)
|
||
|
{
|
||
|
fwrite(pFrm->mpAddr, 1, pFrm->mLen, pChnData->mFpSaveFile);
|
||
|
pChnData->mSaveFileSize += pFrm->mLen;
|
||
|
}
|
||
|
if (pChnData->mUseVqeLib)
|
||
|
{
|
||
|
audioEffectProc(pChnData, pFrm);
|
||
|
}
|
||
|
COMP_BUFFERHEADERTYPE obh;
|
||
|
obh.nOutputPortIndex = pPortTunnelInfo->nPortIndex;
|
||
|
obh.nInputPortIndex = pPortTunnelInfo->nTunnelPortIndex;
|
||
|
obh.pOutputPortPrivate = pFrm;
|
||
|
eError = COMP_EmptyThisBuffer(pOutTunnelComp, &obh);
|
||
|
if(SUCCESS != eError)
|
||
|
{
|
||
|
alogw("Be careful! aiChn[%d-%d]:[AI->%s] send pcm failed!", pChnData->mMppChnInfo.mDevId, pChnData->mMppChnInfo.mChnId,
|
||
|
pChnData->mOutputPortTunnelFlag[AI_OUTPORT_SUFFIX_AENC]?"AEnc":"AO");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//do nothing in non-tunnel mode.
|
||
|
TMessage_WaitQueueNotEmpty(&pChnData->mCmdQueue, 0);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
alogv("AI_Comp not StateExecuting");
|
||
|
TMessage_WaitQueueNotEmpty(&pChnData->mCmdQueue, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EXIT:
|
||
|
alogv("AI channel ComponentThread stopped!");
|
||
|
return NULL;
|
||
|
}
|
||
|
|