OMX_ERRORTYPE VideoFilter::ProcessInputBuffer()
{
    OMX_ERRORTYPE ret = OMX_ErrorNone;

    LOG_DEBUG("Filter In port has #%d buffers.\n", ports[IN_PORT]->BufferNum());

    if(pInBufferHdr == NULL)
    {
        if(ports[IN_PORT]->BufferNum() > 0)
        {
            if(OMX_TRUE != tsmHasEnoughSlot(hTsHandle))
            {
                LOG_DEBUG("No more space to handle input ts.\n");
                return OMX_ErrorNone;
            }

            ports[IN_PORT]->GetBuffer(&pInBufferHdr);
            if(pInBufferHdr == NULL)
                return OMX_ErrorUnderflow;

            LOG_DEBUG("Get Inbuffer %p:%d:%lld:%x\n", pInBufferHdr->pBuffer, pInBufferHdr->nFilledLen, pInBufferHdr->nTimeStamp, pInBufferHdr->nFlags);

            ret = ProcessInBufferFlags();
            if(ret != OMX_ErrorNone)
                return ret;

            ret = SetInputBuffer(pInBufferHdr->pBuffer + pInBufferHdr->nOffset, pInBufferHdr->nFilledLen, bLastInput);
            if(ret != OMX_ErrorNone)
            {
                ReturnInputBuffer();
                return ret;
            }

            if(pInBufferHdr->nFilledLen == 0)
            {
                ReturnInputBuffer();
                return OMX_ErrorNone;
            }

            bNeedInputBuffer = OMX_FALSE;

            tsmSetBlkTs(hTsHandle, pInBufferHdr->nFilledLen, pInBufferHdr->nTimeStamp);
        }
        else
        {
            if(bNeedInputBuffer == OMX_TRUE)
                return OMX_ErrorNoMore;
        }
    }

    return OMX_ErrorNone;
}
OMX_ERRORTYPE VideoFilter::ComponentReturnBuffer(OMX_U32 nPortIndex)
{
    if(nPortIndex == IN_PORT)
    {
        FlushInputBuffer();
        ReturnInputBuffer();
    }

    if(nPortIndex == OUT_PORT)
    {
        FlushOutputBuffer();
        while(1)
        {
            OMX_BUFFERHEADERTYPE *pBufferHdr = NULL;
            pBufferHdr = GetFirstOutBufferHdrFromList();
            if(pBufferHdr == NULL)
                break;
            ports[OUT_PORT]->SendBuffer(pBufferHdr);
        }
        bNeedOutBuffer = OMX_TRUE;
    }

    bInReturnBufferState = OMX_FALSE;

    return OMX_ErrorNone;
}
OMX_ERRORTYPE VideoFilter::FlushComponent(OMX_U32 nPortIndex)
{
    LOG_DEBUG("Flush filter port: %d\n", (int)nPortIndex);

    if(nPortIndex == IN_PORT)
    {
        FlushInputBuffer();
        ReturnInputBuffer();
        bLastInput = OMX_FALSE;
        bLastOutput = OMX_FALSE;
        nDecodeOnly = 0;
        bGetNewSegment = OMX_TRUE;
    }

    if(nPortIndex == OUT_PORT)
    {
        FlushOutputBuffer();
        while(1)
        {
            OMX_BUFFERHEADERTYPE *pBufferHdr = NULL;
            pBufferHdr = GetFirstOutBufferHdrFromList();
            if(pBufferHdr == NULL)
                break;
            ports[OUT_PORT]->SendBuffer(pBufferHdr);
        }
        bNeedOutBuffer = OMX_TRUE;
    }

    return OMX_ErrorNone;
}
OMX_ERRORTYPE VideoFilter::ProcessInBufferFlags()
{
    if(pInBufferHdr->nFlags & OMX_BUFFERFLAG_STARTTIME)
        bGetNewSegment = OMX_TRUE;

    if(bGetNewSegment == OMX_TRUE && (!(pInBufferHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG)))
    {
        LOG_DEBUG("Get New sement buffer, ts %lld\n", pInBufferHdr->nTimeStamp);
        bGetNewSegment = OMX_FALSE;
        bNewSegment = OMX_TRUE;
        bLastInput = OMX_FALSE;
        bLastOutput = OMX_FALSE;
        if(pInBufferHdr->nFlags & OMX_BUFFERFLAG_STARTTRICK)
        {
            LOG_DEBUG("Set ts manager to FIFO mode.\n");
            tsmFlush(hTsHandle, pInBufferHdr->nTimeStamp, MODE_FIFO);
        }
        else
        {
            LOG_DEBUG("Set ts manager to AI mode.\n");
            tsmFlush(hTsHandle, pInBufferHdr->nTimeStamp, MODE_AI);
        }
    }

    if(bLastInput != OMX_FALSE)
    {
        LOG_DEBUG("Filter drop input buffers in EOS state.\n");
        ReturnInputBuffer();
        return OMX_ErrorNoMore;
    }

    if(pInBufferHdr->nFlags & OMX_BUFFERFLAG_EOS)
    {
        bLastInput = OMX_TRUE;
        bNeedInputBuffer = OMX_FALSE;
        pInBufferHdr->nTimeStamp = -1;
        pInBufferHdr->nFilledLen = 0;
        return OMX_ErrorNone;
    }

    if(!(pInBufferHdr->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) && bFilterSupportPartilInput != OMX_TRUE)
    {
        ProcessPartialInput();
        return OMX_ErrorNotReady;
    }

    if(PartialInputHdr.pBuffer != NULL)
    {
        ProcessPartialInput();
        pInBufferHdr = &PartialInputHdr;
    }

    if(pInBufferHdr->nFlags & OMX_BUFFERFLAG_DECODEONLY)
        nDecodeOnly ++;

    if(pInBufferHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG && pInBufferHdr->nFilledLen > 0)
    {
        if(pCodecData == NULL)
        {
            pCodecData = FSL_MALLOC(pInBufferHdr->nFilledLen);
            if(pCodecData == NULL)
            {
                SendEvent(OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL);
                return OMX_ErrorInsufficientResources;
            }
        }
        else
        {
            pCodecData = FSL_REALLOC(pCodecData, nCodecDataLen + pInBufferHdr->nFilledLen);
            if(pCodecData == NULL)
            {
                SendEvent(OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL);
                return OMX_ErrorInsufficientResources;
            }
        }
        fsl_osal_memcpy((char *)pCodecData + nCodecDataLen, pInBufferHdr->pBuffer, pInBufferHdr->nFilledLen);
        nCodecDataLen += pInBufferHdr->nFilledLen;
        LOG_INFO("Get Codec configure data, len: %d\n", nCodecDataLen);
        ReturnInputBuffer();
        return OMX_ErrorNotReady;
    }

    return OMX_ErrorNone;
}
OMX_ERRORTYPE VideoFilter::ProcessDataBuffer()
{
    OMX_ERRORTYPE ret = OMX_ErrorNone;
    OMX_U32 flags=0;

    if(bInReturnBufferState == OMX_TRUE)
        return OMX_ErrorNoMore;

    ret = ProcessInputBuffer();
    if(ret == OMX_ErrorNotReady)
        return OMX_ErrorNone;
    if(ret != OMX_ErrorNone)
        return ret;

    ret = ProcessOutputBuffer();
    if(ret != OMX_ErrorNone)
        return ret;

    FilterBufRetCode DecRet = FILTER_OK;
    DecRet = FilterOneBuffer();
    if(DecRet & FILTER_INPUT_CONSUMED)
    {
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_INPUT_CONSUMED);
        ReturnInputBuffer();
    }

    if(DecRet & FILTER_ONE_FRM_DECODED)
    {
        OMX_S32 nStuffSize;
        OMX_S32 nFrmSize;
        OMX_PTR pFrm;
        ret=GetDecBuffer(&pFrm, &nStuffSize, &nFrmSize);
        if(ret == OMX_ErrorNone)
        {
            LOG_DEBUG("%s: get one decoded frm: 0x%X(%d,%d) \n",__FUNCTION__,(int)pFrm,(int)nStuffSize,(int)nFrmSize);
            tsmSetFrmBoundary(hTsHandle, nStuffSize, nFrmSize, pFrm);
        }
        else
        {
            LOG_ERROR("%s: get decoded buffer failure !\n",__FUNCTION__);
        }
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_ONE_FRM_DECODED);
    }

    switch(DecRet & FILTER_FLAGS_MASK)
    {
    case FILTER_FLAG_CODEC_DATA:
        flags=OMX_BUFFERFLAG_CODECCONFIG;
        break;
    case FILTER_FLAG_NONKEY_FRAME:
        flags=OMX_BUFFERFLAG_ENDOFFRAME;
        break;
    case FILTER_FLAG_KEY_FRAME:
        flags=OMX_BUFFERFLAG_SYNCFRAME|OMX_BUFFERFLAG_ENDOFFRAME;
        break;
    default:
        flags=0;
        break;
    }
    DecRet = (FilterBufRetCode)(DecRet & ~FILTER_FLAGS_MASK);

    if(DecRet > 0)
    {
        LOG_DEBUG("DecRet: %d\n", DecRet);
    }

    switch(DecRet)
    {
    case FILTER_OK:
        break;
    case FILTER_NO_INPUT_BUFFER:
        if(pInBufferHdr != NULL)
            SetInputBuffer(pInBufferHdr->pBuffer + pInBufferHdr->nOffset, pInBufferHdr->nFilledLen, bLastInput);
        else
            bNeedInputBuffer = OMX_TRUE;
        break;
    case FILTER_NO_OUTPUT_BUFFER:
        bNeedOutBuffer = OMX_TRUE;
        break;
    case FILTER_DO_INIT:
        ret = InitFilter();
        if(ret == OMX_ErrorNone)
            bInit = OMX_TRUE;
        break;
    case FILTER_LAST_OUTPUT:
        HandleLastOutput(flags);
        ret = OMX_ErrorNoMore;
        break;
    case FILTER_HAS_OUTPUT:
    {
        OMX_PTR pBuffer = NULL;
        OMX_S32 nOutSize=0;
        OMX_BUFFERHEADERTYPE *pBufferHdr = NULL;
        GetOutputBuffer(&pBuffer,&nOutSize);
        pBufferHdr = GetOutBufferHdrFromList(pBuffer);
        if(pBufferHdr != NULL)
        {
            pBufferHdr->nFlags = flags;
            pBufferHdr->nFilledLen = nOutSize;//pBufferHdr->nAllocLen;
            ReturnOutputBuffer(pBufferHdr,flags);
        }
        else
        {
            SetOutputBuffer(pBuffer);	//still need to return it to vpu to avoid the frame is isolated in the pipeline
            LOG_ERROR("Can't find related bufferhdr with frame: %p\n", pBuffer);
        }
    }
    break;
    case FILTER_SKIP_OUTPUT:
        tsmGetFrmTs(hTsHandle, NULL);
        break;
    case FILTER_ERROR:
        SendEvent(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
        ret=OMX_ErrorStreamCorrupt;
        break;
    default:
        break;
    }

    return ret;
}
void hst_bindings_shmpcm_shmout::process()
{
    OMX_BUFFERHEADERTYPE*    bufIn, *bufOut;
    t_sint32   offset, input_size, output_size;
    t_sint16 * inptr, * outptr;
    int nb_samples_out, nb_samples_in;;

#ifdef SHMPCMOUT_TRACE_CONTROL
    printf("hst_shmpcm_shmout::process\n");
#endif

    if(mPorts[INPUT_PORT].queuedBufferCount() == 0
       || mPorts[OUTPUT_PORT].queuedBufferCount() == 0) {
        return;
    }

    ARMNMF_DBC_ASSERT(mShmConfig.channelsIn == mShmConfig.channelsOut);

    bufIn  =  (OMX_BUFFERHEADERTYPE*) mPorts[INPUT_PORT].getBuffer(0);
    bufOut =  (OMX_BUFFERHEADERTYPE*) mPorts[OUTPUT_PORT].getBuffer(0);

    offset = (t_sint32)bufOut->nFilledLen;

	if ((bInputBufJustArrived == true) && (bufIn->nFlags & OMX_BUFFERFLAG_STARTTIME)) {
		bInputBufJustArrived = false;
		mInitialTS = bufIn->nTimeStamp;
		mNbSamplesForTSComputation = - (offset / (t_sint32)SAMPLE_SIZE_OUT);
        bPropagateTS = true;
	}

    inptr = (t_sint16 *)(bufIn->pBuffer + mDataConsumed);
    outptr = (t_sint16 *)(bufOut->pBuffer + offset);

    input_size = bufIn->nFilledLen - mDataConsumed;
    output_size = bufOut->nAllocLen - offset;

    nb_samples_in = input_size / SAMPLE_SIZE_IN;
    nb_samples_out = output_size / SAMPLE_SIZE_OUT;

    if (nb_samples_in == nb_samples_out) {

        //copy(inptr, outptr, nb_samples_in);
        (*hst_bindings_shmpcm_shmout::Shmout_copy_routine) (inptr, outptr, nb_samples_in);

        bufOut->nFilledLen += nb_samples_in * SAMPLE_SIZE_OUT;
        bufOut->nFlags     |= bufIn->nFlags;

        ReturnInputBuffer();
        ReturnOutputBuffer(bufOut);
    }
    else if (nb_samples_in < nb_samples_out) {

        //copy(inptr, outptr, nb_samples_in);
        (*hst_bindings_shmpcm_shmout::Shmout_copy_routine) (inptr, outptr, nb_samples_in);

        bufOut->nFilledLen += nb_samples_in * SAMPLE_SIZE_OUT;

        if(bufIn->nFlags & OMX_BUFFERFLAG_EOS){
            bufOut->nFlags     = bufIn->nFlags;
            ReturnOutputBuffer(bufOut);
        }

        bufOut->nFlags |= (bufIn->nFlags & OMX_BUFFERFLAG_STARTTIME);

        ReturnInputBuffer();
    }
    else {

      //copy(inptr, outptr, nb_samples_out);
      (*hst_bindings_shmpcm_shmout::Shmout_copy_routine) (inptr, outptr, nb_samples_out);

      mDataConsumed += nb_samples_out * SAMPLE_SIZE_IN;
      bufOut->nFilledLen += nb_samples_out * SAMPLE_SIZE_OUT;

	  bufOut->nFlags |= (bufIn->nFlags & OMX_BUFFERFLAG_STARTTIME);
      if (bufIn->nFlags & OMX_BUFFERFLAG_STARTTIME) {
        bufIn->nFlags ^= OMX_BUFFERFLAG_STARTTIME; // reset STARTTIME flag
      }
      ReturnOutputBuffer(bufOut);

      if(mPorts[OUTPUT_PORT].queuedBufferCount() != 0){
	scheduleProcessEvent();
      }
    }
}
OMX_ERRORTYPE VideoFilter::ProcessDataBuffer()
{
    OMX_ERRORTYPE ret = OMX_ErrorNone;
    OMX_U32 flags=0;

    if(bInReturnBufferState == OMX_TRUE)
        return OMX_ErrorNoMore;

    ret = ProcessInputBuffer();
    if(ret == OMX_ErrorNotReady)
        return OMX_ErrorNone;
    if(ret != OMX_ErrorNone)
        return ret;

    ret = ProcessOutputBuffer();
    if(ret != OMX_ErrorNone)
        return ret;

    FilterBufRetCode DecRet = FILTER_OK;
    DecRet = FilterOneBuffer();
    if(DecRet & FILTER_INPUT_CONSUMED) {
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_INPUT_CONSUMED);
        ReturnInputBuffer();
    }
    if(DecRet & FILTER_INPUT_CONSUMED_EXT_READ) {
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_INPUT_CONSUMED_EXT_READ);        
        if(pInBufferHdr){
            InBufferHdrList.Add(pInBufferHdr);
            pInBufferHdr = NULL;
        }
        else{
            //for eos buffer with size=0, pInBufferHdr may be retured aleady before (in ProcessInputBuffer()) 
        }
    }
    if(DecRet & FILTER_INPUT_CONSUMED_EXT_RETURN) {
        OMX_PTR ptr;
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_INPUT_CONSUMED_EXT_RETURN);
        GetReturnedInputDataPtr(&ptr);
        //since the list is FIFO, we needn't map ptr and pHdr
        if(InBufferHdrList.GetNodeCnt()>0){
            OMX_BUFFERHEADERTYPE* pHdr;
            pHdr=InBufferHdrList.GetNode(0);
            if(pHdr==NULL){
                LOG_ERROR("warning: get one null hdr from InBufferHdrList !\n");
            }
            if(pHdr->pBuffer!=ptr){
                LOG_ERROR("warning: the address doesn't match between ptr and pHdr->pBuffer !\n");
            }
            InBufferHdrList.Remove(pHdr);
            ports[IN_PORT]->SendBuffer(pHdr);
        }
        else{
            //this path is only for eos
            if((DecRet&FILTER_LAST_OUTPUT)==0){
                LOG_ERROR("warning: the numbers between insert and get doesn't matched !\n");
            }
        }
    }

    if(DecRet & FILTER_ONE_FRM_DECODED){
        OMX_S32 nStuffSize;
        OMX_S32 nFrmSize;
        OMX_PTR pFrm;
        ret=GetDecBuffer(&pFrm, &nStuffSize, &nFrmSize);
        if(ret == OMX_ErrorNone){
            LOG_DEBUG("%s: get one decoded frm: 0x%X(%d,%d) \n",__FUNCTION__,(int)pFrm,(int)nStuffSize,(int)nFrmSize);	
            tsmSetFrmBoundary(hTsHandle, nStuffSize, nFrmSize, pFrm);
        }
        else{
            LOG_ERROR("%s: get decoded buffer failure !\n",__FUNCTION__);
        }
        DecRet = (FilterBufRetCode)(DecRet & ~FILTER_ONE_FRM_DECODED);
    }

    switch(DecRet & FILTER_FLAGS_MASK) {
        case FILTER_FLAG_CODEC_DATA:
            flags=OMX_BUFFERFLAG_CODECCONFIG;
            break;
        case FILTER_FLAG_NONKEY_FRAME:
            flags=OMX_BUFFERFLAG_ENDOFFRAME;
            break;
        case FILTER_FLAG_KEY_FRAME:
            flags=OMX_BUFFERFLAG_SYNCFRAME|OMX_BUFFERFLAG_ENDOFFRAME;
            break;
        default:
            flags=0;
            break;
    }
    DecRet = (FilterBufRetCode)(DecRet & ~FILTER_FLAGS_MASK);

    if(DecRet > 0) {
        LOG_DEBUG("DecRet: %d\n", DecRet);
    }

    switch(DecRet) {
        case FILTER_OK:
            break;
        case FILTER_NO_INPUT_BUFFER:
            if(pInBufferHdr != NULL)
                SetInputBuffer(pInBufferHdr->pBuffer + pInBufferHdr->nOffset, pInBufferHdr->nFilledLen, bLastInput);
            else
                bNeedInputBuffer = OMX_TRUE;
            break;
        case FILTER_NO_OUTPUT_BUFFER:
            bNeedOutBuffer = OMX_TRUE;
            break;
        case FILTER_DO_INIT:
            ret = InitFilter();
            if(ret == OMX_ErrorNone)
                bInit = OMX_TRUE;
            break;
        case FILTER_LAST_OUTPUT:
            HandleLastOutput(flags);
            ret = OMX_ErrorNoMore;
            break;
        case FILTER_HAS_OUTPUT:
            {
                OMX_PTR pBuffer = NULL;
                OMX_S32 nOutSize=0;
                OMX_BUFFERHEADERTYPE *pBufferHdr = NULL;
                GetOutputBuffer(&pBuffer,&nOutSize);
				if (nOutSize == 0) {
					nInvalidFrameCnt ++;
					if (nInvalidFrameCnt <= MOSAIC_COUNT) {
						SetOutputBuffer(pBuffer);	//still need to return it to vpu to avoid the frame is isolated in the pipeline
						tsmGetFrmTs(hTsHandle, NULL);
						break;
					}
				} else {
					nInvalidFrameCnt = 0;
				}
                pBufferHdr = GetOutBufferHdrFromList(pBuffer);
                if(pBufferHdr != NULL) {
                    pBufferHdr->nFlags = flags;
                    pBufferHdr->nFilledLen = nOutSize;//pBufferHdr->nAllocLen;
                    ReturnOutputBuffer(pBufferHdr,flags);
                }
                else{
                    SetOutputBuffer(pBuffer);	//still need to return it to vpu to avoid the frame is isolated in the pipeline
                    LOG_ERROR("Can't find related bufferhdr with frame: %p\n", pBuffer);
                }
            }
            break;
        case FILTER_SKIP_OUTPUT:
            tsmGetFrmTs(hTsHandle, NULL);
            break;
        case FILTER_ERROR:
            SendEvent(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
            ret=OMX_ErrorStreamCorrupt;
            break;
        default: 
            break;
    }

    return ret;
}