OMX_ERRORTYPE VideoFilter::ReturnOutputBuffer(OMX_BUFFERHEADERTYPE *pBufferHdr,OMX_U32 flags) { if(nDecodeOnly > 0) { LOG_INFO("VideoFilter drop frame as decode only: %d\n", nDecodeOnly); nDecodeOnly --; pBufferHdr->nFilledLen = 0; tsmGetFrmTs(hTsHandle, pBufferHdr->pBuffer); SetOutputBuffer(pBufferHdr->pBuffer); OutBufferHdrList.Add(pBufferHdr); return OMX_ErrorNone; } if(bNewSegment == OMX_TRUE) { pBufferHdr->nFlags |= OMX_BUFFERFLAG_STARTTIME; bNewSegment = OMX_FALSE; } pBufferHdr->nOffset = 0; if(flags!=OMX_BUFFERFLAG_CODECCONFIG) //check for encoder { pBufferHdr->nTimeStamp = tsmGetFrmTs(hTsHandle, pBufferHdr->pBuffer); } LOG_DEBUG("VideoDecoder send bufer: %p:%lld:%x\n", pBufferHdr->pBuffer, pBufferHdr->nTimeStamp, pBufferHdr->nFlags); if(0) { static int iiCnt=0; static FILE *pfTest = NULL; iiCnt ++; if (iiCnt==1) { pfTest = fopen("/sdcard/DumpData.yuv", "wb"); if(pfTest == NULL) printf("Unable to open test file! \n"); } if(iiCnt > 0 && pfTest != NULL) { if(pBufferHdr->nFilledLen > 0) { printf("dump data %d\n", pBufferHdr->nFilledLen); fwrite(pBufferHdr->pBuffer, sizeof(char), pBufferHdr->nFilledLen, pfTest); fflush(pfTest); fclose(pfTest); pfTest = NULL; } } } ports[OUT_PORT]->SendBuffer(pBufferHdr); return OMX_ErrorNone; }
OMX_ERRORTYPE VideoFilter::ProcessOutputBuffer() { OMX_ERRORTYPE ret = OMX_ErrorNone; if(bLastOutput == OMX_TRUE) return OMX_ErrorNoMore; LOG_DEBUG("Filter Out port has #%d buffers.\n", ports[OUT_PORT]->BufferNum()); if(bNeedOutBuffer != OMX_FALSE) { if(ports[OUT_PORT]->BufferNum() > 0) { OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; ports[OUT_PORT]->GetBuffer(&pBufferHdr); if(pBufferHdr == NULL) return OMX_ErrorUnderflow; if(bNewSegment == OMX_TRUE && bLastInput == OMX_TRUE) { bLastOutput = OMX_TRUE; pBufferHdr->nFlags = OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_STARTTIME; pBufferHdr->nTimeStamp = tsmGetFrmTs(hTsHandle, NULL); ports[OUT_PORT]->SendBuffer(pBufferHdr); return OMX_ErrorNoMore; } ret = SetOutputBuffer(pBufferHdr->pBuffer); if(ret != OMX_ErrorNone) { pBufferHdr->nFilledLen = 0; ports[OUT_PORT]->SendBuffer(pBufferHdr); bNeedOutBuffer = OMX_FALSE; return OMX_ErrorNone; } LOG_DEBUG("Get Outbuffer: %p\n", pBufferHdr->pBuffer); OutBufferHdrList.Add(pBufferHdr); bNeedOutBuffer = OMX_FALSE; } else { OMX_S32 nCnt = OutBufferHdrList.GetNodeCnt(); LOG_DEBUG("No more OutBuffer, #%d buffers holded by filter.\n", nCnt); return OMX_ErrorNoMore; } } 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; }
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; }