upload android base code part4

This commit is contained in:
August 2018-08-08 17:00:29 +08:00
parent b9e30e05b1
commit 78ea2404cd
23455 changed files with 5250148 additions and 0 deletions

View file

@ -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))

View file

@ -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)

View file

@ -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;
}
}

View file

@ -0,0 +1 @@
../include/MediaResourceArbitrator.h

View file

@ -0,0 +1 @@
../include/

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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)

View file

@ -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;
}

View file

@ -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_ */

View file

@ -0,0 +1 @@
../include/

View file

@ -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)

View file

@ -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();
}