upload android base code part4
This commit is contained in:
parent
b9e30e05b1
commit
78ea2404cd
23455 changed files with 5250148 additions and 0 deletions
|
@ -0,0 +1,8 @@
|
|||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
MEDIA_RESOURCE_MANAGER_ROOT := $(LOCAL_PATH)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
|
@ -0,0 +1,25 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
MediaResourceArbitrator.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
liblog \
|
||||
libutils \
|
||||
libcutils \
|
||||
libexpat \
|
||||
libdl \
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(TARGET_OUT_HEADERS)/khronos/openmax \
|
||||
$(call include-path-for, frameworks-native)/media/openmax
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmrm_arbitrator
|
||||
|
||||
LOCAL_CFLAGS += -Werror
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -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 <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", __FUNCTION__);
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
../include/MediaResourceArbitrator.h
|
|
@ -0,0 +1 @@
|
|||
../include/
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -0,0 +1,28 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
OMX_adaptor.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
liblog \
|
||||
libutils \
|
||||
libcutils \
|
||||
libexpat \
|
||||
libdl \
|
||||
libmrm_arbitrator \
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
|
||||
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)
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* * 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 = %p, 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 = %p", 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 %p 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 %p 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 = Resolution_CIF;
|
||||
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");
|
||||
if(pBuffer == 0 || ppBufferHdr == 0) {
|
||||
ALOGV("%s: Null buffer. hComponent:%p, ppBufferHdr:%p, "
|
||||
"nPortIndex:%d, pAppPrivate:%p, nSizeBytes:%d, pBuffer:%p",
|
||||
__FUNCTION__,
|
||||
hComponent,
|
||||
ppBufferHdr,
|
||||
nPortIndex,
|
||||
pAppPrivate,
|
||||
nSizeBytes,
|
||||
pBuffer);
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE err = OMX_ErrorNone;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_RemoveComponent(
|
||||
OMX_HANDLETYPE pComponentHandle) {
|
||||
ALOGV("MRM_OMX_RemoveComponent %p", pComponentHandle);
|
||||
OMX_ERRORTYPE err = OMX_ErrorNone;
|
||||
|
||||
if (mComponentInfoMap.indexOfKey(pComponentHandle) < 0) {
|
||||
ALOGE("component %p was not added by setParameter before! something is wrong?", pComponentHandle);
|
||||
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);
|
||||
mComponentInfoMap.removeItem(pComponentHandle);
|
||||
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 = CODEC_TYPE_MAX;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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_ */
|
|
@ -0,0 +1 @@
|
|||
../include/
|
|
@ -0,0 +1,25 @@
|
|||
# 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
|
||||
|
||||
LOCAL_CFLAGS += -Werror
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
|
@ -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.", i);
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue