OMX_ERRORTYPE OMXVideoEncoderBase::SetVideoEncoderParam() { Encode_Status ret = ENCODE_SUCCESS; PortVideo *port_in = NULL; const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = NULL; LOGV("OMXVideoEncoderBase::SetVideoEncoderParam called\n"); port_in = static_cast<PortVideo *>(ports[INPORT_INDEX]); paramPortDefinitionInput = port_in->GetPortDefinition(); mEncoderParams->resolution.height = paramPortDefinitionInput->format.video.nFrameHeight; mEncoderParams->resolution.width = paramPortDefinitionInput->format.video.nFrameWidth; mEncoderParams->frameRate.frameRateDenom = 1; if(mConfigFramerate.xEncodeFramerate != 0) { mEncoderParams->frameRate.frameRateNum = mConfigFramerate.xEncodeFramerate; } else { mEncoderParams->frameRate.frameRateNum = paramPortDefinitionInput->format.video.xFramerate >> 16; mConfigFramerate.xEncodeFramerate = paramPortDefinitionInput->format.video.xFramerate >> 16; } if(mEncoderParams->intraPeriod == 0) { OMX_U32 intraPeriod = mEncoderParams->frameRate.frameRateNum / 2; mEncoderParams->intraPeriod = (intraPeriod < 15) ? 15 : intraPeriod; // Limit intra frame period to ensure video quality for low bitrate application. } if (paramPortDefinitionInput->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) mEncoderParams->rawFormat = RAW_FORMAT_OPAQUE; else mEncoderParams->rawFormat = RAW_FORMAT_NV12; LOGV("frameRate.frameRateDenom = %d\n", mEncoderParams->frameRate.frameRateDenom); LOGV("frameRate.frameRateNum = %d\n", mEncoderParams->frameRate.frameRateNum); LOGV("intraPeriod = %d\n ", mEncoderParams->intraPeriod); mEncoderParams->rcParams.initQP = mConfigIntelBitrate.nInitialQP; mEncoderParams->rcParams.minQP = mConfigIntelBitrate.nMinQP; mEncoderParams->rcParams.maxQP = 0; mEncoderParams->rcParams.I_minQP = 0; mEncoderParams->rcParams.I_maxQP = 0; mEncoderParams->rcParams.windowSize = mConfigIntelBitrate.nWindowSize; mEncoderParams->rcParams.targetPercentage = mConfigIntelBitrate.nTargetPercentage; mEncoderParams->rcParams.enableIntraFrameQPControl = 0; mEncoderParams->rcParams.bitRate = mParamBitrate.nTargetBitrate; if ((mParamBitrate.eControlRate == OMX_Video_ControlRateConstant )|| (mParamBitrate.eControlRate == OMX_Video_ControlRateConstantSkipFrames)) { LOGV("%s(), eControlRate == OMX_Video_Intel_ControlRateConstant", __func__); mEncoderParams->rcMode = RATE_CONTROL_CBR; } else if ((mParamBitrate.eControlRate == OMX_Video_ControlRateVariable) || (mParamBitrate.eControlRate == OMX_Video_ControlRateVariableSkipFrames)) { LOGV("%s(), eControlRate == OMX_Video_Intel_ControlRateVariable", __func__); mEncoderParams->rcMode = RATE_CONTROL_VBR; } else if (mParamBitrate.eControlRate == (OMX_VIDEO_CONTROLRATETYPE)OMX_Video_Intel_ControlRateVideoConferencingMode) { LOGV("%s(), eControlRate == OMX_Video_Intel_ControlRateVideoConferencingMode ", __func__); mEncoderParams->rcMode = RATE_CONTROL_VCM; if(mConfigIntelBitrate.nMaxEncodeBitrate >0) mEncoderParams->rcParams.bitRate = mConfigIntelBitrate.nMaxEncodeBitrate; if(mConfigIntelAir.bAirEnable == OMX_TRUE) { mEncoderParams->airParams.airAuto = mConfigIntelAir.bAirAuto; mEncoderParams->airParams.airMBs = mConfigIntelAir.nAirMBs; mEncoderParams->airParams.airThreshold = mConfigIntelAir.nAirThreshold; mEncoderParams->refreshType = VIDEO_ENC_AIR; } else { mEncoderParams->refreshType = VIDEO_ENC_NONIR; } LOGV("refreshType = %d\n", mEncoderParams->refreshType); } else { mEncoderParams->rcMode = RATE_CONTROL_NONE; } ret = mVideoEncoder->setParameters(mEncoderParams); CHECK_ENCODE_STATUS("setParameters"); return OMX_ErrorNone; }
OMX_ERRORTYPE OMXVideoEncoderMPEG4::ProcessorProcess( OMX_BUFFERHEADERTYPE **buffers, buffer_retain_t *retains, OMX_U32 numberBuffers) { VideoEncOutputBuffer outBuf; VideoEncRawBuffer inBuf; Encode_Status ret = ENCODE_SUCCESS; OMX_U32 outfilledlen = 0; OMX_S64 outtimestamp = 0; OMX_U32 outflags = 0; OMX_ERRORTYPE oret = OMX_ErrorNone; if(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) { LOGV("%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__); outflags |= OMX_BUFFERFLAG_EOS; } if (!buffers[INPORT_INDEX]->nFilledLen) { LOGV("%s(),%d: input buffer's nFilledLen is zero\n", __func__, __LINE__); goto out; } inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset; inBuf.size = buffers[INPORT_INDEX]->nFilledLen; inBuf.type = FTYPE_UNKNOWN; inBuf.flag = 0; inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp; LOGV("inBuf.data=%p, size=%d", (unsigned long)inBuf.data, inBuf.size); outBuf.data = buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset; outBuf.dataSize = 0; outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset; if (mFrameRetrieved) { // encode and setConfig need to be thread safe pthread_mutex_unlock(&mSerializationLock); ret = mVideoEncoder->encode(&inBuf); pthread_mutex_unlock(&mSerializationLock); CHECK_ENCODE_STATUS("encode"); mFrameRetrieved = OMX_FALSE; // This is for buffer contention, we won't release current buffer // but the last input buffer ports[INPORT_INDEX]->ReturnAllRetainedBuffers(); } if (mFirstFrame) { LOGV("mFirstFrame\n"); outBuf.format = OUTPUT_CODEC_DATA; ret = mVideoEncoder->getOutput(&outBuf); CHECK_ENCODE_STATUS("getOutput"); // Return code could not be ENCODE_BUFFER_TOO_SMALL // If we don't return error, we will have dead lock issue if (ret == ENCODE_BUFFER_TOO_SMALL) { return OMX_ErrorUndefined; } LOGV("output codec data size = %d", outBuf.dataSize); outflags |= OMX_BUFFERFLAG_CODECCONFIG; outflags |= OMX_BUFFERFLAG_ENDOFFRAME; outflags |= OMX_BUFFERFLAG_SYNCFRAME; retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; outfilledlen = outBuf.dataSize; mFirstFrame = OMX_FALSE; } else { if (mSyncEncoding == OMX_FALSE && mFrameInputCount == 1) { retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; mFrameRetrieved = OMX_TRUE; goto out; } outBuf.format = OUTPUT_EVERYTHING; mVideoEncoder->getOutput(&outBuf); CHECK_ENCODE_STATUS("getOutput"); LOGV("output data size = %d", outBuf.dataSize); outfilledlen = outBuf.dataSize; outtimestamp = outBuf.timeStamp; if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) { outflags |= OMX_BUFFERFLAG_SYNCFRAME; } if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) { LOGV("Get buffer done\n"); outflags |= OMX_BUFFERFLAG_ENDOFFRAME; mFrameRetrieved = OMX_TRUE; if (mSyncEncoding) retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; else retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; } else { retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //get again } } if (outfilledlen > 0) { retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; } else { retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; } #if SHOW_FPS { struct timeval t; OMX_TICKS current_ts, interval_ts; float current_fps, average_fps; t.tv_sec = t.tv_usec = 0; gettimeofday(&t, NULL); current_ts = (nsecs_t)t.tv_sec * 1000000000 + (nsecs_t)t.tv_usec * 1000; interval_ts = current_ts - lastTs; lastTs = current_ts; current_fps = (float)1000000000 / (float)interval_ts; average_fps = (current_fps + lastFps) / 2; lastFps = current_fps; LOGV("FPS = %2.1f\n", average_fps); } #endif out: if (retains[OUTPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen; buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp; buffers[OUTPORT_INDEX]->nFlags = outflags; } if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN || retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) { mFrameInputCount ++; } if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN) mFrameOutputCount ++; return oret; }