summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuanjun Huang <yuanjun.huang@intel.com>2015-07-14 17:15:49 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-07-14 17:15:49 +0000
commit1fda5d920dedd63a6b799ba7cb7d824805c73c16 (patch)
treea1d3957e941e52ba4877588f74fa715cd34ce196
parent093da74f74457c1c5e1b9dd60e52103f8d378a97 (diff)
parent9042795f805dffc0be5b900df3e42fe32ae61349 (diff)
downloadutils-1fda5d920dedd63a6b799ba7cb7d824805c73c16.tar.gz
am 9042795f: Implement codec level media resource manager.
* commit '9042795f805dffc0be5b900df3e42fe32ae61349': Implement codec level media resource manager.
-rw-r--r--ISV/Android.mk4
-rw-r--r--ISV/include/isv_omxcomponent.h2
-rw-r--r--ISV/omx/isv_omxcomponent.cpp15
-rw-r--r--ISV/omx/isv_omxcore.cpp25
-rw-r--r--media_resource_manager/Android.mk16
-rw-r--r--media_resource_manager/arbitrator/Android.mk24
-rw-r--r--media_resource_manager/arbitrator/MediaResourceArbitrator.cpp541
-rw-r--r--media_resource_manager/arbitrator/MediaResourceArbitrator.h179
-rw-r--r--media_resource_manager/omx_adaptor/Android.mk26
-rw-r--r--media_resource_manager/omx_adaptor/OMX_adaptor.cpp287
-rw-r--r--media_resource_manager/omx_adaptor/OMX_adaptor.h117
-rw-r--r--media_resource_manager/test/Android.mk23
-rw-r--r--media_resource_manager/test/MediaResourceManager_test.cpp122
13 files changed, 1379 insertions, 2 deletions
diff --git a/ISV/Android.mk b/ISV/Android.mk
index 12965a9..9808e6e 100644
--- a/ISV/Android.mk
+++ b/ISV/Android.mk
@@ -22,7 +22,8 @@ LOCAL_SHARED_LIBRARIES := \
libhardware \
libexpat \
libva \
- libva-android
+ libva-android \
+ libmrm_omx_adaptor \
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
@@ -32,6 +33,7 @@ LOCAL_C_INCLUDES := \
$(TARGET_OUT_HEADERS)/khronos/openmax \
$(TARGET_OUT_HEADERS)/libva \
$(TARGET_OUT_HEADERS)/pvr/hal \
+ $(TARGET_OUT_HEADERS)/media_resource_manager/ \
$(call include-path-for, frameworks-native)/media/openmax
ifeq ($(USE_MEDIASDK),true)
diff --git a/ISV/include/isv_omxcomponent.h b/ISV/include/isv_omxcomponent.h
index 5acea30..1e8d13e 100644
--- a/ISV/include/isv_omxcomponent.h
+++ b/ISV/include/isv_omxcomponent.h
@@ -77,6 +77,8 @@ public:
// return ISV component handle
OMX_COMPONENTTYPE *getBaseComponent(){return &mBaseComponent;}
+ OMX_HANDLETYPE getComponent(){return static_cast<OMX_HANDLETYPE>(mComponent);}
+
static Vector<ISVComponent*> g_isv_components;
private:
/*
diff --git a/ISV/omx/isv_omxcomponent.cpp b/ISV/omx/isv_omxcomponent.cpp
index 1cce8a2..8be096e 100644
--- a/ISV/omx/isv_omxcomponent.cpp
+++ b/ISV/omx/isv_omxcomponent.cpp
@@ -24,10 +24,13 @@
#include <OMX_IndexExt.h>
#include <hal_public.h>
+#include "OMX_adaptor.h"
+
//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "isv-omxil"
+
using namespace android;
/**********************************************************************************
@@ -41,6 +44,8 @@ using namespace android;
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;
@@ -320,7 +325,15 @@ OMX_ERRORTYPE ISVComponent::ISV_SetParameter(
return OMX_ErrorNone;
}
- OMX_ERRORTYPE err = OMX_SetParameter(mComponent, nIndex, pComponentParameterStructure);
+ // 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 =
diff --git a/ISV/omx/isv_omxcore.cpp b/ISV/omx/isv_omxcore.cpp
index 4cd7238..bca96e7 100644
--- a/ISV/omx/isv_omxcore.cpp
+++ b/ISV/omx/isv_omxcore.cpp
@@ -25,6 +25,8 @@
#include "isv_omxcomponent.h"
#include "isv_profile.h"
+#include "OMX_adaptor.h"
+
//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "isv-omxil"
@@ -48,6 +50,8 @@ static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
static ISVOMXCore g_cores[CORE_NUMBER];
static Vector<ISVComponent*> g_isv_components;
+MRM_OMX_Adaptor* g_mrm_omx_adaptor = NULL;
+
/**********************************************************************************
* core entry
*/
@@ -104,6 +108,8 @@ OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
ALOGW("OMX IL core not found");
}
}
+ g_mrm_omx_adaptor = MRM_OMX_Adaptor::getInstance();
+ g_mrm_omx_adaptor->MRM_OMX_Init();
g_initialized = 1;
}
pthread_mutex_unlock(&g_module_lock);
@@ -129,6 +135,10 @@ OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
}
pthread_mutex_unlock(&g_module_lock);
+ if (g_mrm_omx_adaptor != NULL) {
+ g_mrm_omx_adaptor = NULL;
+ }
+
g_initialized = 0;
ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret);
@@ -192,6 +202,14 @@ OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
return OMX_ErrorInsufficientResources;
}
+ ret = g_mrm_omx_adaptor->MRM_OMX_CheckIfFullLoad(cComponentName);
+ if (ret == OMX_ErrorInsufficientResources) {
+ ALOGE("OMX_GetHandle failed. codec under full load status from media resource manager.\
+ return OMX_ErrorInsufficientResources");
+ pthread_mutex_unlock(&g_module_lock);
+ return OMX_ErrorInsufficientResources;
+ }
+
/* find the real component*/
for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
if (g_cores[i].mLibHandle == NULL) {
@@ -208,6 +226,10 @@ OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
*pHandle = pISVComponent->getBaseComponent();
ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle);
+
+ // set component into media resource manager adaptor
+ g_mrm_omx_adaptor->MRM_OMX_SetComponent(tempHandle, cComponentName);
+
pthread_mutex_unlock(&g_module_lock);
return OMX_ErrorNone;
} else if(omx_res == OMX_ErrorInsufficientResources) {
@@ -245,6 +267,9 @@ OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
delete pComp;
g_isv_components.removeAt(i);
ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent);
+
+ // remove it in media resource manager
+ g_mrm_omx_adaptor->MRM_OMX_RemoveComponent(pComp->getComponent());
pthread_mutex_unlock(&g_module_lock);
return OMX_ErrorNone;
}
diff --git a/media_resource_manager/Android.mk b/media_resource_manager/Android.mk
new file mode 100644
index 0000000..c577542
--- /dev/null
+++ b/media_resource_manager/Android.mk
@@ -0,0 +1,16 @@
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO := media_resource_manager
+LOCAL_COPY_HEADERS := \
+ arbitrator/MediaResourceArbitrator.h \
+ omx_adaptor/OMX_adaptor.h
+
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+MEDIA_RESOURCE_MANAGER_ROOT := $(LOCAL_PATH)
+
+include $(CLEAR_VARS)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media_resource_manager/arbitrator/Android.mk b/media_resource_manager/arbitrator/Android.mk
new file mode 100644
index 0000000..382f29f
--- /dev/null
+++ b/media_resource_manager/arbitrator/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ MediaResourceArbitrator.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libcutils \
+ libexpat \
+ libdl \
+
+
+LOCAL_C_INCLUDES := \
+ $(TARGET_OUT_HEADERS)/khronos/openmax \
+ $(call include-path-for, frameworks-native)/media/openmax
+
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libmrm_arbitrator
+
+#LOCAL_CFLAGS += -Werror
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media_resource_manager/arbitrator/MediaResourceArbitrator.cpp b/media_resource_manager/arbitrator/MediaResourceArbitrator.cpp
new file mode 100644
index 0000000..26be60b
--- /dev/null
+++ b/media_resource_manager/arbitrator/MediaResourceArbitrator.cpp
@@ -0,0 +1,541 @@
+/*
+ * * Copyright (c) 2015 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_NDEBUG 0
+#define LOG_TAG "MRM_Arbitrator"
+
+#include <libexpat/expat.h>
+#include <string.h>
+#include <stdio.h>
+#include <utils/Log.h>
+#include <unistd.h>
+#include "MediaResourceArbitrator.h"
+
+using namespace android;
+
+
+MediaResourceArbitrator::MediaResourceArbitrator()
+ : mIsEncoderUnderFullLoad (false),
+ mIsDecoderUnderFullLoad (false) {
+ ALOGV("construct MediaResourceArbitrator");
+ pthread_mutex_init(&mArbitratorLock, NULL);
+ //InitializeCodecNameTypeMap();
+ //InitializeResolutionNameTypeMap();
+}
+
+
+MediaResourceArbitrator::~MediaResourceArbitrator() {}
+
+
+ArbitratorErrorType MediaResourceArbitrator::Config(const char* configFilePath) {
+ FILE *fp = NULL;
+
+ fp = ::fopen(configFilePath, "r");
+ if (fp == NULL) {
+ ALOGV("%s: can not open config xml file.\
+ try to set up default codec limitation");
+ SetupDefaultCodecLimitation();
+ return ArbitratorErrorNone;
+ }
+
+ ParseXMLFile(fp);
+ return ArbitratorErrorNone;
+}
+
+
+bool MediaResourceArbitrator::CheckIfFullLoad(bool isEncoder) {
+ if (isEncoder) {
+ return mIsEncoderUnderFullLoad;
+ } else {
+ return mIsDecoderUnderFullLoad;
+ }
+}
+
+
+ArbitratorErrorType MediaResourceArbitrator::AddResource(
+ /* in */ CodecType codecType,
+ /* in */ bool isEncoder,
+ /* in */ bool isSecured,
+ /* in */ ResolutionType resolution,
+ /* in */ uint frameRate) {
+ ALOGV("MediaResourceArbitrator::AddResource ++");
+ pthread_mutex_lock(&mArbitratorLock);
+
+ ArbitratorErrorType err = ArbitratorErrorNone;
+
+ if (CheckIfFullLoad(isEncoder) == true) {
+ pthread_mutex_unlock(&mArbitratorLock);
+ return ArbitratorErrorInsufficientResources;
+ }
+
+ CodecInfo resource;
+ resource.codecType = codecType;
+ resource.isEncoder = isEncoder;
+ resource.isSecured = isSecured;
+ resource.resolution = resolution;
+ resource.frameRate = frameRate;
+
+ ALOGV("Adding resource: codecType = %d, isEncoder = %d, isSecured = %d, resolution = %d, frameRate = %d",
+ codecType, isEncoder, isSecured, resolution, frameRate);
+
+ if (isEncoder) {
+ mLivingEncodersTable.livingEncoders.push_back(resource);
+ if (resolution > mLivingEncodersTable.maxResolution) {
+ mLivingEncodersTable.maxResolution = resolution;
+ }
+ if (frameRate > mLivingEncodersTable.maxFrameRate) {
+ mLivingEncodersTable.maxFrameRate = frameRate;
+ }
+ } else { // decoder
+ mLivingDecodersTable.livingDecoders.push_back(resource);
+ if (resolution > mLivingDecodersTable.maxResolution) {
+ mLivingDecodersTable.maxResolution = resolution;
+ }
+ if (frameRate > mLivingDecodersTable.maxFrameRate) {
+ mLivingDecodersTable.maxFrameRate = frameRate;
+ }
+ }
+
+ err = ArbitrateFullLoad(resource);
+ pthread_mutex_unlock(&mArbitratorLock);
+
+ ALOGV("AddResource --");
+ return err;
+}
+
+
+uint MediaResourceArbitrator::GetLivingCodecsNum(void) {
+ return mLivingDecodersTable.livingDecoders.size() +
+ mLivingEncodersTable.livingEncoders.size();
+}
+
+
+
+ArbitratorErrorType MediaResourceArbitrator::RemoveResource(
+ CodecType codecType,
+ bool isEncoder,
+ bool isSecured,
+ ResolutionType resolution,
+ uint frameRate) {
+ ALOGV("MediaResourceArbitrator::RemoveResource");
+
+ uint i;
+ ArbitratorErrorType err = ArbitratorErrorNone;
+
+ pthread_mutex_lock(&mArbitratorLock);
+
+ if (isEncoder) {
+ for(i=0; i<mLivingEncodersTable.livingEncoders.size(); i++) {
+ const CodecInfo& livingCodec = mLivingEncodersTable.livingEncoders[i];
+ if ((livingCodec.codecType == codecType) &&
+ (livingCodec.resolution == resolution) &&
+ (livingCodec.frameRate == frameRate)) {
+ mLivingEncodersTable.livingEncoders.removeAt(i);
+ break;
+ }
+ }
+ mIsEncoderUnderFullLoad = false;
+ } else {
+ for(i=0; i<mLivingDecodersTable.livingDecoders.size(); i++) {
+ const CodecInfo& livingCodec = mLivingDecodersTable.livingDecoders[i];
+ if ((livingCodec.codecType == codecType) &&
+ (livingCodec.resolution == resolution) &&
+ (livingCodec.isSecured == isSecured) &&
+ (livingCodec.frameRate == frameRate)) {
+ mLivingDecodersTable.livingDecoders.removeAt(i);
+ break;
+ }
+ }
+ mIsDecoderUnderFullLoad = false;
+ }
+ pthread_mutex_unlock(&mArbitratorLock);
+ return err;
+}
+
+
+void MediaResourceArbitrator::ParseXMLFile(FILE* fp) {
+ ALOGV("MediaResourceArbitrator::ParseXMLFile");
+
+ int done;
+ void *pBuf = NULL;
+
+ XML_Parser parser = ::XML_ParserCreate(NULL);
+ if (NULL == parser) {
+ ALOGE("@%s, line:%d, parser is NULL", __func__, __LINE__);
+ goto exit;
+ }
+ ::XML_SetUserData(parser, this);
+ ::XML_SetElementHandler(parser, startElement, endElement);
+
+ pBuf = malloc(mBufSize);
+ if (NULL == pBuf) {
+ ALOGE("@%s, line:%d, failed to malloc buffer", __func__, __LINE__);
+ goto exit;
+ }
+
+ do {
+ int len = (int)::fread(pBuf, 1, mBufSize, fp);
+ if (!len) {
+ if (ferror(fp)) {
+ clearerr(fp);
+ goto exit;
+ }
+ }
+ done = len < mBufSize;
+ if (XML_Parse(parser, (const char *)pBuf, len, done) == XML_STATUS_ERROR) {
+ ALOGE("@%s, line:%d, XML_Parse error", __func__, __LINE__);
+ goto exit;
+ }
+ } while (!done);
+
+exit:
+ if (parser)
+ ::XML_ParserFree(parser);
+ if (pBuf)
+ free(pBuf);
+ if (fp)
+ ::fclose(fp);
+
+}
+
+
+ArbitratorErrorType MediaResourceArbitrator::ArbitrateFullLoad(CodecInfo& codec) {
+ ALOGV("MediaResourceArbitrator::ArbitrateFullLoad");
+ ALOGV("giving codec type :%d, isEncoder = %d, frameRate = %d",
+ codec.codecType, codec.isEncoder, codec.frameRate);
+ ArbitratorErrorType err = ArbitratorErrorNone;
+ int livingInstanceNum = 0;
+
+ if (codec.isEncoder == true) {
+ livingInstanceNum = mLivingEncodersTable.livingEncoders.size();
+ } else {
+ livingInstanceNum = mLivingDecodersTable.livingDecoders.size();
+ }
+
+ ALOGV("current living codec number of %s is %d",
+ codec.isEncoder ? "encoder" : "decoder", livingInstanceNum);
+
+ // check if living instance number reaches the limitation
+ int targetInstanceLimit = 5; // most optimistic
+ uint i,j;
+
+ if (codec.isEncoder == false) { // decoder
+ for (i=0; i<mLivingDecodersTable.livingDecoders.size(); i++) {
+ const CodecInfo& livingCodec = mLivingDecodersTable.livingDecoders[i];
+ for (j=0; j<mDecoderLimitInfos.size(); j++) {
+ const CodecInfo& targetCodec = mDecoderLimitInfos[j].codecInfo;
+ ALOGV("%dth codec in DecoderLimitInfos.",j);
+ if (CheckCodecMatched(livingCodec, targetCodec) == true) {
+ if (targetInstanceLimit > mDecoderLimitInfos[j].instanceLimit) {
+ targetInstanceLimit = mDecoderLimitInfos[j].instanceLimit;
+ break;
+ }
+ }
+ }
+ }
+ ALOGV("Go through decoder limit table and get current instance limit = %d",
+ targetInstanceLimit);
+ if (livingInstanceNum >= targetInstanceLimit) {
+ ALOGV("setting full load flag to true.");
+ mIsDecoderUnderFullLoad = true;
+ } else {
+ ALOGV("setting full load flag to false.");
+ mIsDecoderUnderFullLoad = false;
+ }
+ } else { // encoder
+ for(i=0; i<mLivingEncodersTable.livingEncoders.size(); i++) {
+ const CodecInfo& livingCodec = mLivingEncodersTable.livingEncoders[i];
+ for (j=0; j<mEncoderLimitInfos.size(); j++) {
+ const CodecInfo& targetCodec = mEncoderLimitInfos[j].codecInfo;
+ if (CheckCodecMatched(livingCodec, targetCodec) == true) {
+ if (targetInstanceLimit > mEncoderLimitInfos[j].instanceLimit) {
+ targetInstanceLimit = mEncoderLimitInfos[j].instanceLimit;
+ break;
+ }
+ }
+ }
+ }
+ ALOGV("Go through encoder limit table and get current instance limit = %d",
+ targetInstanceLimit);
+ if (livingInstanceNum >= targetInstanceLimit) {
+ ALOGV("setting full load flag to true.");
+ mIsEncoderUnderFullLoad = true;
+ } else {
+ ALOGV("setting full load flag to false.");
+ mIsEncoderUnderFullLoad = false;
+ }
+ }
+
+ return err;
+}
+
+
+bool MediaResourceArbitrator::CheckCodecMatched(
+ const CodecInfo& sourceCodec,
+ const CodecInfo& targetCodec) {
+ ALOGV("CheckCodecMatched");
+ return ((sourceCodec.codecType == targetCodec.codecType) &&
+ (sourceCodec.isSecured == targetCodec.isSecured) &&
+ (sourceCodec.resolution == targetCodec.resolution) &&
+ (sourceCodec.frameRate == targetCodec.frameRate));
+}
+
+
+void MediaResourceArbitrator::DumpCodecTypeFromVector(void) {
+ unsigned int i;
+ ALOGV("MediaResourceArbitrator::DumpCodecTypeFromVector");
+ for (i=0; i<mCodecNameTypeMap.size(); i++) {
+ ALOGV("codec type in vector %s : %d",
+ mCodecNameTypeMap.keyAt(i), mCodecNameTypeMap.valueAt(i));
+ }
+}
+
+
+CodecType MediaResourceArbitrator::MapCodecTypeFromName(const char* name) {
+ if (strcmp(name, "CODEC_TYPE_AVC") == 0) {
+ return CODEC_TYPE_AVC;
+ } else if (strcmp(name, "CODEC_TYPE_HEVC") == 0) {
+ return CODEC_TYPE_HEVC;
+ } else if (strcmp(name, "CODEC_TYPE_VP8") == 0) {
+ return CODEC_TYPE_VP8;
+ } else if (strcmp(name, "CODEC_TYPE_VP9") == 0) {
+ return CODEC_TYPE_VP9;
+ } else if (strcmp(name, "CODEC_TYPE_MPEG2") == 0) {
+ return CODEC_TYPE_MPEG2;
+ } else if (strcmp(name, "CODEC_TYPE_MPEG4") == 0){
+ return CODEC_TYPE_MPEG4;
+ } else if (strcmp(name, "CODEC_TYPE_H263") == 0) {
+ return CODEC_TYPE_H263;
+ } else if (strcmp(name, "CODEC_TYPE_WMV") == 0) {
+ return CODEC_TYPE_WMV;
+ } else if (strcmp(name, "CODEC_TYPE_VC1") == 0) {
+ return CODEC_TYPE_VC1;
+ } else {
+ ALOGE("unknown codec name: %s, try to return avc", name);
+ return CODEC_TYPE_AVC;
+ }
+}
+
+
+ResolutionType MediaResourceArbitrator::
+ MapResolutionTypeFromName(const char* name) {
+ if (strcmp(name, "480") == 0) {
+ return Resolution_480;
+ } else if (strcmp(name, "720") == 0) {
+ return Resolution_720;
+ } else if (strcmp(name, "1080") == 0) {
+ return Resolution_1080;
+ } else if (strcmp(name, "2K") == 0) {
+ return Resolution_2K;
+ } else if (strcmp(name, "4K") == 0) {
+ return Resolution_4K;
+ } else {
+ ALOGE("unkown resolution name: %s, try to return 1080", name);
+ return Resolution_1080;
+ }
+}
+
+
+void MediaResourceArbitrator::InitializeCodecNameTypeMap(void) {
+ ALOGV("MediaResourceArbitrator::InitializeCodecNameTypeMap");
+ mCodecNameTypeMap.add("CODEC_TYPE_AVC", CODEC_TYPE_AVC);
+ mCodecNameTypeMap.add("CODEC_TYPE_HEVC", CODEC_TYPE_HEVC);
+ mCodecNameTypeMap.add("CODEC_TYPE_VP8", CODEC_TYPE_VP8);
+ mCodecNameTypeMap.add("CODEC_TYPE_VP9", CODEC_TYPE_VP9);
+ mCodecNameTypeMap.add("CODEC_TYPE_MPEG4", CODEC_TYPE_MPEG4);
+ mCodecNameTypeMap.add("CODEC_TYPE_MPEG2", CODEC_TYPE_MPEG2);
+ mCodecNameTypeMap.add("CODEC_TYPE_H263", CODEC_TYPE_H263);
+ mCodecNameTypeMap.add("CODEC_TYPE_VC1", CODEC_TYPE_VC1);
+ mCodecNameTypeMap.add("CODEC_TYPE_WMV", CODEC_TYPE_WMV);
+ //DumpCodecTypeFromVector();
+}
+
+
+void MediaResourceArbitrator::InitializeResolutionNameTypeMap(void) {
+ ALOGV("MediaResourceArbitrator::InitializeResolutionNameTypeMap");
+ mResolutionNameTypeMap.add("480", Resolution_480);
+ mResolutionNameTypeMap.add("720", Resolution_720);
+ mResolutionNameTypeMap.add("1080", Resolution_1080);
+ mResolutionNameTypeMap.add("2K", Resolution_2K);
+ mResolutionNameTypeMap.add("4K", Resolution_4K);
+}
+
+// Hard coded limitation
+void MediaResourceArbitrator::SetupDefaultCodecLimitation(void) {
+ ALOGV("MediaResourceArbitrator::SetupDefaultCodecLimitation");
+ uint i,j,k;
+ CodecType codecType;
+ ResolutionType resolutionType;
+ uint frameRate;
+
+ // non-secure decoders
+ for (i=(int)CODEC_TYPE_AVC; i<(int)CODEC_TYPE_MAX; i++) {
+ codecType = (CodecType)i;
+ for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
+ resolutionType = (ResolutionType)j;
+ for (k=0; k<2; k++) {
+ frameRate = (k+1)*30;
+ bool isSecured = false;
+ CodecLimitInfo codecLimitInfo;
+ codecLimitInfo.codecInfo.codecType = codecType;
+ codecLimitInfo.codecInfo.resolution = resolutionType;
+ codecLimitInfo.codecInfo.isSecured = isSecured;
+ codecLimitInfo.codecInfo.isEncoder = false;
+ codecLimitInfo.codecInfo.frameRate = frameRate;
+ codecLimitInfo.instanceLimit = 2;
+ mDecoderLimitInfos.add(codecLimitInfo);
+ }
+ }
+ }
+
+ // secure avc decoder
+ codecType = CODEC_TYPE_AVC;
+ for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
+ resolutionType = (ResolutionType)j;
+ for (k=0; k<2; k++) {
+ frameRate = (k+1)*30;
+ bool isSecured = true;
+ CodecLimitInfo codecLimitInfo;
+ codecLimitInfo.codecInfo.codecType = codecType;
+ codecLimitInfo.codecInfo.resolution = resolutionType;
+ codecLimitInfo.codecInfo.isSecured = isSecured;
+ codecLimitInfo.codecInfo.isEncoder = false;
+ codecLimitInfo.instanceLimit = 2;
+ mDecoderLimitInfos.add(codecLimitInfo);
+ }
+ }
+
+ // Encoder limitation Map
+ for (i=(int)CODEC_TYPE_AVC; i<(int)CODEC_TYPE_MAX; i++) {
+ codecType = (CodecType)i;
+ for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
+ resolutionType = (ResolutionType)j;
+ for (k=0; k<2; k++) {
+ frameRate = (k+1)*30;
+ bool isSecured = false;
+ CodecLimitInfo codecLimitInfo;
+ codecLimitInfo.codecInfo.codecType = codecType;
+ codecLimitInfo.codecInfo.resolution = resolutionType;
+ codecLimitInfo.codecInfo.isSecured = isSecured;
+ codecLimitInfo.codecInfo.isEncoder = true;
+ codecLimitInfo.instanceLimit = 2;
+ mEncoderLimitInfos.add(codecLimitInfo);
+ }
+ }
+ }
+}
+
+
+void MediaResourceArbitrator::getConfigData(const char *name,
+ const char **atts) {
+ ALOGV("MediaResourceArbitrator::getConfigData");
+ int attIndex = 0;
+ if (strcmp(name, "CodecResourcesLimitation") == 0) {
+ return;
+ } else if (strcmp(name, "Codec") == 0) {
+ if (strcmp(atts[attIndex], "name") == 0) {
+ ALOGV("Parsing codec %s", atts[attIndex+1]);
+ mIfParsingCodec = true;
+ } else {
+ ALOGE("Codec tag with no name, anything wrong?");
+ }
+ } else if (strcmp(name, "codecType") == 0) {
+ ALOGV("parse tag codecType");
+ if (mIfParsingCodec) {
+ if (strcmp(atts[attIndex], "value") == 0) {
+ //DumpCodecTypeFromVector();
+ mParsingCodecLimitInfo.codecInfo.codecType =
+ MapCodecTypeFromName((const char*)atts[attIndex+1]);
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
+ }
+ } else if (strcmp(name, "isEncoder") == 0) {
+ ALOGV("parse tag isEncoder");
+ if (mIfParsingCodec && !strcmp(atts[attIndex], "value")) {
+ if (!strcmp(atts[attIndex + 1], "false"))
+ mParsingCodecLimitInfo.codecInfo.isEncoder = false;
+ else {
+ mParsingCodecLimitInfo.codecInfo.isEncoder = true;
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this tag couldn't be supported\n", name);
+ }
+ } else if (strcmp(name, "isSecured") == 0) {
+ ALOGV("parse tag isSecured");
+ if (mIfParsingCodec && !strcmp(atts[attIndex], "value")) {
+ if (!strcmp(atts[attIndex + 1], "false"))
+ mParsingCodecLimitInfo.codecInfo.isSecured = false;
+ else {
+ mParsingCodecLimitInfo.codecInfo.isSecured = true;
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this tag couldn't be supported\n", name);
+ }
+ } else if (strcmp(name, "resolutionType") == 0) {
+ ALOGV("parse tag resolutionType");
+ if (mIfParsingCodec) {
+ if (strcmp(atts[attIndex], "value") == 0) {
+ mParsingCodecLimitInfo.codecInfo.resolution =
+ MapResolutionTypeFromName((const char*)atts[attIndex+1]);
+ //mResolutionNameTypeMap.valueFor(atts[attIndex+1]);
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
+ }
+ } else if (strcmp(name, "frameRate") == 0) {
+ ALOGV("parse tag frameRate");
+ if (mIfParsingCodec) {
+ if (strcmp(atts[attIndex], "value") == 0) {
+ mParsingCodecLimitInfo.codecInfo.frameRate = atoi(atts[attIndex+1]);
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
+ }
+ } else if (strcmp(name, "instanceLimit") == 0) {
+ ALOGV("parse tag instanceLimit");
+ if (mIfParsingCodec) {
+ if (strcmp(atts[attIndex], "value") == 0) {
+ mParsingCodecLimitInfo.instanceLimit = atoi(atts[attIndex+1]);
+ }
+ } else {
+ ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
+ }
+ }
+}
+
+// Start tag
+void MediaResourceArbitrator::startElement(void *userData,
+ const char *name,
+ const char **atts) {
+ MediaResourceArbitrator* arbitrator = (MediaResourceArbitrator*)userData;
+ arbitrator->getConfigData(name, atts);
+}
+
+
+// End tag
+void MediaResourceArbitrator::endElement(void *userData, const char *name) {
+ MediaResourceArbitrator* arbitrator = (MediaResourceArbitrator*)userData;
+ if (strcmp(name, "Codec") == 0) {
+ if (arbitrator->mParsingCodecLimitInfo.codecInfo.isEncoder == true) {
+ arbitrator->mEncoderLimitInfos.push_back(arbitrator->mParsingCodecLimitInfo);
+ } else {
+ arbitrator->mDecoderLimitInfos.push_back(arbitrator->mParsingCodecLimitInfo);
+ }
+ arbitrator->mIfParsingCodec = false;
+ }
+}
diff --git a/media_resource_manager/arbitrator/MediaResourceArbitrator.h b/media_resource_manager/arbitrator/MediaResourceArbitrator.h
new file mode 100644
index 0000000..abb7b1a
--- /dev/null
+++ b/media_resource_manager/arbitrator/MediaResourceArbitrator.h
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 2015 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.
+*/
+
+
+#ifndef MEDIA_RESOURCE_ARBITRATOR_H_
+#define MEDIA_RESOURCE_ARBITRATOR_H_
+
+#include <unistd.h>
+#include <string.h>
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+
+#define MAX_BUFFER_SIZE (20 * 1024)
+
+using namespace android;
+
+// This error type keeps align with the OMX error type
+typedef enum _ArbitratorErrorType {
+ ArbitratorErrorNone = 0,
+
+ /** There were insufficient resources to perform the requested operation */
+ ArbitratorErrorInsufficientResources = 0x80001000,
+
+ /** There was an error, but the cause of the error could not be determined */
+ ArbitratorErrorUndefined = 0x80001001
+} ArbitratorErrorType;
+
+
+typedef enum _ResolutionType {
+ Resolution_CIF = 0,
+ Resolution_480,
+ Resolution_720,
+ Resolution_1080,
+ Resolution_2K,
+ Resolution_4K,
+ Resolution_MAX
+} ResolutionType;
+
+
+typedef enum _CodecType {
+ CODEC_TYPE_AVC = 0,
+ CODEC_TYPE_HEVC,
+ CODEC_TYPE_VP8,
+ CODEC_TYPE_VP9,
+ CODEC_TYPE_MPEG4,
+ CODEC_TYPE_MPEG2,
+ CODEC_TYPE_H263,
+ CODEC_TYPE_VC1,
+ CODEC_TYPE_WMV,
+ CODEC_TYPE_MAX
+} CodecType;
+
+
+typedef struct _CodecInfo {
+ CodecType codecType;
+ bool isEncoder;
+ bool isSecured;
+ ResolutionType resolution;
+ uint frameRate;
+} CodecInfo;
+
+
+typedef struct _CodecLimitInfo {
+ CodecInfo codecInfo;
+ int instanceLimit;
+} CodecLimitInfo;
+
+
+typedef struct _LivingDecodersTable {
+ Vector<CodecInfo> livingDecoders;
+ uint maxResolution;
+ uint maxFrameRate;
+} LivingDecodersTable;
+
+
+typedef struct _LivingEncodersTable {
+ Vector<CodecInfo> livingEncoders;
+ uint maxResolution;
+ uint maxFrameRate;
+} LivingEncodersTable;
+
+
+class MediaResourceArbitrator {
+public:
+ MediaResourceArbitrator ();
+ ~MediaResourceArbitrator ();
+
+ /* Initialize the arbitrator.
+ Parse the config XML file if given. */
+ ArbitratorErrorType Config(const char* configFilePath);
+
+ /* Check if the resource limitation is hit and
+ it is under full load status. In such status, there
+ is no room to instantiate codec anymore. */
+ bool CheckIfFullLoad(bool isEncoder);
+
+ /* Add codec in the pool.
+ Resolution and frame rate must be provided.
+ This is not necessarily be called when codec instance
+ is constructed when the resolution and frame rate are
+ not known yet.
+ This may be called when codec is configured,
+ for example in OMX set parameter, etc.
+ Return value is expected to be as one of:
+ ArbitratorErrorNone,
+ ArbitratorErrorInsufficientResources
+ */
+ ArbitratorErrorType AddResource(/* in */ CodecType codecType,
+ /* in */ bool isEncoder,
+ /* in */ bool isSecured,
+ /* in */ ResolutionType resolution,
+ /* in */ uint frameRate);
+
+ /* Remove codec in the pool.*/
+ ArbitratorErrorType RemoveResource(CodecType codecType,
+ bool isEncoder,
+ bool isSecured,
+ ResolutionType resolution,
+ uint frameRate);
+
+ uint GetLivingCodecsNum(void);
+
+ // XML function
+ void ParseXMLFile(FILE* fp);
+ static void startElement(void *userData, const char *name, const char **atts);
+ static void endElement(void *userData, const char *name);
+ void getConfigData(const char *name, const char **atts);
+
+private:
+ // a global table stores all codec limit info
+ Vector<CodecLimitInfo> mDecoderLimitInfos;
+ Vector<CodecLimitInfo> mEncoderLimitInfos;
+
+ // a global talbe stores all living codec info
+ LivingDecodersTable mLivingDecodersTable;
+ LivingEncodersTable mLivingEncodersTable;
+
+ // arbitrator lock
+ pthread_mutex_t mArbitratorLock;
+
+ // indicate whether it is under full load status
+ bool mIsEncoderUnderFullLoad;
+ bool mIsDecoderUnderFullLoad;
+
+ KeyedVector <const char*, CodecType> mCodecNameTypeMap;
+ KeyedVector <const char*, ResolutionType> mResolutionNameTypeMap;
+
+ static const int mBufSize = MAX_BUFFER_SIZE;
+ // indicate XML parser is parsing a codec tag
+ bool mIfParsingCodec;
+ CodecLimitInfo mParsingCodecLimitInfo;
+
+ ArbitratorErrorType ArbitrateFullLoad(CodecInfo& codec);
+
+ bool CheckCodecMatched(const CodecInfo& sourceCodec,
+ const CodecInfo& targetCodec);
+
+ void SetupDefaultCodecLimitation(void);
+ void InitializeCodecNameTypeMap();
+ void InitializeResolutionNameTypeMap();
+ void DumpCodecTypeFromVector(void);
+ CodecType MapCodecTypeFromName(const char* name);
+ ResolutionType MapResolutionTypeFromName(const char* name);
+};
+
+#endif /* MEDIA_RESOURCE_ARBITRATOR_H_ */
diff --git a/media_resource_manager/omx_adaptor/Android.mk b/media_resource_manager/omx_adaptor/Android.mk
new file mode 100644
index 0000000..d30b8c1
--- /dev/null
+++ b/media_resource_manager/omx_adaptor/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ OMX_adaptor.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libcutils \
+ libexpat \
+ libdl \
+ libmrm_arbitrator \
+
+
+LOCAL_C_INCLUDES := \
+ $(TARGET_OUT_HEADERS)/khronos/openmax \
+ $(call include-path-for, frameworks-native)/media/openmax \
+ $(LOCAL_PATH)/../arbitrator \
+
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libmrm_omx_adaptor
+
+#LOCAL_CFLAGS += -Werror
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media_resource_manager/omx_adaptor/OMX_adaptor.cpp b/media_resource_manager/omx_adaptor/OMX_adaptor.cpp
new file mode 100644
index 0000000..2df886c
--- /dev/null
+++ b/media_resource_manager/omx_adaptor/OMX_adaptor.cpp
@@ -0,0 +1,287 @@
+/*
+ * * Copyright (c) 2015 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_NDEBUG 0
+#define LOG_TAG "MRM_OMX_Adaptor"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include "OMX_adaptor.h"
+
+const char* CODECS_LIMITATION_FILE = "/etc/codec_resources_limitation.xml";
+
+using namespace android;
+
+// static member declare
+MRM_OMX_Adaptor* MRM_OMX_Adaptor::sInstance = NULL;
+Mutex MRM_OMX_Adaptor::sLock;
+
+typedef enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1
+} PORT_INDEX;
+
+
+// case insensitive string finding
+static const char* strstri(const char* str, const char* subStr) {
+ int len = strlen(subStr);
+ if (len == 0) {
+ return NULL;
+ }
+
+ while(*str) {
+ if(strncasecmp(str, subStr, len) == 0) {
+ return str;
+ }
+ ++str;
+ }
+ return NULL;
+}
+
+
+//static
+MRM_OMX_Adaptor* MRM_OMX_Adaptor::getInstance() {
+ ALOGV("getInstance()");
+ Mutex::Autolock lock(sLock);
+
+ if (sInstance == NULL) {
+ sInstance = new MRM_OMX_Adaptor();
+ }
+
+ return sInstance;
+}
+
+
+OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_Init(void) {
+ ALOGV("MRM_OMX_Init");
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ if (mArbitrator != NULL) {
+ err = (OMX_ERRORTYPE)mArbitrator->Config(CODECS_LIMITATION_FILE);
+ }
+ return err;
+}
+
+
+OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_CheckIfFullLoad(OMX_STRING cComponentName) {
+ ALOGV("MRM_OMX_CheckIfFullLoad");
+ Mutex::Autolock lock(sLock);
+
+ String8 sComponentName(cComponentName);
+ AdaptorCodecInfo codecInfo;
+ ParseCodecInfoFromComponentName(sComponentName.string(), &codecInfo);
+
+ if (codecInfo.isEncoder) {
+ ALOGV("Checking full load status of encoder.");
+ if (mArbitrator->CheckIfFullLoad(true/*encoder*/)) {
+ ALOGV("encoder in full load status. return OMX_ErrorInsufficientResources");
+ return OMX_ErrorInsufficientResources;
+ } else {
+ return OMX_ErrorNone;
+ }
+ } else {
+ ALOGV("Checking full load status of decoder.");
+ if (mArbitrator->CheckIfFullLoad(false/*decoder*/)) {
+ ALOGV("decoder in full load status. return OMX_ErrorInsufficientResources");
+ return OMX_ErrorInsufficientResources;
+ } else {
+ return OMX_ErrorNone;
+ }
+ }
+}
+
+
+void MRM_OMX_Adaptor::MRM_OMX_SetComponent(
+ OMX_HANDLETYPE pComponentHandle,
+ OMX_STRING cComponentName) {
+ ALOGV("MRM_OMX_SetComponent: %s", cComponentName);
+ String8 sComponentName(cComponentName);
+ ALOGV("pComponentHandle = 0x%x, componentName = %s", pComponentHandle, sComponentName.string());
+ mComponentNameMap.add(pComponentHandle, sComponentName);
+}
+
+
+OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_SetParameter(
+ OMX_HANDLETYPE hComponent,
+ OMX_INDEXTYPE nIndex,
+ OMX_PTR pComponentParameterStructure) {
+ ALOGV("MRM_OMX_SetParameter");
+ ALOGV("hComponent = 0x%x", hComponent);
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ Mutex::Autolock lock(sLock);
+
+ if (nIndex == OMX_IndexParamPortDefinition) {
+ OMX_PARAM_PORTDEFINITIONTYPE *def =
+ static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
+
+ if (def->nPortIndex == kPortIndexInput) {
+ ALOGV("MRM_OMX_SetParameter for inport param def");
+ if (mComponentFramerateMap.indexOfKey(hComponent) >= 0) {
+ ALOGV("setParameter is called again for component 0x%x inport", hComponent);
+ return OMX_ErrorNone;
+ }
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
+ uint frameRate = (uint)(video_def->xFramerate/65536);
+ ALOGV("frame rate from inport = %d", frameRate);
+ mComponentFramerateMap.add(hComponent, frameRate);
+ }
+
+ if (def->nPortIndex == kPortIndexOutput) {
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
+
+ // if setParameter is not first called to this component's outport
+ // do not try to record its info for the second time
+ if (mComponentInfoMap.indexOfKey(hComponent) >= 0) {
+ ALOGV("setParameter is called again for component 0x%x outport", hComponent);
+ return OMX_ErrorNone;
+ }
+
+ String8 sComponentName = mComponentNameMap.valueFor(hComponent);
+ ALOGV("component name from component map is %s", sComponentName.string());
+
+ AdaptorCodecInfo codecInfo;
+ ParseCodecInfoFromComponentName(sComponentName.string(), &codecInfo);
+
+ if (mArbitrator->CheckIfFullLoad(codecInfo.isEncoder)) {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ ResolutionType resolution;
+ unsigned int height = video_def->nFrameHeight;
+ ALOGV("video resulotion = %d x %d", video_def->nFrameWidth, video_def->nFrameHeight);
+ if (height <= 480) {
+ resolution = Resolution_480;
+ } else if (height <= 720) {
+ resolution = Resolution_720;
+ } else if (height <= 1080) {
+ resolution = Resolution_1080;
+ } else if (height <= 1440) {
+ resolution = Resolution_2K;
+ } else if (height <= 2160) {
+ resolution = Resolution_4K;
+ } else {
+ ALOGE("resolution > 4K is not supported!");
+ }
+ codecInfo.resolution = resolution;
+
+ unsigned int frameRate = 0;
+ if (mComponentFramerateMap.indexOfKey(hComponent) >= 0) {
+ frameRate = mComponentFramerateMap.valueFor(hComponent);
+ } else {
+ ALOGW("frame rate was not set in inport def...");
+ }
+
+ ALOGV("frame rate from inport def = %d", frameRate);
+ if ((frameRate > 55) && (frameRate < 65)) {
+ frameRate = 60;
+ // This is a w/a to set default frame rate as 30 in case it is not
+ // set from framewrok.
+ } else {
+ frameRate = 30;
+ }
+ codecInfo.frameRate = frameRate;
+ err = (OMX_ERRORTYPE)mArbitrator->AddResource(codecInfo.codecType,
+ codecInfo.isEncoder,
+ codecInfo.isSecured,
+ codecInfo.resolution,
+ codecInfo.frameRate);
+
+ mComponentInfoMap.add(hComponent, codecInfo);
+ }
+ }
+ return err;
+}
+
+
+OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_UseBuffer(
+ OMX_HANDLETYPE hComponent,
+ OMX_BUFFERHEADERTYPE **ppBufferHdr,
+ OMX_U32 nPortIndex,
+ OMX_PTR pAppPrivate,
+ OMX_U32 nSizeBytes,
+ OMX_U8 *pBuffer) {
+ ALOGV("MRM_OMX_UseBuffer");
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ return err;
+}
+
+
+OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_RemoveComponent(
+ OMX_HANDLETYPE pComponentHandle) {
+ ALOGV("MRM_OMX_RemoveComponent");
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ if (mComponentInfoMap.indexOfKey(pComponentHandle) < 0) {
+ ALOGE("component 0x%x was not added by setParameter before! something is wrong?");
+ return OMX_ErrorNone; // TODO: change to specific error.
+ }
+
+ const AdaptorCodecInfo& codecInfo = mComponentInfoMap.valueFor(pComponentHandle);
+
+ err = (OMX_ERRORTYPE)mArbitrator->RemoveResource(codecInfo.codecType,
+ codecInfo.isEncoder,
+ codecInfo.isSecured,
+ codecInfo.resolution,
+ codecInfo.frameRate);
+ return err;
+}
+
+
+
+
+void MRM_OMX_Adaptor::ParseCodecInfoFromComponentName(
+ const char* componentName,
+ AdaptorCodecInfo* codecInfo) {
+ ALOGV("ParseCodecInfoFromComponentName");
+ ALOGV("componentName = %s", componentName);
+ bool isSecured = false;
+ if (strstri(componentName,"SECURE") != NULL) {
+ isSecured = true;
+ }
+ codecInfo->isSecured = isSecured;
+
+ bool isEncoder = false;
+ if ((strstri(componentName, "ENCODER") != NULL) ||
+ (strstri(componentName, "sw_ve") != NULL)) {
+ isEncoder = true;
+ }
+ codecInfo->isEncoder = isEncoder;
+
+ CodecType codecType;
+ if (strstri(componentName, "AVC") != NULL) {
+ codecType = CODEC_TYPE_AVC;
+ } else if (strstri(componentName, "VP8") != NULL) {
+ codecType = CODEC_TYPE_VP8;
+ } else if (strstri(componentName, "VP9") != NULL) {
+ codecType = CODEC_TYPE_VP9;
+ } else if (strstri(componentName, "MPEG4") != NULL) {
+ codecType = CODEC_TYPE_MPEG4;
+ } else if (strstri(componentName, "MPEG2") != NULL) {
+ codecType = CODEC_TYPE_MPEG2;
+ } else if (strstri(componentName, "H263") != NULL) {
+ codecType = CODEC_TYPE_H263;
+ } else if (strstri(componentName, "H265") != NULL) {
+ codecType = CODEC_TYPE_HEVC;
+ } else if (strstri(componentName, "WMV") != NULL) {
+ codecType = CODEC_TYPE_WMV;
+ }
+ ALOGV("video codec type = %d", codecType);
+ codecInfo->codecType = codecType;
+}
+
+
diff --git a/media_resource_manager/omx_adaptor/OMX_adaptor.h b/media_resource_manager/omx_adaptor/OMX_adaptor.h
new file mode 100644
index 0000000..145233d
--- /dev/null
+++ b/media_resource_manager/omx_adaptor/OMX_adaptor.h
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2015 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.
+*/
+
+
+#ifndef OMX_WRAPPER_H_
+#define OMX_WRAPPER_H_
+
+#include <unistd.h>
+#include <OMX_Core.h>
+#include <OMX_Component.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include "MediaResourceArbitrator.h"
+
+using namespace android;
+
+typedef KeyedVector <OMX_HANDLETYPE, String8> ComponentNameMap;
+typedef KeyedVector <OMX_HANDLETYPE, uint> ComponentFramerateMap;
+
+typedef struct _AdaptorCodecInfo {
+ CodecType codecType;
+ bool isEncoder;
+ bool isSecured;
+ ResolutionType resolution;
+ uint frameRate;
+} AdaptorCodecInfo;
+
+typedef KeyedVector <OMX_HANDLETYPE, AdaptorCodecInfo> ComponentInfoMap;
+
+class MRM_OMX_Adaptor {
+public:
+ // Returns the singleton instance
+ static MRM_OMX_Adaptor* getInstance();
+
+ ~MRM_OMX_Adaptor() {
+ if (sInstance) {
+ delete sInstance;
+ sInstance = NULL;
+ }
+ };
+
+ // create and configure the MRM arbitrator
+ OMX_ERRORTYPE MRM_OMX_Init(void);
+
+
+ // check with MRM arbitrator if codec resource
+ // is under full load status.
+ // this should be called before OMX_GetHandle
+ // return OMX_ErrorInsufficientResources if true.
+ OMX_ERRORTYPE MRM_OMX_CheckIfFullLoad(OMX_STRING cComponentName);
+
+
+ // Set component name and component handle
+ // keeps this mapping but not adds resource yet.
+ // this intends to be called after OMX_GetHandle
+ void MRM_OMX_SetComponent(
+ OMX_HANDLETYPE pComponentHandle,
+ OMX_STRING cComponentName);
+
+
+ // handle the index 'OMX_IndexParamPortDefinition'
+ // when codec is configured, with resolution and
+ // frame rate. this actually adds resource
+ // to the MRM arbitrator.
+ // return OMX_ErrorInsufficientResources if failed.
+ OMX_ERRORTYPE MRM_OMX_SetParameter(
+ OMX_HANDLETYPE hComponent,
+ OMX_INDEXTYPE nIndex,
+ OMX_PTR pComponentParameterStructure);
+
+
+ // check grahpic buffer resource
+ // return OMX_ErrorInsufficientResources if under full load status.
+ OMX_ERRORTYPE MRM_OMX_UseBuffer(
+ OMX_HANDLETYPE hComponent,
+ OMX_BUFFERHEADERTYPE **ppBufferHdr,
+ OMX_U32 nPortIndex,
+ OMX_PTR pAppPrivate,
+ OMX_U32 nSizeBytes,
+ OMX_U8 *pBuffer);
+
+
+ // Remove the component
+ OMX_ERRORTYPE MRM_OMX_RemoveComponent(OMX_HANDLETYPE pComponentHandle);
+
+private:
+ MRM_OMX_Adaptor() { mArbitrator = new MediaResourceArbitrator(); }
+ MRM_OMX_Adaptor& operator=(const MRM_OMX_Adaptor&); // Don't call me
+ MRM_OMX_Adaptor(const MRM_OMX_Adaptor&); // Don't call me
+
+
+ void ParseCodecInfoFromComponentName(const char* componentName,
+ AdaptorCodecInfo* codecInfo);
+
+ MediaResourceArbitrator* mArbitrator;
+ static Mutex sLock;
+ static MRM_OMX_Adaptor* sInstance;
+
+ ComponentNameMap mComponentNameMap;
+ ComponentFramerateMap mComponentFramerateMap;
+ ComponentInfoMap mComponentInfoMap;
+};
+#endif /* OMX_WRAPPER_H_ */
diff --git a/media_resource_manager/test/Android.mk b/media_resource_manager/test/Android.mk
new file mode 100644
index 0000000..7703265
--- /dev/null
+++ b/media_resource_manager/test/Android.mk
@@ -0,0 +1,23 @@
+# Build the unit tests
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := MediaResourceManager_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ MediaResourceManager_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libmrm_arbitrator \
+ libutils \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../arbitrator \
+
+#LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_NATIVE_TEST)
+
diff --git a/media_resource_manager/test/MediaResourceManager_test.cpp b/media_resource_manager/test/MediaResourceManager_test.cpp
new file mode 100644
index 0000000..4531d8c
--- /dev/null
+++ b/media_resource_manager/test/MediaResourceManager_test.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ * 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_NDEBUG 0
+#define LOG_TAG "MediaResourceManager_test"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+#include "MediaResourceArbitrator.h"
+
+using namespace android;
+
+
+class MediaResourceManagerTest : public ::testing::Test {
+public:
+ MediaResourceManagerTest()
+ : mArbitrator(new MediaResourceArbitrator) {
+ mArbitrator->Config(NULL);
+ }
+
+ ~MediaResourceManagerTest() {
+ delete mArbitrator;
+ }
+
+protected:
+ void addDefaultResourceByN(int N) {
+/*
+ CodecInfo codec1;
+ codec1.codecType = CODEC_TYPE_AVC;
+ codec1.isEncoder = false;
+ codec1.isSecured = false;
+ codec1.resolution = Resolution_1080;
+ codec1.frameRate = 30;
+*/
+ int i;
+ ArbitratorErrorType err = ArbitratorErrorNone;
+ for (i=0; i<N; i++) {
+ err = mArbitrator->AddResource(CODEC_TYPE_AVC,
+ false,
+ false,
+ Resolution_1080,
+ 30);
+ if (err == ArbitratorErrorInsufficientResources) {
+ ALOGE("%dth codec can not be added anymore.");
+ return;
+ }
+ }
+ }
+
+ void testAddResource(void) {
+ addDefaultResourceByN(10);
+ EXPECT_EQ(2u, mArbitrator->GetLivingCodecsNum());
+ }
+
+
+ void testRemoveResource(void) {
+ addDefaultResourceByN(5);
+ EXPECT_EQ(2u, mArbitrator->GetLivingCodecsNum());
+ EXPECT_TRUE(mArbitrator->CheckIfFullLoad(false));
+ ArbitratorErrorType err = ArbitratorErrorNone;
+ err = mArbitrator->RemoveResource(CODEC_TYPE_AVC,
+ false,
+ false,
+ Resolution_1080,
+ 30);
+ EXPECT_EQ(1u, mArbitrator->GetLivingCodecsNum());
+ EXPECT_FALSE(mArbitrator->CheckIfFullLoad(false));
+ }
+
+
+ void testCheckFullLoad(void) {
+ EXPECT_FALSE(mArbitrator->CheckIfFullLoad(false));
+ addDefaultResourceByN(5);
+ EXPECT_TRUE(mArbitrator->CheckIfFullLoad(false));
+ }
+
+
+ void testConfigByXML(void) {
+ }
+
+
+ MediaResourceArbitrator* mArbitrator;
+};
+
+
+TEST_F(MediaResourceManagerTest, config) {
+}
+
+
+TEST_F(MediaResourceManagerTest, addResource) {
+ testAddResource();
+}
+
+
+TEST_F(MediaResourceManagerTest, removeResource) {
+ testRemoveResource();
+}
+
+
+TEST_F(MediaResourceManagerTest, checkFullLoad) {
+ testCheckFullLoad();
+}
+
+
+TEST_F(MediaResourceManagerTest, configByXML) {
+ testConfigByXML();
+}
+
+
+