OMX_ERRORTYPE VideoFilter::HandleLastOutput(OMX_U32 flags)
{
    OMX_PTR pBuffer = NULL;
    OMX_S32 nOutSize=0;
    OMX_BUFFERHEADERTYPE *pBufferHdr = NULL;

    bLastOutput = OMX_TRUE;
    GetOutputBuffer(&pBuffer,&nOutSize);
    if(pBuffer != NULL)
        pBufferHdr = GetOutBufferHdrFromList(pBuffer);

    if(pBuffer == NULL || pBufferHdr == NULL)
    {
        pBufferHdr = GetFirstOutBufferHdrFromList();
        if(pBufferHdr == NULL)
        {
            LOG_ERROR("No buffer holded by VideoFilter.\n");
            return OMX_ErrorUndefined;
        }
    }

    pBufferHdr->nFilledLen = nOutSize;//0;
    pBufferHdr->nFlags = OMX_BUFFERFLAG_EOS|flags;
    ReturnOutputBuffer(pBufferHdr,flags);
    LOG_INFO("VideoFilter send last output frame.\n");

    return OMX_ErrorNone;
}
Ejemplo n.º 2
0
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_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;
}
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;
}