You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
964 lines
34 KiB
964 lines
34 KiB
/* |
|
* Copyright (C) 2012 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. |
|
* |
|
*/ |
|
|
|
#include <inttypes.h> |
|
|
|
#include <OMX_Component.h> |
|
#include "isv_omxcomponent.h" |
|
#include <media/hardware/HardwareAPI.h> |
|
#include "isv_profile.h" |
|
#include <OMX_IndexExt.h> |
|
#include <hal_public.h> |
|
#include <nativebase/nativebase.h> |
|
|
|
#include "OMX_adaptor.h" |
|
|
|
//#define LOG_NDEBUG 0 |
|
#undef LOG_TAG |
|
#define LOG_TAG "isv-omxil" |
|
|
|
#define OUTPUT_STARTUP_DEC_BUF_NUM (38) |
|
#define FLUSH_WIDTH 352 |
|
#define FLUSH_HEIGHT 288 |
|
|
|
using namespace android; |
|
|
|
/********************************************************************************** |
|
* component methods & helpers |
|
*/ |
|
#define GET_ISVOMX_COMPONENT(hComponent) \ |
|
ISVComponent *pComp = static_cast<ISVComponent*> \ |
|
((static_cast<OMX_COMPONENTTYPE*>(hComponent))->pComponentPrivate); \ |
|
if (!pComp) \ |
|
return OMX_ErrorBadParameter; |
|
|
|
Vector<ISVComponent*> ISVComponent::g_isv_components; |
|
|
|
extern MRM_OMX_Adaptor* g_mrm_omx_adaptor; |
|
|
|
#ifndef TARGET_VPP_USE_GEN |
|
//global, static |
|
sp<ISVProcessor> ISVComponent::mProcThread = NULL; |
|
#endif |
|
|
|
//global, static |
|
pthread_mutex_t ISVComponent::ProcThreadInstanceLock = PTHREAD_MUTEX_INITIALIZER; |
|
|
|
ISVComponent::ISVComponent( |
|
OMX_PTR pAppData) |
|
: mComponent(NULL), |
|
mpCallBacks(NULL), |
|
mCore(NULL), |
|
mpISVCallBacks(NULL), |
|
mISVBufferManager(NULL), |
|
mThreadRunning(false), |
|
mProcThreadObserver(NULL), |
|
mNumISVBuffers(MIN_ISV_BUFFER_NUM), |
|
mNumDecoderBuffers(0), |
|
mNumDecoderBuffersBak(0), |
|
mOutputDecoderBufferNum(0), |
|
mWidth(0), |
|
mHeight(0), |
|
mUseAndroidNativeBufferIndex(0), |
|
mStoreMetaDataInBuffersIndex(0), |
|
mHackFormat(0), |
|
mUseAndroidNativeBuffer(false), |
|
mUseAndroidNativeBuffer2(false), |
|
mVPPEnabled(false), |
|
mVPPFlushing(false), |
|
mOutputCropChanged(false), |
|
mInitialized(false), |
|
#ifdef TARGET_VPP_USE_GEN |
|
mProcThread(NULL), |
|
#endif |
|
mOwnProcessor(false) |
|
{ |
|
memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE)); |
|
/* handle initialization */ |
|
SetTypeHeader(&mBaseComponent, sizeof(mBaseComponent)); |
|
mBaseComponent.pApplicationPrivate = pAppData; |
|
mBaseComponent.pComponentPrivate = static_cast<OMX_PTR>(this); |
|
|
|
/* connect handle's functions */ |
|
mBaseComponent.GetComponentVersion = NULL; |
|
mBaseComponent.SendCommand = SendCommand; |
|
mBaseComponent.GetParameter = GetParameter; |
|
mBaseComponent.SetParameter = SetParameter; |
|
mBaseComponent.GetConfig = GetConfig; |
|
mBaseComponent.SetConfig = SetConfig; |
|
mBaseComponent.GetExtensionIndex = GetExtensionIndex; |
|
mBaseComponent.GetState = GetState; |
|
mBaseComponent.ComponentTunnelRequest = NULL; |
|
mBaseComponent.UseBuffer = UseBuffer; |
|
mBaseComponent.AllocateBuffer = AllocateBuffer; |
|
mBaseComponent.FreeBuffer = FreeBuffer; |
|
mBaseComponent.EmptyThisBuffer = EmptyThisBuffer; |
|
mBaseComponent.FillThisBuffer = FillThisBuffer; |
|
mBaseComponent.SetCallbacks = SetCallbacks; |
|
mBaseComponent.ComponentDeInit = NULL; |
|
mBaseComponent.UseEGLImage = NULL; |
|
mBaseComponent.ComponentRoleEnum = ComponentRoleEnum; |
|
g_isv_components.push_back(static_cast<ISVComponent*>(this)); |
|
|
|
mVPPOn = ISVProfile::isFRCOn() || ISVProfile::isVPPOn(); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPOn %d", __func__, mVPPOn); |
|
|
|
if (mISVBufferManager == NULL) { |
|
mISVBufferManager = new ISVBufferManager(); |
|
} |
|
|
|
} |
|
|
|
ISVComponent::~ISVComponent() |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
if (mpISVCallBacks) { |
|
free(mpISVCallBacks); |
|
mpISVCallBacks = NULL; |
|
} |
|
|
|
for (OMX_U32 i = 0; i < g_isv_components.size(); i++) { |
|
if (g_isv_components.itemAt(i) == static_cast<ISVComponent*>(this)) { |
|
g_isv_components.removeAt(i); |
|
} |
|
} |
|
|
|
memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE)); |
|
deinit(); |
|
mVPPOn = false; |
|
mISVBufferManager = NULL; |
|
} |
|
|
|
status_t ISVComponent::init(int32_t width, int32_t height) |
|
{ |
|
if (mInitialized) |
|
return STATUS_OK; |
|
|
|
bool frcOn = false; |
|
if (mProcThreadObserver == NULL) |
|
mProcThreadObserver = new ISVProcThreadObserver(&mBaseComponent, mComponent, mpCallBacks, mISVBufferManager); |
|
|
|
pthread_mutex_lock(&ProcThreadInstanceLock); |
|
if (mProcThread == NULL) { |
|
mProcThread = new ISVProcessor(false, mISVBufferManager, mProcThreadObserver, width, height); |
|
mOwnProcessor = true; |
|
mProcThread->start(); |
|
} |
|
#ifndef TARGET_VPP_USE_GEN |
|
else { |
|
mVPPEnabled = false; |
|
mOwnProcessor = false; |
|
ALOGI("%s: failed to alloc isv processor", __func__); |
|
pthread_mutex_unlock(&ProcThreadInstanceLock); |
|
return STATUS_ERROR; |
|
} |
|
#endif |
|
pthread_mutex_unlock(&ProcThreadInstanceLock); |
|
|
|
mInitialized = true; |
|
return STATUS_OK; |
|
} |
|
|
|
void ISVComponent::deinit() |
|
{ |
|
pthread_mutex_lock(&ProcThreadInstanceLock); |
|
if (mOwnProcessor) { |
|
if (mProcThread != NULL) { |
|
mProcThread->stop(); |
|
mProcThread = NULL; |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: delete ISV processor ", __func__); |
|
} |
|
} |
|
pthread_mutex_unlock(&ProcThreadInstanceLock); |
|
|
|
mProcThreadObserver = NULL; |
|
|
|
mInitialized = false; |
|
} |
|
|
|
OMX_CALLBACKTYPE* ISVComponent::getCallBacks(OMX_CALLBACKTYPE* pCallBacks) |
|
{ |
|
//reset component callback functions |
|
mpCallBacks = pCallBacks; |
|
if (mpISVCallBacks) { |
|
free(mpISVCallBacks); |
|
mpISVCallBacks = NULL; |
|
} |
|
|
|
mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE)); |
|
if (!mpISVCallBacks) { |
|
ALOGE("%s: failed to alloc isv callbacks", __func__); |
|
return NULL; |
|
} |
|
mpISVCallBacks->EventHandler = EventHandler; |
|
mpISVCallBacks->EmptyBufferDone = pCallBacks->EmptyBufferDone; |
|
mpISVCallBacks->FillBufferDone = FillBufferDone; |
|
return mpISVCallBacks; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::SendCommand( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_COMMANDTYPE Cmd, |
|
OMX_IN OMX_U32 nParam1, |
|
OMX_IN OMX_PTR pCmdData) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_SendCommand(Cmd, nParam1, pCmdData); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_SendCommand( |
|
OMX_IN OMX_COMMANDTYPE Cmd, |
|
OMX_IN OMX_U32 nParam1, |
|
OMX_IN OMX_PTR pCmdData) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: Cmd index 0x%08x, nParam1 %d", __func__, Cmd, nParam1); |
|
|
|
if (mVPPEnabled && mVPPOn) { |
|
if ((Cmd == OMX_CommandFlush && (nParam1 == kPortIndexOutput || nParam1 == OMX_ALL)) |
|
|| (Cmd == OMX_CommandStateSet && nParam1 == OMX_StateIdle) |
|
|| (Cmd == OMX_CommandPortDisable && nParam1 == 1)) { |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive flush command, notify vpp thread to flush(Seek begin)", __func__); |
|
mVPPFlushing = true; |
|
mProcThread->notifyFlush(); |
|
} |
|
} |
|
|
|
return OMX_SendCommand(mComponent, Cmd, nParam1, pCmdData); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::GetParameter( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_INDEXTYPE nParamIndex, |
|
OMX_INOUT OMX_PTR pComponentParameterStructure) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_GetParameter(nParamIndex, pComponentParameterStructure); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_GetParameter( |
|
OMX_IN OMX_INDEXTYPE nParamIndex, |
|
OMX_INOUT OMX_PTR pComponentParameterStructure) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nParamIndex); |
|
|
|
OMX_ERRORTYPE err = OMX_GetParameter(mComponent, nParamIndex, pComponentParameterStructure); |
|
|
|
if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) { |
|
OMX_PARAM_PORTDEFINITIONTYPE *def = |
|
static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure); |
|
|
|
if (nParamIndex == OMX_IndexParamPortDefinition |
|
&& def->nPortIndex == kPortIndexOutput) { |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: orignal bufferCountActual %d, bufferCountMin %d", __func__, def->nBufferCountActual, def->nBufferCountMin); |
|
#ifndef TARGET_VPP_USE_GEN |
|
//FIXME: THIS IS A HACK!! Request NV12 buffer for YV12 format |
|
//because VSP only support NV12 output |
|
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video; |
|
if ((video_def->eColorFormat == VA_FOURCC_YV12) || |
|
(video_def->eColorFormat == HAL_PIXEL_FORMAT_INTEL_YV12)) { |
|
//FIXME workaround Disable ISV for YV12 input |
|
mVPPEnabled = false; |
|
ALOGI("%s: Disable ISV for YV12 input. mVPPEnabled %d", __func__, mVPPEnabled); |
|
} else { |
|
//FIXME workaround avc low resolution playback |
|
def->nBufferCountActual += mNumISVBuffers + 9; |
|
def->nBufferCountMin += mNumISVBuffers + 9; |
|
} |
|
#endif |
|
} |
|
} |
|
|
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::SetParameter( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_IN OMX_PTR pComponentParameterStructure) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_SetParameter(nIndex, pComponentParameterStructure); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_SetParameter( |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_IN OMX_PTR pComponentParameterStructure) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex); |
|
|
|
if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode)) { |
|
ISV_MODE* def = static_cast<ISV_MODE*>(pComponentParameterStructure); |
|
|
|
if (*def == ISV_AUTO) { |
|
mVPPEnabled = true; |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPEnabled -->true", __func__); |
|
#ifndef TARGET_VPP_USE_GEN |
|
if (mVPPOn) { |
|
uint32_t number = MIN_INPUT_NUM + MIN_OUTPUT_NUM; |
|
OMX_INDEXTYPE index; |
|
status_t error = |
|
OMX_GetExtensionIndex( |
|
mComponent, |
|
(OMX_STRING)"OMX.Intel.index.vppBufferNum", |
|
&index); |
|
if (error == OK) { |
|
error = OMX_SetParameter(mComponent, index, (OMX_PTR)&number); |
|
} else { |
|
// ingore this error |
|
ALOGW("Get vpp number index failed"); |
|
} |
|
} |
|
#endif |
|
} else if (*def == ISV_DISABLE) |
|
mVPPEnabled = false; |
|
return OMX_ErrorNone; |
|
} |
|
|
|
// before setting param to real omx component, firstly set to media resource manager |
|
OMX_ERRORTYPE err = g_mrm_omx_adaptor->MRM_OMX_SetParameter(mComponent, |
|
nIndex, |
|
pComponentParameterStructure); |
|
if (err == OMX_ErrorInsufficientResources) { |
|
return OMX_ErrorInsufficientResources; |
|
} |
|
|
|
err = OMX_SetParameter(mComponent, nIndex, pComponentParameterStructure); |
|
if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) { |
|
if (nIndex == OMX_IndexParamPortDefinition) { |
|
OMX_PARAM_PORTDEFINITIONTYPE *def = |
|
static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure); |
|
|
|
if (def->nPortIndex == kPortIndexOutput) { |
|
//set the buffer count we should fill to decoder before feed buffer to VPP |
|
mNumDecoderBuffersBak = mNumDecoderBuffers = def->nBufferCountActual - MIN_OUTPUT_NUM - UNDEQUEUED_NUM; |
|
mOutputDecoderBufferNum = 0; |
|
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video; |
|
|
|
//FIXME: init itself here |
|
if (mWidth != video_def->nFrameWidth |
|
|| mHeight != video_def->nFrameHeight) { |
|
deinit(); |
|
if (STATUS_OK == init(video_def->nFrameWidth, video_def->nFrameHeight)) { |
|
mWidth = video_def->nFrameWidth; |
|
mHeight = video_def->nFrameHeight; |
|
} |
|
} |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: def->nBufferCountActual %d, mNumDecoderBuffersBak %d", __func__, |
|
def->nBufferCountActual, mNumDecoderBuffersBak); |
|
if (mISVBufferManager != NULL && OK != mISVBufferManager->setBufferCount(def->nBufferCountActual)) { |
|
ALOGE("%s: failed to set ISV buffer count, set VPPEnabled -->false", __func__); |
|
mVPPEnabled = false; |
|
} |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: video frame width %d, height %d", __func__, |
|
video_def->nFrameWidth, video_def->nFrameHeight); |
|
} |
|
|
|
if (def->nPortIndex == kPortIndexInput) { |
|
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video; |
|
|
|
if (mProcThread != NULL) |
|
mProcThread->configFRC(video_def->xFramerate); |
|
} |
|
} |
|
|
|
if (mUseAndroidNativeBuffer |
|
&& nIndex == static_cast<OMX_INDEXTYPE>(mUseAndroidNativeBufferIndex)) { |
|
UseAndroidNativeBufferParams *def = |
|
static_cast<UseAndroidNativeBufferParams*>(pComponentParameterStructure); |
|
|
|
if (mISVBufferManager != NULL && OK != mISVBufferManager->useBuffer(def->nativeBuffer)) { |
|
ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__); |
|
mVPPEnabled = false; |
|
} |
|
} |
|
|
|
if (nIndex == static_cast<OMX_INDEXTYPE>(mStoreMetaDataInBuffersIndex)) { |
|
StoreMetaDataInBuffersParams *params = static_cast<StoreMetaDataInBuffersParams*>(pComponentParameterStructure); |
|
if (params->nPortIndex == kPortIndexOutput) { |
|
if (mISVBufferManager != NULL) { |
|
bool bMetaDataMode = params->bStoreMetaData == OMX_TRUE; |
|
mISVBufferManager->setMetaDataMode(bMetaDataMode); |
|
} else { |
|
ALOGE("%s: falied to set Meta Data Mode ", __func__); |
|
} |
|
} |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive ISVStoreMetaDataInBuffers mISVWorkMode %d", __func__, (params->bStoreMetaData == OMX_TRUE)); |
|
} |
|
} |
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::GetConfig( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_INOUT OMX_PTR pComponentConfigStructure) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_GetConfig(nIndex, pComponentConfigStructure); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_GetConfig( |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_INOUT OMX_PTR pComponentConfigStructure) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex); |
|
|
|
OMX_ERRORTYPE err = OMX_GetConfig(mComponent, nIndex, pComponentConfigStructure); |
|
if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) { |
|
if (nIndex == OMX_IndexConfigCommonOutputCrop) { |
|
OMX_CONFIG_RECTTYPE *rect = static_cast<OMX_CONFIG_RECTTYPE*>(pComponentConfigStructure); |
|
if (rect->nPortIndex == kPortIndexOutput && |
|
rect->nWidth < mWidth && |
|
rect->nHeight < mHeight) { |
|
mISVBufferManager->setBuffersFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mark all buffers need clear", __func__); |
|
} |
|
} |
|
} |
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::SetConfig( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_IN OMX_PTR pComponentConfigStructure) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_SetConfig(nIndex, pComponentConfigStructure); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_SetConfig( |
|
OMX_IN OMX_INDEXTYPE nIndex, |
|
OMX_IN OMX_PTR pComponentConfigStructure) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex); |
|
|
|
if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexConfigAutoFramerateConversion)) { |
|
OMX_CONFIG_BOOLEANTYPE *config = static_cast<OMX_CONFIG_BOOLEANTYPE*>(pComponentConfigStructure); |
|
if (config->bEnabled) { |
|
mVPPEnabled = true; |
|
ALOGI("%s: mVPPEnabled=true", __func__); |
|
} else { |
|
mVPPEnabled = false; |
|
ALOGI("%s: mVPPEnabled=false", __func__); |
|
} |
|
return OMX_ErrorNone; |
|
} |
|
|
|
return OMX_SetConfig(mComponent, nIndex, pComponentConfigStructure); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::GetExtensionIndex( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_STRING cParameterName, |
|
OMX_OUT OMX_INDEXTYPE* pIndexType) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_GetExtensionIndex(cParameterName, pIndexType); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_GetExtensionIndex( |
|
OMX_IN OMX_STRING cParameterName, |
|
OMX_OUT OMX_INDEXTYPE* pIndexType) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s", __func__, cParameterName); |
|
if(!strncmp(cParameterName, "OMX.intel.index.SetISVMode", strlen(cParameterName))) { |
|
*pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode); |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mComponent, cParameterName, pIndexType); |
|
|
|
if(err == OMX_ErrorNone && |
|
!strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer2", strlen(cParameterName))) |
|
mUseAndroidNativeBuffer2 = true; |
|
|
|
if(err == OMX_ErrorNone && |
|
!strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer", strlen(cParameterName))) { |
|
mUseAndroidNativeBuffer = true; |
|
mUseAndroidNativeBufferIndex = static_cast<uint32_t>(*pIndexType); |
|
} |
|
|
|
if(err == OMX_ErrorNone && |
|
!strncmp(cParameterName, "OMX.google.android.index.storeMetaDataInBuffers", strlen(cParameterName))) { |
|
mStoreMetaDataInBuffersIndex = static_cast<uint32_t>(*pIndexType); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: storeMetaDataInBuffersIndex 0x%08x return %d", __func__, mStoreMetaDataInBuffersIndex, err); |
|
} |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s, nIndex 0x%08x", __func__, |
|
cParameterName, *pIndexType); |
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::GetState( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_OUT OMX_STATETYPE* pState) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_GetState(pState); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_GetState( |
|
OMX_OUT OMX_STATETYPE* pState) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
|
|
return OMX_GetState(mComponent, pState); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::UseBuffer( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_PTR pAppPrivate, |
|
OMX_IN OMX_U32 nSizeBytes, |
|
OMX_IN OMX_U8 *pBuffer) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_UseBuffer(ppBufferHdr, nPortIndex, |
|
pAppPrivate, nSizeBytes, pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_UseBuffer( |
|
OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_PTR pAppPrivate, |
|
OMX_IN OMX_U32 nSizeBytes, |
|
OMX_IN OMX_U8 *pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
|
|
OMX_ERRORTYPE err = OMX_UseBuffer(mComponent, ppBufferHdr, nPortIndex, |
|
pAppPrivate, nSizeBytes, pBuffer); |
|
#ifndef USE_IVP |
|
if(err == OMX_ErrorNone |
|
&& mVPPEnabled |
|
&& mVPPOn |
|
&& nPortIndex == kPortIndexOutput |
|
/*&& mUseAndroidNativeBuffer2*/) { |
|
if (mISVBufferManager != NULL) { |
|
if (OK != mISVBufferManager->useBuffer(reinterpret_cast<unsigned long>(pBuffer))) { |
|
ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__); |
|
mVPPEnabled = false; |
|
} else |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPP useBuffer success. buffer handle %p", __func__, pBuffer); |
|
} |
|
} |
|
#endif |
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::AllocateBuffer( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_PTR pAppPrivate, |
|
OMX_IN OMX_U32 nSizeBytes) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_AllocateBuffer(ppBuffer, nPortIndex, |
|
pAppPrivate, nSizeBytes); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_AllocateBuffer( |
|
OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_PTR pAppPrivate, |
|
OMX_IN OMX_U32 nSizeBytes) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
|
|
return OMX_AllocateBuffer(mComponent, ppBuffer, nPortIndex, |
|
pAppPrivate, nSizeBytes); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::FreeBuffer( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_FreeBuffer(nPortIndex, pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_FreeBuffer( |
|
OMX_IN OMX_U32 nPortIndex, |
|
OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer); |
|
|
|
if(mVPPEnabled && mVPPOn |
|
&& nPortIndex == kPortIndexOutput) { |
|
if (mISVBufferManager != NULL && OK != mISVBufferManager->freeBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer))) |
|
ALOGW("%s: pBuffer %p has not been registered into ISV", __func__, pBuffer); |
|
} |
|
return OMX_FreeBuffer(mComponent, nPortIndex, pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::EmptyThisBuffer( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_EmptyThisBuffer(pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_EmptyThisBuffer( |
|
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer); |
|
|
|
return OMX_EmptyThisBuffer(mComponent, pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::FillThisBuffer( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry.", __func__); |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_FillThisBuffer(pBuffer); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_FillThisBuffer( |
|
OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) |
|
{ |
|
if(!mVPPEnabled || !mVPPOn) |
|
return OMX_FillThisBuffer(mComponent, pBuffer); |
|
|
|
ISVBuffer* isvBuffer = NULL; |
|
|
|
if (mISVBufferManager != NULL) { |
|
isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer)); |
|
if (isvBuffer == NULL) { |
|
ALOGE("%s: failed to map ISVBuffer, set mVPPEnabled -->false", __func__); |
|
mVPPEnabled = false; |
|
return OMX_FillThisBuffer(mComponent, pBuffer); |
|
} |
|
|
|
if (OK != isvBuffer->initBufferInfo(mHackFormat)) { |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: isvBuffer %p failed to initBufferInfo", __func__, isvBuffer); |
|
mVPPEnabled = false; |
|
return OMX_FillThisBuffer(mComponent, pBuffer); |
|
} |
|
} |
|
|
|
if (mNumDecoderBuffers > 0) { |
|
Mutex::Autolock autoLock(mDecoderBufLock); |
|
mNumDecoderBuffers--; |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: fill pBuffer %p to the decoder, decoder still need extra %d buffers", __func__, |
|
pBuffer, mNumDecoderBuffers); |
|
|
|
if (isvBuffer != NULL) |
|
isvBuffer->clearIfNeed(); |
|
|
|
return OMX_FillThisBuffer(mComponent, pBuffer); |
|
} |
|
mProcThread->addOutput(pBuffer); |
|
|
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::FillBufferDone( |
|
OMX_OUT OMX_HANDLETYPE hComponent, |
|
OMX_OUT OMX_PTR pAppData, |
|
OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__, |
|
g_isv_components.size(), |
|
g_isv_components.itemAt(0)); |
|
for (OMX_U32 i = 0; i < g_isv_components.size(); i++) { |
|
if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent) |
|
return g_isv_components.itemAt(i)->ISV_FillBufferDone(hComponent, pAppData, pBuffer); |
|
} |
|
return OMX_ErrorUndefined; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_FillBufferDone( |
|
OMX_OUT OMX_HANDLETYPE __maybe_unused hComponent, |
|
OMX_OUT OMX_PTR pAppData, |
|
OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: %p <== buffer_handle_t %p. mVPPEnabled %d, mVPPOn %d", __func__, |
|
pBuffer, pBuffer->pBuffer, mVPPEnabled, mVPPOn); |
|
if (!mpCallBacks) { |
|
ALOGE("%s: no call back functions were registered.", __func__); |
|
return OMX_ErrorUndefined; |
|
} |
|
|
|
if(!mVPPEnabled || !mVPPOn || mVPPFlushing || (pBuffer->nFilledLen == 0 && !(pBuffer->nFlags & OMX_BUFFERFLAG_EOS))) { |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3); |
|
return mpCallBacks->FillBufferDone(&mBaseComponent, pAppData, pBuffer); |
|
} |
|
|
|
if (mOutputCropChanged && mISVBufferManager != NULL) { |
|
ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer)); |
|
if (isvBuffer != NULL) |
|
isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED); |
|
mOutputCropChanged = false; |
|
} |
|
|
|
if ((mWidth > FLUSH_WIDTH) && (mHeight > FLUSH_HEIGHT) && |
|
(pBuffer->nFilledLen != 0) && (mOutputDecoderBufferNum < OUTPUT_STARTUP_DEC_BUF_NUM)) { |
|
Mutex::Autolock autoLock(mDecoderBufLock); |
|
// take one buffer from decoder loop here. Fill one buffer to the loop by mNumDecoderBuffers++ |
|
mNumDecoderBuffers++; |
|
mOutputDecoderBufferNum++; |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: return %d decoder output Buffer, mNumDecoderBuffers get %d input buffer", |
|
__func__, mOutputDecoderBufferNum, mNumDecoderBuffers); |
|
return mpCallBacks->FillBufferDone(&mBaseComponent, pAppData, pBuffer); |
|
} |
|
|
|
mProcThread->addInput(pBuffer); |
|
|
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::EventHandler( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_PTR pAppData, |
|
OMX_IN OMX_EVENTTYPE eEvent, |
|
OMX_IN OMX_U32 nData1, |
|
OMX_IN OMX_U32 nData2, |
|
OMX_IN OMX_PTR pEventData) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__, |
|
g_isv_components.size(), |
|
g_isv_components.itemAt(0)); |
|
for (OMX_U32 i = 0; i < g_isv_components.size(); i++) { |
|
if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent) |
|
return g_isv_components.itemAt(i)->ISV_EventHandler(hComponent, pAppData, eEvent, nData1, nData2, pEventData); |
|
} |
|
return OMX_ErrorUndefined; |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_EventHandler( |
|
OMX_IN OMX_HANDLETYPE __maybe_unused hComponent, |
|
OMX_IN OMX_PTR pAppData, |
|
OMX_IN OMX_EVENTTYPE eEvent, |
|
OMX_IN OMX_U32 nData1, |
|
OMX_IN OMX_U32 nData2, |
|
OMX_IN OMX_PTR pEventData) |
|
{ |
|
if (!mpCallBacks) { |
|
ALOGE("%s: no call back functions were registered.", __func__); |
|
return OMX_ErrorUndefined; |
|
} |
|
|
|
if(!mVPPEnabled || !mVPPOn) |
|
return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData); |
|
|
|
switch (eEvent) { |
|
case OMX_EventCmdComplete: |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: OMX_EventCmdComplete Cmd type 0x%08x, data2 %d", __func__, |
|
nData1, nData2); |
|
if (((OMX_COMMANDTYPE)nData1 == OMX_CommandFlush && (nData2 == kPortIndexOutput || nData2 == OMX_ALL)) |
|
|| ((OMX_COMMANDTYPE)nData1 == OMX_CommandStateSet && nData2 == OMX_StateIdle) |
|
|| ((OMX_COMMANDTYPE)nData1 == OMX_CommandPortDisable && nData2 == 1)) { |
|
mProcThread->waitFlushFinished(); |
|
mVPPFlushing = false; |
|
mNumDecoderBuffers = mNumDecoderBuffersBak; |
|
mOutputDecoderBufferNum = 0; |
|
} |
|
break; |
|
} |
|
|
|
case OMX_EventError: |
|
{ |
|
//do we need do anything here? |
|
ALOGE("%s: ERROR(0x%08x, %d)", __func__, nData1, nData2); |
|
//mProcThread->flush(); |
|
break; |
|
} |
|
|
|
case OMX_EventPortSettingsChanged: |
|
{ |
|
if (nData1 == kPortIndexOutput && nData2 == OMX_IndexConfigCommonOutputCrop) { |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: output crop changed", __func__); |
|
mOutputCropChanged = true; |
|
return OMX_ErrorNone; |
|
} else if (nData1 == kPortIndexOutput && nData2 == OMX_IndexParamPortDefinition) { |
|
ALOGI("%s: output format changed. ISV flush buffers", __func__); |
|
mProcThread->notifyFlush(); |
|
} |
|
break; |
|
} |
|
|
|
default: |
|
{ |
|
ALOGD_IF( |
|
ISV_COMPONENT_DEBUG, "%s: EVENT(%d, %" PRId32 ", %" PRId32 ")", |
|
__func__, eEvent, nData1, nData2); |
|
break; |
|
} |
|
} |
|
return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::SetCallbacks( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_IN OMX_CALLBACKTYPE* pCallbacks, |
|
OMX_IN OMX_PTR pAppData) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_SetCallbacks(pCallbacks, pAppData); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_SetCallbacks( |
|
OMX_IN OMX_CALLBACKTYPE* pCallbacks, |
|
OMX_IN OMX_PTR pAppData) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
|
|
if (mVPPEnabled && mVPPOn) { |
|
if (mpISVCallBacks == NULL) { |
|
mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE)); |
|
if (!mpISVCallBacks) { |
|
ALOGE("%s: failed to alloc isv callbacks", __func__); |
|
return OMX_ErrorUndefined; |
|
} |
|
} |
|
mpISVCallBacks->EventHandler = EventHandler; |
|
mpISVCallBacks->EmptyBufferDone = pCallbacks->EmptyBufferDone; |
|
mpISVCallBacks->FillBufferDone = FillBufferDone; |
|
mpCallBacks = pCallbacks; |
|
return mComponent->SetCallbacks(mComponent, mpISVCallBacks, pAppData); |
|
} |
|
return mComponent->SetCallbacks(mComponent, pCallbacks, pAppData); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ComponentRoleEnum( |
|
OMX_IN OMX_HANDLETYPE hComponent, |
|
OMX_OUT OMX_U8 *cRole, |
|
OMX_IN OMX_U32 nIndex) |
|
{ |
|
GET_ISVOMX_COMPONENT(hComponent); |
|
|
|
return pComp->ISV_ComponentRoleEnum(cRole, nIndex); |
|
} |
|
|
|
OMX_ERRORTYPE ISVComponent::ISV_ComponentRoleEnum( |
|
OMX_OUT OMX_U8 *cRole, |
|
OMX_IN OMX_U32 nIndex) |
|
{ |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__); |
|
|
|
return mComponent->ComponentRoleEnum(mComponent, cRole, nIndex); |
|
} |
|
|
|
|
|
void ISVComponent::SetTypeHeader(OMX_PTR type, OMX_U32 size) |
|
{ |
|
OMX_U32 *nsize; |
|
OMX_VERSIONTYPE *nversion; |
|
|
|
if (!type) |
|
return; |
|
|
|
nsize = (OMX_U32 *)type; |
|
nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32)); |
|
|
|
*nsize = size; |
|
nversion->nVersion = OMX_SPEC_VERSION; |
|
} |
|
|
|
|
|
ISVProcThreadObserver::ISVProcThreadObserver( |
|
OMX_COMPONENTTYPE *pBaseComponent, |
|
OMX_COMPONENTTYPE *pComponent, |
|
OMX_CALLBACKTYPE *pCallBacks, |
|
sp<ISVBufferManager> bufferManager) |
|
: mBaseComponent(pBaseComponent), |
|
mComponent(pComponent), |
|
mpCallBacks(pCallBacks), |
|
mISVBufferManager(bufferManager) |
|
{ |
|
ALOGV("VPPProcThreadObserver!"); |
|
} |
|
|
|
ISVProcThreadObserver::~ISVProcThreadObserver() |
|
{ |
|
ALOGV("~VPPProcThreadObserver!"); |
|
mBaseComponent = NULL; |
|
mComponent = NULL; |
|
mpCallBacks = NULL; |
|
} |
|
|
|
OMX_ERRORTYPE ISVProcThreadObserver::releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool bFLush) |
|
{ |
|
if (!mBaseComponent || !mComponent || !mpCallBacks) |
|
return OMX_ErrorUndefined; |
|
|
|
OMX_ERRORTYPE err = OMX_ErrorNone; |
|
if (bFLush) { |
|
if(index == kPortIndexOutput) { |
|
pBuffer->nFilledLen = 0; |
|
pBuffer->nOffset = 0; |
|
pBuffer->nTimeStamp = 0; |
|
pBuffer->nFlags = 0; |
|
} |
|
err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: flush pBuffer %p", __func__, pBuffer); |
|
return err; |
|
} |
|
|
|
if (index == kPortIndexInput) { |
|
pBuffer->nFilledLen = 0; |
|
pBuffer->nOffset = 0; |
|
pBuffer->nFlags = 0; |
|
pBuffer->nTimeStamp = 0; |
|
|
|
if (mISVBufferManager != NULL) { |
|
ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer)); |
|
if (isvBuffer != NULL) |
|
isvBuffer->clearIfNeed(); |
|
} |
|
|
|
err = OMX_FillThisBuffer(mComponent, pBuffer); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBuffer pBuffer %p", __func__, pBuffer); |
|
} else { |
|
err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer); |
|
ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3); |
|
} |
|
|
|
return err; |
|
} |
|
|
|
OMX_ERRORTYPE ISVProcThreadObserver::reportOutputCrop() |
|
{ |
|
if (!mBaseComponent || !mComponent || !mpCallBacks) |
|
return OMX_ErrorUndefined; |
|
|
|
OMX_ERRORTYPE err = OMX_ErrorNone; |
|
err = mpCallBacks->EventHandler(&mBaseComponent, mBaseComponent->pApplicationPrivate, |
|
OMX_EventPortSettingsChanged, |
|
kPortIndexOutput, OMX_IndexConfigCommonOutputCrop, NULL); |
|
return err; |
|
}
|
|
|