/*
* Copyright (c) 2009-2011 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "OMXVideoEncoderBase"
#include "OMXVideoEncoderBase.h"
#include "IntelMetadataBuffer.h"
#include <cutils/properties.h>
#include <wrs_omxil_core/log.h>
static const char *RAW_MIME_TYPE = "video/raw";
OMXVideoEncoderBase::OMXVideoEncoderBase()
:mVideoEncoder(NULL)
,mEncoderParams(NULL)
,mFrameInputCount(0)
,mFrameOutputCount(0)
,mFirstFrame(OMX_TRUE)
,mFrameRetrieved(OMX_TRUE)
,mStoreMetaDataInBuffers(OMX_FALSE)
,mSyncEncoding(OMX_TRUE)
,mOmxLogLevel(0)
,mBlackFramePointer(NULL) {
mEncoderParams = new VideoParamsCommon();
if (!mEncoderParams) LOGE("OMX_ErrorInsufficientResources");
char logLevelProp[128];
if (property_get("omxenc.debug", logLevelProp, NULL)) {
mOmxLogLevel = atoi(logLevelProp);
LOGD("Debug level is %d", mOmxLogLevel);
}
LOGV("OMXVideoEncoderBase::OMXVideoEncoderBase end");
}
OMXVideoEncoderBase::~OMXVideoEncoderBase() {
// destroy ports
if (this->ports) {
if (this->ports[INPORT_INDEX]) {
delete this->ports[INPORT_INDEX];
this->ports[INPORT_INDEX] = NULL;
}
if (this->ports[OUTPORT_INDEX]) {
delete this->ports[OUTPORT_INDEX];
this->ports[OUTPORT_INDEX] = NULL;
}
}
if (mBlackFramePointer) {
free(mBlackFramePointer);
mBlackFramePointer = NULL;
}
// Release video encoder object
if(mVideoEncoder) {
releaseVideoEncoder(mVideoEncoder);
mVideoEncoder = NULL;
}
if(mEncoderParams) {
delete mEncoderParams;
mEncoderParams = NULL;
}
}
OMX_ERRORTYPE OMXVideoEncoderBase::InitInputPort(void) {
this->ports[INPORT_INDEX] = new PortVideo;
if (this->ports[INPORT_INDEX] == NULL) {
return OMX_ErrorInsufficientResources;
}
PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
// OMX_PARAM_PORTDEFINITIONTYPE
OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
memset(¶mPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
SetTypeHeader(¶mPortDefinitionInput, sizeof(paramPortDefinitionInput));
paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
paramPortDefinitionInput.eDir = OMX_DirInput;
paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
paramPortDefinitionInput.bEnabled = OMX_TRUE;
paramPortDefinitionInput.bPopulated = OMX_FALSE;
paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
paramPortDefinitionInput.format.video.cMIMEType = (OMX_STRING)RAW_MIME_TYPE;
paramPortDefinitionInput.format.video.pNativeRender = NULL;
paramPortDefinitionInput.format.video.nFrameWidth = 176;
paramPortDefinitionInput.format.video.nFrameHeight = 144;
paramPortDefinitionInput.format.video.nStride = 0;
paramPortDefinitionInput.format.video.nSliceHeight = 0;
paramPortDefinitionInput.format.video.nBitrate = 64000;
paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
paramPortDefinitionInput.format.video.pNativeWindow = NULL;
paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
paramPortDefinitionInput.nBufferAlignment = 0;
// Nothing specific to initialize input port.
InitInputPortFormatSpecific(¶mPortDefinitionInput);
port->SetPortDefinition(¶mPortDefinitionInput, true);
// Set port buffer 4k aligned
port->SetMemAlignment(4096);
// OMX_VIDEO_PARAM_PORTFORMATTYPE
OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
memset(¶mPortFormat, 0, sizeof(paramPortFormat));
SetTypeHeader(¶mPortFormat, sizeof(paramPortFormat));
paramPortFormat.nPortIndex = INPORT_INDEX;
paramPortFormat.nIndex = 0;
paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
port->SetPortVideoParam(¶mPortFormat, true);
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::InitOutputPort(void) {
this->ports[OUTPORT_INDEX] = new PortVideo;
if (this->ports[OUTPORT_INDEX] == NULL) {
return OMX_ErrorInsufficientResources;
}
PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
// OMX_VIDEO_PARAM_BITRATETYPE
memset(&mParamBitrate, 0, sizeof(mParamBitrate));
SetTypeHeader(&mParamBitrate, sizeof(mParamBitrate));
mParamBitrate.nPortIndex = OUTPORT_INDEX;
mParamBitrate.eControlRate = OMX_Video_ControlRateVariable;
mParamBitrate.nTargetBitrate = 192000; // to be overridden
// OMX_VIDEO_CONFIG_PRI_INFOTYPE
memset(&mConfigPriInfo, 0, sizeof(mConfigPriInfo));
SetTypeHeader(&mConfigPriInfo, sizeof(mConfigPriInfo));
mConfigPriInfo.nPortIndex = OUTPORT_INDEX;
mConfigPriInfo.nCapacity = 0;
mConfigPriInfo.nHolder = NULL;
// OMX_VIDEO_CONFIG_INTEL_BITRATETYPE
memset(&mConfigIntelBitrate, 0, sizeof(mConfigIntelBitrate));
SetTypeHeader(&mConfigIntelBitrate, sizeof(mConfigIntelBitrate));
mConfigIntelBitrate.nPortIndex = OUTPORT_INDEX;
mConfigIntelBitrate.nMaxEncodeBitrate = 0; // Maximum bitrate
mConfigIntelBitrate.nTargetPercentage = 95; // Target bitrate as percentage of maximum bitrate; e.g. 95 is 95%
mConfigIntelBitrate.nWindowSize = 0; // Window size in milliseconds allowed for bitrate to reach target
mConfigIntelBitrate.nInitialQP = 0; // Initial QP for I frames
mConfigIntelBitrate.nMinQP = 0;
mConfigIntelBitrate.nMaxQP = 0;
mConfigIntelBitrate.nFrameRate = 0;
mConfigIntelBitrate.nTemporalID = 0;
// OMX_VIDEO_CONFIG_INTEL_AIR
memset(&mConfigIntelAir, 0, sizeof(mConfigIntelAir));
SetTypeHeader(&mConfigIntelAir, sizeof(mConfigIntelAir));
mConfigIntelAir.nPortIndex = OUTPORT_INDEX;
mConfigIntelAir.bAirEnable = OMX_FALSE;
mConfigIntelAir.bAirAuto = OMX_FALSE;
mConfigIntelAir.nAirMBs = 0;
mConfigIntelAir.nAirThreshold = 0;
// OMX_VIDEO_CONFIG_INTEL_AIR
memset(&mParamVideoRefresh, 0, sizeof(mParamVideoRefresh));
SetTypeHeader(&mParamVideoRefresh, sizeof(mParamVideoRefresh));
mParamVideoRefresh.nPortIndex = OUTPORT_INDEX;
mParamVideoRefresh.eRefreshMode = OMX_VIDEO_IntraRefreshAdaptive;
mParamVideoRefresh.nAirMBs = 0;
mParamVideoRefresh.nAirRef = 0;
mParamVideoRefresh.nCirMBs = 0;
// OMX_CONFIG_FRAMERATETYPE
memset(&mConfigFramerate, 0, sizeof(mConfigFramerate));
SetTypeHeader(&mConfigFramerate, sizeof(mConfigFramerate));
mConfigFramerate.nPortIndex = OUTPORT_INDEX;
mConfigFramerate.xEncodeFramerate = 0; // Q16 format
// OMX_VIDEO_PARAM_INTEL_ADAPTIVE_SLICE_CONTROL
memset(&mParamIntelAdaptiveSliceControl, 0, sizeof(mParamIntelAdaptiveSliceControl));
SetTypeHeader(&mParamIntelAdaptiveSliceControl, sizeof(mParamIntelAdaptiveSliceControl));
mParamIntelAdaptiveSliceControl.nPortIndex = OUTPORT_INDEX;
mParamIntelAdaptiveSliceControl.bEnable = OMX_FALSE;
mParamIntelAdaptiveSliceControl.nMinPSliceNumber = 5;
mParamIntelAdaptiveSliceControl.nNumPFramesToSkip = 8;
mParamIntelAdaptiveSliceControl.nSliceSizeThreshold = 1200;
// OMX_VIDEO_PARAM_PROFILELEVELTYPE
memset(&mParamProfileLevel, 0, sizeof(mParamProfileLevel));
SetTypeHeader(&mParamProfileLevel, sizeof(mParamProfileLevel));
mParamProfileLevel.nPortIndex = OUTPORT_INDEX;
mParamProfileLevel.eProfile = 0; // undefined profile, to be overridden
mParamProfileLevel.eLevel = 0; // undefined level, to be overridden
// OMX_PARAM_PORTDEFINITIONTYPE
OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
memset(¶mPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
SetTypeHeader(¶mPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
paramPortDefinitionOutput.eDir = OMX_DirOutput;
paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT; // to be overridden
paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
paramPortDefinitionOutput.nBufferSize = OUTPORT_BUFFER_SIZE; // to be overridden
paramPortDefinitionOutput.bEnabled = OMX_TRUE;
paramPortDefinitionOutput.bPopulated = OMX_FALSE;
paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
paramPortDefinitionOutput.format.video.cMIMEType = NULL; // to be overridden
paramPortDefinitionOutput.format.video.pNativeRender = NULL;
paramPortDefinitionOutput.format.video.nFrameWidth = 176;
paramPortDefinitionOutput.format.video.nFrameHeight = 144;
paramPortDefinitionOutput.format.video.nStride = 176;
paramPortDefinitionOutput.format.video.nSliceHeight = 144;
paramPortDefinitionOutput.format.video.nBitrate = 64000;
paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
paramPortDefinitionOutput.nBufferAlignment = 0;
InitOutputPortFormatSpecific(¶mPortDefinitionOutput);
port->SetPortDefinition(¶mPortDefinitionOutput, true);
port->SetPortBitrateParam(&mParamBitrate, true);
// OMX_VIDEO_PARAM_PORTFORMATTYPE
OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
memset(¶mPortFormat, 0, sizeof(paramPortFormat));
SetTypeHeader(¶mPortFormat, sizeof(paramPortFormat));
paramPortFormat.nPortIndex = OUTPORT_INDEX;
paramPortFormat.nIndex = 0;
paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
port->SetPortVideoParam(¶mPortFormat, true);
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
// no format specific to initialize input
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetVideoEncoderParam() {
Encode_Status ret = ENCODE_SUCCESS;
PortVideo *port_in = NULL;
PortVideo *port_out = NULL;
OMX_VIDEO_CONTROLRATETYPE controlrate;
const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = NULL;
LOGV("OMXVideoEncoderBase::SetVideoEncoderParam called\n");
port_in = static_cast<PortVideo *>(ports[INPORT_INDEX]);
port_out = static_cast<PortVideo *>(ports[OUTPORT_INDEX]);
paramPortDefinitionInput = port_in->GetPortDefinition();
mEncoderParams->resolution.height = paramPortDefinitionInput->format.video.nFrameHeight;
mEncoderParams->resolution.width = paramPortDefinitionInput->format.video.nFrameWidth;
const OMX_VIDEO_PARAM_BITRATETYPE *bitrate = port_out->GetPortBitrateParam();
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 OMXVideoEncoderBase::ProcessorInit(void) {
OMX_ERRORTYPE ret = OMX_ErrorNone;
ret = SetVideoEncoderParam();
CHECK_STATUS("SetVideoEncoderParam");
Encode_Status status = mVideoEncoder->start();
if (status != ENCODE_SUCCESS) {
LOGE("Start failed, status = 0x%08x\n", status);
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::ProcessorDeinit(void) {
OMX_ERRORTYPE ret;
if(mVideoEncoder) {
mVideoEncoder->stop();
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::ProcessorStop(void) {
this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase:: ProcessorProcess(
OMX_BUFFERHEADERTYPE **,
buffer_retain_t *,
OMX_U32) {
LOGV("OMXVideoEncoderBase:: ProcessorProcess \n");
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::ProcessorFlush(OMX_U32 portIndex) {
LOGV("OMXVideoEncoderBase::ProcessorFlush\n");
if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
mVideoEncoder->flush();
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::BuildHandlerList(void) {
OMXComponentCodecBase::BuildHandlerList();
AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
AddHandler(OMX_IndexParamVideoBitrate, GetParamVideoBitrate, SetParamVideoBitrate);
AddHandler((OMX_INDEXTYPE)OMX_IndexIntelPrivateInfo, GetIntelPrivateInfo, SetIntelPrivateInfo);
AddHandler((OMX_INDEXTYPE)OMX_IndexConfigIntelBitrate, GetConfigIntelBitrate, SetConfigIntelBitrate);
AddHandler((OMX_INDEXTYPE)OMX_IndexConfigIntelAIR, GetConfigIntelAIR, SetConfigIntelAIR);
AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoIntraRefresh, GetParamVideoIntraRefresh, SetParamVideoIntraRefresh);
AddHandler(OMX_IndexConfigVideoFramerate, GetConfigVideoFramerate, SetConfigVideoFramerate);
AddHandler(OMX_IndexConfigVideoIntraVOPRefresh, GetConfigVideoIntraVOPRefresh, SetConfigVideoIntraVOPRefresh);
//AddHandler(OMX_IndexParamIntelAdaptiveSliceControl, GetParamIntelAdaptiveSliceControl, SetParamIntelAdaptiveSliceControl);
//AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoProfileLevelQuerySupported, SetParamVideoProfileLevelQuerySupported);
AddHandler((OMX_INDEXTYPE)OMX_IndexStoreMetaDataInBuffers, GetStoreMetaDataInBuffers, SetStoreMetaDataInBuffers);
AddHandler((OMX_INDEXTYPE)OMX_IndexExtSyncEncoding, GetSyncEncoding, SetSyncEncoding);
AddHandler((OMX_INDEXTYPE)OMX_IndexExtPrependSPSPPS, GetPrependSPSPPS, SetPrependSPSPPS);
AddHandler((OMX_INDEXTYPE)OMX_IndexExtTemporalLayer, GetTemporalLayer,SetTemporalLayer);
AddHandler((OMX_INDEXTYPE)OMX_IndexExtRequestBlackFramePointer, GetBlackFramePointer, GetBlackFramePointer);
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_U32 index;
OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX_RANGE(p);
CHECK_ENUMERATION_RANGE(p->nIndex, 2);
PortVideo *port = NULL;
port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
index = p->nIndex;
memcpy(p, port->GetPortVideoParam(), sizeof(*p));
// port supports OMX_COLOR_FormatYUV420SemiPlanar & OMX_COLOR_FormatAndroidOpaque
if (index == 1) {
p->nIndex = 1;
p->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX_RANGE(p);
CHECK_SET_PARAM_STATE();
// TODO: do we need to check if port is enabled?
PortVideo *port = NULL;
port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
#if 0
if (p->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
p->nIndex = 0;
p->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
}
#endif
port->SetPortVideoParam(p, false);
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetParamVideoBitrate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_BITRATETYPE *p = (OMX_VIDEO_PARAM_BITRATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mParamBitrate, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetParamVideoBitrate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_BITRATETYPE *p = (OMX_VIDEO_PARAM_BITRATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
CHECK_SET_PARAM_STATE();
OMX_U32 index = p->nPortIndex;
PortVideo *port = NULL;
// This disables other type of bitrate control mechanism
// TODO: check if it is desired
// TODO: can we override mParamBitrate.nPortIndex (See SetPortBitrateParam)
mParamBitrate.eControlRate = p->eControlRate;
mParamBitrate.nTargetBitrate = p->nTargetBitrate;
port = static_cast<PortVideo *>(ports[index]);
ret = port->SetPortBitrateParam(p, false);
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetIntelPrivateInfo(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_CONFIG_PRI_INFOTYPE *p = (OMX_VIDEO_CONFIG_PRI_INFOTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mConfigPriInfo, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetIntelPrivateInfo(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_CONFIG_PRI_INFOTYPE *p = (OMX_VIDEO_CONFIG_PRI_INFOTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// OMX_VIDEO_CONFIG_PRI_INFOTYPE is static parameter?
CHECK_SET_PARAM_STATE();
// TODO: can we override mConfigPriInfo.nPortIndex (See SetPortPrivateInfoParam)
if(p->nHolder != NULL) {
// TODO: do we need to free nHolder?
if (mConfigPriInfo.nHolder) {
free(mConfigPriInfo.nHolder);
}
mConfigPriInfo.nCapacity = p->nCapacity;
// TODO: nCapacity is in 8-bit unit or 32-bit unit?
// TODO: check memory allocation
mConfigPriInfo.nHolder = (OMX_PTR)malloc(sizeof(OMX_U32) * p->nCapacity);
memcpy(mConfigPriInfo.nHolder, p->nHolder, sizeof(OMX_U32) * p->nCapacity);
} else {
mConfigPriInfo.nCapacity = 0;
mConfigPriInfo.nHolder = NULL;
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetConfigIntelBitrate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_CONFIG_INTEL_BITRATETYPE *p = (OMX_VIDEO_CONFIG_INTEL_BITRATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mConfigIntelBitrate, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetConfigIntelBitrate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
Encode_Status retStatus = ENCODE_SUCCESS;
if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax){
LOGE("SetConfigIntelBitrate failed. Feature is disabled.");
return OMX_ErrorUnsupportedIndex;
}
OMX_VIDEO_CONFIG_INTEL_BITRATETYPE *p = (OMX_VIDEO_CONFIG_INTEL_BITRATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
mConfigIntelBitrate = *p;
// return OMX_ErrorNone if not in Executing state
// TODO: return OMX_ErrorIncorrectStateOperation?
CHECK_SET_CONFIG_STATE();
VideoConfigBitRate configBitRate;
configBitRate.rcParams.bitRate = mConfigIntelBitrate.nMaxEncodeBitrate;
configBitRate.rcParams.initQP = mConfigIntelBitrate.nInitialQP;
configBitRate.rcParams.minQP = mConfigIntelBitrate.nMinQP;
configBitRate.rcParams.maxQP = mConfigIntelBitrate.nMaxQP;
configBitRate.rcParams.I_minQP = 0;
configBitRate.rcParams.I_maxQP = 0;
configBitRate.rcParams.windowSize = mConfigIntelBitrate.nWindowSize;
configBitRate.rcParams.targetPercentage = mConfigIntelBitrate.nTargetPercentage;
configBitRate.rcParams.enableIntraFrameQPControl = 0;
configBitRate.rcParams.temporalFrameRate = mConfigIntelBitrate.nFrameRate;
configBitRate.rcParams.temporalID = mConfigIntelBitrate.nTemporalID;
retStatus = mVideoEncoder->setConfig(&configBitRate);
if(retStatus != ENCODE_SUCCESS) {
LOGW("failed to set IntelBitrate");
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetConfigIntelAIR(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_CONFIG_INTEL_AIR *p = (OMX_VIDEO_CONFIG_INTEL_AIR *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mConfigIntelAir, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetConfigIntelAIR(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
Encode_Status retStatus = ENCODE_SUCCESS;
OMX_VIDEO_CONFIG_INTEL_AIR *p = (OMX_VIDEO_CONFIG_INTEL_AIR *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
mConfigIntelAir = *p;
// return OMX_ErrorNone if not in Executing state
// TODO: return OMX_ErrorIncorrectStateOperation?
CHECK_SET_CONFIG_STATE();
VideoConfigAIR configAIR;
VideoConfigIntraRefreshType configIntraRefreshType;
if(mConfigIntelAir.bAirEnable == OMX_TRUE) {
configAIR.airParams.airAuto = mConfigIntelAir.bAirAuto;
configAIR.airParams.airMBs = mConfigIntelAir.nAirMBs;
configAIR.airParams.airThreshold = mConfigIntelAir.nAirThreshold;
configIntraRefreshType.refreshType = VIDEO_ENC_AIR;
} else {
configIntraRefreshType.refreshType = VIDEO_ENC_NONIR;
}
retStatus = mVideoEncoder->setConfig(&configAIR);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set AIR config");
}
retStatus = mVideoEncoder->setConfig(&configIntraRefreshType);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set refresh config");
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetParamVideoIntraRefresh(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_INTRAREFRESHTYPE *p = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mParamVideoRefresh, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetParamVideoIntraRefresh(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
Encode_Status retStatus = ENCODE_SUCCESS;
OMX_VIDEO_PARAM_INTRAREFRESHTYPE *p = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
mParamVideoRefresh = *p;
// return OMX_ErrorNone if not in Executing state
// TODO: return OMX_ErrorIncorrectStateOperation?
CHECK_SET_PARAM_STATE();
VideoConfigIntraRefreshType configIntraRefreshType;
configIntraRefreshType.refreshType = (VideoIntraRefreshType)(mParamVideoRefresh.eRefreshMode + 1);
if(configIntraRefreshType.refreshType == VIDEO_ENC_CIR){
VideoConfigCIR configCIR;
VideoConfigIntraRefreshType configIntraRefreshType;
configCIR.cirParams.cir_num_mbs = mParamVideoRefresh.nCirMBs;
configIntraRefreshType.refreshType = VIDEO_ENC_CIR;
retStatus = mVideoEncoder->setConfig(&configCIR);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set CIR config");
}
}else{
VideoConfigAIR configAIR;
configAIR.airParams.airMBs = mParamVideoRefresh.nAirMBs;
configAIR.airParams.airThreshold = mParamVideoRefresh.nAirRef;
retStatus = mVideoEncoder->setConfig(&configAIR);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set AIR config");
}
}
retStatus = mVideoEncoder->setConfig(&configIntraRefreshType);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set refresh config");
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetConfigVideoFramerate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_CONFIG_FRAMERATETYPE *p = (OMX_CONFIG_FRAMERATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mConfigFramerate, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetConfigVideoFramerate(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
Encode_Status retStatus = ENCODE_SUCCESS;
if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax){
LOGE("SetConfigVideoFramerate failed. Feature is disabled.");
return OMX_ErrorUnsupportedIndex;
}
OMX_CONFIG_FRAMERATETYPE *p = (OMX_CONFIG_FRAMERATETYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
mConfigFramerate = *p;
// return OMX_ErrorNone if not in Executing state
// TODO, return OMX_ErrorIncorrectStateOperation?
CHECK_SET_CONFIG_STATE();
VideoConfigFrameRate framerate;
framerate.frameRate.frameRateDenom = 1;
framerate.frameRate.frameRateNum = mConfigFramerate.xEncodeFramerate >> 16;
retStatus = mVideoEncoder->setConfig(&framerate);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set frame rate config");
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetConfigVideoIntraVOPRefresh(OMX_PTR) {
LOGW("GetConfigVideoIntraVOPRefresh is not supported.");
return OMX_ErrorUnsupportedSetting;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetConfigVideoIntraVOPRefresh(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
Encode_Status retStatus = ENCODE_SUCCESS;
OMX_CONFIG_INTRAREFRESHVOPTYPE *p = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// return OMX_ErrorNone if not in Executing state
// TODO: return OMX_ErrorIncorrectStateOperation?
CHECK_SET_CONFIG_STATE();
if(p->IntraRefreshVOP == OMX_TRUE) {
VideoParamConfigSet configIDRRequest;
configIDRRequest.type = VideoConfigTypeIDRRequest;
retStatus = mVideoEncoder->setConfig(&configIDRRequest);
if(retStatus != ENCODE_SUCCESS) {
LOGW("Failed to set refresh config");
}
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetParamIntelAdaptiveSliceControl(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_INTEL_ADAPTIVE_SLICE_CONTROL *p = (OMX_VIDEO_PARAM_INTEL_ADAPTIVE_SLICE_CONTROL *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mParamIntelAdaptiveSliceControl, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetParamIntelAdaptiveSliceControl(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax) {
LOGE("SetParamIntelAdaptiveSliceControl failed. Feature is disabled.");
return OMX_ErrorUnsupportedIndex;
}
OMX_VIDEO_PARAM_INTEL_ADAPTIVE_SLICE_CONTROL *p = (OMX_VIDEO_PARAM_INTEL_ADAPTIVE_SLICE_CONTROL *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// set only in Loaded state (ComponentSetParam)
CHECK_SET_PARAM_STATE();
mParamIntelAdaptiveSliceControl = *p;
return OMX_ErrorNone;
}
/*
OMX_ERRORTYPE OMXVideoEncoderBase::GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
// assign values instead of memory coping to avoid nProfileIndex being overridden
p->eProfile = mParamProfileLevel.eProfile;
p->eLevel = mParamProfileLevel.eLevel;
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure) {
LOGW("SetParamVideoProfileLevelQuerySupported is not supported.");
return OMX_ErrorUnsupportedSetting;
}
*/
OMX_ERRORTYPE OMXVideoEncoderBase::GetStoreMetaDataInBuffers(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
StoreMetaDataInBuffersParams *p = (StoreMetaDataInBuffersParams *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, INPORT_INDEX);
p->bStoreMetaData = mStoreMetaDataInBuffers;
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::SetStoreMetaDataInBuffers(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
StoreMetaDataInBuffersParams *p = (StoreMetaDataInBuffersParams *)pStructure;
VideoParamsStoreMetaDataInBuffers StoreMetaDataInBuffers;
PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
PortVideo *output_port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
uint32_t maxSize = 0;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, INPORT_INDEX);
LOGD("SetStoreMetaDataInBuffers (enabled = %x)", p->bStoreMetaData);
if(mStoreMetaDataInBuffers == p->bStoreMetaData)
return OMX_ErrorNone;
StoreMetaDataInBuffers.isEnabled = p->bStoreMetaData;
if (mVideoEncoder->setParameters(&StoreMetaDataInBuffers) != ENCODE_SUCCESS)
return OMX_ErrorNotReady;
mStoreMetaDataInBuffers = p->bStoreMetaData;
if(mStoreMetaDataInBuffers){
// for input port buffer
OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput;
const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput_get;
paramPortDefinitionInput_get = port->GetPortDefinition();
paramPortDefinitionInput = (OMX_PARAM_PORTDEFINITIONTYPE *)paramPortDefinitionInput_get;
paramPortDefinitionInput->nBufferSize = IntelMetadataBuffer::GetMaxBufferSize();
}
else
{
const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput_get;
paramPortDefinitionInput_get = port->GetPortDefinition();
port->SetPortDefinition(paramPortDefinitionInput_get, true);
}
LOGD("SetStoreMetaDataInBuffers success");
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::GetSyncEncoding(OMX_PTR pStructure) {
OMX_BOOL* syncEncoding = static_cast<OMX_BOOL*>(pStructure);
*syncEncoding = mSyncEncoding;
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::SetSyncEncoding(OMX_PTR pStructure) {
CHECK_SET_PARAM_STATE();
mSyncEncoding = *(static_cast<OMX_BOOL*>(pStructure));
LOGD("SetSyncEncoding %d", mSyncEncoding);
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::GetPrependSPSPPS(OMX_PTR) {
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::SetPrependSPSPPS(OMX_PTR) {
LOGD("SetPrependSPSPPS success");
return OMX_ErrorNone;
};
OMX_ERRORTYPE OMXVideoEncoderBase::GetTemporalLayer(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_INTEL_TEMPORAL_LAYER* p = static_cast<OMX_VIDEO_PARAM_INTEL_TEMPORAL_LAYER*>(pStructure);
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
memcpy(p, &mTemporalLayer, sizeof(*p));
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetTemporalLayer(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_PARAM_INTEL_TEMPORAL_LAYER *p = (OMX_VIDEO_PARAM_INTEL_TEMPORAL_LAYER *)pStructure;
VideoParamsTemporalLayer TemporalLayer;
OMX_U32 i;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, OUTPORT_INDEX);
LOGE("SetTemporalLayer (enabled = %d)", p->nNumberOfTemporalLayer);
TemporalLayer.numberOfLayer = p->nNumberOfTemporalLayer;
TemporalLayer.nPeriodicity = p->nPeriodicity;
for(i=0;i<p->nPeriodicity;i++)
TemporalLayer.nLayerID[i] = p->nLayerID[i];
if (mVideoEncoder->setParameters(&TemporalLayer) != ENCODE_SUCCESS)
return OMX_ErrorNotReady;
LOGE("SetTemporalLayer success");
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::GetBlackFramePointer(OMX_PTR pStructure) {
OMX_ERRORTYPE ret;
OMX_VIDEO_INTEL_REQUEST_BALCK_FRAME_POINTER *p = (OMX_VIDEO_INTEL_REQUEST_BALCK_FRAME_POINTER *)pStructure;
CHECK_TYPE_HEADER(p);
CHECK_PORT_INDEX(p, INPORT_INDEX);
PortVideo *port_in = static_cast<PortVideo *>(ports[INPORT_INDEX]);
const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = port_in->GetPortDefinition();
OMX_U32 width = paramPortDefinitionInput->format.video.nFrameWidth;
OMX_U32 height = paramPortDefinitionInput->format.video.nFrameHeight;
OMX_U32 lumaSize = width * height;
OMX_U32 bufferSize = width * height * 3 / 2;
if(mBlackFramePointer) {
free(mBlackFramePointer);
mBlackFramePointer = NULL;
} else {
mBlackFramePointer = (OMX_PTR)memalign(4096, bufferSize); // align to page size
if(!mBlackFramePointer) {
return OMX_ErrorInsufficientResources;
}
memset(mBlackFramePointer, 0x0, lumaSize);
memset((OMX_PTR)((uint64_t)mBlackFramePointer + lumaSize), 0x80, lumaSize / 2);
p->nFramePointer = (OMX_U32)mBlackFramePointer;
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE OMXVideoEncoderBase::SetBlackFramePointer(OMX_PTR) {
return OMX_ErrorUnsupportedSetting;
}