OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess( OMX_BUFFERHEADERTYPE ***pBuffers, buffer_retain_t *retains, OMX_U32) { OMX_ERRORTYPE ret; Decode_Status status; OMX_BOOL isResolutionChange = OMX_FALSE; // fill render buffer without draining decoder output queue ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange); if (ret == OMX_ErrorNone) { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; if (isResolutionChange) { HandleFormatChange(); } // TODO: continue decoding return ret; } else if (ret != OMX_ErrorNotReady) { return ret; } VideoDecodeBuffer decodeBuffer; // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer); if (ret == OMX_ErrorNotReady) { retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; return OMX_ErrorNone; } else if (ret != OMX_ErrorNone) { return ret; } if (decodeBuffer.size != 0) { //pthread_mutex_lock(&mSerializationLock); status = mVideoDecoder->decode(&decodeBuffer); //pthread_mutex_unlock(&mSerializationLock); if (status == DECODE_FORMAT_CHANGE) { ret = HandleFormatChange(); CHECK_RETURN_VALUE("HandleFormatChange"); ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0; retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; // real dynamic resolution change will be handled later // Here is just a temporary workaround // don't use the output buffer if format is changed. return OMX_ErrorNone; } else if (status == DECODE_NO_CONFIG) { LOGW("Decoder returns DECODE_NO_CONFIG."); retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; return OMX_ErrorNone; } else if (status == DECODE_NO_REFERENCE) { LOGW("Decoder returns DECODE_NO_REFERENCE."); //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //return OMX_ErrorNone; } else if (status == DECODE_MULTIPLE_FRAME){ if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) { PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData; (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet; (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp; (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet; retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp); } } else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) { if (checkFatalDecoderError(status)) { return TranslateDecodeStatus(status); } else { // For decoder errors that could be omitted, not throw error and continue to decode. TranslateDecodeStatus(status); ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0; // Do not return, and try to drain the output queue // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; // return OMX_ErrorNone; } } } // drain the decoder output queue when in EOS state and fill the render buffer ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange); if (isResolutionChange) { HandleFormatChange(); } bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); // if output port is not eos, retain the input buffer until all the output buffers are drained. if (inputEoS && !outputEoS) { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again. (*pBuffers[INPORT_INDEX])->nFilledLen = 0; } if (ret == OMX_ErrorNotReady) { retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; ret = OMX_ErrorNone; } return ret; }
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( OMX_BUFFERHEADERTYPE ***pBuffers, buffer_retain_t *retains, OMX_U32) { OMX_ERRORTYPE ret; OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true:false; OMX_BOOL isResolutionChange = OMX_FALSE; eos = eos && (inBuffer->nFilledLen == 0); if (inBuffer->pBuffer == NULL) { LOGE("Buffer to decode is empty."); return OMX_ErrorBadParameter; } if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag."); } if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) { LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); } #if LOG_TIME == 1 struct timeval tv_start, tv_end; int32_t time_ms; gettimeofday(&tv_start,NULL); #endif int res = mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen, eos); if (res != 0) { if (res == -2) { if (isReallocateNeeded(inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen)) { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; HandleFormatChange(); return OMX_ErrorNone; } // drain the last frame, keep the current input buffer res = mDecoderDecode(mCtx,mHybridCtx,NULL,0,true); retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; } else { LOGE("on2 decoder failed to decode frame."); return OMX_ErrorBadParameter; } } #if LOG_TIME == 1 gettimeofday(&tv_end,NULL); time_ms = (int32_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000 + (int32_t)(tv_end.tv_usec - tv_start.tv_usec)/1000; LOGI("vpx_codec_decode: %d ms", time_ms); #endif ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], eos? OMX_BUFFERFLAG_EOS:0, &isResolutionChange); if (ret == OMX_ErrorNone) { (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp; } mLastTimeStamp = inBuffer->nTimeStamp; if (isResolutionChange == OMX_TRUE) { HandleFormatChange(); } bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); // if output port is not eos, retain the input buffer // until all the output buffers are drained. if (inputEoS && !outputEoS && retains[INPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; // the input buffer is retained for draining purpose. // Set nFilledLen to 0 so buffer will not be decoded again. (*pBuffers[INPORT_INDEX])->nFilledLen = 0; } if (ret == OMX_ErrorNotReady) { retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; ret = OMX_ErrorNone; } return ret; }
OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorProcess( OMX_BUFFERHEADERTYPE ***pBuffers, buffer_retain_t *retains, OMX_U32) { OMX_ERRORTYPE ret; OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; OMX_BOOL isResolutionChange = OMX_FALSE; if (inBuffer->pBuffer == NULL) { LOGE("Buffer to decode is empty."); return OMX_ErrorBadParameter; } if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag."); } if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) { LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); } if (inBuffer->nFlags & OMX_BUFFERFLAG_EOS) { if (inBuffer->nFilledLen == 0) { (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0; (*pBuffers[OUTPORT_INDEX])->nFlags = OMX_BUFFERFLAG_EOS; return OMX_ErrorNone; } } if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen, NULL, 0)) { LOGE("on2 decoder failed to decode frame."); return OMX_ErrorBadParameter; } ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], ((*pBuffers[INPORT_INDEX]))->nFlags, &isResolutionChange); if (ret == OMX_ErrorNone) { (*pBuffers[OUTPORT_INDEX])->nTimeStamp = inBuffer->nTimeStamp; } if (isResolutionChange) { HandleFormatChange(); } bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); // if output port is not eos, retain the input buffer // until all the output buffers are drained. if (inputEoS && !outputEoS) { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; // the input buffer is retained for draining purpose. // Set nFilledLen to 0 so buffer will not be decoded again. (*pBuffers[INPORT_INDEX])->nFilledLen = 0; } if (ret == OMX_ErrorNotReady) { retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; ret = OMX_ErrorNone; } return ret; }